Merge "ShortcutManager: Fix work profile" into nyc-dev
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 4255582..d57f2e6e 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -40,28 +40,37 @@
     }
 
     public abstract List<ShortcutInfo>
-            getShortcuts(@NonNull String callingPackage, long changedSince,
+            getShortcuts(int launcherUserId,
+            @NonNull String callingPackage, long changedSince,
             @Nullable String packageName, @Nullable ComponentName componentName,
             @ShortcutQuery.QueryFlags int flags,
             int userId);
 
     public abstract List<ShortcutInfo>
-            getShortcutInfo(@NonNull String callingPackage,
+            getShortcutInfo(int launcherUserId, @NonNull String callingPackage,
             @NonNull String packageName, @Nullable List<String> ids, int userId);
 
-    public abstract void pinShortcuts(@NonNull String callingPackage, @NonNull String packageName,
+
+    public abstract boolean
+            isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
+            @NonNull String packageName, @NonNull String id, int userId);
+
+    public abstract void pinShortcuts(int launcherUserId,
+            @NonNull String callingPackage, @NonNull String packageName,
             @NonNull List<String> shortcutIds, int userId);
 
-    public abstract Intent createShortcutIntent(@NonNull String callingPackage,
+    public abstract Intent createShortcutIntent(int launcherUserId, @NonNull String callingPackage,
             @NonNull String packageName, @NonNull String shortcutId, int userId);
 
     public abstract void addListener(@NonNull ShortcutChangeListener listener);
 
-    public abstract int getShortcutIconResId(@NonNull String callingPackage,
+    public abstract int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
             @NonNull ShortcutInfo shortcut, int userId);
 
-    public abstract ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
+    public abstract ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
+            @NonNull String callingPackage,
             @NonNull ShortcutInfo shortcut, int userId);
 
-    public abstract boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId);
+    public abstract boolean hasShortcutHostPermission(int launcherUserId,
+            @NonNull String callingPackage);
 }
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c303ceb..7c71fbc 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -335,40 +335,40 @@
             verifyCallingPackage(callingPackage);
             ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
 
-            if (!mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
-                    user.getIdentifier())) {
+            if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
+                    callingPackage)) {
                 throw new SecurityException("Caller can't access shortcut information");
             }
         }
 
         @Override
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
-                String packageName, ComponentName componentName, int flags, UserHandle user)
-                throws RemoteException {
+                String packageName, ComponentName componentName, int flags, UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
 
             return new ParceledListSlice<>(
-                    mShortcutServiceInternal.getShortcuts(callingPackage, changedSince, packageName,
-                    componentName, flags, user.getIdentifier()));
+                    mShortcutServiceInternal.getShortcuts(getCallingUserId(),
+                            callingPackage, changedSince, packageName,
+                            componentName, flags, user.getIdentifier()));
         }
 
         @Override
         public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
-                List<String> ids, UserHandle user) throws RemoteException {
+                List<String> ids, UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
 
             return new ParceledListSlice<>(
-                    mShortcutServiceInternal.getShortcutInfo(callingPackage, packageName,
-                    ids, user.getIdentifier()));
+                    mShortcutServiceInternal.getShortcutInfo(getCallingUserId(),
+                            callingPackage, packageName, ids, user.getIdentifier()));
         }
 
         @Override
         public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
-                UserHandle user) throws RemoteException {
+                UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
 
-            mShortcutServiceInternal.pinShortcuts(callingPackage, packageName,
-                    ids, user.getIdentifier());
+            mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
+                    callingPackage, packageName, ids, user.getIdentifier());
         }
 
         @Override
@@ -376,8 +376,8 @@
                 UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
 
-            return mShortcutServiceInternal.getShortcutIconResId(callingPackage, shortcut,
-                    user.getIdentifier());
+            return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
+                    callingPackage, shortcut, user.getIdentifier());
         }
 
         @Override
@@ -385,25 +385,31 @@
                 UserHandle user) {
             ensureShortcutPermission(callingPackage, user);
 
-            return mShortcutServiceInternal.getShortcutIconFd(callingPackage, shortcut,
-                    user.getIdentifier());
+            return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
+                    callingPackage, shortcut, user.getIdentifier());
         }
 
         @Override
-        public boolean hasShortcutHostPermission(String callingPackage) throws RemoteException {
+        public boolean hasShortcutHostPermission(String callingPackage) {
             verifyCallingPackage(callingPackage);
-            return mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
-                    getCallingUserId());
+            return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
+                    callingPackage);
         }
 
         @Override
         public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
-                Rect sourceBounds, Bundle startActivityOptions, UserHandle user)
-                throws RemoteException {
-            ensureShortcutPermission(callingPackage, user);
+                Rect sourceBounds, Bundle startActivityOptions, UserHandle user) {
+            verifyCallingPackage(callingPackage);
+            ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
 
-            final Intent intent = mShortcutServiceInternal.createShortcutIntent(callingPackage,
-                    packageName, shortcutId, user.getIdentifier());
+            // Even without the permission, pinned shortcuts are always launchable.
+            if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
+                    callingPackage, packageName, shortcutId, user.getIdentifier())) {
+                ensureShortcutPermission(callingPackage, user);
+            }
+
+            final Intent intent = mShortcutServiceInternal.createShortcutIntent(getCallingUserId(),
+                    callingPackage, packageName, shortcutId, user.getIdentifier());
             if (intent == null) {
                 return false;
             }
@@ -713,9 +719,11 @@
                     BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
                     if (!isEnabledProfileOf(user, cookie.user, "onShortcutChanged")) continue;
 
+                    final int launcherUserId = cookie.user.getIdentifier();
+
                     // Make sure the caller has the permission.
