Merge "Fix adb backup/restore" into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
45c79447ad
@@ -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());
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user