diff options
author | 2020-07-09 08:04:28 +0100 | |
---|---|---|
committer | 2020-07-10 18:25:01 +0100 | |
commit | 2f2e13c1b6cae5fde3e8bfe8a08e7badab9c243a (patch) | |
tree | 618c7569f92f8a49a4b9f386eca1529040a519e8 | |
parent | 2e5a1c222fab8b6f302a01249a92af58b088fbea (diff) |
Add BackupManager API to start migration
Add an override of BackupManager#requestBackup where type of the
operation (a regular backup or a migration) can be specified.
Bug: 160407842
Test: atest UserBackupManagerServiceTest
Change-Id: Ia54fa26b040c3ec3612672585561794ff831afef
8 files changed, 206 insertions, 32 deletions
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index 8136efb6ee99..b1a62bf42cc4 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -752,7 +752,7 @@ public class BackupManager { @SystemApi @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[] packages, BackupObserver observer) { - return requestBackup(packages, observer, null, 0); + return requestBackup(packages, observer, null, 0, OperationType.BACKUP); } /** @@ -777,6 +777,31 @@ public class BackupManager { @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[] packages, BackupObserver observer, BackupManagerMonitor monitor, int flags) { + return requestBackup(packages, observer, monitor, flags, OperationType.BACKUP); + } + + /** + * Request an immediate backup, providing an observer to which results of the backup operation + * will be published. The Android backup system will decide for each package whether it will + * be full app data backup or key/value-pair-based backup. + * + * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all + * provided packages using the remote transport. + * + * @param packages List of package names to backup. + * @param observer The {@link BackupObserver} to receive callbacks during the backup + * operation. Could be {@code null}. + * @param monitor The {@link BackupManagerMonitorWrapper} to receive callbacks of important + * events during the backup operation. Could be {@code null}. + * @param flags {@link #FLAG_NON_INCREMENTAL_BACKUP}. + * @param operationType {@link OperationType} + * @return {@link BackupManager#SUCCESS} on success; nonzero on error. + * @throws IllegalArgumentException on null or empty {@code packages} param. + * @hide + */ + @RequiresPermission(android.Manifest.permission.BACKUP) + public int requestBackup(String[] packages, BackupObserver observer, + BackupManagerMonitor monitor, int flags, @OperationType int operationType) { checkServiceBinder(); if (sService != null) { try { @@ -786,7 +811,8 @@ public class BackupManager { BackupManagerMonitorWrapper monitorWrapper = monitor == null ? null : new BackupManagerMonitorWrapper(monitor); - return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags); + return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags, + operationType); } catch (RemoteException e) { Log.e(TAG, "requestBackup() couldn't connect"); } diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl index 4940976133c5..96b5dd593bbe 100644 --- a/core/java/android/app/backup/IBackupManager.aidl +++ b/core/java/android/app/backup/IBackupManager.aidl @@ -678,7 +678,7 @@ interface IBackupManager { * {@link android.app.backup.IBackupManager.requestBackupForUser} for the calling user id. */ int requestBackup(in String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, - int flags); + int flags, int operationType); /** * Cancel all running backups. After this call returns, no currently running backups will diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index b13bef2de151..c839ce94bd64 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -24,6 +24,7 @@ import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.admin.DevicePolicyManager; import android.app.backup.BackupManager; +import android.app.backup.BackupManager.OperationType; import android.app.backup.IBackupManager; import android.app.backup.IBackupManagerMonitor; import android.app.backup.IBackupObserver; @@ -1338,14 +1339,15 @@ public class BackupManagerService extends IBackupManager.Stub { if (!isUserReadyForBackup(userId)) { return BackupManager.ERROR_BACKUP_NOT_ALLOWED; } - return requestBackup(userId, packages, observer, monitor, flags); + return requestBackup(userId, packages, observer, monitor, flags, OperationType.BACKUP); } @Override public int requestBackup(String[] packages, IBackupObserver observer, - IBackupManagerMonitor monitor, int flags) throws RemoteException { - return requestBackupForUser(binderGetCallingUserId(), packages, - observer, monitor, flags); + IBackupManagerMonitor monitor, int flags, @OperationType int operationType) + throws RemoteException { + return requestBackup(binderGetCallingUserId(), packages, + observer, monitor, flags, operationType); } /** @@ -1357,13 +1359,15 @@ public class BackupManagerService extends IBackupManager.Stub { String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, - int flags) { + int flags, + @OperationType int operationType) { UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(userId, "requestBackup()"); return userBackupManagerService == null ? BackupManager.ERROR_BACKUP_NOT_ALLOWED - : userBackupManagerService.requestBackup(packages, observer, monitor, flags); + : userBackupManagerService.requestBackup(packages, observer, monitor, flags, + operationType); } @Override diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index 2f753e2cfd0d..f4d2f5542da1 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -47,6 +47,7 @@ import android.app.IBackupAgent; import android.app.PendingIntent; import android.app.backup.BackupAgent; import android.app.backup.BackupManager; +import android.app.backup.BackupManager.OperationType; import android.app.backup.BackupManagerMonitor; import android.app.backup.FullBackup; import android.app.backup.IBackupManager; @@ -535,11 +536,12 @@ public class UserBackupManagerService { } @VisibleForTesting - UserBackupManagerService(Context context) { + UserBackupManagerService(Context context, PackageManager packageManager) { mContext = context; mUserId = 0; mRegisterTransportsRequestedTime = 0; + mPackageManager = packageManager; mBaseStateDir = null; mDataDir = null; @@ -550,7 +552,6 @@ public class UserBackupManagerService { mRunInitIntent = null; mAgentTimeoutParameters = null; mTransportManager = null; - mPackageManager = null; mActivityManagerInternal = null; mAlarmManager = null; mConstants = null; @@ -1825,6 +1826,15 @@ public class UserBackupManagerService { */ public int requestBackup(String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor, int flags) { + return requestBackup(packages, observer, monitor, flags, OperationType.BACKUP); + } + + /** + * Requests a backup for the inputted {@code packages} with a specified {@link + * IBackupManagerMonitor} and {@link OperationType}. + */ + public int requestBackup(String[] packages, IBackupObserver observer, + IBackupManagerMonitor monitor, int flags, @OperationType int operationType) { mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup"); if (packages == null || packages.length < 1) { @@ -1872,6 +1882,18 @@ public class UserBackupManagerService { OnTaskFinishedListener listener = caller -> mTransportManager.disposeOfTransportClient(transportClient, caller); + Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP); + msg.obj = getRequestBackupParams(packages, observer, monitor, flags, operationType, + transportClient, transportDirName, listener); + mBackupHandler.sendMessage(msg); + return BackupManager.SUCCESS; + } + + @VisibleForTesting + BackupParams getRequestBackupParams(String[] packages, IBackupObserver observer, + IBackupManagerMonitor monitor, int flags, @OperationType int operationType, + TransportClient transportClient, String transportDirName, + OnTaskFinishedListener listener) { ArrayList<String> fullBackupList = new ArrayList<>(); ArrayList<String> kvBackupList = new ArrayList<>(); for (String packageName : packages) { @@ -1882,12 +1904,13 @@ public class UserBackupManagerService { try { PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId); - if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo, mUserId)) { + if (!appIsEligibleForBackup(packageInfo.applicationInfo, mUserId, + operationType)) { BackupObserverUtils.sendBackupOnPackageResult(observer, packageName, BackupManager.ERROR_BACKUP_NOT_ALLOWED); continue; } - if (AppBackupUtils.appGetsFullBackup(packageInfo)) { + if (appGetsFullBackup(packageInfo, operationType)) { fullBackupList.add(packageInfo.packageName); } else { kvBackupList.add(packageInfo.packageName); @@ -1897,6 +1920,7 @@ public class UserBackupManagerService { BackupManager.ERROR_PACKAGE_NOT_FOUND); } } + EventLog.writeEvent(EventLogTags.BACKUP_REQUESTED, packages.length, kvBackupList.size(), fullBackupList.size()); if (MORE_DEBUG) { @@ -1915,11 +1939,20 @@ public class UserBackupManagerService { boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0; - Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP); - msg.obj = new BackupParams(transportClient, transportDirName, kvBackupList, fullBackupList, - observer, monitor, listener, true, nonIncrementalBackup); - mBackupHandler.sendMessage(msg); - return BackupManager.SUCCESS; + return new BackupParams(transportClient, transportDirName, kvBackupList, fullBackupList, + observer, monitor, listener, /* userInitiated */ true, nonIncrementalBackup, + operationType); + } + + @VisibleForTesting + boolean appIsEligibleForBackup(ApplicationInfo applicationInfo, int userId, + @OperationType int operationType) { + return AppBackupUtils.appIsEligibleForBackup(applicationInfo, userId, operationType); + } + + @VisibleForTesting + boolean appGetsFullBackup(PackageInfo packageInfo, @OperationType int operationType) { + return AppBackupUtils.appGetsFullBackup(packageInfo, operationType); } /** Cancel all running backups. */ diff --git a/services/backup/java/com/android/server/backup/params/BackupParams.java b/services/backup/java/com/android/server/backup/params/BackupParams.java index 2ba8ec16a45c..514434ec9d39 100644 --- a/services/backup/java/com/android/server/backup/params/BackupParams.java +++ b/services/backup/java/com/android/server/backup/params/BackupParams.java @@ -16,6 +16,7 @@ package com.android.server.backup.params; +import android.app.backup.BackupManager.OperationType; import android.app.backup.IBackupManagerMonitor; import android.app.backup.IBackupObserver; @@ -35,11 +36,12 @@ public class BackupParams { public OnTaskFinishedListener listener; public boolean userInitiated; public boolean nonIncrementalBackup; + @OperationType public int operationType; public BackupParams(TransportClient transportClient, String dirName, ArrayList<String> kvPackages, ArrayList<String> fullPackages, IBackupObserver observer, IBackupManagerMonitor monitor, OnTaskFinishedListener listener, boolean userInitiated, - boolean nonIncrementalBackup) { + boolean nonIncrementalBackup, int operationType) { this.transportClient = transportClient; this.dirName = dirName; this.kvPackages = kvPackages; @@ -49,5 +51,6 @@ public class BackupParams { this.listener = listener; this.userInitiated = userInitiated; this.nonIncrementalBackup = nonIncrementalBackup; + this.operationType = operationType; } } diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java index a1bfcdf4bdfa..4a73efe25fdb 100644 --- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java +++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java @@ -38,6 +38,8 @@ import static org.testng.Assert.expectThrows; import android.annotation.UserIdInt; import android.app.Application; +import android.app.backup.BackupManager; +import android.app.backup.BackupManager.OperationType; import android.app.backup.IBackupManagerMonitor; import android.app.backup.IBackupObserver; import android.app.backup.IFullBackupRestoreObserver; @@ -871,7 +873,8 @@ public class BackupManagerServiceRoboTest { SecurityException.class, () -> backupManagerService.requestBackup( - mUserTwoId, packages, observer, monitor, 0)); + mUserTwoId, packages, observer, monitor, 0, + OperationType.BACKUP)); } /** @@ -889,9 +892,11 @@ public class BackupManagerServiceRoboTest { IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class); setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ true); - backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0); + backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0, + OperationType.BACKUP); - verify(mUserTwoService).requestBackup(packages, observer, monitor, /* flags */ 0); + verify(mUserTwoService).requestBackup(packages, observer, monitor, /* flags */ 0, + OperationType.BACKUP); } /** Test that the backup service routes methods correctly to the user that requests it. */ @@ -904,9 +909,11 @@ public class BackupManagerServiceRoboTest { IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class); setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false); - backupManagerService.requestBackup(mUserOneId, packages, observer, monitor, /* flags */ 0); + backupManagerService.requestBackup(mUserOneId, packages, observer, monitor, /* flags */ 0, + OperationType.BACKUP); - verify(mUserOneService).requestBackup(packages, observer, monitor, /* flags */ 0); + verify(mUserOneService).requestBackup(packages, observer, monitor, /* flags */ 0, + OperationType.BACKUP); } /** Test that the backup service routes methods correctly to the user that requests it. */ @@ -919,9 +926,11 @@ public class BackupManagerServiceRoboTest { IBackupManagerMonitor monitor = mock(IBackupManagerMonitor.class); setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false); - backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0); + backupManagerService.requestBackup(mUserTwoId, packages, observer, monitor, /* flags */ 0, + OperationType.BACKUP); - verify(mUserOneService, never()).requestBackup(packages, observer, monitor, /* flags */ 0); + verify(mUserOneService, never()).requestBackup(packages, observer, monitor, /* flags */ 0, + OperationType.BACKUP); } /** diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java index 33b8aa73d293..aa1c6688b01d 100644 --- a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java +++ b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java @@ -62,12 +62,13 @@ public class ShadowAppBackupUtils { } @Implementation - protected static boolean appIsEligibleForBackup(ApplicationInfo app, int userId) { + protected static boolean appIsEligibleForBackup(ApplicationInfo app, int userId, + int operationType) { return sAppsEligibleForBackup.contains(app.packageName); } @Implementation - protected static boolean appGetsFullBackup(PackageInfo packageInfo) { + protected static boolean appGetsFullBackup(PackageInfo packageInfo, int operationType) { return sAppsGetFullBackup.contains(packageInfo.packageName); } diff --git a/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java index 3ebc315fa511..ccb2ea3e46da 100644 --- a/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/backup/UserBackupManagerServiceTest.java @@ -18,11 +18,25 @@ package com.android.server.backup; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +import android.app.backup.BackupManager.OperationType; +import android.app.backup.IBackupManagerMonitor; +import android.app.backup.IBackupObserver; import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; import android.platform.test.annotations.Presubmit; import androidx.test.runner.AndroidJUnit4; +import com.android.server.backup.internal.OnTaskFinishedListener; +import com.android.server.backup.params.BackupParams; +import com.android.server.backup.transport.TransportClient; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,15 +46,25 @@ import org.mockito.MockitoAnnotations; @Presubmit @RunWith(AndroidJUnit4.class) public class UserBackupManagerServiceTest { + private static final String TEST_PACKAGE = "package1"; + private static final String[] TEST_PACKAGES = new String[] { TEST_PACKAGE }; + @Mock Context mContext; + @Mock IBackupManagerMonitor mBackupManagerMonitor; + @Mock IBackupObserver mBackupObserver; + @Mock PackageManager mPackageManager; + @Mock TransportClient mTransportClient; + private TestBackupService mService; @Before - public void setUp() { + public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mService = new TestBackupService(mContext); + mService = new TestBackupService(mContext, mPackageManager); + mService.setEnabled(true); + mService.setSetupComplete(true); } @Test @@ -57,11 +81,72 @@ public class UserBackupManagerServiceTest { assertThat(mService.isEnabledStatePersisted).isTrue(); } + @Test + public void getRequestBackupParams_isMigrationAndAppGetsFullBackup() throws Exception { + when(mPackageManager.getPackageInfoAsUser(anyString(), anyInt(), anyInt())).thenReturn( + getPackageInfo(TEST_PACKAGE)); + mService.mAppIsEligibleForBackup = true; + mService.mAppGetsFullBackup = true; + + BackupParams params = mService.getRequestBackupParams(TEST_PACKAGES, mBackupObserver, + mBackupManagerMonitor, /* flags */ 0, OperationType.MIGRATION, + mTransportClient, /* transportDirName */ "", OnTaskFinishedListener.NOP); + + assertThat(params.kvPackages).isEmpty(); + assertThat(params.fullPackages).contains(TEST_PACKAGE); + assertThat(params.operationType).isEqualTo(OperationType.MIGRATION); + assertThat(mService.mOperationType).isEqualTo(OperationType.MIGRATION); + } + + @Test + public void getRequestBackupParams_isMigrationAndAppGetsKeyValueBackup() throws Exception { + when(mPackageManager.getPackageInfoAsUser(anyString(), anyInt(), anyInt())).thenReturn( + getPackageInfo(TEST_PACKAGE)); + mService.mAppIsEligibleForBackup = true; + mService.mAppGetsFullBackup = false; + + BackupParams params = mService.getRequestBackupParams(TEST_PACKAGES, mBackupObserver, + mBackupManagerMonitor, /* flags */ 0, OperationType.MIGRATION, + mTransportClient, /* transportDirName */ "", OnTaskFinishedListener.NOP); + + assertThat(params.kvPackages).contains(TEST_PACKAGE); + assertThat(params.fullPackages).isEmpty(); + assertThat(params.operationType).isEqualTo(OperationType.MIGRATION); + assertThat(mService.mOperationType).isEqualTo(OperationType.MIGRATION); + } + + @Test + public void getRequestBackupParams_isMigrationAndAppNotEligibleForBackup() throws Exception { + when(mPackageManager.getPackageInfoAsUser(anyString(), anyInt(), anyInt())).thenReturn( + getPackageInfo(TEST_PACKAGE)); + mService.mAppIsEligibleForBackup = false; + mService.mAppGetsFullBackup = false; + + BackupParams params = mService.getRequestBackupParams(TEST_PACKAGES, mBackupObserver, + mBackupManagerMonitor, /* flags */ 0, OperationType.MIGRATION, + mTransportClient, /* transportDirName */ "", OnTaskFinishedListener.NOP); + + assertThat(params.kvPackages).isEmpty(); + assertThat(params.fullPackages).isEmpty(); + assertThat(params.operationType).isEqualTo(OperationType.MIGRATION); + assertThat(mService.mOperationType).isEqualTo(OperationType.MIGRATION); + } + + private static PackageInfo getPackageInfo(String packageName) { + PackageInfo packageInfo = new PackageInfo(); + packageInfo.applicationInfo = new ApplicationInfo(); + packageInfo.packageName = packageName; + return packageInfo; + } + private static class TestBackupService extends UserBackupManagerService { boolean isEnabledStatePersisted = false; + boolean mAppIsEligibleForBackup = false; + boolean mAppGetsFullBackup = false; + int mOperationType = 0; - TestBackupService(Context context) { - super(context); + TestBackupService(Context context, PackageManager packageManager) { + super(context, packageManager); } @Override @@ -76,5 +161,18 @@ public class UserBackupManagerServiceTest { @Override void updateStateOnBackupEnabled(boolean wasEnabled, boolean enable) {} + + @Override + boolean appIsEligibleForBackup(ApplicationInfo applicationInfo, int userId, + @OperationType int operationType) { + mOperationType = operationType; + return mAppIsEligibleForBackup; + } + + @Override + boolean appGetsFullBackup(PackageInfo packageInfo, @OperationType int operationType) { + mOperationType = operationType; + return mAppGetsFullBackup; + } } } |