-                    if (!mShortcutServiceInternal.hasShortcutHostPermission(cookie.packageName,
-                            cookie.user.getIdentifier())) {
+                    if (!mShortcutServiceInternal.hasShortcutHostPermission(
+                            launcherUserId, cookie.packageName)) {
                         continue;
                     }
                     // Each launcher has a different set of pinned shortcuts, so we need to do a
@@ -723,8 +731,9 @@
                     // (As of now, only one launcher has the permission at a time, so it's bit
                     // moot, but we may change the permission model eventually.)
                     final List<ShortcutInfo> list =
-                            mShortcutServiceInternal.getShortcuts(cookie.packageName,
-                            /* changedSince= */ 0, packageName, /* component= */ null,
+                            mShortcutServiceInternal.getShortcuts(launcherUserId,
+                                    cookie.packageName,
+                                    /* changedSince= */ 0, packageName, /* component= */ null,
                                     ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
                                     | ShortcutQuery.FLAG_GET_PINNED
                                     | ShortcutQuery.FLAG_GET_DYNAMIC
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
index 740a8f7..b759e16 100644
--- a/services/core/java/com/android/server/pm/ShortcutLauncher.java
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -40,6 +40,7 @@
     private static final String TAG_PACKAGE = "package";
     private static final String TAG_PIN = "pin";
 
+    private static final String ATTR_LAUNCHER_USER_ID = "launcher-user";
     private static final String ATTR_VALUE = "value";
     private static final String ATTR_PACKAGE_NAME = "package-name";
 
@@ -49,14 +50,19 @@
     @NonNull
     private final String mPackageName;
 
+    @UserIdInt
+    private final int mLauncherUserId;
+
     /**
      * Package name -> IDs.
      */
     final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
 
-    ShortcutLauncher(@UserIdInt int userId, @NonNull String packageName) {
+    ShortcutLauncher(@UserIdInt int userId, @NonNull String packageName,
+            @UserIdInt int launcherUserId) {
         mUserId = userId;
         mPackageName = packageName;
+        mLauncherUserId = launcherUserId;
     }
 
     @UserIdInt
@@ -64,6 +70,11 @@
         return mUserId;
     }
 
+    @UserIdInt
+    public int getLauncherUserId() {
+        return mLauncherUserId;
+    }
+
     @NonNull
     public String getPackageName() {
         return mPackageName;
@@ -120,8 +131,8 @@
         }
 
         out.startTag(null, TAG_ROOT);
-        ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
-                mPackageName);
+        ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, mPackageName);
+        ShortcutService.writeAttr(out, ATTR_LAUNCHER_USER_ID, mLauncherUserId);
 
         for (int i = 0; i < size; i++) {
             out.startTag(null, TAG_PACKAGE);
@@ -142,12 +153,15 @@
     /**
      * Load.
      */
-    public static ShortcutLauncher loadFromXml(XmlPullParser parser, int userId)
+    public static ShortcutLauncher loadFromXml(XmlPullParser parser, int ownerUserId)
             throws IOException, XmlPullParserException {
         final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
                 ATTR_PACKAGE_NAME);
+        final int launcherUserId = ShortcutService.parseIntAttribute(parser,
+                ATTR_LAUNCHER_USER_ID, ownerUserId);
 
-        final ShortcutLauncher ret = new ShortcutLauncher(userId, launcherPackageName);
+        final ShortcutLauncher ret = new ShortcutLauncher(launcherUserId, launcherPackageName,
+                launcherUserId);
 
         ArraySet<String> ids = null;
         final int outerDepth = parser.getDepth();
@@ -184,6 +198,8 @@
         pw.print(prefix);
         pw.print("Launcher: ");
         pw.print(mPackageName);
+        pw.print("  UserId: ");
+        pw.print(mLauncherUserId);
         pw.println();
 
         final int size = mPinnedShortcuts.size();
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 359ea1c..e4d5787 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -104,6 +104,9 @@
         return mPackageName;
     }
 
+    /**
+     * Note this does *not* provide a correct view to the calling launcher.
+     */
     @Nullable
     public ShortcutInfo findShortcutById(String id) {
         return mShortcuts.get(id);
@@ -229,8 +232,8 @@
         }
 
         // Then, for the pinned set for each launcher, set the pin flag one by one.
-        final ArrayMap<String, ShortcutLauncher> launchers =
-                s.getUserShortcutsLocked(mUserId).getLaunchers();
+        final ArrayMap<ShortcutUser.PackageWithUser, ShortcutLauncher> launchers =
+                s.getUserShortcutsLocked(mUserId).getAllLaunchers();
 
         for (int l = launchers.size() - 1; l >= 0; l--) {
             final ShortcutLauncher launcherShortcuts = launchers.valueAt(l);
@@ -301,12 +304,24 @@
      * Find all shortcuts that match {@code query}.
      */
     public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
+            @Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
+        findAll(s, result, query, cloneFlag, null, 0);
+    }
+
+    /**
+     * Find all shortcuts that match {@code query}.
+     *
+     * This will also provide a "view" for each launcher -- a non-dynamic shortcut that's not pinned
+     * by the calling launcher will not be included in the result, and also "isPinned" will be
+     * adjusted for the caller too.
+     */
+    public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
             @Nullable Predicate<ShortcutInfo> query, int cloneFlag,
-            @Nullable String callingLauncher) {
+            @Nullable String callingLauncher, int launcherUserId) {
 
         // Set of pinned shortcuts by the calling launcher.
         final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
-                : s.getLauncherShortcuts(callingLauncher, mUserId)
+                : s.getLauncherShortcuts(callingLauncher, mUserId, launcherUserId)
                     .getPinnedShortcutIds(mPackageName);
 
         for (int i = 0; i < mShortcuts.size(); i++) {
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
index 98dc608..ab45689 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageInfo.java
@@ -48,6 +48,7 @@
     private static final String TAG = ShortcutService.TAG;
 
     static final String TAG_ROOT = "package-info";
+    private static final String ATTR_USER_ID = "user";
     private static final String ATTR_NAME = "name";
     private static final String ATTR_VERSION = "version";
     private static final String ATTR_SHADOW = "shadow";
@@ -55,11 +56,8 @@
     private static final String TAG_SIGNATURE = "signature";
     private static final String ATTR_SIGNATURE_HASH = "hash";
 
-    public interface ShortcutPackageInfoHolder {
-        ShortcutPackageInfo getShortcutPackageInfo();
-    }
-
     private final String mPackageName;
+    private final int mUserId;
 
     /**
      * When true, this package information was restored from the previous device, and the app hasn't
@@ -69,12 +67,13 @@
     private int mVersionCode;
     private ArrayList<byte[]> mSigHashes;
 
-    private ShortcutPackageInfo(String packageName, int versionCode, ArrayList<byte[]> sigHashes,
-            boolean isShadow) {
+    private ShortcutPackageInfo(String packageName, int userId,
+            int versionCode, ArrayList<byte[]> sigHashes, boolean isShadow) {
+        mPackageName = Preconditions.checkNotNull(packageName);
+        mUserId = userId;
         mVersionCode = versionCode;
         mIsShadow = isShadow;
         mSigHashes = sigHashes;
-        mPackageName = Preconditions.checkNotNull(packageName);
     }
 
     @NonNull
@@ -82,6 +81,10 @@
         return mPackageName;
     }
 
+    public int getUserId() {
+        return mUserId;
+    }
+
     public boolean isShadow() {
         return mIsShadow;
     }
@@ -197,7 +200,7 @@
             Slog.e(TAG, "Can't get signatures: package=" + packageName);
             return null;
         }
-        final ShortcutPackageInfo ret = new ShortcutPackageInfo(packageName, pi.versionCode,
+        final ShortcutPackageInfo ret = new ShortcutPackageInfo(packageName, userId, pi.versionCode,
                 hashSignatureArray(pi.signatures), /* shadow=*/ false);
 
         return ret;
@@ -221,6 +224,7 @@
         out.startTag(null, TAG_ROOT);
 
         ShortcutService.writeAttr(out, ATTR_NAME, mPackageName);
+        ShortcutService.writeAttr(out, ATTR_USER_ID, mUserId);
         ShortcutService.writeAttr(out, ATTR_VERSION, mVersionCode);
         ShortcutService.writeAttr(out, ATTR_SHADOW, mIsShadow);
 
@@ -232,10 +236,11 @@
         out.endTag(null, TAG_ROOT);
     }
 
-    public static ShortcutPackageInfo loadFromXml(XmlPullParser parser)
+    public static ShortcutPackageInfo loadFromXml(XmlPullParser parser, int ownerUserId)
             throws IOException, XmlPullParserException {
 
         final String packageName = ShortcutService.parseStringAttribute(parser, ATTR_NAME);
+        final int userId = ShortcutService.parseIntAttribute(parser, ATTR_USER_ID, ownerUserId);
         final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION);
         final boolean shadow = ShortcutService.parseBooleanAttribute(parser, ATTR_SHADOW);
 
@@ -261,7 +266,7 @@
             }
             throw ShortcutService.throwForInvalidTag(depth, tag);
         }
-        return new ShortcutPackageInfo(packageName, versionCode, hashes, shadow);
+        return new ShortcutPackageInfo(packageName, userId, versionCode, hashes, shadow);
     }
 
     public void dump(ShortcutService s, PrintWriter pw, String prefix) {
@@ -273,6 +278,11 @@
         pw.println();
 
         pw.print(prefix);
+        pw.print("  User: ");
+        pw.print(mUserId);
+        pw.println();
+
+        pw.print(prefix);
         pw.print("  IsShadow: ");
         pw.print(mIsShadow);
         pw.println();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 373e8cb..cf11025 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -31,7 +31,6 @@
 import android.content.pm.LauncherApps.ShortcutQuery;
 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.ParceledListSlice;
 import android.content.pm.ResolveInfo;
@@ -78,6 +77,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.ShortcutUser.PackageWithUser;
 
 import libcore.io.IoUtils;
 
@@ -104,14 +104,9 @@
  *
  * - Default launcher check does take a few ms.  Worth caching.
  *
- * - Allow non-default launcher to start pinned shortcuts. (but not dynamic.)
+ * - Don't backup launcher from different profile.
  *
- * - Extract the user/package/launcher classes to their own files.  Maybe rename so they all have
- *   the same "Shortcut" prefix.
- *
- * - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
- *   -> Need to scan all packages when a user starts too.
- *   -> Clear data -> remove all dynamic?  but not the pinned?
+ * - Clear data -> remove all dynamic?  but not the pinned?
  *
  * - Scan and remove orphan bitmaps (just in case).
  *
@@ -455,16 +450,24 @@
         return (int) parseLongAttribute(parser, attribute);
     }
 
+    static int parseIntAttribute(XmlPullParser parser, String attribute, int def) {
+        return (int) parseLongAttribute(parser, attribute, def);
+    }
+
     static long parseLongAttribute(XmlPullParser parser, String attribute) {
+        return parseLongAttribute(parser, attribute, 0);
+    }
+
+    static long parseLongAttribute(XmlPullParser parser, String attribute, long def) {
         final String value = parseStringAttribute(parser, attribute);
         if (TextUtils.isEmpty(value)) {
-            return 0;
+            return def;
         }
         try {
             return Long.parseLong(value);
         } catch (NumberFormatException e) {
             Slog.e(TAG, "Error parsing long " + value);
-            return 0;
+            return def;
         }
     }
 
@@ -825,8 +828,8 @@
     @GuardedBy("mLock")
     @NonNull
     ShortcutLauncher getLauncherShortcuts(
-            @NonNull String packageName, @UserIdInt int userId) {
-        return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName);
+            @NonNull String packageName, @UserIdInt int userId, @UserIdInt int launcherUserId) {
+        return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName, launcherUserId);
     }
 
     // === Caller validation ===
@@ -1324,8 +1327,7 @@
 
         final ArrayList<ShortcutInfo> ret = new ArrayList<>();
 
-        getPackageShortcutsLocked(packageName, userId).findAll(this, ret, query, cloneFlags,
-                /* callingLauncher= */ null);
+        getPackageShortcutsLocked(packageName, userId).findAll(this, ret, query, cloneFlags);
 
         return new ParceledListSlice<>(ret);
     }
@@ -1463,22 +1465,26 @@
     // === House keeping ===
 
     @VisibleForTesting
