summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Christopher Tate <ctate@google.com> 2016-06-28 16:38:40 -0700
committer Chris Tate <ctate@android.com> 2016-07-12 18:34:05 +0000
commitbf13ccf4b7d7e50f24f6eefeeaa34b7a09e25ec8 (patch)
treeb4e61a853b8fe37db1a1251c70ff364c786f5e4c
parent2c5da6668c23ebf288d5af07ef7160904c6f7751 (diff)
Back up / restore lock wallpapers
If writing both system + lock wallpapers winds up hitting the transport-defined quota, the next backup operation steps back to storing only the system wallpaper. Also makes sure to unbind full-backup target agents following the backup operation. In practice this usually doesn't matter because the target gets killed following the operation, but the wallpaper agent runs in the system process where this does not happen, so was mistakenly being left in place and reused for the next operation, failing to re-run the full create + backup lifecycle. Bug 28968107 Change-Id: I219c2ddd7e899a430ef4cf693b1259464c15eed5
-rw-r--r--packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java103
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java7
2 files changed, 84 insertions, 26 deletions
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 47d1493e1574..97efed0130be 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -40,22 +40,30 @@ import java.nio.charset.StandardCharsets;
public class WallpaperBackupAgent extends BackupAgent {
private static final String TAG = "WallpaperBackup";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = true;
// NB: must be kept in sync with WallpaperManagerService but has no
// compile-time visibility.
// Target filenames within the system's wallpaper directory
static final String WALLPAPER = "wallpaper_orig";
+ static final String WALLPAPER_LOCK = "wallpaper_lock_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 LOCK_IMAGE_STAGE = "wallpaper-lock-stage";
static final String INFO_STAGE = "wallpaper-info-stage";
static final String EMPTY_SENTINEL = "empty";
+ static final String QUOTA_SENTINEL = "quota";
- private File mWallpaperInfo; // wallpaper metadata file
- private File mWallpaperFile; // primary wallpaper image file
+ private File mWallpaperInfo; // wallpaper metadata file
+ private File mWallpaperFile; // primary wallpaper image file
+ private File mLockWallpaperFile; // lock wallpaper image file
+
+ // If this file exists, it means we exceeded our quota last time
+ private File mQuotaFile;
+ private boolean mQuotaExceeded;
private WallpaperManager mWm;
@@ -68,7 +76,14 @@ public class WallpaperBackupAgent extends BackupAgent {
File wallpaperDir = Environment.getUserSystemDirectory(UserHandle.USER_SYSTEM);
mWallpaperInfo = new File(wallpaperDir, WALLPAPER_INFO);
mWallpaperFile = new File(wallpaperDir, WALLPAPER);
+ mLockWallpaperFile = new File(wallpaperDir, WALLPAPER_LOCK);
mWm = (WallpaperManager) getSystemService(Context.WALLPAPER_SERVICE);
+
+ mQuotaFile = new File(getFilesDir(), QUOTA_SENTINEL);
+ mQuotaExceeded = mQuotaFile.exists();
+ if (DEBUG) {
+ Slog.v(TAG, "quota file " + mQuotaFile.getPath() + " exists=" + mQuotaExceeded);
+ }
}
@Override
@@ -77,6 +92,7 @@ public class WallpaperBackupAgent extends BackupAgent {
final File filesDir = getFilesDir();
final File infoStage = new File(filesDir, INFO_STAGE);
final File imageStage = new File (filesDir, IMAGE_STAGE);
+ final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE);
final File empty = new File (filesDir, EMPTY_SENTINEL);
try {
@@ -96,11 +112,18 @@ public class WallpaperBackupAgent extends BackupAgent {
// In case of prior muddled state
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
fullBackupFile(infoStage, data);
Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());
fullBackupFile(imageStage, data);
+
+ // Don't try to store the lock image if we overran our quota last time
+ if (!mQuotaExceeded) {
+ Os.link(mLockWallpaperFile.getCanonicalPath(), lockImageStage.getCanonicalPath());
+ fullBackupFile(lockImageStage, data);
+ }
} else {
if (DEBUG) {
Slog.v(TAG, "Wallpaper not backup-eligible; writing no data");
@@ -114,6 +137,26 @@ public class WallpaperBackupAgent extends BackupAgent {
}
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
+
+ // Even if this time we had to back off on attempting to store the lock image
+ // due to exceeding the data quota, try again next time. This will alternate
+ // between "try both" and "only store the primary image" until either there
+ // is no lock image to store, or the quota is raised, or both fit under the
+ // quota.
+ mQuotaFile.delete();
+ }
+ }
+
+ @Override
+ public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
+ if (DEBUG) {
+ Slog.i(TAG, "Quota exceeded (" + backupDataBytes + " vs " + quotaBytes + ')');
+ }
+ try (FileOutputStream f = new FileOutputStream(mQuotaFile)) {
+ f.write(0);
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to record quota-exceeded: " + e.getMessage());
}
}
@@ -124,30 +167,17 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) {
Slog.v(TAG, "onRestoreFinished()");
}
- final File infoStage = new File(getFilesDir(), INFO_STAGE);
- final File imageStage = new File (getFilesDir(), IMAGE_STAGE);
+ final File filesDir = getFilesDir();
+ final File infoStage = new File(filesDir, INFO_STAGE);
+ final File imageStage = new File (filesDir, IMAGE_STAGE);
+ final File lockImageStage = new File (filesDir, LOCK_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; applying");
- }
-
- // 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'
- }
- }
+ // to back up the original image on the source device, or there was no user-supplied
+ // wallpaper image present.
+ restoreFromStage(imageStage, infoStage, "wp", WallpaperManager.FLAG_SYSTEM);
+ restoreFromStage(lockImageStage, infoStage, "kwp", WallpaperManager.FLAG_LOCK);
} catch (Exception e) {
Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
} finally {
@@ -156,10 +186,31 @@ public class WallpaperBackupAgent extends BackupAgent {
}
infoStage.delete();
imageStage.delete();
+ lockImageStage.delete();
+ }
+ }
+
+ private void restoreFromStage(File stage, File info, String hintTag, int which)
+ throws IOException {
+ if (stage.exists()) {
+ if (DEBUG) {
+ Slog.v(TAG, "Got restored wallpaper; applying which=" + which);
+ }
+ // 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(info, hintTag);
+ if (cropHint != null) {
+ if (DEBUG) {
+ Slog.v(TAG, "Restored crop hint " + cropHint + "; now writing data");
+ }
+ try (FileInputStream in = new FileInputStream(stage)) {
+ mWm.setStream(in, cropHint, true, which);
+ } finally {} // auto-closes 'in'
+ }
}
}
- private Rect parseCropHint(File wallpaperInfo) {
+ private Rect parseCropHint(File wallpaperInfo, String sectionTag) {
Rect cropHint = new Rect();
try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
XmlPullParser parser = Xml.newPullParser();
@@ -170,7 +221,7 @@ public class WallpaperBackupAgent extends BackupAgent {
type = parser.next();
if (type == XmlPullParser.START_TAG) {
String tag = parser.getName();
- if ("wp".equals(tag)) {
+ if (sectionTag.equals(tag)) {
cropHint.left = getAttributeInt(parser, "cropLeft", 0);
cropHint.top = getAttributeInt(parser, "cropTop", 0);
cropHint.right = getAttributeInt(parser, "cropRight", 0);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 0b85198d1c2a..8e0ec520c5ba 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -4662,6 +4662,13 @@ public class BackupManagerService {
}
cleanUpPipes(transportPipes);
cleanUpPipes(enginePipes);
+ if (currentPackage.applicationInfo != null) {
+ Slog.i(TAG, "Unbinding agent in " + packageName);
+ addBackupTrace("unbinding " + packageName);
+ try {
+ mActivityManager.unbindBackupAgent(currentPackage.applicationInfo);
+ } catch (RemoteException e) { /* can't happen; activity manager is local */ }
+ }
}
} catch (Exception e) {
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;