Make RestoreSession.getAvailableRestoreSets() asynchronous
This transaction can involve the transport having to query a remote backend over the wire, so it can take a Long Time(tm). Make it main-thread-safe by making it asynchronous, with the results passed as a callback to the invoker's RestoreObserver. We also make the IRestoreObserver callback interface properly oneway. Bug #2550665 Bug #2549422 Change-Id: If18a233a0a3d54c7b55101715c9e6195b762c5a0
This commit is contained in:
@ -104,7 +104,8 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
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_TIMEOUT = 6;
|
||||
private static final int MSG_RUN_GET_RESTORE_SETS = 6;
|
||||
private static final int MSG_TIMEOUT = 7;
|
||||
|
||||
// Timeout interval for deciding that a bind or clear-data has taken too long
|
||||
static final long TIMEOUT_INTERVAL = 10 * 1000;
|
||||
@ -177,6 +178,19 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
IBackupTransport mLocalTransport, mGoogleTransport;
|
||||
ActiveRestoreSession mActiveRestoreSession;
|
||||
|
||||
class RestoreGetSetsParams {
|
||||
public IBackupTransport transport;
|
||||
public ActiveRestoreSession session;
|
||||
public IRestoreObserver observer;
|
||||
|
||||
RestoreGetSetsParams(IBackupTransport _transport, ActiveRestoreSession _session,
|
||||
IRestoreObserver _observer) {
|
||||
transport = _transport;
|
||||
session = _session;
|
||||
observer = _observer;
|
||||
}
|
||||
}
|
||||
|
||||
class RestoreParams {
|
||||
public IBackupTransport transport;
|
||||
public IRestoreObserver observer;
|
||||
@ -333,6 +347,36 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_RUN_GET_RESTORE_SETS:
|
||||
{
|
||||
// Like other async operations, this is entered with the wakelock held
|
||||
RestoreSet[] sets = null;
|
||||
RestoreGetSetsParams params = (RestoreGetSetsParams)msg.obj;
|
||||
try {
|
||||
sets = params.transport.getAvailableRestoreSets();
|
||||
// cache the result in the active session
|
||||
synchronized (params.session) {
|
||||
params.session.mRestoreSets = sets;
|
||||
}
|
||||
if (sets == null) EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Error from transport getting set list");
|
||||
} finally {
|
||||
if (params.observer != null) {
|
||||
try {
|
||||
params.observer.restoreSetsAvailable(sets);
|
||||
} catch (RemoteException re) {
|
||||
Slog.e(TAG, "Unable to report listing to observer");
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Restore observer threw", e);
|
||||
}
|
||||
}
|
||||
|
||||
mWakelock.release();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_TIMEOUT:
|
||||
{
|
||||
synchronized (mCurrentOpLock) {
|
||||
@ -2343,24 +2387,28 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
}
|
||||
|
||||
// --- Binder interface ---
|
||||
public synchronized RestoreSet[] getAvailableRestoreSets() {
|
||||
public synchronized int getAvailableRestoreSets(IRestoreObserver observer) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
|
||||
"getAvailableRestoreSets");
|
||||
if (observer == null) {
|
||||
throw new IllegalArgumentException("Observer must not be null");
|
||||
}
|
||||
|
||||
long oldId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (mRestoreTransport == null) {
|
||||
Slog.w(TAG, "Null transport getting restore sets");
|
||||
return null;
|
||||
return -1;
|
||||
}
|
||||
if (mRestoreSets == null) { // valid transport; do the one-time fetch
|
||||
mRestoreSets = mRestoreTransport.getAvailableRestoreSets();
|
||||
if (mRestoreSets == null) EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
|
||||
}
|
||||
return mRestoreSets;
|
||||
// spin off the transport request to our service thread
|
||||
mWakelock.acquire();
|
||||
Message msg = mBackupHandler.obtainMessage(MSG_RUN_GET_RESTORE_SETS,
|
||||
new RestoreGetSetsParams(mRestoreTransport, this, observer));
|
||||
mBackupHandler.sendMessage(msg);
|
||||
return 0;
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Error in getAvailableRestoreSets", e);
|
||||
return null;
|
||||
return -1;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(oldId);
|
||||
}
|
||||
|
Reference in New Issue
Block a user