-    void cleanUpPackageLocked(String packageName, int userId) {
-        final boolean wasUserLoaded = isUserLoadedLocked(userId);
+    void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
+        final boolean wasUserLoaded = isUserLoadedLocked(owningUserId);
 
-        final ShortcutUser mUser = getUserShortcutsLocked(userId);
+        final ShortcutUser mUser = getUserShortcutsLocked(owningUserId);
         boolean doNotify = false;
 
         // First, remove the package from the package list (if the package is a publisher).
-        if (mUser.getPackages().remove(packageName) != null) {
-            doNotify = true;
+        if (packageUserId == owningUserId) {
+            if (mUser.getPackages().remove(packageName) != null) {
+                doNotify = true;
+            }
         }
+
         // Also remove from the launcher list (if the package is a launcher).
-        mUser.getLaunchers().remove(packageName);
+        mUser.removeLauncher(packageUserId, packageName);
 
         // Then remove pinned shortcuts from all launchers.
-        for (int i = mUser.getLaunchers().size() - 1; i >= 0; i--) {
-            mUser.getLaunchers().valueAt(i).cleanUpPackage(packageName);
+        final ArrayMap<PackageWithUser, ShortcutLauncher> launchers = mUser.getAllLaunchers();
+        for (int i = launchers.size() - 1; i >= 0; i--) {
+            launchers.valueAt(i).cleanUpPackage(packageName);
         }
         // Now there may be orphan shortcuts because we removed pinned shortucts at the previous
         // step.  Remove them too.
@@ -1487,17 +1493,17 @@
         }
 
         // Remove the package info too.
-        mUser.getPackageInfos().remove(packageName);
+        mUser.removePackageInfo(packageUserId, packageName);
 
-        scheduleSaveUser(userId);
+        scheduleSaveUser(owningUserId);
 
         if (doNotify) {
-            notifyListeners(packageName, userId);
+            notifyListeners(packageName, owningUserId);
         }
 
         if (!wasUserLoaded) {
             // Note this will execute the scheduled save.
-            unloadUserLocked(userId);
+            unloadUserLocked(owningUserId);
         }
     }
 
@@ -1506,7 +1512,7 @@
      */
     private class LocalService extends ShortcutServiceInternal {
         @Override
-        public List<ShortcutInfo> getShortcuts(
+        public List<ShortcutInfo> getShortcuts(int launcherUserId,
                 @NonNull String callingPackage, long changedSince,
                 @Nullable String packageName, @Nullable ComponentName componentName,
                 int queryFlags, int userId) {
@@ -1518,14 +1524,14 @@
 
             synchronized (mLock) {
                 if (packageName != null) {
-                    getShortcutsInnerLocked(
+                    getShortcutsInnerLocked(launcherUserId,
                             callingPackage, packageName, changedSince,
                             componentName, queryFlags, userId, ret, cloneFlag);
                 } else {
                     final ArrayMap<String, ShortcutPackage> packages =
                             getUserShortcutsLocked(userId).getPackages();
                     for (int i = packages.size() - 1; i >= 0; i--) {
-                        getShortcutsInnerLocked(
+                        getShortcutsInnerLocked(launcherUserId,
                                 callingPackage, packages.keyAt(i), changedSince,
                                 componentName, queryFlags, userId, ret, cloneFlag);
                     }
@@ -1534,7 +1540,7 @@
             return ret;
         }
 
-        private void getShortcutsInnerLocked(@NonNull String callingPackage,
+        private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
                 @Nullable String packageName,long changedSince,
                 @Nullable ComponentName componentName, int queryFlags,
                 int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
@@ -1554,11 +1560,11 @@
                                 ((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0)
                                         && si.isPinned();
                         return matchDynamic || matchPinned;
-                    }, cloneFlag, callingPackage);
+                    }, cloneFlag, callingPackage, launcherUserId);
         }
 
         @Override
-        public List<ShortcutInfo> getShortcutInfo(
+        public List<ShortcutInfo> getShortcutInfo(int launcherUserId,
                 @NonNull String callingPackage,
                 @NonNull String packageName, @Nullable List<String> ids, int userId) {
             // Calling permission must be checked by LauncherAppsImpl.
@@ -1570,13 +1576,41 @@
                 getPackageShortcutsLocked(packageName, userId).findAll(
                         ShortcutService.this, ret,
                         (ShortcutInfo si) -> idSet.contains(si.getId()),
-                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage);
+                        ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage, launcherUserId);
             }
             return ret;
         }
 
         @Override
-        public void pinShortcuts(@NonNull String callingPackage, @NonNull String packageName,
+        public boolean isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
+                @NonNull String packageName, @NonNull String shortcutId, int userId) {
+            Preconditions.checkStringNotEmpty(packageName, "packageName");
+            Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
+
+            synchronized (mLock) {
+                final ShortcutInfo si = getShortcutInfoLocked(
+                        launcherUserId, callingPackage, packageName, shortcutId, userId);
+                return si != null && si.isPinned();
+            }
+        }
+
+        public ShortcutInfo getShortcutInfoLocked(
+                int launcherUserId, @NonNull String callingPackage,
+                @NonNull String packageName, @NonNull String shortcutId, int userId) {
+            Preconditions.checkStringNotEmpty(packageName, "packageName");
+            Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
+
+            final ArrayList<ShortcutInfo> list = new ArrayList<>(1);
+            getPackageShortcutsLocked(packageName, userId).findAll(
+                    ShortcutService.this, list,
+                    (ShortcutInfo si) -> shortcutId.equals(si.getId()),
+                    /* clone flags=*/ 0, callingPackage, launcherUserId);
+            return list.size() == 0 ? null : list.get(0);
+        }
+
+        @Override
+        public void pinShortcuts(int launcherUserId,
+                @NonNull String callingPackage, @NonNull String packageName,
                 @NonNull List<String> shortcutIds, int userId) {
             // Calling permission must be checked by LauncherAppsImpl.
             Preconditions.checkStringNotEmpty(packageName, "packageName");
@@ -1584,26 +1618,31 @@
 
             synchronized (mLock) {
                 getUserShortcutsLocked(userId).ensurePackageInfo(
-                        ShortcutService.this, callingPackage, userId);
+                        ShortcutService.this, callingPackage, launcherUserId);
 
-                getLauncherShortcuts(callingPackage, userId).pinShortcuts(
+                getLauncherShortcuts(callingPackage, userId, launcherUserId).pinShortcuts(
                         ShortcutService.this, packageName, shortcutIds);
             }
             userPackageChanged(packageName, userId);
         }
 
         @Override
-        public Intent createShortcutIntent(@NonNull String callingPackage,
+        public Intent createShortcutIntent(int launcherUserId,
+                @NonNull String callingPackage,
                 @NonNull String packageName, @NonNull String shortcutId, int userId) {
             // Calling permission must be checked by LauncherAppsImpl.
             Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty");
             Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
 
             synchronized (mLock) {
-                final ShortcutInfo fullShortcut =
-                        getPackageShortcutsLocked(packageName, userId)
-                        .findShortcutById(shortcutId);
-                return fullShortcut == null ? null : fullShortcut.getIntent();
+                // Make sure the shortcut is actually visible to the launcher.
+                final ShortcutInfo si = getShortcutInfoLocked(
+                        launcherUserId, callingPackage, packageName, shortcutId, userId);
+                // "si == null" should suffice here, but check the flags too just to make sure.
+                if (si == null || !(si.isDynamic() || si.isPinned())) {
+                    return null;
+                }
+                return si.getIntent();
             }
         }
 
@@ -1615,7 +1654,8 @@
         }
 
         @Override
-        public int getShortcutIconResId(@NonNull String callingPackage,
+        public int getShortcutIconResId(int launcherUserId,
+                @NonNull String callingPackage,
                 @NonNull ShortcutInfo shortcut, int userId) {
             Preconditions.checkNotNull(shortcut, "shortcut");
 
@@ -1628,7 +1668,8 @@
         }
 
         @Override
-        public ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
+        public ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
+                @NonNull String callingPackage,
                 @NonNull ShortcutInfo shortcutIn, int userId) {
             Preconditions.checkNotNull(shortcutIn, "shortcut");
 
@@ -1654,8 +1695,9 @@
         }
 
         @Override
-        public boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
-            return ShortcutService.this.hasShortcutHostPermission(callingPackage, userId);
+        public boolean hasShortcutHostPermission(int launcherUserId,
+                @NonNull String callingPackage) {
+            return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId);
         }
     }
 
@@ -1684,28 +1726,31 @@
      * Called when a user is unlocked.  Check all known packages still exist, and otherwise
      * perform cleanup.
      */
-    private void cleanupGonePackages(@UserIdInt int userId) {
+    @VisibleForTesting
+    void cleanupGonePackages(@UserIdInt int userId) {
         if (DEBUG) {
             Slog.d(TAG, "cleanupGonePackages() userId=" + userId);
         }
-        ArrayList<String> gonePackages = null;
+        ArrayList<PackageWithUser> gonePackages = null;
 
-        final ShortcutUser user = getUserShortcutsLocked(userId);
-        final ArrayMap<String, ShortcutPackageInfo> infos = user.getPackageInfos();
-        for (int i = infos.size() -1; i >= 0; i--) {
-            final ShortcutPackageInfo info = infos.valueAt(i);
-            if (info.isShadow()) {
-                continue;
+        synchronized (mLock) {
+            final ShortcutUser user = getUserShortcutsLocked(userId);
+            final ArrayMap<PackageWithUser, ShortcutPackageInfo> infos = user.getAllPackageInfos();
+            for (int i = infos.size() -1; i >= 0; i--) {
+                final ShortcutPackageInfo info = infos.valueAt(i);
+                if (info.isShadow()) {
+                    continue;
+                }
+                if (isPackageInstalled(info.getPackageName(), info.getUserId())) {
+                    continue;
+                }
+                gonePackages = ArrayUtils.add(gonePackages,
+                        PackageWithUser.of(info.getUserId(), info.getPackageName()));
             }
-            if (isPackageInstalled(info.getPackageName(), userId)) {
-                continue;
-            }
-            gonePackages = ArrayUtils.add(gonePackages, info.getPackageName());
-        }
-        if (gonePackages != null) {
-            synchronized (mLock) {
+            if (gonePackages != null) {
                 for (int i = gonePackages.size() - 1; i >= 0; i--) {
-                    cleanUpPackageLocked(gonePackages.get(i), userId);
+                    final PackageWithUser pu = gonePackages.get(i);
+                    cleanUpPackageLocked(pu.packageName, userId, pu.userId);
                 }
             }
         }
@@ -1716,9 +1761,8 @@
             Slog.d(TAG, String.format("handlePackageAdded: %s user=%d", packageName, userId));
         }
         synchronized (mLock) {
-            final ArrayMap<String, ShortcutPackageInfo> infos =
-                    getUserShortcutsLocked(userId).getPackageInfos();
-            final ShortcutPackageInfo existing = infos.get(packageName);
+            final ShortcutPackageInfo existing = getUserShortcutsLocked(userId)
+                    .getPackageInfo(userId, packageName);
 
             if (existing != null && existing.isShadow()) {
                 Slog.w(TAG, "handlePackageAdded: TODO Restore not implemented");
@@ -1732,7 +1776,7 @@
         }
         synchronized (mLock) {
             final ShortcutPackageInfo spi =
-                    getUserShortcutsLocked(userId).getPackageInfos().get(packageName);
+                    getUserShortcutsLocked(userId).getPackageInfo(userId, packageName);
             if (spi != null) {
                 spi.refreshAndSave(this, userId);
             }
@@ -1744,7 +1788,7 @@
             Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName, userId));
         }
         synchronized (mLock) {
-            cleanUpPackageLocked(packageName, userId);
+            cleanUpPackageLocked(packageName, userId, userId);
         }
     }
 
@@ -2161,11 +2205,16 @@
 
     @VisibleForTesting
     ShortcutPackageInfo getPackageInfoForTest(String packageName, int userId) {
+        return getPackageInfoForTest(packageName, userId, userId);
+    }
+
+    @VisibleForTesting
+    ShortcutPackageInfo getPackageInfoForTest(String packageName, int userId, int packageUserId) {
         synchronized (mLock) {
             final ShortcutUser user = mUsers.get(userId);
             if (user == null) return null;
 
-            return user.getPackageInfos().get(packageName);
+            return user.getPackageInfo(packageUserId, packageName);
         }
     }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
index 1a00cda..19feb2a 100644
--- a/services/core/java/com/android/server/pm/ShortcutUser.java
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -21,6 +21,8 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.internal.util.Preconditions;
+
 import libcore.util.Objects;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -41,14 +43,48 @@
 
     private static final String ATTR_VALUE = "value";
 
+    static final class PackageWithUser {
+        final int userId;
+        final String packageName;
+
+        private PackageWithUser(int userId, String packageName) {
+            this.userId = userId;
+            this.packageName = Preconditions.checkNotNull(packageName);
+        }
+
+        public static PackageWithUser of(int launcherUserId, String packageName) {
+            return new PackageWithUser(launcherUserId, packageName);
+        }
+
+        @Override
+        public int hashCode() {
+            return packageName.hashCode() ^ userId;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof PackageWithUser)) {
+                return false;
+            }
+            final PackageWithUser that = (PackageWithUser) obj;
+
+            return userId == that.userId && packageName.equals(that.packageName);
+        }
+
+        @Override
+        public String toString() {
+            return String.format("{Launcher: %d, %s}", userId, packageName);
+        }
+    }
+
     @UserIdInt
     final int mUserId;
 
     private final ArrayMap<String, ShortcutPackage> mPackages = new ArrayMap<>();
 
-    private final ArrayMap<String, ShortcutLauncher> mLaunchers = new ArrayMap<>();
+    private final ArrayMap<PackageWithUser, ShortcutLauncher> mLaunchers = new ArrayMap<>();
 
-    private final ArrayMap<String, ShortcutPackageInfo> mPackageInfos = new ArrayMap<>();
+    private final ArrayMap<PackageWithUser, ShortcutPackageInfo> mPackageInfos = new ArrayMap<>();
 
     private ComponentName mLauncherComponent;
 
@@ -60,14 +96,41 @@
         return mPackages;
     }
 
