Merge "Fix adb backup/restore" into nyc-dev

This commit is contained in:
TreeHugger Robot
2016-06-22 22:56:34 +00:00
committed by Android (Google) Code Review
2 changed files with 141 additions and 12 deletions

View File

@@ -92,6 +92,11 @@ public class WallpaperBackupAgent extends BackupAgent {
if (DEBUG) { if (DEBUG) {
Slog.v(TAG, "Wallpaper is backup-eligible; linking & writing"); Slog.v(TAG, "Wallpaper is backup-eligible; linking & writing");
} }
// In case of prior muddled state
infoStage.delete();
imageStage.delete();
Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath()); Os.link(mWallpaperInfo.getCanonicalPath(), infoStage.getCanonicalPath());
fullBackupFile(infoStage, data); fullBackupFile(infoStage, data);
Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath()); Os.link(mWallpaperFile.getCanonicalPath(), imageStage.getCanonicalPath());

View File

@@ -725,6 +725,19 @@ public class BackupManagerService {
return true; return true;
} }
/* adb backup: is this app only capable of doing key/value? We say otherwise if
* the app has a backup agent and does not say fullBackupOnly, *unless* it
* is a package that we know _a priori_ explicitly supports both key/value and
* full-data backup.
*/
private static boolean appIsKeyValueOnly(PackageInfo pkg) {
if ("com.android.providers.settings".equals(pkg.packageName)) {
return false;
}
return !appGetsFullBackup(pkg);
}
// ----- Asynchronous backup/restore handler thread ----- // ----- Asynchronous backup/restore handler thread -----
private class BackupHandler extends Handler { private class BackupHandler extends Handler {
@@ -3446,8 +3459,8 @@ public class BackupManagerService {
Intent obbIntent = new Intent().setComponent(new ComponentName( Intent obbIntent = new Intent().setComponent(new ComponentName(
"com.android.sharedstoragebackup", "com.android.sharedstoragebackup",
"com.android.sharedstoragebackup.ObbBackupService")); "com.android.sharedstoragebackup.ObbBackupService"));
BackupManagerService.this.mContext.bindService( BackupManagerService.this.mContext.bindServiceAsUser(
obbIntent, this, Context.BIND_AUTO_CREATE); obbIntent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
} }
public void tearDown() { public void tearDown() {
@@ -3965,7 +3978,7 @@ public class BackupManagerService {
} }
// Full backup task variant used for adb backup // Full backup task variant used for adb backup
class PerformAdbBackupTask extends FullBackupTask { class PerformAdbBackupTask extends FullBackupTask implements BackupRestoreTask {
FullBackupEngine mBackupEngine; FullBackupEngine mBackupEngine;
final AtomicBoolean mLatch; final AtomicBoolean mLatch;
@@ -3979,6 +3992,7 @@ public class BackupManagerService {
boolean mIncludeSystem; boolean mIncludeSystem;
boolean mCompress; boolean mCompress;
ArrayList<String> mPackages; ArrayList<String> mPackages;
PackageInfo mCurrentTarget;
String mCurrentPassword; String mCurrentPassword;
String mEncryptPassword; String mEncryptPassword;
@@ -4009,6 +4023,9 @@ public class BackupManagerService {
} else { } else {
mEncryptPassword = encryptPassword; mEncryptPassword = encryptPassword;
} }
if (MORE_DEBUG) {
Slog.w(TAG, "Encrypting backup with passphrase=" + mEncryptPassword);
}
mCompress = doCompress; mCompress = doCompress;
} }
@@ -4165,7 +4182,9 @@ public class BackupManagerService {
Iterator<Entry<String, PackageInfo>> iter = packagesToBackup.entrySet().iterator(); Iterator<Entry<String, PackageInfo>> iter = packagesToBackup.entrySet().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
PackageInfo pkg = iter.next().getValue(); PackageInfo pkg = iter.next().getValue();
if (!appIsEligibleForBackup(pkg.applicationInfo)) { if (!appIsEligibleForBackup(pkg.applicationInfo)
|| appIsStopped(pkg.applicationInfo)
|| appIsKeyValueOnly(pkg)) {
iter.remove(); iter.remove();
} }
} }
@@ -4267,9 +4286,11 @@ public class BackupManagerService {
final boolean isSharedStorage = final boolean isSharedStorage =
pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE); pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
mBackupEngine = new FullBackupEngine(out, null, pkg, mIncludeApks, null); mBackupEngine = new FullBackupEngine(out, null, pkg, mIncludeApks, this);
sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName); sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
// Don't need to check preflight result as there is no preflight hook. // Don't need to check preflight result as there is no preflight hook.
mCurrentTarget = pkg;
mBackupEngine.backupOnePackage(); mBackupEngine.backupOnePackage();
// after the app's agent runs to handle its private filesystem // after the app's agent runs to handle its private filesystem
@@ -4308,6 +4329,28 @@ public class BackupManagerService {
mWakelock.release(); mWakelock.release();
} }
} }
// BackupRestoreTask methods, used for timeout handling
@Override
public void execute() {
// Unused
}
@Override
public void operationComplete(long result) {
// Unused
}
@Override
public void handleTimeout() {
final PackageInfo target = mCurrentTarget;
if (DEBUG) {
Slog.w(TAG, "adb backup timeout of " + target);
}
if (target != null) {
tearDownAgentAndKill(mCurrentTarget.applicationInfo);
}
}
} }
// Full backup task extension used for transport-oriented operation // Full backup task extension used for transport-oriented operation
@@ -5255,7 +5298,7 @@ public class BackupManagerService {
byte[] mWidgetData = null; byte[] mWidgetData = null;
// Runner that can be placed in a separate thread to do in-process // Runner that can be placed in a separate thread to do in-process
// invocations of the full restore API asynchronously // invocations of the full restore API asynchronously. Used by adb restore.
class RestoreFileRunnable implements Runnable { class RestoreFileRunnable implements Runnable {
IBackupAgent mAgent; IBackupAgent mAgent;
FileMetadata mInfo; FileMetadata mInfo;
@@ -6404,6 +6447,46 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// ***** end new engine class *** // ***** end new engine class ***
// Used for synchronizing doRestoreFinished during adb restore
class AdbRestoreFinishedLatch implements BackupRestoreTask {
static final String TAG = "AdbRestoreFinishedLatch";
final CountDownLatch mLatch;
AdbRestoreFinishedLatch() {
mLatch = new CountDownLatch(1);
}
void await() {
boolean latched = false;
try {
latched = mLatch.await(TIMEOUT_FULL_BACKUP_INTERVAL, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Slog.w(TAG, "Interrupted!");
}
}
@Override
public void execute() {
// Unused
}
@Override
public void operationComplete(long result) {
if (MORE_DEBUG) {
Slog.w(TAG, "adb onRestoreFinished() complete");
}
mLatch.countDown();
}
@Override
public void handleTimeout() {
if (DEBUG) {
Slog.w(TAG, "adb onRestoreFinished() timed out");
}
mLatch.countDown();
}
}
class PerformAdbRestoreTask implements Runnable { class PerformAdbRestoreTask implements Runnable {
ParcelFileDescriptor mInputFile; ParcelFileDescriptor mInputFile;
String mCurrentPassword; String mCurrentPassword;
@@ -6419,6 +6502,27 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
long mBytes; long mBytes;
// Runner that can be placed on a separate thread to do in-process invocation
// of the "restore finished" API asynchronously. Used by adb restore.
class RestoreFinishedRunnable implements Runnable {
final IBackupAgent mAgent;
final int mToken;
RestoreFinishedRunnable(IBackupAgent agent, int token) {
mAgent = agent;
mToken = token;
}
@Override
public void run() {
try {
mAgent.doRestoreFinished(mToken, mBackupManagerBinder);
} catch (RemoteException e) {
// never happens; this is used only for local binder calls
}
}
}
// possible handling states for a given package in the restore dataset // possible handling states for a given package in the restore dataset
final HashMap<String, RestorePolicy> mPackagePolicies final HashMap<String, RestorePolicy> mPackagePolicies
= new HashMap<String, RestorePolicy>(); = new HashMap<String, RestorePolicy>();
@@ -6560,7 +6664,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
Slog.e(TAG, "Unable to read restore input"); Slog.e(TAG, "Unable to read restore input");
} finally { } finally {
tearDownPipes(); tearDownPipes();
tearDownAgent(mTargetApp); tearDownAgent(mTargetApp, true);
try { try {
if (rawDataIn != null) rawDataIn.close(); if (rawDataIn != null) rawDataIn.close();
@@ -6714,7 +6818,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (DEBUG) Slog.d(TAG, "Saw new package; finalizing old one"); if (DEBUG) Slog.d(TAG, "Saw new package; finalizing old one");
// Now we're really done // Now we're really done
tearDownPipes(); tearDownPipes();
tearDownAgent(mTargetApp); tearDownAgent(mTargetApp, true);
mTargetApp = null; mTargetApp = null;
mAgentPackage = null; mAgentPackage = null;
} }
@@ -6936,10 +7040,12 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// okay, if the remote end failed at any point, deal with // okay, if the remote end failed at any point, deal with
// it by ignoring the rest of the restore on it // it by ignoring the rest of the restore on it
if (!agentSuccess) { if (!agentSuccess) {
if (DEBUG) {
Slog.d(TAG, "Agent failure restoring " + pkg + "; now ignoring");
}
mBackupHandler.removeMessages(MSG_TIMEOUT); mBackupHandler.removeMessages(MSG_TIMEOUT);
tearDownPipes(); tearDownPipes();
tearDownAgent(mTargetApp); tearDownAgent(mTargetApp, false);
mAgent = null;
mPackagePolicies.put(pkg, RestorePolicy.IGNORE); mPackagePolicies.put(pkg, RestorePolicy.IGNORE);
} }
} }
@@ -6988,9 +7094,27 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
} }
} }
void tearDownAgent(ApplicationInfo app) { void tearDownAgent(ApplicationInfo app, boolean doRestoreFinished) {
if (mAgent != null) { if (mAgent != null) {
try { try {
// In the adb restore case, we do restore-finished here
if (doRestoreFinished) {
final int token = generateToken();
final AdbRestoreFinishedLatch latch = new AdbRestoreFinishedLatch();
prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, latch);
if (mTargetApp.processName.equals("system")) {
if (MORE_DEBUG) {
Slog.d(TAG, "system agent - restoreFinished on thread");
}
Runnable runner = new RestoreFinishedRunnable(mAgent, token);
new Thread(runner, "restore-sys-finished-runner").start();
} else {
mAgent.doRestoreFinished(token, mBackupManagerBinder);
}
latch.await();
}
// unbind and tidy up even on timeout or failure, just in case // unbind and tidy up even on timeout or failure, just in case
mActivityManager.unbindBackupAgent(app); mActivityManager.unbindBackupAgent(app);
@@ -9354,7 +9478,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
"com.android.backupconfirm.BackupRestoreConfirmation"); "com.android.backupconfirm.BackupRestoreConfirmation");
confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token); confIntent.putExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, token);
confIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); confIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(confIntent); mContext.startActivityAsUser(confIntent, UserHandle.SYSTEM);
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
return false; return false;
} }