diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 999b34f8a9303..c8f64061e6fc2 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -127,9 +127,10 @@ public class LauncherApps { public static final String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST"; - private Context mContext; - private ILauncherApps mService; - private PackageManager mPm; + private final Context mContext; + private final ILauncherApps mService; + private final PackageManager mPm; + private final UserManager mUserManager; private List mCallbacks = new ArrayList(); @@ -387,6 +388,7 @@ public class LauncherApps { mContext = context; mService = service; mPm = context.getPackageManager(); + mUserManager = context.getSystemService(UserManager.class); } /** @hide */ @@ -396,6 +398,16 @@ public class LauncherApps { ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE))); } + /** + * Show an error log on logcat, when the calling user is a managed profile, and the target + * user is different from the calling user, in order to help developers to detect it. + */ + private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) { + if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) { + Log.e(TAG, "Accessing other profiles/users from managed profile is no longer allowed."); + } + } + /** * Return a list of profiles that the caller can access via the {@link LauncherApps} APIs. * @@ -403,14 +415,13 @@ public class LauncherApps { * Otherwise it'll return the same list as {@link UserManager#getUserProfiles()} would. */ public List getProfiles() { - final UserManager um = mContext.getSystemService(UserManager.class); - if (um.isManagedProfile()) { + if (mUserManager.isManagedProfile()) { // If it's a managed profile, only return the current profile. final List result = new ArrayList(1); result.add(android.os.Process.myUserHandle()); return result; } else { - return um.getUserProfiles(); + return mUserManager.getUserProfiles(); } } @@ -424,6 +435,7 @@ public class LauncherApps { * @return List of launchable activities. Can be an empty list but will not be null. */ public List getActivityList(String packageName, UserHandle user) { + logErrorForInvalidProfileAccess(user); try { return convertToActivityList(mService.getLauncherActivities(mContext.getPackageName(), packageName, user), user); @@ -441,6 +453,7 @@ public class LauncherApps { * @return An activity info object if there is a match. */ public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) { + logErrorForInvalidProfileAccess(user); try { ActivityInfo ai = mService.resolveActivity(mContext.getPackageName(), intent.getComponent(), user); @@ -464,6 +477,7 @@ public class LauncherApps { */ public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds, Bundle opts) { + logErrorForInvalidProfileAccess(user); if (DEBUG) { Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier()); } @@ -486,6 +500,7 @@ public class LauncherApps { */ public void startAppDetailsActivity(ComponentName component, UserHandle user, Rect sourceBounds, Bundle opts) { + logErrorForInvalidProfileAccess(user); try { mService.showAppDetailsAsUser(mContext.getPackageName(), component, sourceBounds, opts, user); @@ -507,6 +522,7 @@ public class LauncherApps { */ public List getShortcutConfigActivityList(@Nullable String packageName, @NonNull UserHandle user) { + logErrorForInvalidProfileAccess(user); try { return convertToActivityList(mService.getShortcutConfigActivities( mContext.getPackageName(), packageName, user), @@ -553,6 +569,7 @@ public class LauncherApps { * @see Intent#ACTION_CREATE_SHORTCUT * @see android.app.Activity#startIntentSenderForResult */ + @Nullable public IntentSender getShortcutConfigActivityIntent(@NonNull LauncherActivityInfo info) { try { return mService.getShortcutConfigActivityIntent( @@ -571,6 +588,7 @@ public class LauncherApps { * @return true if the package exists and is enabled. */ public boolean isPackageEnabled(String packageName, UserHandle user) { + logErrorForInvalidProfileAccess(user); try { return mService.isPackageEnabled(mContext.getPackageName(), packageName, user); } catch (RemoteException re) { @@ -591,6 +609,7 @@ public class LauncherApps { */ public ApplicationInfo getApplicationInfo(String packageName, @ApplicationInfoFlags int flags, UserHandle user) { + logErrorForInvalidProfileAccess(user); try { return mService.getApplicationInfo(mContext.getPackageName(), packageName, flags, user); } catch (RemoteException re) { @@ -607,6 +626,7 @@ public class LauncherApps { * @return true if the activity exists and is enabled. */ public boolean isActivityEnabled(ComponentName component, UserHandle user) { + logErrorForInvalidProfileAccess(user); try { return mService.isActivityEnabled(mContext.getPackageName(), component, user); } catch (RemoteException re) { @@ -656,6 +676,7 @@ public class LauncherApps { @Nullable public List getShortcuts(@NonNull ShortcutQuery query, @NonNull UserHandle user) { + logErrorForInvalidProfileAccess(user); try { return mService.getShortcuts(mContext.getPackageName(), query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity, @@ -699,6 +720,7 @@ public class LauncherApps { */ public void pinShortcuts(@NonNull String packageName, @NonNull List shortcutIds, @NonNull UserHandle user) { + logErrorForInvalidProfileAccess(user); try { mService.pinShortcuts(mContext.getPackageName(), packageName, shortcutIds, user); } catch (RemoteException e) { @@ -866,6 +888,8 @@ public class LauncherApps { public void startShortcut(@NonNull String packageName, @NonNull String shortcutId, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions, @NonNull UserHandle user) { + logErrorForInvalidProfileAccess(user); + startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions, user.getIdentifier()); } diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index b6611eb9fcfdb..179f310019059 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -64,6 +64,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -216,29 +217,35 @@ public class LauncherAppsService extends SystemService { } } - /** - * Checks if the caller is in the same group as the userToCheck. - */ - private void ensureInUserProfiles( - String callingPackage, UserHandle userToCheck, String message) { - ensureInUserProfiles(callingPackage, userToCheck.getIdentifier(), message); + /** See {@link #canAccessProfile(String, int, String)} */ + private boolean canAccessProfile( + String callingPackage, UserHandle targetUser, String message) { + return canAccessProfile(callingPackage, targetUser.getIdentifier(), message); } - private void ensureInUserProfiles(String callingPackage, int targetUserId, String message) { + /** + * Checks if the calling user is in the same group as {@code targetUser}, and allowed + * to access it. + * + * @return TRUE if the calling user can access {@code targetUserId}. FALSE if not *but + * they're still in the same profile group*. + * + * @throws SecurityException if the calling user and {@code targetUser} are not in the same + * group. + */ + private boolean canAccessProfile(String callingPackage, int targetUserId, String message) { final int callingUserId = injectCallingUserId(); - if (targetUserId == callingUserId) return; + if (targetUserId == callingUserId) return true; long ident = injectClearCallingIdentity(); try { UserInfo callingUserInfo = mUm.getUserInfo(callingUserId); if (callingUserInfo.isManagedProfile()) { - // TODO: Make it SecurityException. See b/34650921 - // throw new SecurityException(message + " for another profile " + targetUserId); - - // TODO: Report caller package name. Slog.wtfStack(TAG, message + " by " + callingPackage + " for another profile " + targetUserId + " from " + callingUserId); + + return false; } UserInfo targetUserInfo = mUm.getUserInfo(targetUserId); @@ -250,6 +257,7 @@ public class LauncherAppsService extends SystemService { } finally { injectRestoreCallingIdentity(ident); } + return true; } @VisibleForTesting // We override it in unit tests @@ -301,7 +309,9 @@ public class LauncherAppsService extends SystemService { public ActivityInfo resolveActivity( String callingPackage, ComponentName component, UserHandle user) throws RemoteException { - ensureInUserProfiles(callingPackage, user, "Cannot resolve activity"); + if (!canAccessProfile(callingPackage, user, "Cannot resolve activity")) { + return null; + } if (!isUserEnabled(user)) { return null; } @@ -328,7 +338,9 @@ public class LauncherAppsService extends SystemService { private ParceledListSlice queryActivitiesForUser(String callingPackage, Intent intent, UserHandle user) { - ensureInUserProfiles(callingPackage, user, "Cannot retrieve activities"); + if (!canAccessProfile(callingPackage, user, "Cannot retrieve activities")) { + return null; + } if (!isUserEnabled(user)) { return null; } @@ -348,7 +360,10 @@ public class LauncherAppsService extends SystemService { @Override public IntentSender getShortcutConfigActivityIntent(String callingPackage, ComponentName component, UserHandle user) throws RemoteException { - ensureShortcutPermission(callingPackage, user); + ensureShortcutPermission(callingPackage); + if (!canAccessProfile(callingPackage, user, "Cannot check package")) { + return null; + } Preconditions.checkNotNull(component); Preconditions.checkArgument(isUserEnabled(user), "User not enabled"); @@ -356,11 +371,11 @@ public class LauncherAppsService extends SystemService { Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component); final long identity = Binder.clearCallingIdentity(); try { - return PendingIntent.getActivityAsUser( + final PendingIntent pi = PendingIntent.getActivityAsUser( mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT, - null, user) - .getIntentSender(); + null, user); + return pi == null ? null : pi.getIntentSender(); } finally { Binder.restoreCallingIdentity(identity); } @@ -369,7 +384,9 @@ public class LauncherAppsService extends SystemService { @Override public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user) throws RemoteException { - ensureInUserProfiles(callingPackage, user, "Cannot check package"); + if (!canAccessProfile(callingPackage, user, "Cannot check package")) { + return false; + } if (!isUserEnabled(user)) { return false; } @@ -391,7 +408,9 @@ public class LauncherAppsService extends SystemService { public ApplicationInfo getApplicationInfo( String callingPackage, String packageName, int flags, UserHandle user) throws RemoteException { - ensureInUserProfiles(callingPackage, user, "Cannot check package"); + if (!canAccessProfile(callingPackage, user, "Cannot check package")) { + return null; + } if (!isUserEnabled(user)) { return null; } @@ -407,14 +426,8 @@ public class LauncherAppsService extends SystemService { } } - private void ensureShortcutPermission(@NonNull String callingPackage, UserHandle user) { - ensureShortcutPermission(callingPackage, user.getIdentifier()); - } - - private void ensureShortcutPermission(@NonNull String callingPackage, int userId) { + private void ensureShortcutPermission(@NonNull String callingPackage) { verifyCallingPackage(callingPackage); - ensureInUserProfiles(callingPackage, userId, "Cannot access shortcuts"); - if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(), callingPackage)) { throw new SecurityException("Caller can't access shortcut information"); @@ -424,10 +437,11 @@ public class LauncherAppsService extends SystemService { @Override public ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName, List shortcutIds, ComponentName componentName, int flags, - UserHandle user) { - ensureShortcutPermission(callingPackage, user); - if (!isUserEnabled(user)) { - return new ParceledListSlice<>(new ArrayList(0)); + UserHandle targetUser) { + ensureShortcutPermission(callingPackage); + if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts") + || !isUserEnabled(targetUser)) { + return new ParceledListSlice<>(Collections.EMPTY_LIST); } if (shortcutIds != null && packageName == null) { throw new IllegalArgumentException( @@ -438,44 +452,53 @@ public class LauncherAppsService extends SystemService { return new ParceledListSlice<>((List) mShortcutServiceInternal.getShortcuts(getCallingUserId(), callingPackage, changedSince, packageName, shortcutIds, - componentName, flags, user.getIdentifier())); + componentName, flags, targetUser.getIdentifier())); } @Override public void pinShortcuts(String callingPackage, String packageName, List ids, - UserHandle user) { - ensureShortcutPermission(callingPackage, user); - if (!isUserEnabled(user)) { + UserHandle targetUser) { + ensureShortcutPermission(callingPackage); + if (!canAccessProfile(callingPackage, targetUser, "Cannot pin shortcuts")) { + return; + } + if (!isUserEnabled(targetUser)) { throw new IllegalStateException("Cannot pin shortcuts for disabled profile " - + user); + + targetUser); } mShortcutServiceInternal.pinShortcuts(getCallingUserId(), - callingPackage, packageName, ids, user.getIdentifier()); + callingPackage, packageName, ids, targetUser.getIdentifier()); } @Override public int getShortcutIconResId(String callingPackage, String packageName, String id, - int userId) { - ensureShortcutPermission(callingPackage, userId); - if (!isUserEnabled(userId)) { + int targetUserId) { + ensureShortcutPermission(callingPackage); + if (!canAccessProfile(callingPackage, targetUserId, "Cannot access shortcuts")) { + return 0; + } + if (!isUserEnabled(targetUserId)) { return 0; } return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(), - callingPackage, packageName, id, userId); + callingPackage, packageName, id, targetUserId); } @Override public ParcelFileDescriptor getShortcutIconFd(String callingPackage, - String packageName, String id, int userId) { - ensureShortcutPermission(callingPackage, userId); - if (!isUserEnabled(userId)) { + String packageName, String id, int targetUserId) { + ensureShortcutPermission(callingPackage); + if (!canAccessProfile(callingPackage, targetUserId, "Cannot access shortcuts")) { + return null; + } + if (!isUserEnabled(targetUserId)) { return null; } return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(), - callingPackage, packageName, id, userId); + callingPackage, packageName, id, targetUserId); } @Override @@ -487,23 +510,27 @@ public class LauncherAppsService extends SystemService { @Override public boolean startShortcut(String callingPackage, String packageName, String shortcutId, - Rect sourceBounds, Bundle startActivityOptions, int userId) { + Rect sourceBounds, Bundle startActivityOptions, int targetUserId) { verifyCallingPackage(callingPackage); - ensureInUserProfiles(callingPackage, userId, "Cannot start activity"); - - if (!isUserEnabled(userId)) { + if (!canAccessProfile(callingPackage, targetUserId, "Cannot start activity")) { + return false; + } + if (!canAccessProfile(callingPackage, targetUserId, "Cannot access shortcuts")) { + return false; + } + if (!isUserEnabled(targetUserId)) { throw new IllegalStateException("Cannot start a shortcut for disabled profile " - + userId); + + targetUserId); } // Even without the permission, pinned shortcuts are always launchable. if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(), - callingPackage, packageName, shortcutId, userId)) { - ensureShortcutPermission(callingPackage, userId); + callingPackage, packageName, shortcutId, targetUserId)) { + ensureShortcutPermission(callingPackage); } final Intent[] intents = mShortcutServiceInternal.createShortcutIntents( - getCallingUserId(), callingPackage, packageName, shortcutId, userId); + getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId); if (intents == null || intents.length == 0) { return false; } @@ -513,7 +540,7 @@ public class LauncherAppsService extends SystemService { intents[0].setSourceBounds(sourceBounds); return startShortcutIntentsAsPublisher( - intents, packageName, startActivityOptions, userId); + intents, packageName, startActivityOptions, targetUserId); } private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents, @@ -543,7 +570,9 @@ public class LauncherAppsService extends SystemService { public boolean isActivityEnabled( String callingPackage, ComponentName component, UserHandle user) throws RemoteException { - ensureInUserProfiles(callingPackage , user, "Cannot check component"); + if (!canAccessProfile(callingPackage , user, "Cannot check component")) { + return false; + } if (!isUserEnabled(user)) { return false; } @@ -565,7 +594,9 @@ public class LauncherAppsService extends SystemService { public void startActivityAsUser(String callingPackage, ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException { - ensureInUserProfiles(callingPackage, user, "Cannot start activity"); + if (!canAccessProfile(callingPackage, user, "Cannot start activity")) { + return; + } if (!isUserEnabled(user)) { throw new IllegalStateException("Cannot start activity for disabled profile " + user); } @@ -618,7 +649,9 @@ public class LauncherAppsService extends SystemService { @Override public void showAppDetailsAsUser(String callingPackage, ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException { - ensureInUserProfiles(callingPackage, user, "Cannot show app details"); + if (!canAccessProfile(callingPackage, user, "Cannot show app details")) { + return; + } if (!isUserEnabled(user)) { throw new IllegalStateException("Cannot show app details for disabled profile " + user); @@ -642,9 +675,13 @@ public class LauncherAppsService extends SystemService { private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, String debugMsg) { if (user.getIdentifier() == listeningUser.getIdentifier()) { - if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg); + if (DEBUG) Log.d(TAG, "Delivering msg to same user: " + debugMsg); return true; } + if (mUm.isManagedProfile(listeningUser.getIdentifier())) { + if (DEBUG) Log.d(TAG, "Managed profile can't see other profiles: " + debugMsg); + return false; + } long ident = injectClearCallingIdentity(); try { UserInfo userInfo = mUm.getUserInfo(user.getIdentifier()); diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index 8c23a91d427fb..e2e18447a709e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -602,12 +602,14 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected static final int USER_0 = UserHandle.USER_SYSTEM; protected static final int USER_10 = 10; protected static final int USER_11 = 11; - protected static final int USER_P0 = 20; // profile of user 0 + protected static final int USER_P0 = 20; // profile of user 0 (MANAGED_PROFILE *not* set) + protected static final int USER_P1 = 21; // another profile of user 0 (MANAGED_PROFILE set) protected static final UserHandle HANDLE_USER_0 = UserHandle.of(USER_0); protected static final UserHandle HANDLE_USER_10 = UserHandle.of(USER_10); protected static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11); protected static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0); + protected static final UserHandle HANDLE_USER_P1 = UserHandle.of(USER_P1); protected static final UserInfo USER_INFO_0 = withProfileGroupId( new UserInfo(USER_0, "user0", @@ -630,6 +632,10 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { protected static final UserInfo USER_INFO_P0 = withProfileGroupId( new UserInfo(USER_P0, "userP0", UserInfo.FLAG_INITIALIZED), 0); + protected static final UserInfo USER_INFO_P1 = withProfileGroupId( + new UserInfo(USER_P1, "userP1", + UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_MANAGED_PROFILE), 0); + protected BiPredicate mDefaultLauncherChecker = (callingPackage, userId) -> LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage) @@ -746,6 +752,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { mUserInfos.put(USER_10, USER_INFO_10); mUserInfos.put(USER_11, USER_INFO_11); mUserInfos.put(USER_P0, USER_INFO_P0); + mUserInfos.put(USER_P1, USER_INFO_P1); // Set up isUserRunning and isUserUnlocked. when(mMockUserManager.isUserRunning(anyInt())).thenAnswer(new AnswerWithSystemCheck<>( @@ -775,6 +782,13 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { assertNotNull(parent); return parent; })); + when(mMockUserManager.isManagedProfile(anyInt())) + .thenAnswer(new AnswerWithSystemCheck<>(inv -> { + final int userId = (Integer) inv.getArguments()[0]; + final UserInfo ui = mUserInfos.get(userId); + assertNotNull(ui); + return ui.isManagedProfile(); + })); when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn( ActivityManager.PROCESS_STATE_CACHED_EMPTY); @@ -784,12 +798,14 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { mRunningUsers.put(USER_10, false); mRunningUsers.put(USER_11, false); mRunningUsers.put(USER_P0, true); + mRunningUsers.put(USER_P1, true); // Unlock all users by default. mUnlockedUsers.put(USER_0, true); mUnlockedUsers.put(USER_10, true); mUnlockedUsers.put(USER_11, true); mUnlockedUsers.put(USER_P0, true); + mUnlockedUsers.put(USER_P1, true); // Set up resources setUpAppResources(); diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index 74c1ca5015c8a..980aa2d34c79d 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -2099,6 +2099,24 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { list("s1", "s2", "s3"), HANDLE_USER_10); }); + // First, make sure managed profile can't see other profiles. + runWithCaller(LAUNCHER_1, USER_P1, () -> { + + final ShortcutQuery q = new ShortcutQuery().setQueryFlags( + ShortcutQuery.FLAG_MATCH_DYNAMIC | ShortcutQuery.FLAG_MATCH_PINNED + | ShortcutQuery.FLAG_MATCH_MANIFEST); + + // No shortcuts are visible. + assertWith(mLauncherApps.getShortcuts(q, HANDLE_USER_0)).isEmpty(); + + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0); + + // Should have no effects. + assertWith(mLauncherApps.getShortcuts(q, HANDLE_USER_0)).isEmpty(); + + assertShortcutNotLaunched(CALLING_PACKAGE_1, "s1", USER_0); + }); + // Cross profile pinning. final int PIN_AND_DYNAMIC = ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC; @@ -2930,6 +2948,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { final LauncherApps.Callback c0_4 = mock(LauncherApps.Callback.class); final LauncherApps.Callback cP0_1 = mock(LauncherApps.Callback.class); + final LauncherApps.Callback cP1_1 = mock(LauncherApps.Callback.class); final LauncherApps.Callback c10_1 = mock(LauncherApps.Callback.class); final LauncherApps.Callback c10_2 = mock(LauncherApps.Callback.class); final LauncherApps.Callback c11_1 = mock(LauncherApps.Callback.class); @@ -2943,6 +2962,8 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { return LAUNCHER_2.equals(pkg); case USER_P0: return LAUNCHER_1.equals(pkg); + case USER_P1: + return LAUNCHER_1.equals(pkg); case USER_10: return LAUNCHER_1.equals(pkg); case USER_11: @@ -2957,6 +2978,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { runWithCaller(LAUNCHER_3, USER_0, () -> mLauncherApps.registerCallback(c0_3, h)); runWithCaller(LAUNCHER_4, USER_0, () -> mLauncherApps.registerCallback(c0_4, h)); runWithCaller(LAUNCHER_1, USER_P0, () -> mLauncherApps.registerCallback(cP0_1, h)); + runWithCaller(LAUNCHER_1, USER_P1, () -> mLauncherApps.registerCallback(cP1_1, h)); runWithCaller(LAUNCHER_1, USER_10, () -> mLauncherApps.registerCallback(c10_1, h)); runWithCaller(LAUNCHER_2, USER_10, () -> mLauncherApps.registerCallback(c10_2, h)); runWithCaller(LAUNCHER_1, USER_11, () -> mLauncherApps.registerCallback(c11_1, h)); @@ -2977,6 +2999,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { assertCallbackNotReceived(c11_1); assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3"); assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4"); + assertCallbackNotReceived(cP1_1); // User 0, different package. @@ -2995,6 +3018,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { assertCallbackReceived(c0_2, HANDLE_USER_0, CALLING_PACKAGE_3, "s1", "s2", "s3", "s4"); assertCallbackReceived(cP0_1, HANDLE_USER_0, CALLING_PACKAGE_3, "s1", "s2", "s3", "s4", "s5", "s6"); + assertCallbackNotReceived(cP1_1); // Work profile. resetAll(all); @@ -3011,6 +3035,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { assertCallbackNotReceived(c11_1); assertCallbackReceived(c0_2, HANDLE_USER_P0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s5"); assertCallbackReceived(cP0_1, HANDLE_USER_P0, CALLING_PACKAGE_1, "s1", "s2", "s3", "s4"); + assertCallbackNotReceived(cP1_1); // Normal secondary user. mRunningUsers.put(USER_10, true); @@ -3030,6 +3055,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { assertCallbackNotReceived(c11_1); assertCallbackReceived(c10_1, HANDLE_USER_10, CALLING_PACKAGE_1, "x1", "x2", "x3", "x4", "x5"); + assertCallbackNotReceived(cP1_1); } // === Test for persisting ===