-    public ArrayMap<String, ShortcutLauncher> getLaunchers() {
+    public ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchers() {
         return mLaunchers;
     }
 
-    public ArrayMap<String, ShortcutPackageInfo> getPackageInfos() {
+    public ShortcutLauncher getLauncher(@UserIdInt int userId, @NonNull String packageName) {
+        return mLaunchers.get(PackageWithUser.of(userId, packageName));
+    }
+
+    public void addLauncher(ShortcutLauncher launcher) {
+        mLaunchers.put(PackageWithUser.of(launcher.getUserId(), launcher.getPackageName()),
+                launcher);
+    }
+
+    public ShortcutLauncher removeLauncher(
+            @UserIdInt int userId, @NonNull String packageName) {
+        return mLaunchers.remove(PackageWithUser.of(userId, packageName));
+    }
+
+    public ArrayMap<PackageWithUser, ShortcutPackageInfo> getAllPackageInfos() {
         return mPackageInfos;
     }
 
+    public ShortcutPackageInfo getPackageInfo(@UserIdInt int userId, @NonNull String packageName) {
+        return mPackageInfos.get(PackageWithUser.of(userId, packageName));
+    }
+
+    public void addPackageInfo(ShortcutPackageInfo spi) {
+        mPackageInfos.put(PackageWithUser.of(spi.getUserId(), spi.getPackageName()), spi);
+    }
+
+    public ShortcutPackageInfo removePackageInfo(
+            @UserIdInt int userId, @NonNull String packageName) {
+        return mPackageInfos.remove(PackageWithUser.of(userId, packageName));
+    }
+
     public ShortcutPackage getPackageShortcuts(@NonNull String packageName) {
         ShortcutPackage ret = mPackages.get(packageName);
         if (ret == null) {
@@ -77,17 +140,20 @@
         return ret;
     }
 
-    public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName) {
-        ShortcutLauncher ret = mLaunchers.get(packageName);
+    public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName,
+            @UserIdInt int launcherUserId) {
+        final PackageWithUser key = PackageWithUser.of(launcherUserId, packageName);
+        ShortcutLauncher ret = mLaunchers.get(key);
         if (ret == null) {
-            ret = new ShortcutLauncher(mUserId, packageName);
-            mLaunchers.put(packageName, ret);
+            ret = new ShortcutLauncher(mUserId, packageName, launcherUserId);
+            mLaunchers.put(key, ret);
         }
         return ret;
     }
 
     public void ensurePackageInfo(ShortcutService s, String packageName, @UserIdInt int userId) {
-        final ShortcutPackageInfo existing = mPackageInfos.get(packageName);
+        final PackageWithUser key = PackageWithUser.of(userId, packageName);
+        final ShortcutPackageInfo existing = mPackageInfos.get(key);
 
         if (existing != null) {
             return;
@@ -97,7 +163,7 @@
         }
         final ShortcutPackageInfo newSpi = ShortcutPackageInfo.generateForInstalledPackage(
                 s, packageName, userId);
-        mPackageInfos.put(packageName, newSpi);
+        mPackageInfos.put(key, newSpi);
         s.scheduleSaveUser(mUserId);
     }
 
@@ -166,18 +232,12 @@
                 }
 
                 case ShortcutLauncher.TAG_ROOT: {
-                    final ShortcutLauncher shortcuts =
-                            ShortcutLauncher.loadFromXml(parser, userId);
-
-                    ret.getLaunchers().put(shortcuts.getPackageName(), shortcuts);
+                    ret.addLauncher(ShortcutLauncher.loadFromXml(parser, userId));
                     continue;
                 }
 
                 case ShortcutPackageInfo.TAG_ROOT: {
-                    final ShortcutPackageInfo pi =
-                            ShortcutPackageInfo.loadFromXml(parser);
-
-                    ret.getPackageInfos().put(pi.getPackageName(), pi);
+                    ret.addPackageInfo(ShortcutPackageInfo.loadFromXml(parser, userId));
                     continue;
                 }
             }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index bd4ed16..61249ae 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -20,11 +20,14 @@
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.content.BroadcastReceiver;
@@ -72,6 +75,7 @@
 import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
 import com.android.server.pm.ShortcutService.ConfigConstants;
 import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
+import com.android.server.pm.ShortcutUser.PackageWithUser;
 
 import libcore.io.IoUtils;
 
@@ -118,7 +122,8 @@
      */
     private static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH true
 
