diff options
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | core/java/android/backup/IRestoreObserver.aidl | 50 | ||||
-rw-r--r-- | core/java/android/backup/IRestoreSession.aidl | 5 | ||||
-rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 64 |
4 files changed, 113 insertions, 7 deletions
@@ -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; |