diff options
author | Christopher Tate <ctate@google.com> | 2016-02-25 12:43:38 -0800 |
---|---|---|
committer | Christopher Tate <ctate@google.com> | 2016-04-20 14:34:07 -0700 |
commit | d7faf53605838487cace9979e577005cc7c8cabc (patch) | |
tree | 775e47954ed2443bb60381e8f39145d3a7c57a33 | |
parent | 66e640d8b459ff285c7d9533f97990e92f9cc0da (diff) |
Don't back up wallpapers that we've been told not to
In addition, now that the full uncropped wallpaper image is being
backed up, we now handle that via the full-data backup path instead
of key/value. Restore still knows about legacy data that gets
delivered via the older key/value mechanism.
This change also has the effect of removing the size limitations
around wallpaper restore acceptance. Any size source imagery is
valid, as crop & scale are rerun in a device-appropriate way
after the restore.
Bug 25453848
Bug 25727875
Change-Id: Idc64a2eaab97a8ecc9d2b8ca5dc011f29cab324d
8 files changed, 320 insertions, 62 deletions
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index 2fc6533f2cd0..a42aed6fe28a 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -43,7 +43,8 @@ interface IWallpaperManager { * new wallpaper content is ready to display. */ ParcelFileDescriptor setWallpaper(String name, in String callingPackage, - in Rect cropHint, out Bundle extras, int which, IWallpaperManagerCallback completion); + in Rect cropHint, boolean allowBackup, out Bundle extras, int which, + IWallpaperManagerCallback completion); /** * Set the live wallpaper. This only affects the system wallpaper. @@ -125,6 +126,11 @@ interface IWallpaperManager { boolean isWallpaperSettingAllowed(in String callingPackage); /* + * Backup: is the current system wallpaper image eligible for off-device backup? + */ + boolean isWallpaperBackupEligible(int userId); + + /* * Keyguard: register a callback for being notified that lock-state relevant * wallpaper content has changed. */ diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 72b9318c2acd..18a559368e66 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1,5 +1,5 @@ /* -h * Copyright (C) 2009 The Android Open Source Project + * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -875,7 +875,7 @@ public class WallpaperManager { /* Set the wallpaper to the default values */ ParcelFileDescriptor fd = sGlobals.mService.setWallpaper( "res:" + resources.getResourceName(resid), - mContext.getOpPackageName(), null, result, which, completion); + mContext.getOpPackageName(), null, false, result, which, completion); if (fd != null) { FileOutputStream fos = null; boolean ok = false; @@ -985,7 +985,8 @@ public class WallpaperManager { final WallpaperSetCompletion completion = new WallpaperSetCompletion(); try { ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null, - mContext.getOpPackageName(), visibleCropHint, result, which, completion); + mContext.getOpPackageName(), visibleCropHint, allowBackup, + result, which, completion); if (fd != null) { FileOutputStream fos = null; try { @@ -1102,7 +1103,8 @@ public class WallpaperManager { final WallpaperSetCompletion completion = new WallpaperSetCompletion(); try { ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null, - mContext.getOpPackageName(), visibleCropHint, result, which, completion); + mContext.getOpPackageName(), visibleCropHint, allowBackup, + result, which, completion); if (fd != null) { FileOutputStream fos = null; try { @@ -1565,6 +1567,25 @@ public class WallpaperManager { } } + /** + * Is the current system wallpaper eligible for backup? + * + * Only the OS itself may use this method. + * @hide + */ + public boolean isWallpaperBackupEligible() { + if (sGlobals.mService == null) { + Log.w(TAG, "WallpaperService not running"); + return false; + } + try { + return sGlobals.mService.isWallpaperBackupEligible(mContext.getUserId()); + } catch (RemoteException e) { + Log.e(TAG, "Exception querying wallpaper backup eligibility: " + e.getMessage()); + } + return false; + } + // Private completion callback for setWallpaper() synchronization private class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub { final CountDownLatch mLatch; diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java index 2d12fcda87c1..3e4530944b9e 100644 --- a/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/core/java/com/android/server/backup/SystemBackupAgent.java @@ -76,26 +76,6 @@ public class SystemBackupAgent extends BackupAgentHelper { @Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { - // We only back up the data under the current "wallpaper" schema with metadata - IWallpaperManager wallpaper = (IWallpaperManager)ServiceManager.getService( - Context.WALLPAPER_SERVICE); - String[] files = new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }; - String[] keys = new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY }; - if (wallpaper != null) { - try { - final String wallpaperName = wallpaper.getName(); - if (wallpaperName != null && wallpaperName.length() > 0) { - // When the wallpaper has a name, back up the info by itself. - // TODO: Don't rely on the innards of the service object like this! - // TODO: Send a delete for any stored wallpaper image in this case? - files = new String[] { WALLPAPER_INFO }; - keys = new String[] { WALLPAPER_INFO_KEY }; - } - } catch (RemoteException re) { - Slog.e(TAG, "Couldn't get wallpaper name\n" + re); - } - } - addHelper(WALLPAPER_HELPER, new WallpaperBackupHelper(this, files, keys)); addHelper(SYNC_SETTINGS_HELPER, new AccountSyncSettingsBackupHelper(this)); addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); @@ -107,30 +87,20 @@ public class SystemBackupAgent extends BackupAgentHelper { @Override public void onFullBackup(FullBackupDataOutput data) throws IOException { - // At present we back up only the wallpaper - fullWallpaperBackup(data); - } - - private void fullWallpaperBackup(FullBackupDataOutput output) { - // Back up the data files directly. We do them in this specific order -- - // info file followed by image -- because then we need take no special - // steps during restore; the restore will happen properly when the individual - // files are restored piecemeal. - FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null, - WALLPAPER_INFO_DIR, WALLPAPER_INFO, output); - FullBackup.backupToTar(getPackageName(), FullBackup.ROOT_TREE_TOKEN, null, - WALLPAPER_IMAGE_DIR, WALLPAPER_IMAGE, output); + // At present we don't back up anything } @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { + // Slot in a restore helper for the older wallpaper backup schema to support restore + // from devices still generating data in that format. mWallpaperHelper = new WallpaperBackupHelper(this, new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }, new String[] { WALLPAPER_IMAGE_KEY, WALLPAPER_INFO_KEY} ); addHelper(WALLPAPER_HELPER, mWallpaperHelper); - // On restore, we also support a previous data schema "system_files" + // On restore, we also support a long-ago wallpaper data schema "system_files" addHelper("system_files", new WallpaperBackupHelper(this, new String[] { WALLPAPER_IMAGE }, new String[] { WALLPAPER_IMAGE_KEY} )); diff --git a/packages/WallpaperBackup/Android.mk b/packages/WallpaperBackup/Android.mk new file mode 100644 index 000000000000..cf0424966c10 --- /dev/null +++ b/packages/WallpaperBackup/Android.mk @@ -0,0 +1,34 @@ +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +LOCAL_PACKAGE_NAME := WallpaperBackup +LOCAL_CERTIFICATE := platform +LOCAL_PRIVILEGED_MODULE := false + +include $(BUILD_PACKAGE) + +######################## +include $(call all-makefiles-under,$(LOCAL_PATH)) + diff --git a/packages/WallpaperBackup/AndroidManifest.xml b/packages/WallpaperBackup/AndroidManifest.xml new file mode 100644 index 000000000000..b8cea20afcd4 --- /dev/null +++ b/packages/WallpaperBackup/AndroidManifest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (c) 2016 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.wallpaperbackup" + android:sharedUserId="android.uid.system" > + + <application android:allowClearUserData="false" + android:process="system" + android:killAfterRestore="false" + android:allowBackup="true" + android:backupAgent=".WallpaperBackupAgent" + android:fullBackupOnly="true" > + </application> +</manifest> diff --git a/packages/WallpaperBackup/proguard.flags b/packages/WallpaperBackup/proguard.flags new file mode 100644 index 000000000000..247e6efb10ef --- /dev/null +++ b/packages/WallpaperBackup/proguard.flags @@ -0,0 +1 @@ +-keep class com.android.wallpaperbackup.WallpaperBackupAgent diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java new file mode 100644 index 000000000000..2f79079c9188 --- /dev/null +++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wallpaperbackup; + +import android.app.WallpaperManager; +import android.app.backup.BackupAgent; +import android.app.backup.BackupDataInput; +import android.app.backup.BackupDataOutput; +import android.app.backup.FullBackupDataOutput; +import android.content.Context; +import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.os.UserHandle; +import android.system.Os; +import android.util.Slog; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +public class WallpaperBackupAgent extends BackupAgent { + private static final String TAG = "WallpaperBackup"; + private static final boolean DEBUG = false; + + // NB: must be kept in sync with WallpaperManagerService but has no + // compile-time visiblity. + + // Target filenames within the system's wallpaper directory + static final String WALLPAPER = "wallpaper_orig"; + static final String WALLPAPER_INFO = "wallpaper_info.xml"; + + // Names of our local-data stage files/links + static final String IMAGE_STAGE = "wallpaper-stage"; + static final String INFO_STAGE = "wallpaper-info-stage"; + static final String EMPTY_SENTINEL = "empty"; + + private File mWallpaperInfo; // wallpaper metadata file + private File mWallpaperFile; // primary wallpaper image file + + private WallpaperManager mWm; + + @Override + public void onCreate() { + if (DEBUG) { + Slog.v(TAG, "onCreate()"); + } + + File wallpaperDir = Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM); + mWallpaperInfo = new File(wallpaperDir, WALLPAPER_INFO); + mWallpaperFile = new File(wallpaperDir, WALLPAPER); + mWm = (WallpaperManager) getSystemService(Context.WALLPAPER_SERVICE); + } + + @Override + public void onFullBackup(FullBackupDataOutput data) throws IOException { + // To avoid data duplication and disk churn, use links as the stage. + final File filesDir = getFilesDir(); + final File infoStage = new File(filesDir, INFO_STAGE); + final File imageStage = new File (filesDir, IMAGE_STAGE); + final File empty = new File (filesDir, EMPTY_SENTINEL); + + try { + // We always back up this 'empty' file to ensure that the absence of + // storable wallpaper imagery still produces a non-empty backup data + // stream, otherwise it'd simply be ignored in preflight. + FileOutputStream touch = new FileOutputStream(empty); + touch.close(); + fullBackupFile(empty, data); + + // only back up the wallpaper if we've been told it's allowed + if (mWm.isWallpaperBackupEligible()) { + if (DEBUG) { + Slog.v(TAG, "Wallpaper is backup-eligible; linking & writing"); + } + Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath()); + fullBackupFile(infoStage, data); + Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath()); + fullBackupFile(imageStage, data); + } else { + if (DEBUG) { + Slog.v(TAG, "Wallpaper not backup-eligible; writing no data"); + } + } + } catch (Exception e) { + Slog.e(TAG, "Unable to back up wallpaper: " + e.getMessage()); + } finally { + if (DEBUG) { + Slog.v(TAG, "Removing backup stage links"); + } + infoStage.delete(); + imageStage.delete(); + } + } + + // We use the default onRestoreFile() implementation that will recreate our stage files, + // then postprocess in onRestoreFinished() to move them on top of the live data. + // + // NOTE: this relies on our local files dir being on the same filesystem as the live + // system wallpaper data. If this is not the case then an actual copy operation will + // be needed. + @Override + public void onRestoreFinished() { + if (DEBUG) { + Slog.v(TAG, "onRestoreFinished()"); + } + final File infoStage = new File(getFilesDir(), INFO_STAGE); + final File imageStage = new File (getFilesDir(), IMAGE_STAGE); + + try { + // It is valid for the imagery to be absent; it means that we were not permitted + // to back up the original image on the source device. + if (imageStage.exists()) { + if (DEBUG) { + Slog.v(TAG, "Got restored wallpaper; renaming into place"); + } + // Rename the image file into place last because that is the trigger for + // the wallpaper observer to generate a new crop/scale + Os.rename(infoStage.getCanonicalPath(), mWallpaperInfo.getCanonicalPath()); + Os.rename(imageStage.getCanonicalPath(), mWallpaperFile.getCanonicalPath()); + } + } catch (Exception e) { + Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage()); + mWm.clearWallpaper(WallpaperManager.FLAG_SYSTEM, UserHandle.USER_SYSTEM); + } finally { + // These "should" not exist because of the renames, but make sure + // in case of errors/exceptions/etc. + if (DEBUG) { + Slog.v(TAG, "Removing restore stage files"); + } + infoStage.delete(); + imageStage.delete(); + } + } + + // + // Key/value API: abstract, so required, but not used + // + + @Override + public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + // Intentionally blank + } + + @Override + public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) + throws IOException { + // Intentionally blank + } +}
\ No newline at end of file diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 91b6914e7621..d6ace91f64d4 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -34,7 +34,6 @@ import android.app.PendingIntent; import android.app.WallpaperInfo; import android.app.WallpaperManager; import android.app.admin.DevicePolicyManager; -import android.app.backup.BackupManager; import android.app.backup.WallpaperBackupHelper; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -61,6 +60,7 @@ import android.os.FileObserver; import android.os.FileUtils; import android.os.IBinder; import android.os.IRemoteCallback; +import android.os.Process; import android.os.ParcelFileDescriptor; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -205,7 +205,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { if (path == null) { return; } - final boolean written = (event == CLOSE_WRITE || event == MOVED_TO); + final boolean moved = (event == MOVED_TO); + final boolean written = (event == CLOSE_WRITE || moved); final File changedFile = new File(mWallpaperDir, path); // System and system+lock changes happen on the system wallpaper input file; @@ -224,13 +225,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { + " written=" + written); } synchronized (mLock) { - if (sysWallpaperChanged || mWallpaperInfoFile.equals(changedFile)) { - // changing the wallpaper means we'll need to back up the new one - long origId = Binder.clearCallingIdentity(); - BackupManager bm = new BackupManager(mContext); - bm.dataChanged(); - Binder.restoreCallingIdentity(origId); - } if (sysWallpaperChanged || lockWallpaperChanged) { notifyCallbacksLocked(wallpaper); if (wallpaper.wallpaperComponent == null @@ -244,6 +238,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { if (DEBUG) { Slog.v(TAG, "Wallpaper written; generating crop"); } + if (moved) { + // This is a restore, so generate the crop using any just-restored new + // crop guidelines, making sure to preserve our local dimension hints. + if (DEBUG) { + Slog.v(TAG, "moved-to, therefore restore; reloading metadata"); + } + loadSettingsLocked(wallpaper.userId, true); + } generateCrop(wallpaper); if (DEBUG) { Slog.v(TAG, "Crop done; invoking completion callback"); @@ -491,6 +493,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { IWallpaperManagerCallback setComplete; /** + * Is the OS allowed to back up this wallpaper imagery? + */ + boolean allowBackup; + + /** * Resource name if using a picture from the wallpaper gallery */ String name = ""; @@ -811,7 +818,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { mMonitor = new MyPackageMonitor(); mMonitor.register(context, null, UserHandle.ALL, true); getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs(); - loadSettingsLocked(UserHandle.USER_SYSTEM); + loadSettingsLocked(UserHandle.USER_SYSTEM, false); } private static File getWallpaperDir(int userId) { @@ -1024,7 +1031,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaper = mWallpaperMap.get(userId); if (wallpaper == null) { // Might need to bring it in the first time to establish our rewrite - loadSettingsLocked(userId); + loadSettingsLocked(userId, false); wallpaper = mWallpaperMap.get(userId); } } @@ -1102,7 +1109,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { WallpaperData wd = mWallpaperMap.get(user.id); if (wd == null) { // User hasn't started yet, so load her settings to peek at the wallpaper - loadSettingsLocked(user.id); + loadSettingsLocked(user.id, false); wd = mWallpaperMap.get(user.id); } if (wd != null && name.equals(wd.name)) { @@ -1235,7 +1242,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { if (wallpaper == null) { // common case, this is the first lookup post-boot of the system or // unified lock, so we bring up the saved state lazily now and recheck. - loadSettingsLocked(wallpaperUserId); + loadSettingsLocked(wallpaperUserId, false); wallpaper = whichSet.get(wallpaperUserId); if (wallpaper == null) { return null; @@ -1304,7 +1311,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { @Override public ParcelFileDescriptor setWallpaper(String name, String callingPackage, - Rect cropHint, Bundle extras, int which, IWallpaperManagerCallback completion) { + Rect cropHint, boolean allowBackup, Bundle extras, int which, + IWallpaperManagerCallback completion) { checkPermission(android.Manifest.permission.SET_WALLPAPER); if ((which & (FLAG_LOCK|FLAG_SYSTEM)) == 0) { @@ -1342,6 +1350,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaper.whichPending = which; wallpaper.setComplete = completion; wallpaper.cropHint.set(cropHint); + if ((which & FLAG_SYSTEM) != 0) { + wallpaper.allowBackup = allowBackup; + } } return pfd; } finally { @@ -1651,6 +1662,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { return !um.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER); } + @Override + public boolean isWallpaperBackupEligible(int userId) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Only the system may call isWallpaperBackupEligible"); + } + + WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM); + return (wallpaper != null) ? wallpaper.allowBackup : false; + } + private static JournaledFile makeJournaledFile(int userId) { final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath(); return new JournaledFile(new File(base), new File(base + ".tmp")); @@ -1721,6 +1742,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { out.attribute(null, "component", wallpaper.wallpaperComponent.flattenToShortString()); } + + if (wallpaper.allowBackup) { + out.attribute(null, "backup", "true"); + } + out.endTag(null, tag); } @@ -1764,7 +1790,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { if (wallpaper == null) { // common case, this is the first lookup post-boot of the system or // unified lock, so we bring up the saved state lazily now and recheck. - loadSettingsLocked(userId); + loadSettingsLocked(userId, false); wallpaper = whichSet.get(userId); // if it's still null here, this is a lock-only operation and there is not // yet a lock-only wallpaper set for this user, so we need to establish @@ -1788,7 +1814,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { return wallpaper; } - private void loadSettingsLocked(int userId) { + private void loadSettingsLocked(int userId, boolean keepDimensionHints) { if (DEBUG) Slog.v(TAG, "loadSettingsLocked"); JournaledFile journal = makeJournaledFile(userId); @@ -1801,6 +1827,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { WallpaperData wallpaper = mWallpaperMap.get(userId); if (wallpaper == null) { wallpaper = new WallpaperData(userId, WALLPAPER, WALLPAPER_CROP); + wallpaper.allowBackup = true; mWallpaperMap.put(userId, wallpaper); if (!wallpaper.cropExists()) { generateCrop(wallpaper); @@ -1819,7 +1846,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { String tag = parser.getName(); if ("wp".equals(tag)) { // Common to system + lock wallpapers - parseWallpaperAttributes(parser, wallpaper); + parseWallpaperAttributes(parser, wallpaper, keepDimensionHints); // A system wallpaper might also be a live wallpaper String comp = parser.getAttributeValue(null, "component"); @@ -1848,7 +1875,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { WALLPAPER_LOCK_ORIG, WALLPAPER_LOCK_CROP); mLockWallpaperMap.put(userId, lockWallpaper); } - parseWallpaperAttributes(parser, lockWallpaper); + parseWallpaperAttributes(parser, lockWallpaper, false); } } } while (type != XmlPullParser.END_DOCUMENT); @@ -1909,7 +1936,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } - private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper) { + private void parseWallpaperAttributes(XmlPullParser parser, WallpaperData wallpaper, + boolean keepDimensionHints) { final String idString = parser.getAttributeValue(null, "id"); if (idString != null) { final int id = wallpaper.wallpaperId = Integer.parseInt(idString); @@ -1920,9 +1948,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaper.wallpaperId = makeWallpaperIdLocked(); } - wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width")); - wallpaper.height = Integer.parseInt(parser - .getAttributeValue(null, "height")); + if (!keepDimensionHints) { + wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width")); + wallpaper.height = Integer.parseInt(parser + .getAttributeValue(null, "height")); + } wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0); wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0); wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0); @@ -1932,6 +1962,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0); wallpaper.padding.bottom = getAttributeInt(parser, "paddingBottom", 0); wallpaper.name = parser.getAttributeValue(null, "name"); + wallpaper.allowBackup = "true".equals(parser.getAttributeValue(null, "backup")); } private int getMaximumSizeDimension() { @@ -1952,9 +1983,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { WallpaperData wallpaper = null; boolean success = false; synchronized (mLock) { - loadSettingsLocked(UserHandle.USER_SYSTEM); + loadSettingsLocked(UserHandle.USER_SYSTEM, false); wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM); wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore + wallpaper.allowBackup = true; // by definition if it was restored if (wallpaper.nextWallpaperComponent != null && !wallpaper.nextWallpaperComponent.equals(mImageWallpaper)) { if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false, |