-    private class BaseContext extends MockContext {
+    // public for mockito
+    public class BaseContext extends MockContext {
         @Override
         public Object getSystemService(String name) {
             switch (name) {
@@ -152,7 +157,7 @@
     }
 
     /** Context used in the client side */
-    private class ClientContext extends BaseContext {
+    public class ClientContext extends BaseContext {
         @Override
         public String getPackageName() {
             return mInjectedClientPackage;
@@ -160,7 +165,7 @@
     }
 
     /** Context used in the service side */
-    private final class ServiceContext extends BaseContext {
+    public class ServiceContext extends BaseContext {
         long injectClearCallingIdentity() {
             final int prevCallingUid = mInjectedCallingUid;
             mInjectedCallingUid = Process.SYSTEM_UID;
@@ -170,6 +175,11 @@
         void injectRestoreCallingIdentity(long token) {
             mInjectedCallingUid = (int) token;
         }
+
+        @Override
+        public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
+                UserHandle userId) {
+        }
     }
 
     /** ShortcutService with injection override methods. */
@@ -310,9 +320,17 @@
             if (getCallingUserId() == userToCheck.getIdentifier()) {
                 return; // okay
             }
+            if (getCallingUserId() == USER_0 && userToCheck.getIdentifier() == USER_P0) {
+                return; // profile, okay.
+            }
+            if (getCallingUserId() == USER_P0 && userToCheck.getIdentifier() == USER_0) {
+                return; // profile, okay.
+            }
 
-            assertEquals(Process.SYSTEM_UID, mInjectedCallingUid);
-            // SKIP
+            if (mInjectedCallingUid != Process.SYSTEM_UID) {
+                throw new SecurityException("To access other users, you need to be SYSTEM" +
+                        ", but current UID=" + mInjectedCallingUid);
+            }
         }
 
         @Override
@@ -333,6 +351,11 @@
             r.run();
             mContext.injectRestoreCallingIdentity(token);
         }
+
+        @Override
+        int injectBinderCallingUid() {
+            return mInjectedCallingUid;
+        }
     }
 
     private class LauncherAppsTestable extends LauncherApps {
@@ -371,6 +394,8 @@
 
     private Map<String, PackageInfo> mInjectedPackages;
 
+    private ArrayList<PackageWithUser> mUninstalledPackages;
+
     private PackageManager mMockPackageManager;
     private PackageManagerInternal mMockPackageManagerInternal;
     private UserManager mMockUserManager;
@@ -393,6 +418,13 @@
     private static final int USER_0 = UserHandle.USER_SYSTEM;
     private static final int USER_10 = 10;
     private static final int USER_11 = 11;
+    private static final int USER_P0 = 20; // profile of user 0
+
+    private static final UserHandle HANDLE_USER_0 = UserHandle.of(USER_0);
+    private static final UserHandle HANDLE_USER_10 = UserHandle.of(USER_10);
+    private static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11);
+    private static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0);
+
 
     private static final long START_TIME = 1440000000101L;
 
@@ -410,7 +442,7 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        mServiceContext = new ServiceContext();
+        mServiceContext = spy(new ServiceContext());
         mClientContext = new ClientContext();
 
         mMockPackageManager = mock(PackageManager.class);
@@ -428,6 +460,8 @@
         addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4);
         addPackage(LAUNCHER_2, LAUNCHER_UID_2, 5);
 
+        mUninstalledPackages = new ArrayList<>();
+
         mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files");
 
         // Empty the data directory.
@@ -466,6 +500,10 @@
         addPackage(packageName, uid, version, packageName);
     }
 
+    private <T> List<T> list(T... array) {
+        return Arrays.asList(array);
+    }
+
     private Signature[] genSignatures(String... signatures) {
         final Signature[] sigs = new Signature[signatures.length];
         for (int i = 0; i < signatures.length; i++){
@@ -491,6 +529,10 @@
         mInjectedPackages.put(packageName, genPackage(packageName, uid, version, signatures));
     }
 
+    private void uninstallPackage(int userId, String packageName) {
+        mUninstalledPackages.add(PackageWithUser.of(userId, packageName));
+    }
+
     PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId,
             boolean getSignatures) {
         final PackageInfo pi = mInjectedPackages.get(packageName);
@@ -501,6 +543,9 @@
         ret.versionCode = pi.versionCode;
         ret.applicationInfo = new ApplicationInfo(pi.applicationInfo);
         ret.applicationInfo.uid = UserHandle.getUid(userId, pi.applicationInfo.uid);
+        if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) {
+            ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+        }
 
         if (getSignatures) {
             ret.signatures = pi.signatures;
@@ -753,7 +798,7 @@
     private List<ShortcutInfo> assertShortcutIds(@NonNull List<ShortcutInfo> actualShortcuts,
             String... expectedIds) {
         assertEquals(expectedIds.length, actualShortcuts.size());
-        final HashSet<String> expected = new HashSet<>(Arrays.asList(expectedIds));
+        final HashSet<String> expected = new HashSet<>(list(expectedIds));
         final HashSet<String> actual = new HashSet<>();
         for (ShortcutInfo s : actualShortcuts) {
             actual.add(s.getId());
@@ -884,6 +929,21 @@
         return actualShortcuts;
     }
 
+    private void assertDynamicOnly(ShortcutInfo si) {
+        assertTrue(si.isDynamic());
+        assertFalse(si.isPinned());
+    }
+
+    private void assertPinnedOnly(ShortcutInfo si) {
+        assertFalse(si.isDynamic());
+        assertTrue(si.isPinned());
+    }
+
+    private void assertDynamicAndPinned(ShortcutInfo si) {
+        assertTrue(si.isDynamic());
+        assertTrue(si.isPinned());
+    }
+
     private void assertBitmapSize(int expectedWidth, int expectedHeight, @NonNull Bitmap bitmap) {
         assertEquals("width", expectedWidth, bitmap.getWidth());
         assertEquals("height", expectedHeight, bitmap.getHeight());
@@ -937,6 +997,39 @@
         assertTrue(getPackageShortcut(packageName, shortcutId, userId) == null);
     }
 
+    private Intent launchShortcutAndGetIntent(
+            @NonNull String packageName, @NonNull String shortcutId, int userId) {
+        reset(mServiceContext);
+        assertTrue(mLauncherApps.startShortcut(packageName, shortcutId, null, null,
+                UserHandle.of(userId)));
+
+        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mServiceContext).startActivityAsUser(
+                intentCaptor.capture(),
+                any(Bundle.class),
+                eq(UserHandle.of(userId)));
+        return intentCaptor.getValue();
+    }
+
+    private void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId,
+            int userId) {
+        assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId));
+    }
+
+    private void assertShortcutNotLaunchable(@NonNull String packageName,
+            @NonNull String shortcutId, int userId) {
+        try {
+            final boolean ok = mLauncherApps.startShortcut(packageName, shortcutId, null, null,
+                    UserHandle.of(userId));
+            if (!ok) {
+                return; // didn't launch, okay.
+            }
+            fail();
+        } catch (SecurityException expected) {
+            // security exception is okay too.
+        }
+    }
+
     private ShortcutInfo getPackageShortcut(String packageName, String shortcutId) {
         return getPackageShortcut(packageName, shortcutId, getCallingUserId());
     }
@@ -1130,7 +1223,7 @@
                 /* weight */ 12);
         final ShortcutInfo si3 = makeShortcut("shortcut3");
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
         assertShortcutIds(assertAllNotKeyFieldsOnly(
                 mManager.getDynamicShortcuts()),
                 "shortcut1", "shortcut2");
@@ -1143,13 +1236,13 @@
 
         // TODO: Check fields
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertShortcutIds(assertAllNotKeyFieldsOnly(
                 mManager.getDynamicShortcuts()),
                 "shortcut1");
         assertEquals(1, mManager.getRemainingCallCount());
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList()));
+        assertTrue(mManager.setDynamicShortcuts(list()));
         assertEquals(0, mManager.getDynamicShortcuts().size());
         assertEquals(0, mManager.getRemainingCallCount());
 
@@ -1160,13 +1253,13 @@
 
         dumpsysOnLogcat();
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2, si3)));
+        assertTrue(mManager.setDynamicShortcuts(list(si2, si3)));
         assertEquals(2, mManager.getDynamicShortcuts().size());
 
         // TODO Check max number
 
         runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(makeShortcut("s1"))));
+            assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))));
 
             assertShortcutPackageInfo(CALLING_PACKAGE_1, USER_0, 1);
             assertNoShortcutPackageInfo(CALLING_PACKAGE_2, USER_0);
@@ -1184,7 +1277,7 @@
 
         assertEquals(3, mManager.getRemainingCallCount());
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
         assertShortcutIds(assertAllNotKeyFieldsOnly(
                 mManager.getDynamicShortcuts()),
@@ -1218,7 +1311,7 @@
         final ShortcutInfo si2 = makeShortcut("shortcut2");
         final ShortcutInfo si3 = makeShortcut("shortcut3");
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
         assertShortcutIds(assertAllNotKeyFieldsOnly(
                 mManager.getDynamicShortcuts()),
                 "shortcut1", "shortcut2", "shortcut3");
@@ -1260,7 +1353,7 @@
         final ShortcutInfo si2 = makeShortcut("shortcut2");
         final ShortcutInfo si3 = makeShortcut("shortcut3");
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
         assertShortcutIds(assertAllNotKeyFieldsOnly(
                 mManager.getDynamicShortcuts()),
                 "shortcut1", "shortcut2", "shortcut3");
@@ -1277,7 +1370,7 @@
         assertEquals(0, mManager.getDynamicShortcuts().size());
 
         // This should still work.
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2, si3)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
         assertEquals(3, mManager.getDynamicShortcuts().size());
 
         // Still 1 call left
