Merge "Apply restored wallpaper via API rather than rename-into-place" into nyc-dev
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 2f79079..a3ea592 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -22,22 +22,28 @@
import android.app.backup.BackupDataOutput;
import android.app.backup.FullBackupDataOutput;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
import android.system.Os;
import android.util.Slog;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
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.
+ // compile-time visibility.
// Target filenames within the system's wallpaper directory
static final String WALLPAPER = "wallpaper_orig";
@@ -107,11 +113,7 @@
}
// 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.
+ // then post-process in onRestoreFinished() to apply the new wallpaper.
@Override
public void onRestoreFinished() {
if (DEBUG) {
@@ -125,19 +127,25 @@
// to back up the original image on the source device.
if (imageStage.exists()) {
if (DEBUG) {
- Slog.v(TAG, "Got restored wallpaper; renaming into place");
+ Slog.v(TAG, "Got restored wallpaper; applying");
}
- // 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());
+
+ // Parse the restored info file to find the crop hint. Note that this currently
+ // relies on a priori knowledge of the wallpaper info file schema.
+ Rect cropHint = parseCropHint(infoStage);
+ if (cropHint != null) {
+ if (DEBUG) {
+ Slog.v(TAG, "Restored crop hint " + cropHint + "; now writing data");
+ }
+ WallpaperManager wm = getSystemService(WallpaperManager.class);
+ try (FileInputStream in = new FileInputStream(imageStage)) {
+ wm.setStream(in, cropHint, true, WallpaperManager.FLAG_SYSTEM);
+ } finally {} // auto-closes 'in'
+ }
}
} 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");
}
@@ -146,8 +154,41 @@
}
}
+ private Rect parseCropHint(File wallpaperInfo) {
+ Rect cropHint = new Rect();
+ try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, StandardCharsets.UTF_8.name());
+
+ int type;
+ do {
+ type = parser.next();
+ if (type == XmlPullParser.START_TAG) {
+ String tag = parser.getName();
+ if ("wp".equals(tag)) {
+ cropHint.left = getAttributeInt(parser, "cropLeft", 0);
+ cropHint.top = getAttributeInt(parser, "cropTop", 0);
+ cropHint.right = getAttributeInt(parser, "cropRight", 0);
+ cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
+ }
+ }
+ } while (type != XmlPullParser.END_DOCUMENT);
+ } catch (Exception e) {
+ // Whoops; can't process the info file at all. Report failure.
+ Slog.w(TAG, "Failed to parse restored metadata: " + e.getMessage());
+ return null;
+ }
+
+ return cropHint;
+ }
+
+ private int getAttributeInt(XmlPullParser parser, String name, int defValue) {
+ final String value = parser.getAttributeValue(null, name);
+ return (value == null) ? defValue : Integer.parseInt(value);
+ }
+
//
- // Key/value API: abstract, so required, but not used
+ // Key/value API: abstract, therefore required; but not used
//
@Override