summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java111
-rw-r--r--core/java/android/app/backup/IBackupManager.aidl9
-rw-r--r--core/java/android/app/backup/IBackupObserver.aidl14
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java81
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java3
-rw-r--r--services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java34
-rw-r--r--services/backup/java/com/android/server/backup/Trampoline.java9
-rw-r--r--services/backup/java/com/android/server/backup/internal/BackupHandler.java14
-rw-r--r--services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java39
-rw-r--r--services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java12
10 files changed, 246 insertions, 80 deletions
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 1b77427c5b72..b61cdecbfb7b 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -17,8 +17,8 @@
package com.android.commands.bmgr;
import android.app.backup.BackupManager;
-import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupProgress;
+import android.app.backup.BackupTransport;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupObserver;
import android.app.backup.IRestoreObserver;
@@ -30,8 +30,11 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.UserHandle;
-import android.util.Log;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.HashSet;
@@ -97,6 +100,11 @@ public final class Bmgr {
return;
}
+ if ("init".equals(op)) {
+ doInit();
+ return;
+ }
+
if ("list".equals(op)) {
doList();
return;
@@ -204,7 +212,7 @@ public final class Bmgr {
System.out.println("Performing full transport backup");
String pkg;
- ArrayList<String> allPkgs = new ArrayList<String>();
+ ArraySet<String> allPkgs = new ArraySet<String>();
while ((pkg = nextArg()) != null) {
allPkgs.add(pkg);
}
@@ -218,45 +226,77 @@ public final class Bmgr {
}
}
- class BackupObserver extends IBackupObserver.Stub {
- boolean done = false;
+ // IBackupObserver generically usable for any backup/init operation
+ abstract class Observer extends IBackupObserver.Stub {
+ private final Object trigger = new Object();
+
+ @GuardedBy("trigger")
+ private volatile boolean done = false;
@Override
public void onUpdate(String currentPackage, BackupProgress backupProgress) {
- System.out.println(
- "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred
- + "/" + backupProgress.bytesExpected);
}
@Override
public void onResult(String currentPackage, int status) {
- System.out.println("Package " + currentPackage + " with result: "
- + convertBackupStatusToString(status));
}
@Override
public void backupFinished(int status) {
- System.out.println("Backup finished with result: "
- + convertBackupStatusToString(status));
- synchronized (this) {
+ synchronized (trigger) {
done = true;
- this.notify();
+ trigger.notify();
}
}
+ public boolean done() {
+ return this.done;
+ }
+
+ // Wait forever
public void waitForCompletion() {
+ waitForCompletion(0);
+ }
+
+ // Wait for a given time and then give up
+ public void waitForCompletion(long timeout) {
// The backupFinished() callback will throw the 'done' flag; we
// just sit and wait on that notification.
- synchronized (this) {
- while (!this.done) {
+ final long targetTime = SystemClock.elapsedRealtime() + timeout;
+ synchronized (trigger) {
+ // Wait until either we're done, or we've reached a stated positive timeout
+ while (!done && (timeout <= 0 || SystemClock.elapsedRealtime() < targetTime)) {
try {
- this.wait();
+ trigger.wait(1000L);
} catch (InterruptedException ex) {
}
}
}
}
+ }
+
+ class BackupObserver extends Observer {
+ @Override
+ public void onUpdate(String currentPackage, BackupProgress backupProgress) {
+ super.onUpdate(currentPackage, backupProgress);
+ System.out.println(
+ "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred
+ + "/" + backupProgress.bytesExpected);
+ }
+ @Override
+ public void onResult(String currentPackage, int status) {
+ super.onResult(currentPackage, status);
+ System.out.println("Package " + currentPackage + " with result: "
+ + convertBackupStatusToString(status));
+ }
+
+ @Override
+ public void backupFinished(int status) {
+ super.backupFinished(status);
+ System.out.println("Backup finished with result: "
+ + convertBackupStatusToString(status));
+ }
}
private static String convertBackupStatusToString(int errorCode) {
@@ -349,7 +389,9 @@ public final class Bmgr {
} else if (pkg.equals("--incremental")) {
nonIncrementalBackup = false;
} else {
- allPkgs.add(pkg);
+ if (!allPkgs.contains(pkg)) {
+ allPkgs.add(pkg);
+ }
}
}
if (backupAll) {
@@ -470,6 +512,39 @@ public final class Bmgr {
}
}
+ class InitObserver extends Observer {
+ public int result = BackupTransport.TRANSPORT_ERROR;
+
+ @Override
+ public void backupFinished(int status) {
+ super.backupFinished(status);
+ result = status;
+ }
+ }
+
+ private void doInit() {
+ ArraySet<String> transports = new ArraySet<>();
+ String transport;
+ while ((transport = nextArg()) != null) {
+ transports.add(transport);
+ }
+ if (transports.size() == 0) {
+ showUsage();
+ return;
+ }
+
+ InitObserver observer = new InitObserver();
+ try {
+ System.out.println("Initializing transports: " + transports);
+ mBmgr.initializeTransports(transports.toArray(new String[transports.size()]), observer);
+ observer.waitForCompletion(30*1000L);
+ System.out.println("Initialization result: " + observer.result);
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(BMGR_NOT_RUNNING_ERR);
+ }
+ }
+
private void doList() {
String arg = nextArg(); // sets, transports, packages set#
if ("transports".equals(arg)) {
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 9c3b11009243..f1dc6d293914 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -57,6 +57,15 @@ interface IBackupManager {
void clearBackupData(String transportName, String packageName);
/**
+ * Run an initialize operation on the given transports. This will wipe all data from
+ * the backing data store and establish a clean starting point for all backup
+ * operations.
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ */
+ void initializeTransports(in String[] transportNames, IBackupObserver observer);
+
+ /**
* Notifies the Backup Manager Service that an agent has become available. This
* method is only invoked by the Activity Manager.
*/
diff --git a/core/java/android/app/backup/IBackupObserver.aidl b/core/java/android/app/backup/IBackupObserver.aidl
index 821a58946311..07a6634b5a1e 100644
--- a/core/java/android/app/backup/IBackupObserver.aidl
+++ b/core/java/android/app/backup/IBackupObserver.aidl
@@ -29,20 +29,22 @@ oneway interface IBackupObserver {
* This method could be called several times for packages with full data backup.
* It will tell how much of backup data is already saved and how much is expected.
*
- * @param currentBackupPackage The name of the package that now being backuped.
+ * @param currentBackupPackage The name of the package that now being backed up.
* @param backupProgress Current progress of backup for the package.
*/
void onUpdate(String currentPackage, in BackupProgress backupProgress);
/**
- * The backup of single package has completed. This method will be called at most one time
- * for each package and could be not called if backup is failed before and
- * backupFinished() is called.
+ * Backup of one package or initialization of one transport has completed. This
+ * method will be called at most one time for each package or transport, and might not
+ * be not called if the operation fails before backupFinished(); for example, if the
+ * requested package/transport does not exist.
*
- * @param currentBackupPackage The name of the package that was backuped.
+ * @param target The name of the package that was backed up, or of the transport
+ * that was initialized
* @param status Zero on success; a nonzero error code if the backup operation failed.
*/
- void onResult(String currentPackage, int status);
+ void onResult(String target, int status);
/**
* The backup process has completed. This method will always be called,
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 4bfe10fdd8c5..1127eff955da 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -106,6 +106,7 @@ import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Log;
@@ -123,8 +124,8 @@ import com.android.server.EventLogTags;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
-
import com.android.server.power.BatterySaverPolicy.ServiceType;
+
import libcore.io.IoUtils;
import java.io.BufferedInputStream;
@@ -259,7 +260,6 @@ public class BackupManagerService implements BackupManagerServiceInterface {
private static final int MSG_RUN_ADB_BACKUP = 2;
private static final int MSG_RUN_RESTORE = 3;
private static final int MSG_RUN_CLEAR = 4;
- private static final int MSG_RUN_INITIALIZE = 5;
private static final int MSG_RUN_GET_RESTORE_SETS = 6;
private static final int MSG_RESTORE_SESSION_TIMEOUT = 8;
private static final int MSG_FULL_CONFIRMATION_TIMEOUT = 9;
@@ -733,7 +733,7 @@ public class BackupManagerService implements BackupManagerServiceInterface {
// Persistently track the need to do a full init
static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
- HashSet<String> mPendingInits = new HashSet<String>(); // transport names
+ ArraySet<String> mPendingInits = new ArraySet<String>(); // transport names
// Round-robin queue for scheduling full backup passes
static final int SCHEDULE_FILE_VERSION = 1; // current version of the schedule file
@@ -1044,20 +1044,6 @@ public class BackupManagerService implements BackupManagerServiceInterface {
break;
}
- case MSG_RUN_INITIALIZE:
- {
- HashSet<String> queue;
-
- // Snapshot the pending-init queue and work on that
- synchronized (mQueueLock) {
- queue = new HashSet<String>(mPendingInits);
- mPendingInits.clear();
- }
-
- (new PerformInitializeTask(queue)).run();
- break;
- }
-
case MSG_RETRY_INIT:
{
synchronized (mQueueLock) {
@@ -1321,7 +1307,7 @@ public class BackupManagerService implements BackupManagerServiceInterface {
Intent initIntent = new Intent(RUN_INITIALIZE_ACTION);
backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mRunInitIntent = PendingIntent.getBroadcast(context, MSG_RUN_INITIALIZE, initIntent, 0);
+ mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0);
// Set up the backup-request journaling
mJournalDir = new File(mBaseStateDir, "pending");
@@ -1408,15 +1394,15 @@ public class BackupManagerService implements BackupManagerServiceInterface {
private class RunInitializeReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (RUN_INITIALIZE_ACTION.equals(intent.getAction())) {
+ // Snapshot the pending-init queue and work on that
synchronized (mQueueLock) {
- if (DEBUG) Slog.v(TAG, "Running a device init");
+ String[] queue = mPendingInits.toArray(new String[mPendingInits.size()]);
+ mPendingInits.clear();
// Acquire the wakelock and pass it to the init thread. it will
// be released once init concludes.
mWakelock.acquire();
-
- Message msg = mBackupHandler.obtainMessage(MSG_RUN_INITIALIZE);
- mBackupHandler.sendMessage(msg);
+ mBackupHandler.post(new PerformInitializeTask(queue, null));
}
}
}
@@ -9768,13 +9754,37 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
class PerformInitializeTask implements Runnable {
- HashSet<String> mQueue;
+ String[] mQueue;
+ IBackupObserver mObserver;
- PerformInitializeTask(HashSet<String> transportNames) {
+ PerformInitializeTask(String[] transportNames, IBackupObserver observer) {
mQueue = transportNames;
+ mObserver = observer;
+ }
+
+ private void notifyResult(String target, int status) {
+ try {
+ if (mObserver != null) {
+ mObserver.onResult(target, status);
+ }
+ } catch (RemoteException ignored) {
+ mObserver = null; // don't try again
+ }
+ }
+
+ private void notifyFinished(int status) {
+ try {
+ if (mObserver != null) {
+ mObserver.backupFinished(status);
+ }
+ } catch (RemoteException ignored) {
+ mObserver = null;
+ }
}
public void run() {
+ // mWakelock is *acquired* when execution begins here
+ int result = BackupTransport.TRANSPORT_OK;
try {
for (String transportName : mQueue) {
IBackupTransport transport =
@@ -9803,6 +9813,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
synchronized (mQueueLock) {
recordInitPendingLocked(false, transportName);
}
+ notifyResult(transportName, BackupTransport.TRANSPORT_OK);
} else {
// If this didn't work, requeue this one and try again
// after a suitable interval
@@ -9811,6 +9822,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
synchronized (mQueueLock) {
recordInitPendingLocked(true, transportName);
}
+ notifyResult(transportName, status);
+ result = status;
+
// do this via another alarm to make sure of the wakelock states
long delay = transport.requestBackupTime();
Slog.w(TAG, "Init failed on " + transportName + " resched in " + delay);
@@ -9820,8 +9834,10 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
} catch (Exception e) {
Slog.e(TAG, "Unexpected error performing init", e);
+ result = BackupTransport.TRANSPORT_ERROR;
} finally {
// Done; release the wakelock
+ notifyFinished(result);
mWakelock.release();
}
}
@@ -9939,6 +9955,23 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
});
}
+ // Run an initialize operation for the given transport
+ @Override
+ public void initializeTransports(String[] transportNames, IBackupObserver observer) {
+ mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "initializeTransport");
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "initializeTransports() of " + transportNames);
+ }
+
+ final long oldId = Binder.clearCallingIdentity();
+ try {
+ mWakelock.acquire();
+ mBackupHandler.post(new PerformInitializeTask(transportNames, observer));
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
+ }
+ }
+
// Clear the given package's backup data from the current transport
@Override
public void clearBackupData(String transportName, String packageName) {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
index e41549431b56..5dfa6302093e 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java
@@ -77,6 +77,9 @@ public interface BackupManagerServiceInterface {
void dataChanged(String packageName);
+ // Initialize the given transport
+ void initializeTransports(String[] transportName, IBackupObserver observer);
+
// Clear the given package's backup data from the current transport
void clearBackupData(String transportName, String packageName);
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index b57c0bc964b4..828162d4dc2f 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -17,7 +17,6 @@
package com.android.server.backup;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
-
import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_OPERATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_FULL_CONFIRMATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_OP_COMPLETE;
@@ -30,7 +29,6 @@ import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_BACKU
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_RESTORE;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_BACKUP;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_CLEAR;
-import static com.android.server.backup.internal.BackupHandler.MSG_RUN_INITIALIZE;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
import static com.android.server.backup.internal.BackupHandler.MSG_SCHEDULE_BACKUP_PACKAGE;
@@ -83,6 +81,7 @@ import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.Pair;
@@ -102,6 +101,7 @@ import com.android.server.backup.internal.BackupHandler;
import com.android.server.backup.internal.BackupRequest;
import com.android.server.backup.internal.ClearDataObserver;
import com.android.server.backup.internal.Operation;
+import com.android.server.backup.internal.PerformInitializeTask;
import com.android.server.backup.internal.ProvisionedObserver;
import com.android.server.backup.internal.RunBackupReceiver;
import com.android.server.backup.internal.RunInitializeReceiver;
@@ -142,6 +142,7 @@ import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -517,12 +518,12 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
mCurrentToken = currentToken;
}
- public HashSet<String> getPendingInits() {
+ public ArraySet<String> getPendingInits() {
return mPendingInits;
}
- public void setPendingInits(HashSet<String> pendingInits) {
- mPendingInits = pendingInits;
+ public void clearPendingInits() {
+ mPendingInits.clear();
}
public PerformFullTransportBackupTask getRunningFullBackupTask() {
@@ -659,7 +660,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
// Persistently track the need to do a full init
private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
- private HashSet<String> mPendingInits = new HashSet<>(); // transport names
+ private ArraySet<String> mPendingInits = new ArraySet<>(); // transport names
// Round-robin queue for scheduling full backup passes
private static final int SCHEDULE_FILE_VERSION = 1; // current version of the schedule file
@@ -806,11 +807,11 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
Intent backupIntent = new Intent(RUN_BACKUP_ACTION);
backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mRunBackupIntent = PendingIntent.getBroadcast(context, MSG_RUN_BACKUP, backupIntent, 0);
+ mRunBackupIntent = PendingIntent.getBroadcast(context, 0, backupIntent, 0);
Intent initIntent = new Intent(RUN_INITIALIZE_ACTION);
backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mRunInitIntent = PendingIntent.getBroadcast(context, MSG_RUN_INITIALIZE, initIntent, 0);
+ mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0);
// Set up the backup-request journaling
mJournalDir = new File(mBaseStateDir, "pending");
@@ -2544,6 +2545,23 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
});
}
+ // Run an initialize operation for the given transport
+ @Override
+ public void initializeTransports(String[] transportNames, IBackupObserver observer) {
+ mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "initializeTransport");
+ if (MORE_DEBUG || true) {
+ Slog.v(TAG, "initializeTransport(): " + Arrays.asList(transportNames));
+ }
+
+ final long oldId = Binder.clearCallingIdentity();
+ try {
+ mWakelock.acquire();
+ mBackupHandler.post(new PerformInitializeTask(this, transportNames, observer));
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
+ }
+ }
+
// Clear the given package's backup data from the current transport
@Override
public void clearBackupData(String transportName, String packageName) {
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 9e7a29e036fc..fcd929a7aeed 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -199,6 +199,15 @@ public class Trampoline extends IBackupManager.Stub {
}
@Override
+ public void initializeTransports(String[] transportNames, IBackupObserver observer)
+ throws RemoteException {
+ BackupManagerServiceInterface svc = mService;
+ if (svc != null) {
+ svc.initializeTransports(transportNames, observer);
+ }
+ }
+
+ @Override
public void clearBackupData(String transportName, String packageName)
throws RemoteException {
BackupManagerServiceInterface svc = mService;
diff --git a/services/backup/java/com/android/server/backup/internal/BackupHandler.java b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
index 886d1f8043c6..edd389403f02 100644
--- a/services/backup/java/com/android/server/backup/internal/BackupHandler.java
+++ b/services/backup/java/com/android/server/backup/internal/BackupHandler.java
@@ -64,7 +64,6 @@ public class BackupHandler extends Handler {
public static final int MSG_RUN_ADB_BACKUP = 2;
public static final int MSG_RUN_RESTORE = 3;
public static final int MSG_RUN_CLEAR = 4;
- public static final int MSG_RUN_INITIALIZE = 5;
public static final int MSG_RUN_GET_RESTORE_SETS = 6;
public static final int MSG_RESTORE_SESSION_TIMEOUT = 8;
public static final int MSG_FULL_CONFIRMATION_TIMEOUT = 9;
@@ -265,19 +264,6 @@ public class BackupHandler extends Handler {
break;
}
- case MSG_RUN_INITIALIZE: {
- HashSet<String> queue;
-
- // Snapshot the pending-init queue and work on that
- synchronized (backupManagerService.getQueueLock()) {
- queue = new HashSet<>(backupManagerService.getPendingInits());
- backupManagerService.getPendingInits().clear();
- }
-
- (new PerformInitializeTask(backupManagerService, queue)).run();
- break;
- }
-
case MSG_RETRY_INIT: {
synchronized (backupManagerService.getQueueLock()) {
backupManagerService.recordInitPendingLocked(msg.arg1 != 0, (String) msg.obj);
diff --git a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
index 5a75b664628b..939b1ae11b95 100644
--- a/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
+++ b/services/backup/java/com/android/server/backup/internal/PerformInitializeTask.java
@@ -20,6 +20,8 @@ import static com.android.server.backup.RefactoredBackupManagerService.TAG;
import android.app.AlarmManager;
import android.app.backup.BackupTransport;
+import android.app.backup.IBackupObserver;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.util.EventLog;
import android.util.Slog;
@@ -29,20 +31,43 @@ import com.android.server.EventLogTags;
import com.android.server.backup.RefactoredBackupManagerService;
import java.io.File;
-import java.util.HashSet;
public class PerformInitializeTask implements Runnable {
private RefactoredBackupManagerService backupManagerService;
- HashSet<String> mQueue;
+ String[] mQueue;
+ IBackupObserver mObserver;
- PerformInitializeTask(RefactoredBackupManagerService backupManagerService,
- HashSet<String> transportNames) {
+ public PerformInitializeTask(RefactoredBackupManagerService backupManagerService,
+ String[] transportNames, IBackupObserver observer) {
this.backupManagerService = backupManagerService;
mQueue = transportNames;
+ mObserver = observer;
+ }
+
+ private void notifyResult(String target, int status) {
+ try {
+ if (mObserver != null) {
+ mObserver.onResult(target, status);
+ }
+ } catch (RemoteException ignored) {
+ mObserver = null; // don't try again
+ }
+ }
+
+ private void notifyFinished(int status) {
+ try {
+ if (mObserver != null) {
+ mObserver.backupFinished(status);
+ }
+ } catch (RemoteException ignored) {
+ mObserver = null;
+ }
}
public void run() {
+ // mWakelock is *acquired* when execution begins here
+ int result = BackupTransport.TRANSPORT_OK;
try {
for (String transportName : mQueue) {
IBackupTransport transport =
@@ -74,6 +99,7 @@ public class PerformInitializeTask implements Runnable {
synchronized (backupManagerService.getQueueLock()) {
backupManagerService.recordInitPendingLocked(false, transportName);
}
+ notifyResult(transportName, BackupTransport.TRANSPORT_OK);
} else {
// If this didn't work, requeue this one and try again
// after a suitable interval
@@ -82,6 +108,9 @@ public class PerformInitializeTask implements Runnable {
synchronized (backupManagerService.getQueueLock()) {
backupManagerService.recordInitPendingLocked(true, transportName);
}
+ notifyResult(transportName, status);
+ result = status;
+
// do this via another alarm to make sure of the wakelock states
long delay = transport.requestBackupTime();
Slog.w(TAG, "Init failed on " + transportName + " resched in " + delay);
@@ -92,8 +121,10 @@ public class PerformInitializeTask implements Runnable {
}
} catch (Exception e) {
Slog.e(TAG, "Unexpected error performing init", e);
+ result = BackupTransport.TRANSPORT_ERROR;
} finally {
// Done; release the wakelock
+ notifyFinished(result);
backupManagerService.getWakelock().release();
}
}
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index 1621a9149d91..a6897d0e7671 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -19,12 +19,10 @@ package com.android.server.backup.internal;
import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
import static com.android.server.backup.RefactoredBackupManagerService.RUN_INITIALIZE_ACTION;
import static com.android.server.backup.RefactoredBackupManagerService.TAG;
-import static com.android.server.backup.internal.BackupHandler.MSG_RUN_INITIALIZE;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.Message;
import android.util.Slog;
import com.android.server.backup.RefactoredBackupManagerService;
@@ -44,13 +42,15 @@ public class RunInitializeReceiver extends BroadcastReceiver {
Slog.v(TAG, "Running a device init");
}
+ String[] pendingInits = (String[]) backupManagerService.getPendingInits().toArray();
+ backupManagerService.clearPendingInits();
+ PerformInitializeTask initTask = new PerformInitializeTask(backupManagerService,
+ pendingInits, null);
+
// Acquire the wakelock and pass it to the init thread. it will
// be released once init concludes.
backupManagerService.getWakelock().acquire();
-
- Message msg = backupManagerService.getBackupHandler().obtainMessage(
- MSG_RUN_INITIALIZE);
- backupManagerService.getBackupHandler().sendMessage(msg);
+ backupManagerService.getBackupHandler().post(initTask);
}
}
}