@@ -1289,62 +1382,62 @@
     public void testThrottling() {
         final ShortcutInfo si1 = makeShortcut("shortcut1");
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(1, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         // Reached the max
 
         mInjectedCurrentTimeLillis++;
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertFalse(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         // Still throttled
         mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertFalse(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
         // Now it should work.
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1))); // fail
+        assertTrue(mManager.setDynamicShortcuts(list(si1))); // fail
         assertEquals(2, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(1, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertFalse(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
 
         // 4 days later...
         mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(1, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
 
@@ -1354,7 +1447,7 @@
         assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
     }
@@ -1362,7 +1455,7 @@
     public void testThrottling_rewind() {
         final ShortcutInfo si1 = makeShortcut("shortcut1");
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
         assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
 
@@ -1381,7 +1474,7 @@
         mInjectedCurrentTimeLillis = START_TIME - 100000;
         assertEquals(3, mManager.getRemainingCallCount());
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
 
         // Forward again, should be reset now.
@@ -1392,21 +1485,21 @@
     public void testThrottling_perPackage() {
         final ShortcutInfo si1 = makeShortcut("shortcut1");
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(2, mManager.getRemainingCallCount());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(1, mManager.getRemainingCallCount());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
 
         // Reached the max
 
         mInjectedCurrentTimeLillis++;
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertFalse(mManager.setDynamicShortcuts(list(si1)));
 
         // Try from a different caller.
         mInjectedClientPackage = CALLING_PACKAGE_2;
@@ -1417,11 +1510,11 @@
 
         assertEquals(3, mManager.getRemainingCallCount());
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertTrue(mManager.setDynamicShortcuts(list(si2)));
         assertEquals(2, mManager.getRemainingCallCount());
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertTrue(mManager.setDynamicShortcuts(list(si2)));
         assertEquals(1, mManager.getRemainingCallCount());
 
         // Back to the original caller, still throttled.
@@ -1430,37 +1523,37 @@
 
         mInjectedCurrentTimeLillis = START_TIME + INTERVAL - 1;
         assertEquals(0, mManager.getRemainingCallCount());
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertFalse(mManager.setDynamicShortcuts(list(si1)));
         assertEquals(0, mManager.getRemainingCallCount());
 
         // Now it should work.
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
 
         mInjectedCurrentTimeLillis++;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
 
         mInjectedCurrentTimeLillis++;
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertFalse(mManager.setDynamicShortcuts(list(si1)));
 
         mInjectedCurrentTimeLillis = START_TIME + 4 * INTERVAL;
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1)));
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
+        assertTrue(mManager.setDynamicShortcuts(list(si1)));
+        assertFalse(mManager.setDynamicShortcuts(list(si1)));
 
         mInjectedClientPackage = CALLING_PACKAGE_2;
         mInjectedCallingUid = CALLING_UID_2;
 
         assertEquals(3, mManager.getRemainingCallCount());
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si2)));
-        assertFalse(mManager.setDynamicShortcuts(Arrays.asList(si2)));
+        assertTrue(mManager.setDynamicShortcuts(list(si2)));
+        assertTrue(mManager.setDynamicShortcuts(list(si2)));
+        assertTrue(mManager.setDynamicShortcuts(list(si2)));
+        assertFalse(mManager.setDynamicShortcuts(list(si2)));
     }
 
     public void testIcons() {
@@ -1477,7 +1570,7 @@
 
         // Set from package 1
         setCaller(CALLING_PACKAGE_1);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+        assertTrue(mManager.setDynamicShortcuts(list(
                 makeShortcutWithIcon("res32x32", res32x32),
                 makeShortcutWithIcon("res64x64", res64x64),
                 makeShortcutWithIcon("bmp32x32", bmp32x32),
@@ -1497,7 +1590,7 @@
 
         // Call from another caller with the same ID, just to make sure storage is per-package.
         setCaller(CALLING_PACKAGE_2);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+        assertTrue(mManager.setDynamicShortcuts(list(
                 makeShortcutWithIcon("res32x32", res512x512),
                 makeShortcutWithIcon("res64x64", res512x512),
                 makeShortcutWithIcon("none", res512x512)
@@ -1518,23 +1611,23 @@
 
         // Check hasIconResource()/hasIconFile().
         assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, Arrays.asList("res32x32"),
+                CALLING_PACKAGE_1, list("res32x32"),
                 getCallingUser())), "res32x32");
 
         assertShortcutIds(assertAllHaveIconResId(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, Arrays.asList("res64x64"), getCallingUser())),
+                CALLING_PACKAGE_1, list("res64x64"), getCallingUser())),
                 "res64x64");
 
         assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, Arrays.asList("bmp32x32"), getCallingUser())),
+                CALLING_PACKAGE_1, list("bmp32x32"), getCallingUser())),
                 "bmp32x32");
 
         assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, Arrays.asList("bmp64x64"), getCallingUser())),
+                CALLING_PACKAGE_1, list("bmp64x64"), getCallingUser())),
                 "bmp64x64");
 
         assertShortcutIds(assertAllHaveIconFile(mLauncherApps.getShortcutInfo(
-                CALLING_PACKAGE_1, Arrays.asList("bmp512x512"), getCallingUser())),
+                CALLING_PACKAGE_1, list("bmp512x512"), getCallingUser())),
                 "bmp512x512");
 
         // Check
@@ -1629,7 +1722,7 @@
         final File p11_1_3 = openIconFileForWriteAndGetPath(11, CALLING_PACKAGE_1);
 
         // Make sure their paths are all unique
-        assertAllUnique(Arrays.asList(
+        assertAllUnique(list(
                 p10_1_1,
                 p10_1_2,
                 p10_1_3,
@@ -1658,7 +1751,7 @@
         assertEquals(p11_1_1.getParent(), p11_1_3.getParent());
 
         // Check the parents are still unique.
-        assertAllUnique(Arrays.asList(
+        assertAllUnique(list(
                 p10_1_1.getParent(),
                 p10_2_1.getParent(),
                 p11_1_1.getParent()
@@ -1683,7 +1776,7 @@
 
     public void testUpdateShortcuts() {
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"),
                     makeShortcut("s2"),
                     makeShortcut("s3"),
@@ -1692,7 +1785,7 @@
             )));
         });
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"),
                     makeShortcut("s2"),
                     makeShortcut("s3"),
@@ -1701,9 +1794,9 @@
             )));
         });
         runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s2", "s3"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
                     getCallingUser());
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s4", "s5"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
                     getCallingUser());
         });
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
@@ -1743,7 +1836,7 @@
                     .setTitle("new title")
                     .build();
 
-            mManager.updateShortcuts(Arrays.asList(s2, s4));
+            mManager.updateShortcuts(list(s2, s4));
         });
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
             ShortcutInfo s2 = makeShortcutBuilder()
@@ -1757,7 +1850,7 @@
                     .setIntent(new Intent(Intent.ACTION_ALL_APPS))
                     .build();
 
-            mManager.updateShortcuts(Arrays.asList(s2, s4));
+            mManager.updateShortcuts(list(s2, s4));
         });
 
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
@@ -1807,7 +1900,7 @@
         runWithCaller(CALLING_PACKAGE_2, USER_11, () -> {
             assertNoShortcutPackageInfo(CALLING_PACKAGE_2, USER_11);
 
-            mManager.updateShortcuts(Arrays.asList());
+            mManager.updateShortcuts(list());
 
             // Even an empty update call will populate the package info.
             assertShortcutPackageInfo(CALLING_PACKAGE_2, USER_11, 2);
@@ -1838,17 +1931,17 @@
         final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 5000);
         final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 1000);
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+        assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
 
         setCaller(CALLING_PACKAGE_2);
         final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
         final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
         final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+        assertTrue(mManager.setDynamicShortcuts(list(s2_2, s2_3, s2_4)));
 
         setCaller(CALLING_PACKAGE_3);
         final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s3", 5000);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s3_2)));
+        assertTrue(mManager.setDynamicShortcuts(list(s3_2)));
 
         setCaller(LAUNCHER_1);
 
@@ -1886,7 +1979,7 @@
 
         // Pin some shortcuts.
         mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                Arrays.asList("s3", "s4"), getCallingUser());
+                list("s3", "s4"), getCallingUser());
 
         // Pinned ones only
         assertAllPinned(assertAllHaveTitle(assertAllNotHaveIntents(assertShortcutIds(
@@ -1929,7 +2022,7 @@
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
                 /* weight */ 12);
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+        assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
         dumpsysOnLogcat();
 
         setCaller(CALLING_PACKAGE_2);
@@ -1941,14 +2034,14 @@
                 makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
                 /* weight */ 10);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_1)));
+        assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
         dumpsysOnLogcat();
 
         // Pin some.
         setCaller(LAUNCHER_1);
 
         mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                Arrays.asList("s2"), getCallingUser());
+                list("s2"), getCallingUser());
 
         dumpsysOnLogcat();
 
@@ -1967,19 +2060,19 @@
         list = assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
                 assertAllNotKeyFieldsOnly(
                 mLauncherApps.getShortcutInfo(CALLING_PACKAGE_1,
-                Arrays.asList("s2", "s1", "s3", null), getCallingUser())))),
+                list("s2", "s1", "s3", null), getCallingUser())))),
                 "s1", "s2");
         assertEquals("Title 1", findById(list, "s1").getTitle());
         assertEquals("Title 2", findById(list, "s2").getTitle());
 
         assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
                 mLauncherApps.getShortcutInfo(CALLING_PACKAGE_1,
-                        Arrays.asList("s3"), getCallingUser())))
+                        list("s3"), getCallingUser())))
                 /* none */);
 
         list = assertShortcutIds(assertAllHaveTitle(assertAllNotHaveIntents(
                 mLauncherApps.getShortcutInfo(CALLING_PACKAGE_2,
-                        Arrays.asList("s1", "s2", "s3"), getCallingUser()))),
+                        list("s1", "s2", "s3"), getCallingUser()))),
                 "s1");
         assertEquals("ABC", findById(list, "s1").getTitle());
     }
@@ -1990,19 +2083,19 @@
             final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000);
             final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000);
 
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+            assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
         });
 
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
             final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500);
             final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000);
             final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500);
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4)));
+            assertTrue(mManager.setDynamicShortcuts(list(s2_2, s2_3, s2_4)));
         });
 
         runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
             final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000);
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s3_2)));
+            assertTrue(mManager.setDynamicShortcuts(list(s3_2)));
         });
 
         // Pin some.
@@ -2010,7 +2103,7 @@
             assertNoShortcutPackageInfo(LAUNCHER_1, USER_0);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    Arrays.asList("s2", "s3"), getCallingUser());
+                    list("s2", "s3"), getCallingUser());
 
             assertShortcutPackageInfo(LAUNCHER_1, USER_0, 4);
             assertNoShortcutPackageInfo(LAUNCHER_2, USER_0);
