summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/backup/FileBackupHelperBase.java3
-rw-r--r--core/java/android/app/backup/WallpaperBackupHelper.java124
-rw-r--r--services/java/com/android/server/SystemBackupAgent.java15
3 files changed, 132 insertions, 10 deletions
diff --git a/core/java/android/app/backup/FileBackupHelperBase.java b/core/java/android/app/backup/FileBackupHelperBase.java
index 1e3158f..887a2e6 100644
--- a/core/java/android/app/backup/FileBackupHelperBase.java
+++ b/core/java/android/app/backup/FileBackupHelperBase.java
@@ -81,7 +81,7 @@ class FileBackupHelperBase {
}
}
- void writeFile(File f, BackupDataInputStream in) {
+ boolean writeFile(File f, BackupDataInputStream in) {
int result = -1;
// Create the enclosing directory.
@@ -98,6 +98,7 @@ class FileBackupHelperBase {
mExceptionLogged = true;
}
}
+ return (result == 0);
}
public void writeNewStateDescription(ParcelFileDescriptor fd) {
diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java
new file mode 100644
index 0000000..9808200
--- /dev/null
+++ b/core/java/android/app/backup/WallpaperBackupHelper.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2010 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 android.app.backup;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.BitmapFactory;
+import android.os.ParcelFileDescriptor;
+import android.util.Slog;
+
+import java.io.File;
+
+/**
+ * Helper for backing up / restoring wallpapers. Basically an AbsoluteFileBackupHelper,
+ * but with logic for deciding what to do with restored wallpaper images.
+ *
+ * @hide
+ */
+public class WallpaperBackupHelper extends FileBackupHelperBase implements BackupHelper {
+ private static final String TAG = "WallpaperBackupHelper";
+ private static final boolean DEBUG = false;
+
+ // This path must match what the WallpaperManagerService uses
+ private static final String WALLPAPER_IMAGE = "/data/data/com.android.settings/files/wallpaper";
+
+ // Stage file - should be adjacent to the WALLPAPER_IMAGE location. The wallpapers
+ // will be saved to this file from the restore stream, then renamed to the proper
+ // location if it's deemed suitable.
+ private static final String STAGE_FILE = "/data/data/com.android.settings/files/wallpaper-tmp";
+
+ Context mContext;
+ String[] mFiles;
+ double mDesiredMinWidth;
+ double mDesiredMinHeight;
+
+ /**
+ * Construct a helper for backing up / restoring the files at the given absolute locations
+ * within the file system.
+ *
+ * @param context
+ * @param files
+ */
+ public WallpaperBackupHelper(Context context, String... files) {
+ super(context);
+
+ mContext = context;
+ mFiles = files;
+
+ WallpaperManager wpm;
+ wpm = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
+ mDesiredMinWidth = (double) wpm.getDesiredMinimumWidth();
+ mDesiredMinHeight = (double) wpm.getDesiredMinimumHeight();
+ }
+
+ /**
+ * Based on oldState, determine which of the files from the application's data directory
+ * need to be backed up, write them to the data stream, and fill in newState with the
+ * state as it exists now.
+ */
+ public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) {
+ performBackup_checked(oldState, data, newState, mFiles, mFiles);
+ }
+
+ /**
+ * Restore one absolute file entity from the restore stream. If we're restoring the
+ * magic wallpaper file, take specific action to determine whether it is suitable for
+ * the current device.
+ */
+ public void restoreEntity(BackupDataInputStream data) {
+ final String key = data.getKey();
+ if (isKeyInList(key, mFiles)) {
+ if (key.equals(WALLPAPER_IMAGE)) {
+ // restore the file to the stage for inspection
+ File f = new File(STAGE_FILE);
+ if (writeFile(f, data)) {
+
+ // Preflight the restored image's dimensions without loading it
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(STAGE_FILE, options);
+
+ if (DEBUG) Slog.v(TAG, "Restoring wallpaper image w=" + options.outWidth
+ + " h=" + options.outHeight);
+
+ // how much does the image differ from our preference?
+ double widthRatio = mDesiredMinWidth / options.outWidth;
+ double heightRatio = mDesiredMinHeight / options.outHeight;
+ if (widthRatio > 0.8 && widthRatio < 1.25
+ && heightRatio > 0.8 && heightRatio < 1.25) {
+ // sufficiently close to our resolution; go ahead and use it
+ if (DEBUG) Slog.v(TAG, "wallpaper dimension match; using");
+ f.renameTo(new File(WALLPAPER_IMAGE));
+ // TODO: spin a service to copy the restored image to sd/usb storage,
+ // since it does not exist anywhere other than the private wallpaper
+ // file.
+ } else {
+ if (DEBUG) Slog.v(TAG, "dimensions too far off: wr=" + widthRatio
+ + " hr=" + heightRatio);
+ f.delete();
+ }
+ }
+ } else {
+ // Some other normal file; just decode it to its destination
+ File f = new File(key);
+ writeFile(f, data);
+ }
+ }
+ }
+}
diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java
index fff1874..a1f43b4 100644
--- a/services/java/com/android/server/SystemBackupAgent.java
+++ b/services/java/com/android/server/SystemBackupAgent.java
@@ -16,18 +16,16 @@
package com.android.server;
-import android.app.backup.AbsoluteFileBackupHelper;
import android.app.backup.BackupDataInput;
-import android.app.backup.BackupDataInputStream;
import android.app.backup.BackupDataOutput;
-import android.app.backup.BackupHelper;
import android.app.backup.BackupAgentHelper;
+import android.app.backup.WallpaperBackupHelper;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.ServiceManager;
-import android.os.SystemService;
import android.util.Slog;
+
import java.io.File;
import java.io.IOException;
@@ -54,7 +52,7 @@ public class SystemBackupAgent extends BackupAgentHelper {
// TODO: Send a delete for any stored wallpaper image in this case?
files = new String[] { WALLPAPER_INFO };
}
- addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this, files));
+ addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this, files));
super.onBackup(oldState, data, newState);
}
@@ -62,12 +60,11 @@ public class SystemBackupAgent extends BackupAgentHelper {
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
// On restore, we also support a previous data schema "system_files"
- addHelper("wallpaper", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+ addHelper("wallpaper", new WallpaperBackupHelper(SystemBackupAgent.this,
new String[] { WALLPAPER_IMAGE, WALLPAPER_INFO }));
- addHelper("system_files", new AbsoluteFileBackupHelper(SystemBackupAgent.this,
+ addHelper("system_files", new WallpaperBackupHelper(SystemBackupAgent.this,
new String[] { WALLPAPER_IMAGE }));
- boolean success = false;
try {
super.onRestore(data, appVersionCode, newState);
@@ -75,7 +72,7 @@ public class SystemBackupAgent extends BackupAgentHelper {
Context.WALLPAPER_SERVICE);
wallpaper.settingsRestored();
} catch (IOException ex) {
- // If there was a failure, delete everything for the wallpaper, this is too aggresive,
+ // If there was a failure, delete everything for the wallpaper, this is too aggressive,
// but this is hopefully a rare failure.
Slog.d(TAG, "restore failed", ex);
(new File(WALLPAPER_IMAGE)).delete();