Serialize restore operations

This cl introduces logic to serialize restore
operations. An incoming restore operation will
wait for the currently running restore to
complete.

Bug: 29010684

Test: Tested manually by installing an app while a restore was in
progress.

Change-Id: Ic88fdf2a6dcfab64853fe460c649380eea644774
This commit is contained in:
Shreyas Basarge
2017-02-17 21:59:46 +00:00
parent 14fd9cebe9
commit a88d8e04af

View File

@@ -35,15 +35,15 @@ import android.app.backup.BackupProgress;
import android.app.backup.BackupTransport;
import android.app.backup.FullBackup;
import android.app.backup.FullBackupDataOutput;
import android.app.backup.IBackupObserver;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.app.backup.SelectBackupTransportCallback;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -133,6 +133,7 @@ import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -143,6 +144,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
@@ -324,6 +326,11 @@ public class BackupManagerService {
final Object mClearDataLock = new Object();
volatile boolean mClearingData;
@GuardedBy("mPendingRestores")
private boolean mIsRestoreInProgress;
@GuardedBy("mPendingRestores")
private final Queue<PerformUnifiedRestoreTask> mPendingRestores = new ArrayDeque<>();
ActiveRestoreSession mActiveRestoreSession;
// Watch the device provisioning operation during setup
@@ -906,11 +913,28 @@ public class BackupManagerService {
{
RestoreParams params = (RestoreParams)msg.obj;
Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
BackupRestoreTask task = new PerformUnifiedRestoreTask(params.transport,
PerformUnifiedRestoreTask task = new PerformUnifiedRestoreTask(params.transport,
params.observer, params.monitor, params.token, params.pkgInfo,
params.pmToken, params.isSystemRestore, params.filterSet);
Message restoreMsg = obtainMessage(MSG_BACKUP_RESTORE_STEP, task);
sendMessage(restoreMsg);
synchronized (mPendingRestores) {
if (mIsRestoreInProgress) {
if (DEBUG) {
Slog.d(TAG, "Restore in progress, queueing.");
}
mPendingRestores.add(task);
// This task will be picked up and executed when the the currently running
// restore task finishes.
} else {
if (DEBUG) {
Slog.d(TAG, "Starting restore.");
}
mIsRestoreInProgress = true;
Message restoreMsg = obtainMessage(MSG_BACKUP_RESTORE_STEP, task);
sendMessage(restoreMsg);
}
}
break;
}
@@ -9103,6 +9127,24 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// done; we can finally release the wakelock and be legitimately done.
Slog.i(TAG, "Restore complete.");
synchronized (mPendingRestores) {
if (mPendingRestores.size() > 0) {
if (DEBUG) {
Slog.d(TAG, "Starting next pending restore.");
}
PerformUnifiedRestoreTask task = mPendingRestores.remove();
mBackupHandler.sendMessage(
mBackupHandler.obtainMessage(MSG_BACKUP_RESTORE_STEP, task));
} else {
mIsRestoreInProgress = false;
if (MORE_DEBUG) {
Slog.d(TAG, "No pending restores.");
}
}
}
mWakelock.release();
}