@@ -2018,10 +2111,10 @@
             assertNoShortcutPackageInfo(LAUNCHER_2, USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    Arrays.asList("s3", "s4", "s5"), getCallingUser());
+                    list("s3", "s4", "s5"), getCallingUser());
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
-                    Arrays.asList("s3"), getCallingUser());  // Note ID doesn't exist
+                    list("s3"), getCallingUser());  // Note ID doesn't exist
         });
 
         // Delete some.
@@ -2066,12 +2159,12 @@
     public void testPinShortcutAndGetPinnedShortcuts_multi() {
         // Create some shortcuts.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
@@ -2085,13 +2178,13 @@
         // Pin some.
         runWithCaller(LAUNCHER_1, USER_0, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    Arrays.asList("s3", "s4"), getCallingUser());
+                    list("s3", "s4"), getCallingUser());
 
             assertShortcutPackageInfo(LAUNCHER_1, USER_0, 4);
             assertNoShortcutPackageInfo(LAUNCHER_2, USER_0);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    Arrays.asList("s1", "s2", "s4"), getCallingUser());
+                    list("s1", "s2", "s4"), getCallingUser());
         });
 
         dumpsysOnLogcat();
@@ -2168,13 +2261,13 @@
 
             // Now pin some.
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                    Arrays.asList("s1", "s2"), getCallingUser());
+                    list("s1", "s2"), getCallingUser());
 
             assertShortcutPackageInfo(LAUNCHER_2, USER_0, 5);
             assertNoShortcutPackageInfo(LAUNCHER_2, USER_10);
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                    Arrays.asList("s1", "s2"), getCallingUser());
+                    list("s1", "s2"), getCallingUser());
 
             assertShortcutIds(assertAllDynamic(
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
@@ -2266,7 +2359,7 @@
 
             // Update pined.  Note s2 and s3 are actually available, but not visible to this
             // launcher, so still can't be pinned.
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3", "s4"),
                     getCallingUser());
 
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
@@ -2288,7 +2381,7 @@
                     "s3");
 
             // Now "s1" is visible, so can be pinned.
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s2", "s3", "s4"),
                     getCallingUser());
 
             assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly(
@@ -2299,8 +2392,8 @@
 
         // Now clear pinned shortcuts.  First, from launcher 1.
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), getCallingUser());
 
             assertEquals(0,
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
@@ -2320,8 +2413,8 @@
 
         // Clear all pins from launcher 2.
         runWithCaller(LAUNCHER_2, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser());
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), getCallingUser());
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), getCallingUser());
 
             assertEquals(0,
                     mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
@@ -2340,7 +2433,502 @@
         });
     }
 
-    public void testCreateShortcutIntent() {
+    public void testPinShortcutAndGetPinnedShortcuts_crossProfile_plusLaunch() {
+        // Create some shortcuts.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
+                    makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
+        });
+
+        // Pin some shortcuts and see the result.
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s1"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    list("s1", "s2", "s3"), HANDLE_USER_0);
+        });
+
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s2"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    list("s2", "s3"), HANDLE_USER_0);
+        });
+
+        runWithCaller(LAUNCHER_2, USER_P0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s3"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    list("s3"), HANDLE_USER_0);
+        });
+
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s1", "s2", "s3"), HANDLE_USER_10);
+        });
+
+        // Cross profile pinning.
+        final int PIN_AND_DYNAMIC = ShortcutQuery.FLAG_GET_PINNED | ShortcutQuery.FLAG_GET_DYNAMIC;
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_2, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2", "s3", "s4", "s5", "s6");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2", "s3", "s4", "s5", "s6");
+        });
+
+        // Remove some dynamic shortcuts.
+
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"))));
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"))));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"))));
+        });
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_2, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s3");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_2, USER_10, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_10)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_10)),
+                    "s1", "s2", "s3");
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+
+        // Save & load and make sure we still have the same information.
+        mService.saveDirtyInfo();
+        initService();
+        mService.handleUnlockUser(USER_0);
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s2");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s2", "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s2", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+        runWithCaller(LAUNCHER_2, USER_P0, () -> {
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s3");
+
+            assertShortcutIds(assertAllPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), HANDLE_USER_0)),
+                    "s3");
+            assertShortcutIds(assertAllDynamic(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, ShortcutQuery.FLAG_GET_DYNAMIC), HANDLE_USER_0)),
+                    "s1");
+            assertShortcutIds(assertAllDynamicOrPinned(
+                    mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2,
+                    /* activity =*/ null, PIN_AND_DYNAMIC), HANDLE_USER_0)),
+                    "s1", "s3");
+
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_1, "s3", USER_0);
+
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s1", USER_0);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_2, "s2", USER_0);
+            assertShortcutLaunchable(CALLING_PACKAGE_2, "s3", USER_0);
+
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s1", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s2", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s3", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s4", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s5", USER_10);
+            assertShortcutNotLaunchable(CALLING_PACKAGE_1, "s6", USER_10);
+        });
+    }
+
+    public void testStartShortcut() {
         // Create some shortcuts.
         setCaller(CALLING_PACKAGE_1);
         final ShortcutInfo s1_1 = makeShortcut(
@@ -2360,7 +2948,7 @@
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
                 /* weight */ 12);
 
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2)));
+        assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
 
         setCaller(CALLING_PACKAGE_2);
         final ShortcutInfo s2_1 = makeShortcut(
@@ -2371,15 +2959,15 @@
                 makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
                 /* weight */ 10);
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_1)));
+        assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
 
         // Pin all.
         setCaller(LAUNCHER_1);
         mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
-                Arrays.asList("s1", "s2"), getCallingUser());
+                list("s1", "s2"), getCallingUser());
 
         mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
-                Arrays.asList("s1"), getCallingUser());
+                list("s1"), getCallingUser());
 
         // Just to make it complicated, delete some.
         setCaller(CALLING_PACKAGE_1);
@@ -2387,17 +2975,16 @@
 
         // intent and check.
         setCaller(LAUNCHER_1);
+
         Intent intent;
-        intent = mInternal.createShortcutIntent(getCallingPackage(),
-                CALLING_PACKAGE_1, "s1", getCallingUserId());
+        intent = launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s1", USER_0);
         assertEquals(ShortcutActivity2.class.getName(), intent.getComponent().getClassName());
 
-        intent = mInternal.createShortcutIntent(getCallingPackage(),
-                CALLING_PACKAGE_1, "s2", getCallingUserId());
+
+        intent = launchShortcutAndGetIntent(CALLING_PACKAGE_1, "s2", USER_0);
         assertEquals(ShortcutActivity3.class.getName(), intent.getComponent().getClassName());
 
-        intent = mInternal.createShortcutIntent(getCallingPackage(),
-                CALLING_PACKAGE_2, "s1", getCallingUserId());
+        intent = launchShortcutAndGetIntent(CALLING_PACKAGE_2, "s1", USER_0);
         assertEquals(ShortcutActivity.class.getName(), intent.getComponent().getClassName());
 
         // TODO Check extra, etc
@@ -2419,7 +3006,7 @@
         });
 
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
 
@@ -2428,7 +3015,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_1),
                 shortcuts.capture(),
-                eq(UserHandle.of(USER_0))
+                eq(HANDLE_USER_0)
         );
         assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
                 "s1", "s2", "s3");
@@ -2436,7 +3023,7 @@
         // From different package.
         reset(c0);
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
         waitOnMainThread();
@@ -2444,7 +3031,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_2),
                 shortcuts.capture(),
-                eq(UserHandle.of(USER_0))
+                eq(HANDLE_USER_0)
         );
         assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
                 "s1", "s2", "s3");
@@ -2452,7 +3039,7 @@
         // Different user, callback shouldn't be called.
         reset(c0);
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
         });
         waitOnMainThread();
@@ -2473,7 +3060,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_1),
                 shortcuts.capture(),
-                eq(UserHandle.of(USER_0))
+                eq(HANDLE_USER_0)
         );
         assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
                 "s1", "s2", "s3", "s4");
@@ -2489,7 +3076,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_1),
                 shortcuts.capture(),
-                eq(UserHandle.of(USER_0))
+                eq(HANDLE_USER_0)
         );
         assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
                 "s2", "s3", "s4");
@@ -2497,7 +3084,7 @@
         // Test for update
         reset(c0);
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
-            assertTrue(mManager.updateShortcuts(Arrays.asList(
+            assertTrue(mManager.updateShortcuts(list(
                     makeShortcut("s1"), makeShortcut("s2"))));
         });
 
@@ -2506,7 +3093,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_1),
                 shortcuts.capture(),
-                eq(UserHandle.of(USER_0))
+                eq(HANDLE_USER_0)
         );
         assertShortcutIds(assertAllDynamic(shortcuts.getValue()),
                 "s2", "s3", "s4");
@@ -2522,13 +3109,13 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_1),
                 shortcuts.capture(),
-                eq(UserHandle.of(USER_0))
+                eq(HANDLE_USER_0)
         );
         assertEquals(0, shortcuts.getValue().size());
 
         // Remove CALLING_PACKAGE_2
         reset(c0);
-        mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_0);
+        mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_0, USER_0);
 
         // Should get a callback with an empty list.
         waitOnMainThread();
@@ -2536,7 +3123,7 @@
         verify(c0).onShortcutsChanged(
                 eq(CALLING_PACKAGE_2),
                 shortcuts.capture(),
-                eq(UserHandle.of(USER_0))
+                eq(HANDLE_USER_0)
         );
         assertEquals(0, shortcuts.getValue().size());
     }
