diff options
15 files changed, 203 insertions, 96 deletions
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java index e4ce62d0a5b5..4a1e5b9910bf 100644 --- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java +++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java @@ -23,9 +23,9 @@ import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; @@ -49,9 +49,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Set; - import java.util.Objects; +import java.util.Set; /** * We back up the signatures of each package so that during a system restore, @@ -95,6 +94,7 @@ public class PackageManagerBackupAgent extends BackupAgent { // is coming from pre-Android P device. private static final int UNDEFINED_ANCESTRAL_RECORD_VERSION = -1; + private int mUserId; private List<PackageInfo> mAllPackages; private PackageManager mPackageManager; // version & signature info of each app in a restore set @@ -129,17 +129,18 @@ public class PackageManagerBackupAgent extends BackupAgent { // We're constructed with the set of applications that are participating // in backup. This set changes as apps are installed & removed. - public PackageManagerBackupAgent(PackageManager packageMgr, List<PackageInfo> packages) { - init(packageMgr, packages); + public PackageManagerBackupAgent( + PackageManager packageMgr, List<PackageInfo> packages, int userId) { + init(packageMgr, packages, userId); } - public PackageManagerBackupAgent(PackageManager packageMgr) { - init(packageMgr, null); + public PackageManagerBackupAgent(PackageManager packageMgr, int userId) { + init(packageMgr, null, userId); evaluateStorablePackages(); } - private void init(PackageManager packageMgr, List<PackageInfo> packages) { + private void init(PackageManager packageMgr, List<PackageInfo> packages, int userId) { mPackageManager = packageMgr; mAllPackages = packages; mRestoredSignatures = null; @@ -147,17 +148,19 @@ public class PackageManagerBackupAgent extends BackupAgent { mStoredSdkVersion = Build.VERSION.SDK_INT; mStoredIncrementalVersion = Build.VERSION.INCREMENTAL; + mUserId = userId; } // We will need to refresh our understanding of what is eligible for // backup periodically; this entry point serves that purpose. public void evaluateStorablePackages() { - mAllPackages = getStorableApplications(mPackageManager); + mAllPackages = getStorableApplications(mPackageManager, mUserId); } - public static List<PackageInfo> getStorableApplications(PackageManager pm) { - List<PackageInfo> pkgs; - pkgs = pm.getInstalledPackages(PackageManager.GET_SIGNING_CERTIFICATES); + /** Gets all packages installed on user {@code userId} eligible for backup. */ + public static List<PackageInfo> getStorableApplications(PackageManager pm, int userId) { + List<PackageInfo> pkgs = + pm.getInstalledPackagesAsUser(PackageManager.GET_SIGNING_CERTIFICATES, userId); int N = pkgs.size(); for (int a = N-1; a >= 0; a--) { PackageInfo pkg = pkgs.get(a); @@ -237,8 +240,8 @@ public class PackageManagerBackupAgent extends BackupAgent { ComponentName home = getPreferredHomeComponent(); if (home != null) { try { - homeInfo = mPackageManager.getPackageInfo(home.getPackageName(), - PackageManager.GET_SIGNING_CERTIFICATES); + homeInfo = mPackageManager.getPackageInfoAsUser(home.getPackageName(), + PackageManager.GET_SIGNING_CERTIFICATES, mUserId); homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName()); homeVersion = homeInfo.getLongVersionCode(); SigningInfo signingInfo = homeInfo.signingInfo; @@ -315,8 +318,8 @@ public class PackageManagerBackupAgent extends BackupAgent { } else { PackageInfo info = null; try { - info = mPackageManager.getPackageInfo(packName, - PackageManager.GET_SIGNING_CERTIFICATES); + info = mPackageManager.getPackageInfoAsUser(packName, + PackageManager.GET_SIGNING_CERTIFICATES, mUserId); } catch (NameNotFoundException e) { // Weird; we just found it, and now are told it doesn't exist. // Treat it as having been removed from the device. diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index ed6a46cc58aa..0412b0fd89e2 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -496,11 +496,18 @@ public class UserBackupManagerService { mBaseStateDir = checkNotNull(baseStateDir, "baseStateDir cannot be null"); mBaseStateDir.mkdirs(); if (!SELinux.restorecon(mBaseStateDir)) { - Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir); + Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir); } mDataDir = checkNotNull(dataDir, "dataDir cannot be null"); - + // TODO(b/120424138): Remove when the system user moves out of the cache dir. The cache dir + // is managed by init.rc so we don't have to create it below. + if (userId != UserHandle.USER_SYSTEM) { + mDataDir.mkdirs(); + if (!SELinux.restorecon(mDataDir)) { + Slog.w(TAG, "SELinux restorecon failed on " + mDataDir); + } + } mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng); // Receivers for scheduled backups and transport initialization operations. @@ -797,7 +804,7 @@ public class UserBackupManagerService { * non-lifecycle agent instance, so we manually set up the context topology for it. */ public BackupAgent makeMetadataAgent() { - PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager); + PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager, mUserId); pmAgent.attach(mContext); pmAgent.onCreate(); return pmAgent; @@ -808,7 +815,7 @@ public class UserBackupManagerService { */ public PackageManagerBackupAgent makeMetadataAgent(List<PackageInfo> packages) { PackageManagerBackupAgent pmAgent = - new PackageManagerBackupAgent(mPackageManager, packages); + new PackageManagerBackupAgent(mPackageManager, packages, mUserId); pmAgent.attach(mContext); pmAgent.onCreate(); return pmAgent; @@ -879,7 +886,7 @@ public class UserBackupManagerService { boolean changed = false; ArrayList<FullBackupEntry> schedule = null; List<PackageInfo> apps = - PackageManagerBackupAgent.getStorableApplications(mPackageManager); + PackageManagerBackupAgent.getStorableApplications(mPackageManager, mUserId); if (mFullBackupScheduleFile.exists()) { try (FileInputStream fstream = new FileInputStream(mFullBackupScheduleFile); @@ -1428,8 +1435,7 @@ public class UserBackupManagerService { mConnecting = true; mConnectedAgent = null; try { - if (mActivityManager.bindBackupAgent(app.packageName, mode, - UserHandle.USER_OWNER)) { + if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId)) { Slog.d(TAG, "awaiting agent for " + app); // success; wait for the agent to arrive @@ -1488,7 +1494,7 @@ public class UserBackupManagerService { public void clearApplicationDataSynchronous(String packageName, boolean keepSystemState) { // Don't wipe packages marked allowClearUserData=false try { - PackageInfo info = mPackageManager.getPackageInfo(packageName, 0); + PackageInfo info = mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId); if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) { if (MORE_DEBUG) { Slog.i(TAG, "allowClearUserData=false so not wiping " @@ -1507,7 +1513,7 @@ public class UserBackupManagerService { mClearingData = true; try { mActivityManager.clearApplicationUserData( - packageName, keepSystemState, observer, 0); + packageName, keepSystemState, observer, mUserId); } catch (RemoteException e) { // can't happen because the activity manager is in this process } @@ -1616,8 +1622,8 @@ public class UserBackupManagerService { continue; } try { - PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, - PackageManager.GET_SIGNING_CERTIFICATES); + PackageInfo packageInfo = mPackageManager.getPackageInfoAsUser(packageName, + PackageManager.GET_SIGNING_CERTIFICATES, mUserId); if (!AppBackupUtils.appIsEligibleForBackup(packageInfo.applicationInfo, mPackageManager)) { BackupObserverUtils.sendBackupOnPackageResult(observer, packageName, @@ -2339,8 +2345,8 @@ public class UserBackupManagerService { if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName + " on " + transportName); PackageInfo info; try { - info = mPackageManager.getPackageInfo(packageName, - PackageManager.GET_SIGNING_CERTIFICATES); + info = mPackageManager.getPackageInfoAsUser(packageName, + PackageManager.GET_SIGNING_CERTIFICATES, mUserId); } catch (NameNotFoundException e) { Slog.d(TAG, "No such package '" + packageName + "' - not clearing backup data"); return; @@ -3258,7 +3264,7 @@ public class UserBackupManagerService { if (packageName != null) { PackageInfo app = null; try { - app = mPackageManager.getPackageInfo(packageName, 0); + app = mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId); } catch (NameNotFoundException nnf) { Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName); throw new IllegalArgumentException("Package " + packageName + " not found"); @@ -3362,7 +3368,7 @@ public class UserBackupManagerService { mTransportManager.getCurrentTransportClient(callerLogString); boolean eligible = AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport( - transportClient, packageName, mPackageManager); + transportClient, packageName, mPackageManager, mUserId); if (transportClient != null) { mTransportManager.disposeOfTransportClient(transportClient, callerLogString); } @@ -3386,7 +3392,7 @@ public class UserBackupManagerService { for (String packageName : packages) { if (AppBackupUtils .appIsRunningAndEligibleForBackupWithTransport( - transportClient, packageName, mPackageManager)) { + transportClient, packageName, mPackageManager, mUserId)) { eligibleApps.add(packageName); } } diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java index ef7ff9270a66..862ca711e694 100644 --- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java +++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java @@ -45,7 +45,6 @@ import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.SELinux; -import android.os.UserHandle; import android.os.WorkSource; import com.android.internal.annotations.GuardedBy; @@ -241,6 +240,7 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { private final boolean mUserInitiated; private final boolean mNonIncremental; private final int mCurrentOpToken; + private final int mUserId; private final File mStateDirectory; private final File mDataDirectory; private final File mBlankStateFile; @@ -320,6 +320,7 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { mCurrentOpToken = backupManagerService.generateRandomIntegerToken(); mQueueLock = mBackupManagerService.getQueueLock(); mBlankStateFile = new File(mStateDirectory, BLANK_STATE_FILE_NAME); + mUserId = backupManagerService.getUserId(); } private void registerTask() { @@ -480,8 +481,8 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { final PackageInfo packageInfo; try { packageInfo = - mPackageManager.getPackageInfo( - packageName, PackageManager.GET_SIGNING_CERTIFICATES); + mPackageManager.getPackageInfoAsUser( + packageName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId); } catch (PackageManager.NameNotFoundException e) { mReporter.onAgentUnknown(packageName); throw AgentException.permanent(e); @@ -770,8 +771,7 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { private void writeWidgetPayloadIfAppropriate(FileDescriptor fd, String pkgName) throws IOException { - // TODO: http://b/22388012 - byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName, UserHandle.USER_SYSTEM); + byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName, mUserId); File widgetFile = new File(mStateDirectory, pkgName + "_widget"); boolean priorStateExists = widgetFile.exists(); if (!priorStateExists && widgetState == null) { diff --git a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java index e273b329d51a..0fa0f89e329e 100644 --- a/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java +++ b/services/backup/java/com/android/server/backup/restore/ActiveRestoreSession.java @@ -54,6 +54,7 @@ public class ActiveRestoreSession extends IRestoreSession.Stub { private final TransportManager mTransportManager; private final String mTransportName; private final UserBackupManagerService mBackupManagerService; + private final int mUserId; @Nullable private final String mPackageName; public RestoreSet[] mRestoreSets = null; boolean mEnded = false; @@ -67,6 +68,7 @@ public class ActiveRestoreSession extends IRestoreSession.Stub { mPackageName = packageName; mTransportManager = backupManagerService.getTransportManager(); mTransportName = transportName; + mUserId = backupManagerService.getUserId(); } public void markTimedOut() { @@ -304,7 +306,8 @@ public class ActiveRestoreSession extends IRestoreSession.Stub { final PackageInfo app; try { - app = mBackupManagerService.getPackageManager().getPackageInfo(packageName, 0); + app = mBackupManagerService.getPackageManager().getPackageInfoAsUser( + packageName, 0, mUserId); } catch (NameNotFoundException nnf) { Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName); return -1; diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java index 45a398f80351..c7f3315493b4 100644 --- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java @@ -272,7 +272,7 @@ public class FullRestoreEngine extends RestoreEngine { instream, mBackupManagerService.getContext(), mDeleteObserver, mManifestSignatures, mPackagePolicies, info, installerPackageName, - bytesReadListener); + bytesReadListener, mBackupManagerService.getUserId()); // good to go; promote to ACCEPT mPackagePolicies.put(pkg, isSuccessfullyInstalled ? RestorePolicy.ACCEPT diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java index f7efad604e35..5284d94c2aa7 100644 --- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java @@ -48,7 +48,6 @@ import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; -import android.os.UserHandle; import android.util.EventLog; import android.util.Slog; @@ -81,6 +80,7 @@ import java.util.List; public class PerformUnifiedRestoreTask implements BackupRestoreTask { private UserBackupManagerService backupManagerService; + private final int mUserId; private final TransportManager mTransportManager; // Transport client we're working with to do the restore private final TransportClient mTransportClient; @@ -175,6 +175,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { @Nullable String[] filterSet, OnTaskFinishedListener listener) { this.backupManagerService = backupManagerService; + mUserId = backupManagerService.getUserId(); mTransportManager = backupManagerService.getTransportManager(); mEphemeralOpToken = backupManagerService.generateRandomIntegerToken(); mState = UnifiedRestoreState.INITIAL; @@ -204,7 +205,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // We want everything and a pony List<PackageInfo> apps = PackageManagerBackupAgent.getStorableApplications( - backupManagerService.getPackageManager()); + backupManagerService.getPackageManager(), mUserId); filterSet = packagesToNames(apps); if (DEBUG) { Slog.i(TAG, "Full restore; asking about " + filterSet.length + " apps"); @@ -221,7 +222,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { for (int i = 0; i < filterSet.length; i++) { try { PackageManager pm = backupManagerService.getPackageManager(); - PackageInfo info = pm.getPackageInfo(filterSet[i], 0); + PackageInfo info = pm.getPackageInfoAsUser(filterSet[i], 0, mUserId); if ("android".equals(info.packageName)) { hasSystem = true; continue; @@ -240,16 +241,16 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { } if (hasSystem) { try { - mAcceptSet.add(0, - backupManagerService.getPackageManager().getPackageInfo("android", 0)); + mAcceptSet.add(0, backupManagerService.getPackageManager().getPackageInfoAsUser( + "android", 0, mUserId)); } catch (NameNotFoundException e) { // won't happen; we know a priori that it's valid } } if (hasSettings) { try { - mAcceptSet.add(backupManagerService.getPackageManager().getPackageInfo( - SETTINGS_PACKAGE, 0)); + mAcceptSet.add(backupManagerService.getPackageManager().getPackageInfoAsUser( + SETTINGS_PACKAGE, 0, mUserId)); } catch (NameNotFoundException e) { // this one is always valid too } @@ -360,7 +361,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // If we're starting a full-system restore, set up to begin widget ID remapping if (mIsSystemRestore) { // TODO: http://b/22388012 - AppWidgetBackupBridge.restoreStarting(UserHandle.USER_SYSTEM); + AppWidgetBackupBridge.restoreStarting(mUserId); } try { @@ -508,8 +509,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { } try { - mCurrentPackage = backupManagerService.getPackageManager().getPackageInfo( - pkgName, PackageManager.GET_SIGNING_CERTIFICATES); + mCurrentPackage = backupManagerService.getPackageManager().getPackageInfoAsUser( + pkgName, PackageManager.GET_SIGNING_CERTIFICATES, mUserId); } catch (NameNotFoundException e) { // Whoops, we thought we could restore this package but it // turns out not to be present. Skip it. @@ -1079,7 +1080,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { // Kick off any work that may be needed regarding app widget restores // TODO: http://b/22388012 - AppWidgetBackupBridge.restoreFinished(UserHandle.USER_SYSTEM); + AppWidgetBackupBridge.restoreFinished(mUserId); // If this was a full-system restore, record the ancestral // dataset information diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java index e465c7e5264f..054879b077ad 100644 --- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java +++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java @@ -91,10 +91,13 @@ public class AppBackupUtils { * </ol> */ public static boolean appIsRunningAndEligibleForBackupWithTransport( - @Nullable TransportClient transportClient, String packageName, PackageManager pm) { + @Nullable TransportClient transportClient, + String packageName, + PackageManager pm, + int userId) { try { - PackageInfo packageInfo = pm.getPackageInfo(packageName, - PackageManager.GET_SIGNING_CERTIFICATES); + PackageInfo packageInfo = pm.getPackageInfoAsUser(packageName, + PackageManager.GET_SIGNING_CERTIFICATES, userId); ApplicationInfo applicationInfo = packageInfo.applicationInfo; if (!appIsEligibleForBackup(applicationInfo, pm) || appIsStopped(applicationInfo) diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java index df7e6d45ba0f..cce5b3b4e238 100644 --- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java +++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java @@ -72,7 +72,9 @@ public class RestoreUtils { HashMap<String, Signature[]> manifestSignatures, HashMap<String, RestorePolicy> packagePolicies, FileMetadata info, - String installerPackageName, BytesReadListener bytesReadListener) { + String installerPackageName, + BytesReadListener bytesReadListener, + int userId) { boolean okay = true; if (DEBUG) { @@ -144,8 +146,8 @@ public class RestoreUtils { uninstall = true; } else { try { - PackageInfo pkg = packageManager.getPackageInfo(info.packageName, - PackageManager.GET_SIGNING_CERTIFICATES); + PackageInfo pkg = packageManager.getPackageInfoAsUser(info.packageName, + PackageManager.GET_SIGNING_CERTIFICATES, userId); if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) { Slog.w(TAG, "Restore stream contains apk of package " diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java index 0d3b6b2afd2c..b8db3f39eb62 100644 --- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java +++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java @@ -46,6 +46,7 @@ import android.platform.test.annotations.Presubmit; import android.util.SparseArray; import com.android.server.backup.testing.TransportData; +import com.android.server.testing.shadows.ShadowApplicationPackageManager; import com.android.server.testing.shadows.ShadowBinder; import org.junit.After; @@ -65,7 +66,7 @@ import java.io.PrintWriter; /** Tests for the user-aware backup/restore system service {@link BackupManagerService}. */ @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowBinder.class}) +@Config(shadows = {ShadowApplicationPackageManager.class, ShadowBinder.class}) @Presubmit public class BackupManagerServiceTest { private static final String TEST_PACKAGE = "package"; diff --git a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java index 496817613216..3b7fa3d6ed05 100644 --- a/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java +++ b/services/robotests/backup/src/com/android/server/backup/UserBackupManagerServiceTest.java @@ -42,6 +42,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; import android.os.Binder; import android.os.HandlerThread; import android.os.PowerManager; @@ -54,6 +56,7 @@ import com.android.server.backup.testing.TransportData; import com.android.server.backup.testing.TransportTestUtils.TransportMock; import com.android.server.backup.transport.TransportNotRegisteredException; import com.android.server.testing.shadows.ShadowAppBackupUtils; +import com.android.server.testing.shadows.ShadowApplicationPackageManager; import com.android.server.testing.shadows.ShadowBinder; import com.android.server.testing.shadows.ShadowKeyValueBackupJob; import com.android.server.testing.shadows.ShadowKeyValueBackupTask; @@ -80,7 +83,7 @@ import java.util.List; * UserBackupManagerService} that performs operations for its target user. */ @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowAppBackupUtils.class}) +@Config(shadows = {ShadowAppBackupUtils.class, ShadowApplicationPackageManager.class}) @Presubmit public class UserBackupManagerServiceTest { private static final String TAG = "BMSTest"; @@ -137,6 +140,7 @@ public class UserBackupManagerServiceTest { public void tearDown() throws Exception { mBackupThread.quit(); ShadowAppBackupUtils.reset(); + ShadowApplicationPackageManager.reset(); } /** @@ -195,6 +199,7 @@ public class UserBackupManagerServiceTest { public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); setUpCurrentTransport(mTransportManager, mTransport); + registerPackages(PACKAGE_1); UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks(); boolean result = backupManagerService.isAppEligibleForBackup(PACKAGE_1); @@ -210,6 +215,7 @@ public class UserBackupManagerServiceTest { public void testIsAppEligibleForBackup_whenAppEligible() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport()); + registerPackages(PACKAGE_1); ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1); UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks(); @@ -228,6 +234,7 @@ public class UserBackupManagerServiceTest { public void testIsAppEligibleForBackup_withoutPermission() throws Exception { mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); setUpCurrentTransport(mTransportManager, mTransport); + registerPackages(PACKAGE_1); ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1); UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks(); @@ -245,6 +252,7 @@ public class UserBackupManagerServiceTest { public void testFilterAppsEligibleForBackup() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport); + registerPackages(PACKAGE_1, PACKAGE_2); ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1); UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks(); @@ -264,6 +272,7 @@ public class UserBackupManagerServiceTest { @Test public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); + registerPackages(PACKAGE_1, PACKAGE_2); UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks(); String[] filtered = @@ -281,6 +290,7 @@ public class UserBackupManagerServiceTest { public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception { mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); setUpCurrentTransport(mTransportManager, mTransport); + registerPackages(PACKAGE_1, PACKAGE_2); UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks(); expectThrows( @@ -749,7 +759,7 @@ public class UserBackupManagerServiceTest { private void setUpForRequestBackup(String... packages) throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); for (String packageName : packages) { - mShadowPackageManager.addPackage(packageName); + registerPackages(packageName); ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(packageName); } setUpCurrentTransport(mTransportManager, mTransport); @@ -864,7 +874,7 @@ public class UserBackupManagerServiceTest { @Test public void testRequestBackup_whenAppNotEligibleForBackup() throws Exception { mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); - mShadowPackageManager.addPackage(PACKAGE_1); + registerPackages(PACKAGE_1); setUpCurrentTransport(mTransportManager, mTransport); UserBackupManagerService backupManagerService = createUserBackupManagerServiceAndRunTasks(); backupManagerService.setEnabled(true); @@ -1127,6 +1137,22 @@ public class UserBackupManagerServiceTest { backupManagerService.setPowerManager(powerManagerMock); } + private PackageInfo getPackageInfo(String packageName) { + PackageInfo packageInfo = new PackageInfo(); + packageInfo.packageName = packageName; + packageInfo.applicationInfo = new ApplicationInfo(); + packageInfo.applicationInfo.packageName = packageName; + return packageInfo; + } + + private void registerPackages(String... packages) { + for (String packageName : packages) { + PackageInfo packageInfo = getPackageInfo(packageName); + mShadowPackageManager.installPackage(packageInfo); + ShadowApplicationPackageManager.addInstalledPackage(packageName, packageInfo); + } + } + /** * We can't mock the void method {@link #schedule(Context, long, BackupManagerConstants)} so we * extend {@link ShadowKeyValueBackupJob} and throw an exception at the end of the method. diff --git a/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java b/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java index b08ae6d5756e..bfb2b1479c74 100644 --- a/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java +++ b/services/robotests/backup/src/com/android/server/backup/internal/SetupObserverTest.java @@ -29,6 +29,7 @@ import com.android.server.backup.TransportManager; import com.android.server.backup.UserBackupManagerService; import com.android.server.backup.testing.BackupManagerServiceTestUtils; import com.android.server.backup.testing.TestUtils; +import com.android.server.testing.shadows.ShadowApplicationPackageManager; import org.junit.Before; import org.junit.Test; @@ -37,6 +38,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import java.io.File; @@ -45,6 +47,7 @@ import java.io.File; * UserBackupManagerService}. */ @RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowApplicationPackageManager.class}) @Presubmit public class SetupObserverTest { private static final String TAG = "SetupObserverTest"; diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java index b923bb09a423..4811523b22f9 100644 --- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java +++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java @@ -71,7 +71,6 @@ import static java.util.stream.Collectors.toList; import android.annotation.Nullable; import android.app.Application; -import android.app.ApplicationPackageManager; import android.app.IBackupAgent; import android.app.backup.BackupAgent; import android.app.backup.BackupDataInput; @@ -116,6 +115,7 @@ import com.android.server.backup.testing.TransportData; import com.android.server.backup.testing.TransportTestUtils; import com.android.server.backup.testing.TransportTestUtils.TransportMock; import com.android.server.testing.shadows.FrameworkShadowLooper; +import com.android.server.testing.shadows.ShadowApplicationPackageManager; import com.android.server.testing.shadows.ShadowBackupDataInput; import com.android.server.testing.shadows.ShadowBackupDataOutput; import com.android.server.testing.shadows.ShadowEventLog; @@ -135,8 +135,6 @@ import org.mockito.stubbing.Answer; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; -import org.robolectric.annotation.Implements; -import org.robolectric.annotation.Resetter; import org.robolectric.shadows.ShadowLooper; import org.robolectric.shadows.ShadowPackageManager; import org.robolectric.shadows.ShadowQueuedWork; @@ -160,7 +158,7 @@ import java.util.stream.Stream; @Config( shadows = { FrameworkShadowLooper.class, - KeyValueBackupTaskTest.ShadowApplicationPackageManager.class, + ShadowApplicationPackageManager.class, ShadowBackupDataInput.class, ShadowBackupDataOutput.class, ShadowEventLog.class, @@ -2437,11 +2435,12 @@ public class KeyValueBackupTaskTest { private AgentMock setUpAgent(PackageData packageData) { try { + String packageName = packageData.packageName; mPackageManager.setApplicationEnabledSetting( - packageData.packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); + packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); PackageInfo packageInfo = getPackageInfo(packageData); mShadowPackageManager.installPackage(packageInfo); - ShadowApplicationPackageManager.setPackageInfo(packageInfo); + ShadowApplicationPackageManager.addInstalledPackage(packageName, packageInfo); mContext.sendBroadcast(getPackageAddedIntent(packageData)); // Run the backup looper because on the receiver we post MSG_SCHEDULE_BACKUP_PACKAGE mShadowBackupLooper.runToEndOfTasks(); @@ -2537,7 +2536,7 @@ public class KeyValueBackupTaskTest { private PackageManagerBackupAgent createPmAgent() { PackageManagerBackupAgent pmAgent = - new PackageManagerBackupAgent(mApplication.getPackageManager()); + new PackageManagerBackupAgent(mApplication.getPackageManager(), USER_ID); pmAgent.attach(mApplication); pmAgent.onCreate(); return pmAgent; @@ -2842,7 +2841,7 @@ public class KeyValueBackupTaskTest { ThrowingPackageManagerBackupAgent( PackageManager packageManager, RuntimeException exception) { - super(packageManager); + super(packageManager, USER_ID); mException = exception; } @@ -2854,29 +2853,4 @@ public class KeyValueBackupTaskTest { throw mException; } } - - /** - * Extends {@link org.robolectric.shadows.ShadowApplicationPackageManager} to return the correct - * package in user-specific invocations. - */ - @Implements(value = ApplicationPackageManager.class) - public static class ShadowApplicationPackageManager - extends org.robolectric.shadows.ShadowApplicationPackageManager { - private static PackageInfo sPackageInfo; - - static void setPackageInfo(PackageInfo packageInfo) { - sPackageInfo = packageInfo; - } - - @Override - protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) { - return sPackageInfo; - } - - /** Clear {@link #sPackageInfo}. */ - @Resetter - public static void reset() { - sPackageInfo = null; - } - } } diff --git a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java index 4009876314e8..f17a9fe48c61 100644 --- a/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java +++ b/services/robotests/backup/src/com/android/server/backup/restore/ActiveRestoreSessionTest.java @@ -57,6 +57,7 @@ import com.android.server.backup.internal.BackupHandler; import com.android.server.backup.testing.TransportData; import com.android.server.backup.testing.TransportTestUtils; import com.android.server.backup.testing.TransportTestUtils.TransportMock; +import com.android.server.testing.shadows.ShadowApplicationPackageManager; import com.android.server.testing.shadows.ShadowEventLog; import com.android.server.testing.shadows.ShadowPerformUnifiedRestoreTask; @@ -77,7 +78,13 @@ import org.robolectric.shadows.ShadowPackageManager; import java.util.ArrayDeque; @RunWith(RobolectricTestRunner.class) -@Config(shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class, ShadowBinder.class}) +@Config( + shadows = { + ShadowApplicationPackageManager.class, + ShadowBinder.class, + ShadowEventLog.class, + ShadowPerformUnifiedRestoreTask.class + }) @Presubmit public class ActiveRestoreSessionTest { private static final String PACKAGE_1 = "com.example.package1"; @@ -140,6 +147,7 @@ public class ActiveRestoreSessionTest { @After public void tearDown() throws Exception { + ShadowApplicationPackageManager.reset(); ShadowPerformUnifiedRestoreTask.reset(); } @@ -561,7 +569,8 @@ public class ActiveRestoreSessionTest { packageInfo.packageName = packageName; packageInfo.applicationInfo = new ApplicationInfo(); packageInfo.applicationInfo.uid = uid; - mShadowPackageManager.addPackage(packageInfo); + mShadowPackageManager.installPackage(packageInfo); + ShadowApplicationPackageManager.addInstalledPackage(packageName, packageInfo); } private IRestoreSession createActiveRestoreSession( 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 5fffb149fd96..aefc871d2639 100644 --- a/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java +++ b/services/robotests/src/com/android/server/testing/shadows/ShadowAppBackupUtils.java @@ -54,7 +54,10 @@ public class ShadowAppBackupUtils { @Implementation protected static boolean appIsRunningAndEligibleForBackupWithTransport( - @Nullable TransportClient transportClient, String packageName, PackageManager pm) { + @Nullable TransportClient transportClient, + String packageName, + PackageManager pm, + int userId) { return sAppsRunningAndEligibleForBackupWithTransport.contains(packageName); } diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java new file mode 100644 index 000000000000..dc322094add8 --- /dev/null +++ b/services/robotests/src/com/android/server/testing/shadows/ShadowApplicationPackageManager.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 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 com.android.server.testing.shadows; + +import static android.content.pm.PackageManager.NameNotFoundException; + +import android.app.ApplicationPackageManager; +import android.content.pm.PackageInfo; +import android.util.ArrayMap; + +import org.robolectric.annotation.Implements; +import org.robolectric.annotation.Resetter; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Extends {@link org.robolectric.shadows.ShadowApplicationPackageManager} to return the correct + * package in user-specific invocations. + */ +@Implements(value = ApplicationPackageManager.class) +public class ShadowApplicationPackageManager + extends org.robolectric.shadows.ShadowApplicationPackageManager { + private static final Map<String, PackageInfo> sPackageInfos = new ArrayMap<>(); + private static final List<PackageInfo> sInstalledPackages = new ArrayList<>(); + + /** + * Registers the package {@code packageName} to be returned when invoking {@link + * ApplicationPackageManager#getPackageInfoAsUser(String, int, int)} and {@link + * ApplicationPackageManager#getInstalledPackagesAsUser(int, int)}. + */ + public static void addInstalledPackage(String packageName, PackageInfo packageInfo) { + sPackageInfos.put(packageName, packageInfo); + sInstalledPackages.add(packageInfo); + } + + @Override + protected PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId) + throws NameNotFoundException { + if (!sPackageInfos.containsKey(packageName)) { + throw new NameNotFoundException(packageName); + } + return sPackageInfos.get(packageName); + } + + @Override + protected List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) { + return sInstalledPackages; + } + + /** Clear package state. */ + @Resetter + public static void reset() { + sPackageInfos.clear(); + sInstalledPackages.clear(); + org.robolectric.shadows.ShadowApplicationPackageManager.reset(); + } +} |