summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2009-06-25 18:03:43 -0700
committerChristopher Tate <ctate@google.com>2009-06-25 18:09:28 -0700
commit7d562ec393d54dd9ef387c49d1283243bfdbd2b1 (patch)
treeac2590ef8df168167789764153a1869c80363748
parentb505ae4195d9b8a93c71b1f9da6d7d8c3aaa3c08 (diff)
downloadframeworks_base-7d562ec393d54dd9ef387c49d1283243bfdbd2b1.zip
frameworks_base-7d562ec393d54dd9ef387c49d1283243bfdbd2b1.tar.gz
frameworks_base-7d562ec393d54dd9ef387c49d1283243bfdbd2b1.tar.bz2
Add a new IRestoreObserver callback class to the restore process
The observer is told when restore begins how many packages are being restored. It then gets an onUpdate() call telling it that the Nth package is now undergoing restore. Ultimately, its restoreFinished() callback is invoked, passing a simple success/fail error code, to let it know that the restore operation has concluded.
-rw-r--r--Android.mk1
-rw-r--r--core/java/android/backup/IRestoreObserver.aidl50
-rw-r--r--core/java/android/backup/IRestoreSession.aidl5
-rw-r--r--services/java/com/android/server/BackupManagerService.java64
4 files changed, 113 insertions, 7 deletions
diff --git a/Android.mk b/Android.mk
index 0e8793d..f32129e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -82,6 +82,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/IWallpaperService.aidl \
core/java/android/app/IWallpaperServiceCallback.aidl \
core/java/android/backup/IBackupManager.aidl \
+ core/java/android/backup/IRestoreObserver.aidl \
core/java/android/backup/IRestoreSession.aidl \
core/java/android/bluetooth/IBluetoothA2dp.aidl \
core/java/android/bluetooth/IBluetoothDevice.aidl \
diff --git a/core/java/android/backup/IRestoreObserver.aidl b/core/java/android/backup/IRestoreObserver.aidl
new file mode 100644
index 0000000..59e59fc
--- /dev/null
+++ b/core/java/android/backup/IRestoreObserver.aidl
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.backup;
+
+/**
+ * Callback class for receiving progress reports during a restore operation.
+ *
+ * @hide
+ */
+interface IRestoreObserver {
+ /**
+ * The restore operation has begun.
+ *
+ * @param numPackages The total number of packages being processed in
+ * this restore operation.
+ */
+ void restoreStarting(int numPackages);
+
+ /**
+ * An indication of which package is being restored currently, out of the
+ * total number provided in the restoreStarting() callback. This method
+ * is not guaranteed to be called.
+ *
+ * @param nowBeingRestored The index, between 1 and the numPackages parameter
+ * to the restoreStarting() callback, of the package now being restored.
+ */
+ void onUpdate(int nowBeingRestored);
+
+ /**
+ * The restore operation has completed.
+ *
+ * @param error Zero on success; a nonzero error code if the restore operation
+ * as a whole failed.
+ */
+ void restoreFinished(int error);
+}
diff --git a/core/java/android/backup/IRestoreSession.aidl b/core/java/android/backup/IRestoreSession.aidl
index 6bca865..ac01c2d 100644
--- a/core/java/android/backup/IRestoreSession.aidl
+++ b/core/java/android/backup/IRestoreSession.aidl
@@ -17,6 +17,7 @@
package android.backup;
import android.backup.RestoreSet;
+import android.backup.IRestoreObserver;
/**
* Binder interface used by clients who wish to manage a restore operation. Every
@@ -41,8 +42,10 @@ interface IRestoreSession {
*
* @param token The token from {@link getAvailableRestoreSets()} corresponding to
* the restore set that should be used.
+ * @param observer If non-null, this binder points to an object that will receive
+ * progress callbacks during the restore operation.
*/
- int performRestore(int token);
+ int performRestore(int token, IRestoreObserver observer);
/**
* End this restore session. After this method is called, the IRestoreSession binder
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index e131c6e..bc2eaed 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -47,6 +47,7 @@ import android.util.Log;
import android.util.SparseArray;
import android.backup.IBackupManager;
+import android.backup.IRestoreObserver;
import android.backup.IRestoreSession;
import android.backup.BackupManager;
import android.backup.RestoreSet;
@@ -81,6 +82,7 @@ class BackupManagerService extends IBackupManager.Stub {
private static final int MSG_RUN_BACKUP = 1;
private static final int MSG_RUN_FULL_BACKUP = 2;
private static final int MSG_RUN_RESTORE = 3;
+ private static final String RESTORE_OBSERVER_KEY = "_resOb";
// Timeout interval for deciding that a bind or clear-data has taken too long
static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -133,6 +135,16 @@ class BackupManagerService extends IBackupManager.Stub {
private IBackupTransport mLocalTransport, mGoogleTransport;
private RestoreSession mActiveRestoreSession;
+ private class RestoreParams {
+ public IBackupTransport transport;
+ public IRestoreObserver observer;
+
+ RestoreParams(IBackupTransport _transport, IRestoreObserver _obs) {
+ transport = _transport;
+ observer = _obs;
+ }
+ }
+
// Where we keep our journal files and other bookkeeping
private File mBaseStateDir;
private File mDataDir;
@@ -336,8 +348,8 @@ class BackupManagerService extends IBackupManager.Stub {
case MSG_RUN_RESTORE:
{
int token = msg.arg1;
- IBackupTransport transport = (IBackupTransport)msg.obj;
- (new PerformRestoreThread(transport, token)).start();
+ RestoreParams params = (RestoreParams)msg.obj;
+ (new PerformRestoreThread(params.transport, params.observer, token)).start();
break;
}
}
@@ -748,6 +760,7 @@ class BackupManagerService extends IBackupManager.Stub {
class PerformRestoreThread extends Thread {
private IBackupTransport mTransport;
+ private IRestoreObserver mObserver;
private int mToken;
private RestoreSet mImage;
private File mStateDir;
@@ -762,8 +775,10 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- PerformRestoreThread(IBackupTransport transport, int restoreSetToken) {
+ PerformRestoreThread(IBackupTransport transport, IRestoreObserver observer,
+ int restoreSetToken) {
mTransport = transport;
+ mObserver = observer;
mToken = restoreSetToken;
try {
@@ -792,6 +807,8 @@ class BackupManagerService extends IBackupManager.Stub {
* 4. shut down the transport
*/
+ int error = -1; // assume error
+
// build the set of apps to restore
try {
RestoreSet[] images = mTransport.getAvailableRestoreSets();
@@ -818,6 +835,18 @@ class BackupManagerService extends IBackupManager.Stub {
List<PackageInfo> agentPackages = allAgentPackages();
restorePackages.addAll(agentPackages);
+ // let the observer know that we're running
+ if (mObserver != null) {
+ try {
+ // !!! TODO: get an actual count from the transport after
+ // its startRestore() runs?
+ mObserver.restoreStarting(restorePackages.size());
+ } catch (RemoteException e) {
+ Log.d(TAG, "Restore observer died at restoreStarting");
+ mObserver = null;
+ }
+ }
+
// STOPSHIP TODO: pick out the set for this token (instead of images[0])
long token = images[0].token;
if (!mTransport.startRestore(token, restorePackages.toArray(new PackageInfo[0]))) {
@@ -845,6 +874,7 @@ class BackupManagerService extends IBackupManager.Stub {
mPackageManager, agentPackages);
processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+ int count = 0;
for (;;) {
packageName = mTransport.nextRestorePackage();
if (packageName == null) {
@@ -855,6 +885,16 @@ class BackupManagerService extends IBackupManager.Stub {
break;
}
+ if (mObserver != null) {
+ ++count;
+ try {
+ mObserver.onUpdate(count);
+ } catch (RemoteException e) {
+ Log.d(TAG, "Restore observer died in onUpdate");
+ mObserver = null;
+ }
+ }
+
Metadata metaInfo = pmAgent.getRestoredMetadata(packageName);
if (metaInfo == null) {
Log.e(TAG, "Missing metadata for " + packageName);
@@ -898,6 +938,9 @@ class BackupManagerService extends IBackupManager.Stub {
mActivityManager.unbindBackupAgent(packageInfo.applicationInfo);
}
}
+
+ // if we get this far, report success to the observer
+ error = 0;
} catch (NameNotFoundException e) {
// STOPSHIP TODO: Handle the failure somehow?
Log.e(TAG, "Invalid paackage restoring data", e);
@@ -910,6 +953,14 @@ class BackupManagerService extends IBackupManager.Stub {
} catch (RemoteException e) {
Log.e(TAG, "Error finishing restore", e);
}
+
+ if (mObserver != null) {
+ try {
+ mObserver.restoreFinished(error);
+ } catch (RemoteException e) {
+ Log.d(TAG, "Restore observer died at restoreFinished");
+ }
+ }
}
}
@@ -1147,14 +1198,15 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
- public int performRestore(int token) throws android.os.RemoteException {
+ public int performRestore(int token, IRestoreObserver observer)
+ throws android.os.RemoteException {
mContext.enforceCallingPermission("android.permission.BACKUP", "performRestore");
if (mRestoreSets != null) {
for (int i = 0; i < mRestoreSets.length; i++) {
if (token == mRestoreSets[i].token) {
- Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE,
- mRestoreTransport);
+ Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
+ msg.obj = new RestoreParams(mRestoreTransport, observer);
msg.arg1 = token;
mBackupHandler.sendMessage(msg);
return 0;