@@ -2544,7 +3131,7 @@
     // === Test for persisting ===
 
     public void testSaveAndLoadUser_empty() {
-        assertTrue(mManager.setDynamicShortcuts(Arrays.asList()));
+        assertTrue(mManager.setDynamicShortcuts(list()));
 
         Log.i(TAG, "Saved state");
         dumpsysOnLogcat();
@@ -2584,7 +3171,7 @@
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
                         /* weight */ 12);
 
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+            assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
             assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
             assertEquals(2, mManager.getRemainingCallCount());
@@ -2611,7 +3198,7 @@
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
                         /* weight */ 12);
 
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+            assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
             assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
             assertEquals(2, mManager.getRemainingCallCount());
@@ -2638,7 +3225,7 @@
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
                         /* weight */ 12);
 
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(si1, si2)));
+            assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
             assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
             assertEquals(2, mManager.getRemainingCallCount());
@@ -2715,45 +3302,45 @@
 
     public void testCleanupPackage() {
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s0_1"))));
         });
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s0_2"))));
         });
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s0_1"),
-                    UserHandle.of(USER_0));
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s0_2"),
-                    UserHandle.of(USER_0));
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s0_1"),
+                    HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s0_2"),
+                    HANDLE_USER_0);
         });
         runWithCaller(LAUNCHER_2, USER_0, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s0_1"),
-                    UserHandle.of(USER_0));
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s0_2"),
-                    UserHandle.of(USER_0));
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s0_1"),
+                    HANDLE_USER_0);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s0_2"),
+                    HANDLE_USER_0);
         });
 
         runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s10_1"))));
         });
         runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
-            assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+            assertTrue(mManager.setDynamicShortcuts(list(
                     makeShortcut("s10_2"))));
         });
         runWithCaller(LAUNCHER_1, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s10_1"),
-                    UserHandle.of(USER_10));
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s10_2"),
-                    UserHandle.of(USER_10));
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s10_1"),
+                    HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s10_2"),
+                    HANDLE_USER_10);
         });
         runWithCaller(LAUNCHER_2, USER_10, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s10_1"),
-                    UserHandle.of(USER_10));
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s10_2"),
-                    UserHandle.of(USER_10));
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s10_1"),
+                    HANDLE_USER_10);
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s10_2"),
+                    HANDLE_USER_10);
         });
 
         // Remove all dynamic shortcuts; now all shortcuts are just pinned.
@@ -2781,15 +3368,19 @@
 
 
         // Check the registered packages.
-
+        dumpsysOnLogcat();
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 set(user0.getPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 set(user10.getPackages().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user0.getLaunchers().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user10.getLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+                        PackageWithUser.of(USER_0, LAUNCHER_2)),
+                set(user0.getAllLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
+                        PackageWithUser.of(USER_10, LAUNCHER_2)),
+                set(user10.getAllLaunchers().keySet()));
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
                 "s0_1", "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -2811,17 +3402,21 @@
         mService.saveDirtyInfo();
 
         // Nonexistent package.
-        mService.cleanUpPackageLocked("abc", USER_0);
+        mService.cleanUpPackageLocked("abc", USER_0, USER_0);
 
         // No changes.
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 set(user0.getPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 set(user10.getPackages().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user0.getLaunchers().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user10.getLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+                        PackageWithUser.of(USER_0, LAUNCHER_2)),
+                set(user0.getAllLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
+                        PackageWithUser.of(USER_10, LAUNCHER_2)),
+                set(user10.getAllLaunchers().keySet()));
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
                 "s0_1", "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -2843,16 +3438,20 @@
         mService.saveDirtyInfo();
 
         // Remove a package.
-        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0);
+        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0, USER_0);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
                 set(user0.getPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 set(user10.getPackages().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user0.getLaunchers().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user10.getLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+                        PackageWithUser.of(USER_0, LAUNCHER_2)),
+                set(user0.getAllLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_10, LAUNCHER_1),
+                        PackageWithUser.of(USER_10, LAUNCHER_2)),
+                set(user10.getAllLaunchers().keySet()));
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
                 "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -2874,16 +3473,19 @@
         mService.saveDirtyInfo();
 
         // Remove a launcher.
-        mService.cleanUpPackageLocked(LAUNCHER_1, USER_10);
+        mService.cleanUpPackageLocked(LAUNCHER_1, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
                 set(user0.getPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
                 set(user10.getPackages().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user0.getLaunchers().keySet()));
-        assertEquals(makeSet(LAUNCHER_2),
-                set(user10.getLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+                        PackageWithUser.of(USER_0, LAUNCHER_2)),
+                set(user0.getAllLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_10, LAUNCHER_2)),
+                set(user10.getAllLaunchers().keySet()));
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
                 "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -2898,16 +3500,19 @@
         mService.saveDirtyInfo();
 
         // Remove a package.
-        mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10);
+        mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
                 set(user0.getPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1),
                 set(user10.getPackages().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user0.getLaunchers().keySet()));
-        assertEquals(makeSet(LAUNCHER_2),
-                set(user10.getLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+                        PackageWithUser.of(USER_0, LAUNCHER_2)),
+                set(user0.getAllLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_10, LAUNCHER_2)),
+                set(user10.getAllLaunchers().keySet()));
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
                 "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -2927,16 +3532,19 @@
         mService.saveDirtyInfo();
 
         // Remove the other launcher from user 10 too.
-        mService.cleanUpPackageLocked(LAUNCHER_2, USER_10);
+        mService.cleanUpPackageLocked(LAUNCHER_2, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
                 set(user0.getPackages().keySet()));
         assertEquals(makeSet(CALLING_PACKAGE_1),
                 set(user10.getPackages().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user0.getLaunchers().keySet()));
-        assertEquals(makeSet(),
-                set(user10.getLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+                        PackageWithUser.of(USER_0, LAUNCHER_2)),
+                set(user0.getAllLaunchers().keySet()));
+        assertEquals(
+                makeSet(),
+                set(user10.getAllLaunchers().keySet()));
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
                 "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -2951,16 +3559,18 @@
         mService.saveDirtyInfo();
 
         // More remove.
-        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10);
+        mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10, USER_10);
 
         assertEquals(makeSet(CALLING_PACKAGE_2),
                 set(user0.getPackages().keySet()));
         assertEquals(makeSet(),
                 set(user10.getPackages().keySet()));
-        assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
-                set(user0.getLaunchers().keySet()));
+        assertEquals(
+                makeSet(PackageWithUser.of(USER_0, LAUNCHER_1),
+                        PackageWithUser.of(USER_0, LAUNCHER_2)),
+                set(user0.getAllLaunchers().keySet()));
         assertEquals(makeSet(),
-                set(user10.getLaunchers().keySet()));
+                set(user10.getAllLaunchers().keySet()));
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
                 "s0_2");
         assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
@@ -2975,6 +3585,367 @@
         mService.saveDirtyInfo();
     }
 
+    public void testHandleGonePackage_crossProfile() {
+        // Create some shortcuts.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
+        });
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        // Pin some.
+
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s1"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s2"), UserHandle.of(USER_P0));
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    list("s3"), HANDLE_USER_0);
+        });
+
+        runWithCaller(LAUNCHER_1, USER_P0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s2"), HANDLE_USER_0);
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s3"), UserHandle.of(USER_P0));
+
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_2,
+                    list("s1"), HANDLE_USER_0);
+        });
+
+        runWithCaller(LAUNCHER_1, USER_10, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1,
+                    list("s3"), HANDLE_USER_10);
+        });
+
+        // Check the state.
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        // These two shouldn't exist
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0, USER_P0));
+
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+        // Make sure all the information is persisted.
+        mService.saveDirtyInfo();
+        initService();
+        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_10);
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        // These two shouldn't exist
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0, USER_P0));
+
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+
+        // Start uninstalling.
+        uninstallPackage(USER_10, LAUNCHER_1);
+        mService.cleanupGonePackages(USER_10);
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+        // Uninstall.
+        uninstallPackage(USER_10, CALLING_PACKAGE_1);
+        mService.cleanupGonePackages(USER_10);
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+        uninstallPackage(USER_P0, LAUNCHER_1);
+        mService.cleanupGonePackages(USER_0);
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+        mService.cleanupGonePackages(USER_P0);
+        
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+        uninstallPackage(USER_P0, CALLING_PACKAGE_1);
+
+        mService.saveDirtyInfo();
+        initService();
+        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_10);
+
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicAndPinned(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+        // Uninstall
+        uninstallPackage(USER_0, LAUNCHER_1);
+
+        mService.saveDirtyInfo();
+        initService();
+        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_10);
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+
+        uninstallPackage(USER_0, CALLING_PACKAGE_2);
+
+        mService.saveDirtyInfo();
+        initService();
+        mService.handleUnlockUser(USER_0);
+        mService.handleUnlockUser(USER_P0);
+        mService.handleUnlockUser(USER_10);
+
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_0));
+        assertDynamicOnly(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_P0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_P0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_P0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s1", USER_0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s2", USER_0));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_2, "s3", USER_0));
+
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s1", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s2", USER_10));
+        assertNull(getPackageShortcut(CALLING_PACKAGE_1, "s3", USER_10));
+
+        assertNotNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_P0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_2, USER_0));
+        assertNull(mService.getPackageInfoForTest(CALLING_PACKAGE_1, USER_10));
+
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_P0, USER_P0));
+        assertNull(mService.getPackageInfoForTest(LAUNCHER_1, USER_10, USER_10));
+    }
+
     // TODO Detailed test for hasShortcutPermissionInner().
 
     // TODO Add tests for the command line functions too.