diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java index 83ef21e7528b5..b0c295c331d79 100644 --- a/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java +++ b/apex/blobstore/service/java/com/android/server/blob/BlobAccessMode.java @@ -24,6 +24,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.os.Binder; import android.os.UserHandle; import android.util.ArraySet; @@ -32,6 +33,7 @@ import android.util.DebugUtils; import android.util.IndentingPrintWriter; import com.android.internal.util.XmlUtils; +import com.android.server.LocalServices; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -108,7 +110,7 @@ class BlobAccessMode { } if ((mAccessType & ACCESS_TYPE_SAME_SIGNATURE) != 0) { - if (checkSignatures(context, callingUid, committerUid)) { + if (checkSignatures(callingUid, committerUid)) { return true; } } @@ -133,11 +135,11 @@ class BlobAccessMode { /** * Compare signatures for two packages of different users. */ - private boolean checkSignatures(Context context, int uid1, int uid2) { + private boolean checkSignatures(int uid1, int uid2) { final long token = Binder.clearCallingIdentity(); try { - return context.getPackageManager().checkSignatures(uid1, uid2) - == PackageManager.SIGNATURE_MATCH; + return LocalServices.getService(PackageManagerInternal.class) + .checkUidSignaturesForAllUsers(uid1, uid2) == PackageManager.SIGNATURE_MATCH; } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index c42d836202e50..7cb7c0bed0ea7 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -28,6 +28,7 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.PackageManager.SignatureResult; import android.content.pm.SigningDetails.CertCapabilities; import android.content.pm.overlay.OverlayPaths; import android.os.Bundle; @@ -1283,4 +1284,15 @@ public abstract class PackageManagerInternal { public abstract void shutdown(); public abstract DynamicCodeLogger getDynamicCodeLogger(); + + /** + * Compare the signatures of two packages that are installed in different users. + * + * @param uid1 First UID whose signature will be compared. + * @param uid2 Second UID whose signature will be compared. + * @return {@link PackageManager#SIGNATURE_MATCH} if signatures are matched. + * @throws SecurityException if the caller does not hold the + * {@link android.Manifest.permission#INTERACT_ACROSS_USERS}. + */ + public abstract @SignatureResult int checkUidSignaturesForAllUsers(int uid1, int uid2); } diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java index bb8a74493a16a..2b95b11a09cd4 100644 --- a/services/core/java/com/android/server/firewall/IntentFirewall.java +++ b/services/core/java/com/android/server/firewall/IntentFirewall.java @@ -25,6 +25,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import android.os.Binder; import android.os.Environment; import android.os.FileObserver; import android.os.Handler; @@ -129,7 +130,7 @@ public class IntentFirewall { mObserver.startWatching(); } - private PackageManagerInternal getPackageManager() { + PackageManagerInternal getPackageManager() { if (mPackageManager == null) { mPackageManager = LocalServices.getService(PackageManagerInternal.class); } @@ -623,12 +624,13 @@ public class IntentFirewall { } boolean signaturesMatch(int uid1, int uid2) { + final long token = Binder.clearCallingIdentity(); try { - IPackageManager pm = AppGlobals.getPackageManager(); - return pm.checkUidSignatures(uid1, uid2) == PackageManager.SIGNATURE_MATCH; - } catch (RemoteException ex) { - Slog.e(TAG, "Remote exception while checking signatures", ex); - return false; + // Compare signatures of two packages for different users. + return getPackageManager() + .checkUidSignaturesForAllUsers(uid1, uid2) == PackageManager.SIGNATURE_MATCH; + } finally { + Binder.restoreCallingIdentity(token); } } diff --git a/services/core/java/com/android/server/firewall/SenderFilter.java b/services/core/java/com/android/server/firewall/SenderFilter.java index 0074119623298..40684fab5c70a 100644 --- a/services/core/java/com/android/server/firewall/SenderFilter.java +++ b/services/core/java/com/android/server/firewall/SenderFilter.java @@ -16,14 +16,11 @@ package com.android.server.firewall; -import android.app.AppGlobals; import android.content.ComponentName; import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.IPackageManager; +import android.content.pm.PackageManagerInternal; import android.os.Process; -import android.os.RemoteException; -import android.util.Slog; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -37,22 +34,12 @@ class SenderFilter { private static final String VAL_SYSTEM_OR_SIGNATURE = "system|signature"; private static final String VAL_USER_ID = "userId"; - static boolean isPrivilegedApp(int callerUid, int callerPid) { + static boolean isPrivilegedApp(PackageManagerInternal pmi, int callerUid, int callerPid) { if (callerUid == Process.SYSTEM_UID || callerUid == 0 || callerPid == Process.myPid() || callerPid == 0) { return true; } - - IPackageManager pm = AppGlobals.getPackageManager(); - try { - return (pm.getPrivateFlagsForUid(callerUid) & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) - != 0; - } catch (RemoteException ex) { - Slog.e(IntentFirewall.TAG, "Remote exception while retrieving uid flags", - ex); - } - - return false; + return pmi.isUidPrivileged(callerUid); } public static final FilterFactory FACTORY = new FilterFactory("sender") { @@ -89,7 +76,7 @@ class SenderFilter { @Override public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent, int callerUid, int callerPid, String resolvedType, int receivingUid) { - return isPrivilegedApp(callerUid, callerPid); + return isPrivilegedApp(ifw.getPackageManager(), callerUid, callerPid); } }; @@ -97,8 +84,8 @@ class SenderFilter { @Override public boolean matches(IntentFirewall ifw, ComponentName resolvedComponent, Intent intent, int callerUid, int callerPid, String resolvedType, int receivingUid) { - return isPrivilegedApp(callerUid, callerPid) || - ifw.signaturesMatch(callerUid, receivingUid); + return isPrivilegedApp(ifw.getPackageManager(), callerUid, callerPid) + || ifw.signaturesMatch(callerUid, receivingUid); } }; diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java index a978fed724c0d..3042667a2e808 100644 --- a/services/core/java/com/android/server/pm/Computer.java +++ b/services/core/java/com/android/server/pm/Computer.java @@ -228,8 +228,28 @@ public interface Computer extends PackageDataSnapshot { int userId); boolean shouldFilterApplication(@NonNull SharedUserSetting sus, int callingUid, int userId); + /** + * Different form {@link #shouldFilterApplication(PackageStateInternal, int, int)}, the function + * returns {@code true} if the target package is not found in the device or uninstalled in the + * current user. Unless the caller's function needs to handle the package's uninstalled state + * by itself, using this function to keep the consistent behavior between conditions of package + * uninstalled and visibility not allowed to avoid the side channel leakage of package + * existence. + *

+ * Package with {@link PackageManager#SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN} is not + * treated as an uninstalled package for the carrier apps customization. + */ boolean shouldFilterApplicationIncludingUninstalled(@Nullable PackageStateInternal ps, int callingUid, int userId); + /** + * Different from {@link #shouldFilterApplication(SharedUserSetting, int, int)}, the function + * returns {@code true} if packages with the same shared user are all uninstalled in the current + * user. + * + * @see #shouldFilterApplicationIncludingUninstalled(PackageStateInternal, int, int) + */ + boolean shouldFilterApplicationIncludingUninstalled(@NonNull SharedUserSetting sus, + int callingUid, int userId); int checkUidPermission(String permName, int uid); int getPackageUidInternal(String packageName, long flags, int userId, int callingUid); long updateFlagsForApplication(long flags, int userId); @@ -378,6 +398,8 @@ public interface Computer extends PackageDataSnapshot { int checkUidSignatures(int uid1, int uid2); + int checkUidSignaturesForAllUsers(int uid1, int uid2); + boolean hasSigningCertificate(@NonNull String packageName, @NonNull byte[] certificate, @PackageManager.CertificateInputType int type); diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index f91026964f661..c545e7d731dc7 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -2793,6 +2793,26 @@ public class ComputerEngine implements Computer { ps, callingUid, null, TYPE_UNKNOWN, userId, true /* filterUninstall */); } + /** + * @see #shouldFilterApplication(PackageStateInternal, int, ComponentName, int, int, boolean) + */ + public final boolean shouldFilterApplicationIncludingUninstalled( + @NonNull SharedUserSetting sus, int callingUid, int userId) { + if (shouldFilterApplication(sus, callingUid, userId)) { + return true; + } + final ArraySet packageStates = + (ArraySet) sus.getPackageStates(); + for (int index = 0; index < packageStates.size(); index++) { + final PackageStateInternal ps = packageStates.valueAt(index); + if (ps.getUserStateOrDefault(userId).isInstalled() || ps.isHiddenUntilInstalled()) { + return false; + } + } + // Filter it, all packages with the same shared uid are uninstalled. + return true; + } + /** * Verification statuses are ordered from the worse to the best, except for * INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER, which is the worse. @@ -4253,54 +4273,58 @@ public class ComputerEngine implements Computer { public int checkUidSignatures(int uid1, int uid2) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - // Map to base uids. - final int appId1 = UserHandle.getAppId(uid1); - final int appId2 = UserHandle.getAppId(uid2); - SigningDetails p1SigningDetails; - SigningDetails p2SigningDetails; - Object obj = mSettings.getSettingBase(appId1); - if (obj != null) { - if (obj instanceof SharedUserSetting) { - final SharedUserSetting sus = (SharedUserSetting) obj; - if (shouldFilterApplication(sus, callingUid, callingUserId)) { - return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; - } - p1SigningDetails = sus.signatures.mSigningDetails; - } else if (obj instanceof PackageSetting) { - final PackageSetting ps = (PackageSetting) obj; - if (shouldFilterApplication(ps, callingUid, callingUserId)) { - return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; - } - p1SigningDetails = ps.getSigningDetails(); - } else { - return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; - } - } else { - return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; - } - obj = mSettings.getSettingBase(appId2); - if (obj != null) { - if (obj instanceof SharedUserSetting) { - final SharedUserSetting sus = (SharedUserSetting) obj; - if (shouldFilterApplication(sus, callingUid, callingUserId)) { - return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; - } - p2SigningDetails = sus.signatures.mSigningDetails; - } else if (obj instanceof PackageSetting) { - final PackageSetting ps = (PackageSetting) obj; - if (shouldFilterApplication(ps, callingUid, callingUserId)) { - return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; - } - p2SigningDetails = ps.getSigningDetails(); - } else { - return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; - } - } else { + final SigningDetails p1SigningDetails = + getSigningDetailsAndFilterAccess(uid1, callingUid, callingUserId); + final SigningDetails p2SigningDetails = + getSigningDetailsAndFilterAccess(uid2, callingUid, callingUserId); + if (p1SigningDetails == null || p2SigningDetails == null) { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } return checkSignaturesInternal(p1SigningDetails, p2SigningDetails); } + @Override + public int checkUidSignaturesForAllUsers(int uid1, int uid2) { + final int callingUid = Binder.getCallingUid(); + final int userId1 = UserHandle.getUserId(uid1); + final int userId2 = UserHandle.getUserId(uid2); + enforceCrossUserPermission(callingUid, userId1, false /* requireFullPermission */, + false /* checkShell */, "checkUidSignaturesForAllUsers"); + enforceCrossUserPermission(callingUid, userId2, false /* requireFullPermission */, + false /* checkShell */, "checkUidSignaturesForAllUsers"); + final SigningDetails p1SigningDetails = + getSigningDetailsAndFilterAccess(uid1, callingUid, userId1); + final SigningDetails p2SigningDetails = + getSigningDetailsAndFilterAccess(uid2, callingUid, userId2); + if (p1SigningDetails == null || p2SigningDetails == null) { + return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; + } + return checkSignaturesInternal(p1SigningDetails, p2SigningDetails); + } + + private SigningDetails getSigningDetailsAndFilterAccess(int uid, int callingUid, int userId) { + // Map to base uids. + final int appId = UserHandle.getAppId(uid); + final Object obj = mSettings.getSettingBase(appId); + if (obj == null) { + return null; + } + if (obj instanceof SharedUserSetting) { + final SharedUserSetting sus = (SharedUserSetting) obj; + if (shouldFilterApplicationIncludingUninstalled(sus, callingUid, userId)) { + return null; + } + return sus.signatures.mSigningDetails; + } else if (obj instanceof PackageSetting) { + final PackageSetting ps = (PackageSetting) obj; + if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) { + return null; + } + return ps.getSigningDetails(); + } + return null; + } + private int checkSignaturesInternal(SigningDetails p1SigningDetails, SigningDetails p2SigningDetails) { if (p1SigningDetails == null) { @@ -4363,27 +4387,9 @@ public class ComputerEngine implements Computer { @PackageManager.CertificateInputType int type) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - // Map to base uids. - final int appId = UserHandle.getAppId(uid); - final SigningDetails signingDetails; - final Object obj = mSettings.getSettingBase(appId); - if (obj != null) { - if (obj instanceof SharedUserSetting) { - final SharedUserSetting sus = (SharedUserSetting) obj; - if (shouldFilterApplication(sus, callingUid, callingUserId)) { - return false; - } - signingDetails = sus.signatures.mSigningDetails; - } else if (obj instanceof PackageSetting) { - final PackageSetting ps = (PackageSetting) obj; - if (shouldFilterApplication(ps, callingUid, callingUserId)) { - return false; - } - signingDetails = ps.getSigningDetails(); - } else { - return false; - } - } else { + final SigningDetails signingDetails = + getSigningDetailsAndFilterAccess(uid, callingUid, callingUserId); + if (signingDetails == null) { return false; } switch (type) { @@ -4446,13 +4452,13 @@ public class ComputerEngine implements Computer { final Object obj = mSettings.getSettingBase(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; - if (shouldFilterApplication(sus, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(sus, callingUid, callingUserId)) { return null; } return sus.name + ":" + sus.mAppId; } else if (obj instanceof PackageSetting) { final PackageSetting ps = (PackageSetting) obj; - if (shouldFilterApplication(ps, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, callingUserId)) { return null; } return ps.getPackageName(); @@ -4481,14 +4487,14 @@ public class ComputerEngine implements Computer { final Object obj = mSettings.getSettingBase(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; - if (shouldFilterApplication(sus, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(sus, callingUid, callingUserId)) { names[i] = null; } else { names[i] = "shared:" + sus.name; } } else if (obj instanceof PackageSetting) { final PackageSetting ps = (PackageSetting) obj; - if (shouldFilterApplication(ps, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, callingUserId)) { names[i] = null; } else { names[i] = ps.getPackageName(); @@ -4510,7 +4516,7 @@ public class ComputerEngine implements Computer { return Process.INVALID_UID; } final SharedUserSetting suid = mSettings.getSharedUserFromId(sharedUserName); - if (suid != null && !shouldFilterApplication(suid, callingUid, + if (suid != null && !shouldFilterApplicationIncludingUninstalled(suid, callingUid, UserHandle.getUserId(callingUid))) { return suid.mAppId; } @@ -4531,13 +4537,13 @@ public class ComputerEngine implements Computer { final Object obj = mSettings.getSettingBase(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; - if (shouldFilterApplication(sus, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(sus, callingUid, callingUserId)) { return 0; } return sus.getFlags(); } else if (obj instanceof PackageSetting) { final PackageSetting ps = (PackageSetting) obj; - if (shouldFilterApplication(ps, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, callingUserId)) { return 0; } return ps.getFlags(); @@ -4559,13 +4565,13 @@ public class ComputerEngine implements Computer { final Object obj = mSettings.getSettingBase(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; - if (shouldFilterApplication(sus, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(sus, callingUid, callingUserId)) { return 0; } return sus.getPrivateFlags(); } else if (obj instanceof PackageSetting) { final PackageSetting ps = (PackageSetting) obj; - if (shouldFilterApplication(ps, callingUid, callingUserId)) { + if (shouldFilterApplicationIncludingUninstalled(ps, callingUid, callingUserId)) { return 0; } return ps.getPrivateFlags(); diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java index 618403f7781d4..b594866fdf442 100644 --- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java +++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java @@ -720,6 +720,11 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal { return snapshot().isUidPrivileged(uid); } + @Override + public int checkUidSignaturesForAllUsers(int uid1, int uid2) { + return snapshot().checkUidSignaturesForAllUsers(uid1, uid2); + } + @NonNull @Override @Deprecated diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java index a7ba45f0c4c2b..d7b442c8eaf8a 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java +++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java @@ -27,6 +27,8 @@ import android.app.Instrumentation; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.KeySet; +import android.content.pm.PackageManager; +import android.os.Process; import android.os.UserHandle; import androidx.test.platform.app.InstrumentationRegistry; @@ -56,8 +58,12 @@ public class CrossUserPackageVisibilityTests { private static final String TEST_DATA_DIR = "/data/local/tmp/appenumerationtests"; private static final String CROSS_USER_TEST_PACKAGE_NAME = "com.android.appenumeration.crossuserpackagevisibility"; + private static final String SHARED_USER_TEST_PACKAGE_NAME = + "com.android.appenumeration.shareduid"; private static final File CROSS_USER_TEST_APK_FILE = new File(TEST_DATA_DIR, "AppEnumerationCrossUserPackageVisibilityTestApp.apk"); + private static final File SHARED_USER_TEST_APK_FILE = + new File(TEST_DATA_DIR, "AppEnumerationSharedUserTestApp.apk"); @ClassRule @Rule @@ -66,6 +72,7 @@ public class CrossUserPackageVisibilityTests { private Instrumentation mInstrumentation; private IPackageManager mIPackageManager; private Context mContext; + private UserReference mCurrentUser; private UserReference mOtherUser; @Before @@ -77,17 +84,21 @@ public class CrossUserPackageVisibilityTests { // Get another user final UserReference primaryUser = sDeviceState.primaryUser(); if (primaryUser.id() == UserHandle.myUserId()) { + mCurrentUser = primaryUser; mOtherUser = sDeviceState.secondaryUser(); } else { + mCurrentUser = sDeviceState.secondaryUser(); mOtherUser = primaryUser; } uninstallPackage(CROSS_USER_TEST_PACKAGE_NAME); + uninstallPackage(SHARED_USER_TEST_PACKAGE_NAME); } @After public void tearDown() { uninstallPackage(CROSS_USER_TEST_PACKAGE_NAME); + uninstallPackage(SHARED_USER_TEST_PACKAGE_NAME); } @Test @@ -151,16 +162,61 @@ public class CrossUserPackageVisibilityTests { assertThat(e1.getMessage()).isEqualTo(e2.getMessage()); } + @Test + public void testGetFlagsForUid_cannotDetectCrossUserPkg() throws Exception { + installPackage(CROSS_USER_TEST_APK_FILE); + final int uid = mContext.getPackageManager().getPackageUid( + CROSS_USER_TEST_PACKAGE_NAME, PackageManager.PackageInfoFlags.of(0)); + + uninstallPackageForUser(CROSS_USER_TEST_PACKAGE_NAME, mCurrentUser); + + assertThat(mIPackageManager.getFlagsForUid(uid)).isEqualTo(0); + } + + @Test + public void testGetUidForSharedUser_cannotDetectSharedUserPkg() throws Exception { + assertThat(mIPackageManager.getUidForSharedUser(SHARED_USER_TEST_PACKAGE_NAME)) + .isEqualTo(Process.INVALID_UID); + + installPackageForUser(SHARED_USER_TEST_APK_FILE, mOtherUser, true /* forceQueryable */); + + assertThat(mIPackageManager.getUidForSharedUser(SHARED_USER_TEST_PACKAGE_NAME)) + .isEqualTo(Process.INVALID_UID); + } + + private static void installPackage(File apk) { + installPackageForUser(apk, null, false /* forceQueryable */); + } + private static void installPackageForUser(File apk, UserReference user) { + installPackageForUser(apk, user, false /* forceQueryable */); + } + + private static void installPackageForUser(File apk, UserReference user, + boolean forceQueryable) { assertThat(apk.exists()).isTrue(); - final StringBuilder cmd = new StringBuilder("pm install --user "); - cmd.append(user.id()).append(" "); + final StringBuilder cmd = new StringBuilder("pm install -t "); + if (forceQueryable) { + cmd.append("--force-queryable "); + } + if (user != null) { + cmd.append("--user ").append(user.id()).append(" "); + } cmd.append(apk.getPath()); final String result = runShellCommand(cmd.toString()); assertThat(result.trim()).contains("Success"); } private static void uninstallPackage(String packageName) { - runShellCommand("pm uninstall " + packageName); + uninstallPackageForUser(packageName, null /* user */); + } + + private static void uninstallPackageForUser(String packageName, UserReference user) { + final StringBuilder cmd = new StringBuilder("pm uninstall "); + if (user != null) { + cmd.append("--user ").append(user.id()).append(" "); + } + cmd.append(packageName); + runShellCommand(cmd.toString()); } } diff --git a/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/AndroidManifest-crossUserPackageVisibility.xml b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/AndroidManifest-crossUserPackageVisibility.xml index 874a1fc5ff3e8..9d38ddfab5f10 100644 --- a/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/AndroidManifest-crossUserPackageVisibility.xml +++ b/services/tests/PackageManagerServiceTests/appenumeration/test-apps/target/AndroidManifest-crossUserPackageVisibility.xml @@ -17,6 +17,6 @@ - +