Merge "Trigger unbindBackupAgent if app dies during backup"

This commit is contained in:
Paul Hadfield
2021-12-15 12:12:44 +00:00
committed by Android (Google) Code Review
3 changed files with 62 additions and 10 deletions

View File

@@ -3718,7 +3718,6 @@ public class UserBackupManagerService {
* only be called from the {@link ActivityManager}.
*/
public void agentDisconnected(String packageName) {
// TODO: handle backup being interrupted
synchronized (mAgentConnectLock) {
if (Binder.getCallingUid() == Process.SYSTEM_UID) {
mConnectedAgent = null;
@@ -3732,6 +3731,20 @@ public class UserBackupManagerService {
+ Binder.getCallingUid()
+ " claiming agent disconnected"));
}
Slog.w(TAG, "agentDisconnected: the backup agent for " + packageName
+ " died: cancel current operations");
// handleCancel() causes the PerformFullTransportBackupTask to go on to
// tearDownAgentAndKill: that will unbindBackupAgent in the Activity Manager, so
// that the package being backed up doesn't get stuck in restricted mode until the
// backup time-out elapses.
for (int token : mOperationStorage.operationTokensForPackage(packageName)) {
if (MORE_DEBUG) {
Slog.d(TAG, "agentDisconnected: will handleCancel(all) for token:"
+ Integer.toHexString(token));
}
handleCancel(token, true /* cancelAll */);
}
mAgentConnectLock.notifyAll();
}
}

View File

@@ -56,12 +56,15 @@ import com.android.server.backup.utils.BackupEligibilityRules;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.BackupObserverUtils;
import com.google.android.collect.Sets;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -195,8 +198,6 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
return;
}
registerTask();
for (String pkg : whichPackages) {
try {
PackageManager pm = backupManagerService.getPackageManager();
@@ -262,11 +263,15 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
mPackages = backupManagerService.filterUserFacingPackages(mPackages);
}
private void registerTask() {
Set<String> packageNames = Sets.newHashSet();
for (PackageInfo pkgInfo : mPackages) {
packageNames.add(pkgInfo.packageName);
}
Slog.d(TAG, "backupmanager pftbt token=" + Integer.toHexString(mCurrentOpToken));
mOperationStorage.registerOperation(mCurrentOpToken, OpState.PENDING, this, OpType.BACKUP);
mOperationStorage.registerOperationForPackages(mCurrentOpToken, OpState.PENDING,
packageNames, this, OpType.BACKUP);
}
// public, because called from KeyValueBackupTask.finishTask.
@@ -834,12 +839,13 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
mBackupResult = BackupTransport.AGENT_ERROR;
mQuota = quota;
mTransportFlags = transportFlags;
registerTask();
registerTask(target.packageName);
}
void registerTask() {
mOperationStorage.registerOperation(mCurrentOpToken,
OpState.PENDING, this, OpType.BACKUP_WAIT);
void registerTask(String packageName) {
Set<String> packages = Sets.newHashSet(packageName);
mOperationStorage.registerOperationForPackages(mCurrentOpToken, OpState.PENDING,
packages, this, OpType.BACKUP_WAIT);
}
void unregisterTask() {

View File

@@ -19,8 +19,12 @@ package com.android.server.backup;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.backup.BackupAgent;
@@ -42,12 +46,16 @@ import com.android.server.backup.transport.BackupTransportClient;
import com.android.server.backup.transport.TransportConnection;
import com.android.server.backup.utils.BackupEligibilityRules;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.function.IntConsumer;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class UserBackupManagerServiceTest {
@@ -163,6 +171,31 @@ public class UserBackupManagerServiceTest {
assertThat(operationType).isEqualTo(OperationType.MIGRATION);
}
@Test
public void testAgentDisconnected_cancelsCurrentOperations() throws Exception {
when(mOperationStorage.operationTokensForPackage(eq("com.android.foo"))).thenReturn(
ImmutableSet.of(123, 456, 789)
);
mService.agentDisconnected("com.android.foo");
verify(mOperationStorage).cancelOperation(eq(123), eq(true), any(IntConsumer.class));
verify(mOperationStorage).cancelOperation(eq(456), eq(true), any());
verify(mOperationStorage).cancelOperation(eq(789), eq(true), any());
}
@Test
public void testAgentDisconnected_unknownPackageName_cancelsNothing() throws Exception {
when(mOperationStorage.operationTokensForPackage(eq("com.android.foo"))).thenReturn(
ImmutableSet.of()
);
mService.agentDisconnected("com.android.foo");
verify(mOperationStorage, never())
.cancelOperation(anyInt(), anyBoolean(), any(IntConsumer.class));
}
private static PackageInfo getPackageInfo(String packageName) {
PackageInfo packageInfo = new PackageInfo();
packageInfo.applicationInfo = new ApplicationInfo();