Merge "Ensure window has been added in isTopOfTask" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index 0857c8b..c416044 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -576,6 +576,7 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
+    field public static final int forceHasOverlappingRendering = 16844068; // 0x1010524
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -42345,6 +42346,7 @@
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
+    method public void forceHasOverlappingRendering(boolean);
     method public void forceLayout();
     method public static int generateViewId();
     method public java.lang.CharSequence getAccessibilityClassName();
@@ -42390,6 +42392,7 @@
     method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
     method public final boolean getGlobalVisibleRect(android.graphics.Rect);
     method public android.os.Handler getHandler();
+    method public final boolean getHasOverlappingRendering();
     method public final int getHeight();
     method public void getHitRect(android.graphics.Rect);
     method public int getHorizontalFadingEdgeLength();
@@ -57330,6 +57333,7 @@
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public boolean removeIf(java.util.function.Predicate<? super E>);
+    method public void replaceAll(java.util.function.UnaryOperator<E>);
     method public int size();
     method public void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
@@ -57967,6 +57971,7 @@
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public boolean replace(K, V, V);
   }
 
   public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -57987,6 +57992,9 @@
     ctor public Hashtable(java.util.Map<? extends K, ? extends V>);
     method public synchronized void clear();
     method public synchronized java.lang.Object clone();
+    method public synchronized V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public synchronized V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public synchronized V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public synchronized boolean contains(java.lang.Object);
     method public synchronized boolean containsKey(java.lang.Object);
     method public boolean containsValue(java.lang.Object);
@@ -57994,13 +58002,19 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public synchronized V get(java.lang.Object);
+    method public synchronized V getOrDefault(java.lang.Object, V);
     method public synchronized boolean isEmpty();
     method public java.util.Set<K> keySet();
     method public synchronized java.util.Enumeration<K> keys();
+    method public synchronized V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public synchronized V put(K, V);
     method public synchronized void putAll(java.util.Map<? extends K, ? extends V>);
+    method public synchronized V putIfAbsent(K, V);
     method protected void rehash();
     method public synchronized V remove(java.lang.Object);
+    method public synchronized boolean remove(java.lang.Object, java.lang.Object);
+    method public synchronized boolean replace(K, V, V);
+    method public synchronized V replace(K, V);
     method public synchronized int size();
     method public java.util.Collection<V> values();
   }
@@ -58145,9 +58159,11 @@
     method public abstract boolean remove(java.lang.Object);
     method public abstract E remove(int);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default void replaceAll(java.util.function.UnaryOperator<E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract E set(int, E);
     method public abstract int size();
+    method public default void sort(java.util.Comparator<? super E>);
     method public abstract java.util.List<E> subList(int, int);
     method public abstract java.lang.Object[] toArray();
     method public abstract T[] toArray(T[]);
@@ -59062,9 +59078,11 @@
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
     method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
+    method public synchronized void replaceAll(java.util.function.UnaryOperator<E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public synchronized void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
@@ -59530,6 +59548,7 @@
     method public java.lang.Object clone();
     method public boolean contains(java.lang.Object);
     method public boolean containsAll(java.util.Collection<?>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public int indexOf(E, int);
     method public int indexOf(java.lang.Object);
@@ -66433,3 +66452,4 @@
   }
 
 }
+
diff --git a/api/system-current.txt b/api/system-current.txt
index eff0660..e372d98 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -671,6 +671,7 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
+    field public static final int forceHasOverlappingRendering = 16844068; // 0x1010524
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -45071,6 +45072,7 @@
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
+    method public void forceHasOverlappingRendering(boolean);
     method public void forceLayout();
     method public static int generateViewId();
     method public java.lang.CharSequence getAccessibilityClassName();
@@ -45116,6 +45118,7 @@
     method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
     method public final boolean getGlobalVisibleRect(android.graphics.Rect);
     method public android.os.Handler getHandler();
+    method public final boolean getHasOverlappingRendering();
     method public final int getHeight();
     method public void getHitRect(android.graphics.Rect);
     method public int getHorizontalFadingEdgeLength();
@@ -60394,6 +60397,7 @@
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public boolean removeIf(java.util.function.Predicate<? super E>);
+    method public void replaceAll(java.util.function.UnaryOperator<E>);
     method public int size();
     method public void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
@@ -61031,6 +61035,7 @@
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public boolean replace(K, V, V);
   }
 
   public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -61051,6 +61056,9 @@
     ctor public Hashtable(java.util.Map<? extends K, ? extends V>);
     method public synchronized void clear();
     method public synchronized java.lang.Object clone();
+    method public synchronized V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public synchronized V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public synchronized V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public synchronized boolean contains(java.lang.Object);
     method public synchronized boolean containsKey(java.lang.Object);
     method public boolean containsValue(java.lang.Object);
@@ -61058,13 +61066,19 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public synchronized V get(java.lang.Object);
+    method public synchronized V getOrDefault(java.lang.Object, V);
     method public synchronized boolean isEmpty();
     method public java.util.Set<K> keySet();
     method public synchronized java.util.Enumeration<K> keys();
+    method public synchronized V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public synchronized V put(K, V);
     method public synchronized void putAll(java.util.Map<? extends K, ? extends V>);
+    method public synchronized V putIfAbsent(K, V);
     method protected void rehash();
     method public synchronized V remove(java.lang.Object);
+    method public synchronized boolean remove(java.lang.Object, java.lang.Object);
+    method public synchronized boolean replace(K, V, V);
+    method public synchronized V replace(K, V);
     method public synchronized int size();
     method public java.util.Collection<V> values();
   }
@@ -61209,9 +61223,11 @@
     method public abstract boolean remove(java.lang.Object);
     method public abstract E remove(int);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default void replaceAll(java.util.function.UnaryOperator<E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract E set(int, E);
     method public abstract int size();
+    method public default void sort(java.util.Comparator<? super E>);
     method public abstract java.util.List<E> subList(int, int);
     method public abstract java.lang.Object[] toArray();
     method public abstract T[] toArray(T[]);
@@ -62126,9 +62142,11 @@
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
     method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
+    method public synchronized void replaceAll(java.util.function.UnaryOperator<E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public synchronized void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
@@ -62594,6 +62612,7 @@
     method public java.lang.Object clone();
     method public boolean contains(java.lang.Object);
     method public boolean containsAll(java.util.Collection<?>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public int indexOf(E, int);
     method public int indexOf(java.lang.Object);
@@ -69497,3 +69516,4 @@
   }
 
 }
+
diff --git a/api/test-current.txt b/api/test-current.txt
index 6cf047a..e4153f1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -576,6 +576,7 @@
     field public static final int fontFamily = 16843692; // 0x10103ac
     field public static final int fontFeatureSettings = 16843959; // 0x10104b7
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
+    field public static final int forceHasOverlappingRendering = 16844068; // 0x1010524
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
     field public static final int foregroundTint = 16843885; // 0x101046d
@@ -42419,6 +42420,7 @@
     method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
     method public android.view.View focusSearch(int);
+    method public void forceHasOverlappingRendering(boolean);
     method public void forceLayout();
     method public static int generateViewId();
     method public java.lang.CharSequence getAccessibilityClassName();
@@ -42464,6 +42466,7 @@
     method public boolean getGlobalVisibleRect(android.graphics.Rect, android.graphics.Point);
     method public final boolean getGlobalVisibleRect(android.graphics.Rect);
     method public android.os.Handler getHandler();
+    method public final boolean getHasOverlappingRendering();
     method public final int getHeight();
     method public void getHitRect(android.graphics.Rect);
     method public int getHorizontalFadingEdgeLength();
@@ -57404,6 +57407,7 @@
     method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public boolean removeIf(java.util.function.Predicate<? super E>);
+    method public void replaceAll(java.util.function.UnaryOperator<E>);
     method public int size();
     method public void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
@@ -58041,6 +58045,7 @@
     method public java.lang.Object clone();
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public void forEach(java.util.function.BiConsumer<? super K, ? super V>);
+    method public boolean replace(K, V, V);
   }
 
   public class HashSet extends java.util.AbstractSet implements java.lang.Cloneable java.io.Serializable java.util.Set {
@@ -58061,6 +58066,9 @@
     ctor public Hashtable(java.util.Map<? extends K, ? extends V>);
     method public synchronized void clear();
     method public synchronized java.lang.Object clone();
+    method public synchronized V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
+    method public synchronized V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>);
+    method public synchronized V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>);
     method public synchronized boolean contains(java.lang.Object);
     method public synchronized boolean containsKey(java.lang.Object);
     method public boolean containsValue(java.lang.Object);
@@ -58068,13 +58076,19 @@
     method public java.util.Set<java.util.Map.Entry<K, V>> entrySet();
     method public synchronized void forEach(java.util.function.BiConsumer<? super K, ? super V>);
     method public synchronized V get(java.lang.Object);
+    method public synchronized V getOrDefault(java.lang.Object, V);
     method public synchronized boolean isEmpty();
     method public java.util.Set<K> keySet();
     method public synchronized java.util.Enumeration<K> keys();
+    method public synchronized V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>);
     method public synchronized V put(K, V);
     method public synchronized void putAll(java.util.Map<? extends K, ? extends V>);
+    method public synchronized V putIfAbsent(K, V);
     method protected void rehash();
     method public synchronized V remove(java.lang.Object);
+    method public synchronized boolean remove(java.lang.Object, java.lang.Object);
+    method public synchronized boolean replace(K, V, V);
+    method public synchronized V replace(K, V);
     method public synchronized int size();
     method public java.util.Collection<V> values();
   }
@@ -58219,9 +58233,11 @@
     method public abstract boolean remove(java.lang.Object);
     method public abstract E remove(int);
     method public abstract boolean removeAll(java.util.Collection<?>);
+    method public default void replaceAll(java.util.function.UnaryOperator<E>);
     method public abstract boolean retainAll(java.util.Collection<?>);
     method public abstract E set(int, E);
     method public abstract int size();
+    method public default void sort(java.util.Comparator<? super E>);
     method public abstract java.util.List<E> subList(int, int);
     method public abstract java.lang.Object[] toArray();
     method public abstract T[] toArray(T[]);
@@ -59136,9 +59152,11 @@
     method public synchronized boolean removeElement(java.lang.Object);
     method public synchronized void removeElementAt(int);
     method public synchronized boolean removeIf(java.util.function.Predicate<? super E>);
+    method public synchronized void replaceAll(java.util.function.UnaryOperator<E>);
     method public synchronized void setElementAt(E, int);
     method public synchronized void setSize(int);
     method public synchronized int size();
+    method public synchronized void sort(java.util.Comparator<? super E>);
     method public java.util.Spliterator<E> spliterator();
     method public synchronized void trimToSize();
     field protected int capacityIncrement;
@@ -59604,6 +59622,7 @@
     method public java.lang.Object clone();
     method public boolean contains(java.lang.Object);
     method public boolean containsAll(java.util.Collection<?>);
+    method public void forEach(java.util.function.Consumer<? super E>);
     method public E get(int);
     method public int indexOf(E, int);
     method public int indexOf(java.lang.Object);
@@ -66507,3 +66526,4 @@
   }
 
 }
+
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/core/java/android/view/View.java b/core/java/android/view/View.java
index 4e6735a..6811aed 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2429,7 +2429,11 @@
      *                     1             PFLAG3_SCROLL_INDICATOR_START
      *                    1              PFLAG3_SCROLL_INDICATOR_END
      *                   1               PFLAG3_ASSIST_BLOCKED
-     *            1111111                PFLAG3_POINTER_ICON_MASK
+     *                  1                PFLAG3_POINTER_ICON_NULL
+     *                 1                 PFLAG3_POINTER_ICON_VALUE_START
+     *           11111111                PFLAG3_POINTER_ICON_MASK
+     *          1                        PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE
+     *         1                         PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED
      * |-------|-------|-------|-------|
      */
 
@@ -2518,8 +2522,6 @@
      */
     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
 
-    /* End of masks for mPrivateFlags3 */
-
     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
 
     static final int SCROLL_INDICATORS_NONE = 0x0000;
@@ -2651,6 +2653,23 @@
     private static final int PFLAG3_POINTER_ICON_VALUE_START = 2 << PFLAG3_POINTER_ICON_LSHIFT;
 
     /**
+     * Whether this view has rendered elements that overlap (see {@link
+     * #hasOverlappingRendering()}, {@link #forceHasOverlappingRendering(boolean)}, and
+     * {@link #getHasOverlappingRendering()} ). The value in this bit is only valid when
+     * PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED has been set. Otherwise, the value is
+     * determined by whatever {@link #hasOverlappingRendering()} returns.
+     */
+    private static final int PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE = 0x800000;
+
+    /**
+     * Whether {@link #forceHasOverlappingRendering(boolean)} has been called. When true, value
+     * in PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE is valid.
+     */
+    private static final int PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED = 0x1000000;
+
+    /* End of masks for mPrivateFlags3 */
+
+    /**
      * Always allow a user to over-scroll this view, provided it is a
      * view that can scroll.
      *
@@ -4516,6 +4535,12 @@
                         }
                     }
                     break;
+                case R.styleable.View_forceHasOverlappingRendering:
+                    if (a.peekValue(attr) != null) {
+                        forceHasOverlappingRendering(a.getBoolean(attr, true));
+                    }
+                    break;
+
             }
         }
 
@@ -12116,6 +12141,42 @@
     }
 
     /**
+     * Sets the behavior for overlapping rendering for this view (see {@link
+     * #hasOverlappingRendering()} for more details on this behavior). Calling this method
+     * is an alternative to overriding {@link #hasOverlappingRendering()} in a subclass,
+     * providing the value which is then used internally. That is, when {@link
+     * #forceHasOverlappingRendering(boolean)} is called, the value of {@link
+     * #hasOverlappingRendering()} is ignored and the value passed into this method is used
+     * instead.
+     *
+     * @param hasOverlappingRendering The value for overlapping rendering to be used internally
+     * instead of that returned by {@link #hasOverlappingRendering()}.
+     *
+     * @attr ref android.R.styleable#View_forceHasOverlappingRendering
+     */
+    public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {
+        mPrivateFlags3 |= PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED;
+        if (hasOverlappingRendering) {
+            mPrivateFlags3 |= PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
+        } else {
+            mPrivateFlags3 &= ~PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE;
+        }
+    }
+
+    /**
+     * Returns the value for overlapping rendering that is used internally. This is either
+     * the value passed into {@link #forceHasOverlappingRendering(boolean)}, if called, or
+     * the return value of {@link #hasOverlappingRendering()}, otherwise.
+     *
+     * @return The value for overlapping rendering being used internally.
+     */
+    public final boolean getHasOverlappingRendering() {
+        return (mPrivateFlags3 & PFLAG3_HAS_OVERLAPPING_RENDERING_FORCED) != 0 ?
+                (mPrivateFlags3 & PFLAG3_OVERLAPPING_RENDERING_FORCED_VALUE) != 0 :
+                hasOverlappingRendering();
+    }
+
+    /**
      * Returns whether this View has content which overlaps.
      *
      * <p>This function, intended to be overridden by specific View types, is an optimization when
@@ -12131,6 +12192,9 @@
      * necessitates that a View return true if it uses the methods internally without passing the
      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
      *
+     * <p><strong>Note:</strong> The return value of this method is ignored if {@link
+     * #forceHasOverlappingRendering(boolean)} has been called on this view.</p>
+     *
      * @return true if the content in this view might overlap, false otherwise.
      */
     @ViewDebug.ExportedProperty(category = "drawing")
@@ -16566,7 +16630,7 @@
      */
     void setDisplayListProperties(RenderNode renderNode) {
         if (renderNode != null) {
-            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
+            renderNode.setHasOverlappingRendering(getHasOverlappingRendering());
             renderNode.setClipToBounds(mParent instanceof ViewGroup
                     && ((ViewGroup) mParent).getClipChildren());
 
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index f18b7ac..c5b8849 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -1113,13 +1113,6 @@
             if (mListener != null) {
                 mListener.onAnimationEnd(animation);
             }
-            if (mAnimatorOnEndMap != null) {
-                Runnable r = mAnimatorOnEndMap.get(animation);
-                if (r != null) {
-                    r.run();
-                }
-                mAnimatorOnEndMap.remove(animation);
-            }
             if (mAnimatorCleanupMap != null) {
                 Runnable r = mAnimatorCleanupMap.get(animation);
                 if (r != null) {
@@ -1127,6 +1120,13 @@
                 }
                 mAnimatorCleanupMap.remove(animation);
             }
+            if (mAnimatorOnEndMap != null) {
+                Runnable r = mAnimatorOnEndMap.get(animation);
+                if (r != null) {
+                    r.run();
+                }
+                mAnimatorOnEndMap.remove(animation);
+            }
             mAnimatorMap.remove(animation);
         }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3b4163f..5d4ee874 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2126,7 +2126,7 @@
 
         boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
 
-        if (!cancelDraw) {
+        if (!cancelDraw && !newSurface) {
             if (mPendingTransitions != null && mPendingTransitions.size() > 0) {
                 for (int i = 0; i < mPendingTransitions.size(); ++i) {
                     mPendingTransitions.get(i).startChangingAnimations();
@@ -2175,7 +2175,6 @@
             }
         }
     }
-
     private void handleOutOfResourcesException(Surface.OutOfResourcesException e) {
         Log.e(mTag, "OutOfResourcesException initializing HW surface", e);
         try {
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index c22d60d..3ad730b 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -157,6 +158,15 @@
     public abstract void setMagnificationSpec(MagnificationSpec spec);
 
     /**
+     * Obtains the magnified and available regions.
+     *
+     * @param outMagnified the currently magnified region
+     * @param outAvailable the region available for magnification
+     */
+    public abstract void getMagnificationRegions(@NonNull Region outMagnified,
+            @NonNull Region outAvailable);
+
+    /**
      * Gets the magnification and translation applied to a window given its token.
      * Not all windows are magnified and the window manager policy determines which
      * windows are magnified. The returned result also takes into account the compat
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 10027b6..5e8f4a2 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -27,7 +27,6 @@
 import android.content.pm.PackageInfo;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
-import android.os.SELinux;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.StructStat;
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index bd97e5d..4738f5e 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -346,16 +346,6 @@
             }
             return false;
         }
-
-        @Override
-        protected boolean onForwardingStopped() {
-            final ShowableListMenu popup = getPopup();
-            if (popup != null) {
-                popup.dismiss();
-                return true;
-            }
-            return false;
-        }
     }
 
     public static abstract class PopupCallback {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a52c4e5..00eb81a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2846,6 +2846,11 @@
             <!-- Pointer icon of a hand sign while grabbing something. -->
             <enum name="grabbing" value="1021" />
         </attr>
+
+        <!-- Whether this view has elements that may overlap when drawn. See
+             {@link android.view.View#forceHasOverlappingRendering(boolean)}. -->
+        <attr name="forceHasOverlappingRendering" format="boolean" />
+
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7fd5456..ac29f92 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2710,6 +2710,7 @@
     <public type="attr" name="popupEnterTransition" />
     <public type="attr" name="popupExitTransition" />
     <public type="attr" name="minimalHeight" />
+    <public type="attr" name="forceHasOverlappingRendering" />
 
     <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" />
     <public type="style" name="Widget.Material.SeekBar.Discrete" />
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 2246cf9c..76e587e 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -244,7 +244,7 @@
     int64_t totalDuration =
             frame[FrameInfoIndex::FrameCompleted] - frame[FrameInfoIndex::IntendedVsync];
     uint32_t framebucket = frameCountIndexForFrameTime(
-            totalDuration, mData->frameCounts.size());
+            totalDuration, mData->frameCounts.size() - 1);
     // Keep the fast path as fast as possible.
     if (CC_LIKELY(totalDuration < mFrameInterval)) {
         mData->frameCounts[framebucket]++;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index e6b22e6..7ad4a09 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -30,6 +30,7 @@
 import android.provider.DocumentsContract;
 import android.util.Log;
 
+import com.android.documentsui.State.ActionType;
 import com.android.documentsui.model.DocumentInfo;
 import com.android.documentsui.model.RootInfo;
 import com.android.documentsui.services.FileOperationService;
@@ -502,7 +503,7 @@
      * @param name The name of the histogram.
      * @param bucket The bucket to increment.
      */
-    private static void logHistogram(Context context, String name, int bucket) {
+    private static void logHistogram(Context context, String name, @ActionType int bucket) {
         if (DEBUG) Log.d(TAG, name + ": " + bucket);
         MetricsLogger.histogram(context, name, bucket);
     }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 35da8cc..8b4f40e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -17,6 +17,7 @@
 package com.android.documentsui;
 
 import static com.android.documentsui.Shared.DEBUG;
+import static com.android.documentsui.State.ACTION_OPEN_TREE;
 
 import android.app.Fragment;
 import android.app.FragmentManager;
@@ -117,7 +118,7 @@
 
                 Intent handlerAppIntent = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
 
-                mAdapter = new RootsAdapter(context, result, handlerAppIntent);
+                mAdapter = new RootsAdapter(context, result, handlerAppIntent, state);
                 mList.setAdapter(mAdapter);
 
                 onCurrentRootChanged();
@@ -308,8 +309,8 @@
          * @param handlerAppIntent When not null, apps capable of handling the original
          *     intent will be included in list of roots (in special section at bottom).
          */
-        public RootsAdapter(
-                Context context, Collection<RootInfo> roots, @Nullable Intent handlerAppIntent) {
+        public RootsAdapter(Context context, Collection<RootInfo> roots,
+                @Nullable Intent handlerAppIntent, State state) {
             super(context, 0);
 
             final List<RootItem> libraries = new ArrayList<>();
@@ -320,7 +321,8 @@
 
                 if (root.isHome() && Shared.isHomeRootHidden(context)) {
                     continue;
-                } else if (root.isAdvanced() && Shared.areAdvancedRootsHidden(context)) {
+                } else if (root.isAdvanced()
+                        && Shared.areAdvancedRootsHidden(context, state)) {
                     continue;
                 } else if (root.isLibrary()) {
                     if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index d21afee..655359a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -22,6 +22,11 @@
 import android.text.format.DateUtils;
 import android.text.format.Time;
 import android.view.WindowManager;
+
+import com.android.documentsui.State.ActionType;
+
+import static com.android.documentsui.State.ACTION_OPEN_TREE;
+
 import android.app.AlertDialog;
 
 import java.text.Collator;
@@ -179,8 +184,9 @@
     /*
      * Indicates if the advanced roots should be hidden.
      */
-    public static boolean areAdvancedRootsHidden(Context context) {
-        return context.getResources().getBoolean(R.bool.advanced_roots_hidden);
+    public static boolean areAdvancedRootsHidden(Context context, State state) {
+        return context.getResources().getBoolean(R.bool.advanced_roots_hidden)
+                && state.action != ACTION_OPEN_TREE;
     }
 
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index 16b7660..534a483 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -43,10 +43,19 @@
 
     private static final String TAG = "State";
 
+    @IntDef(flag = true, value = {
+            ACTION_BROWSE,
+            ACTION_PICK_COPY_DESTINATION,
+            ACTION_OPEN,
+            ACTION_CREATE,
+            ACTION_GET_CONTENT,
+            ACTION_OPEN_TREE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ActionType {}
     // File manager and related private picking activity.
     public static final int ACTION_BROWSE = 1;
     public static final int ACTION_PICK_COPY_DESTINATION = 2;
-
     // All public picking activities
     public static final int ACTION_OPEN = 3;
     public static final int ACTION_CREATE = 4;
@@ -69,7 +78,7 @@
     public static final int SORT_ORDER_LAST_MODIFIED = 2;
     public static final int SORT_ORDER_SIZE = 3;
 
-    public int action;
+    public @ActionType int action;
     public String[] acceptMimes;
 
     /** Derived from local preferences */
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 64910fd..c3a5089 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -155,8 +155,10 @@
             mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
             updateDrawer();
         } else {
-            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
-            mDrawerLayout = null;
+            if (mDrawerLayout != null) {
+                mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
+                mDrawerLayout = null;
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
index bb43899..d9bf539 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarController.java
@@ -106,7 +106,7 @@
 
         String category = getPackageCategory(packageName);
         if (mFacetCategoryMap.containsKey(category)) {
-            int index = mFacetCategoryMap.get(packageName);
+            int index = mFacetCategoryMap.get(category);
             mFacetHasMultipleAppsCache.put(index, facetHasMultiplePackages(index));
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 12035b9..023c4d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -789,8 +789,9 @@
     }
 
     private boolean isInQsArea(float x, float y) {
-        return (x >= mQsContainer.getX() && x <= mQsContainer.getX() + mQsContainer.getWidth()) &&
-                (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+        return (x >= mQsDensityContainer.getX()
+                && x <= mQsDensityContainer.getX() + mQsDensityContainer.getWidth())
+                && (y <= mNotificationStackScroller.getBottomMostNotificationBottom()
                 || y <= mQsContainer.getY() + mQsContainer.getHeight());
     }
 
@@ -1337,7 +1338,8 @@
             return false;
         }
         View header = mKeyguardShowing ? mKeyguardStatusBar : mQsContainer.getHeader();
-        boolean onHeader = x >= header.getX() && x <= header.getX() + header.getWidth()
+        boolean onHeader = x >= mQsDensityContainer.getX()
+                && x <= mQsDensityContainer.getX() + mQsDensityContainer.getWidth()
                 && y >= header.getTop() && y <= header.getBottom();
         if (mQsExpanded) {
             return onHeader || (yDiff < 0 && isInQsArea(x, y));
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index a093d92..e15b785 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -111,12 +111,18 @@
     public void register() {
         mScreenStateObserver.register();
         mWindowStateObserver.register();
+
+        // Obtain initial state.
+        mWindowStateObserver.getRegions(mMagnifiedRegion, mAvailableRegion);
+        mMagnifiedRegion.getBounds(mMagnifiedBounds);
     }
 
     /**
      * Unregisters magnification-related observers.
      */
     public void unregister() {
+        mSpecAnimationBridge.cancel();
+
         mScreenStateObserver.unregister();
         mWindowStateObserver.unregister();
     }
@@ -149,8 +155,10 @@
             final float offsetY = sentSpec.offsetY;
 
             // Compute the new center and update spec as needed.
-            final float centerX = (mMagnifiedBounds.width() / 2.0f - offsetX) / scale;
-            final float centerY = (mMagnifiedBounds.height() / 2.0f - offsetY) / scale;
+            final float centerX = (mMagnifiedBounds.width() / 2.0f
+                    + mMagnifiedBounds.left - offsetX) / scale;
+            final float centerY = (mMagnifiedBounds.height() / 2.0f
+                    + mMagnifiedBounds.top - offsetY) / scale;
             if (updateSpec) {
                 setScaleAndCenter(scale, centerX, centerY, false);
             } else {
@@ -246,7 +254,8 @@
      */
     public float getCenterX() {
         synchronized (mLock) {
-            return  (mMagnifiedBounds.width() / 2.0f - getOffsetX()) / getScale();
+            return  (mMagnifiedBounds.width() / 2.0f
+                    + mMagnifiedBounds.left - getOffsetX()) / getScale();
         }
     }
 
@@ -268,7 +277,8 @@
      */
     public float getCenterY() {
         synchronized (mLock) {
-            return (mMagnifiedBounds.height() / 2.0f - getOffsetY()) / getScale();
+            return (mMagnifiedBounds.height() / 2.0f
+                    + mMagnifiedBounds.top - getOffsetY()) / getScale();
         }
     }
 
@@ -471,18 +481,25 @@
      *         otherwise
      */
     private boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY) {
+        // Handle defaults.
+        if (Float.isNaN(centerX)) {
+            centerX = getCenterX();
+        }
+        if (Float.isNaN(centerY)) {
+            centerY = getCenterY();
+        }
+        if (Float.isNaN(scale)) {
+            scale = getScale();
+        }
+
+        // Ensure requested center is within the available region.
         if (!availableRegionContains(centerX, centerY)) {
             return false;
         }
 
-        boolean changed = false;
-
+        // Compute changes.
         final MagnificationSpec currSpec = mCurrentMagnificationSpec;
-
-        // Handle scale.
-        if (Float.isNaN(scale)) {
-            scale = getScale();
-        }
+        boolean changed = false;
 
         final float normScale = MathUtils.constrain(scale, MIN_SCALE, MAX_SCALE);
         if (Float.compare(currSpec.scale, normScale) != 0) {
@@ -490,24 +507,16 @@
             changed = true;
         }
 
-        // Handle X offset.
-        if (Float.isNaN(centerX)) {
-            centerX = getCenterX();
-        }
-
-        final float nonNormOffsetX = mMagnifiedBounds.width() / 2.0f - centerX * scale;
+        final float nonNormOffsetX = mMagnifiedBounds.width() / 2.0f
+                + mMagnifiedBounds.left - centerX * scale;
         final float offsetX = MathUtils.constrain(nonNormOffsetX, getMinOffsetXLocked(), 0);
         if (Float.compare(currSpec.offsetX, offsetX) != 0) {
             currSpec.offsetX = offsetX;
             changed = true;
         }
 
-        // Handle Y offset.
-        if (Float.isNaN(centerY)) {
-            centerY = getCenterY();
-        }
-
-        final float nonNormOffsetY = mMagnifiedBounds.height() / 2.0f - centerY * scale;
+        final float nonNormOffsetY = mMagnifiedBounds.height() / 2.0f
+                + mMagnifiedBounds.top - centerY * scale;
         final float offsetY = MathUtils.constrain(nonNormOffsetY, getMinOffsetYLocked(), 0);
         if (Float.compare(currSpec.offsetY, offsetY) != 0) {
             currSpec.offsetY = offsetY;
@@ -661,6 +670,12 @@
             mTransformationAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
         }
 
+        public void cancel() {
+            if (mTransformationAnimator != null && mTransformationAnimator.isRunning()) {
+                mTransformationAnimator.cancel();
+            }
+        }
+
         public void updateSentSpec(MagnificationSpec spec, boolean animate) {
             if (Thread.currentThread().getId() == mMainThreadId) {
                 // Already on the main thread, don't bother proxying.
@@ -811,9 +826,6 @@
         private static final int MESSAGE_ON_USER_CONTEXT_CHANGED = 3;
         private static final int MESSAGE_ON_ROTATION_CHANGED = 4;
 
-        private final Rect mTempRect = new Rect();
-        private final Rect mTempRect1 = new Rect();
-
         private final MagnificationController mController;
         private final WindowManagerInternal mWindowManager;
         private final Handler mHandler;
@@ -884,6 +896,10 @@
             mController.resetIfNeeded(true);
         }
 
+        public void getRegions(@NonNull Region outMagnified, @NonNull Region outAvailable) {
+            mWindowManager.getMagnificationRegions(outMagnified, outAvailable);
+        }
+
         private class CallbackHandler extends Handler {
             public CallbackHandler(Context context) {
                 super(context.getMainLooper());
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index b737ae2..6288b56 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -1818,7 +1818,7 @@
             File initSentinel = new File(stateDir, INIT_SENTINEL_FILE_NAME);
             if (initSentinel.exists()) {
                 synchronized (mQueueLock) {
-                    mPendingInits.add(transportName);
+                    mPendingInits.add(name);
 
                     // TODO: pick a better starting time than now + 1 minute
                     long delay = 1000 * 60; // one minute, in milliseconds
@@ -2316,6 +2316,25 @@
         }
     }
 
+    // What name is this transport registered under...?
+    private String getTransportName(IBackupTransport transport) {
+        if (MORE_DEBUG) {
+            Slog.v(TAG, "Searching for transport name of " + transport);
+        }
+        synchronized (mTransports) {
+            final int N = mTransports.size();
+            for (int i = 0; i < N; i++) {
+                if (mTransports.valueAt(i).equals(transport)) {
+                    if (MORE_DEBUG) {
+                        Slog.v(TAG, "  Name found: " + mTransports.keyAt(i));
+                    }
+                    return mTransports.keyAt(i);
+                }
+            }
+        }
+        return null;
+    }
+
     // fire off a backup agent, blocking until it attaches or times out
     IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) {
         IBackupAgent agent = null;
@@ -2921,7 +2940,15 @@
                     if (MORE_DEBUG) Slog.d(TAG, "Server requires init; rerunning");
                     addBackupTrace("init required; rerunning");
                     try {
-                        mPendingInits.add(mTransport.transportDirName());
+                        final String name = getTransportName(mTransport);
+                        if (name != null) {
+                            mPendingInits.add(name);
+                        } else {
+                            if (DEBUG) {
+                                Slog.w(TAG, "Couldn't find name of transport " + mTransport
+                                        + " for init");
+                            }
+                        }
                     } catch (Exception e) {
                         Slog.w(TAG, "Failed to query transport name heading for init", e);
                         // swallow it and proceed; we don't rely on this
@@ -7590,77 +7617,6 @@
 
     // ----- Restore handling -----
 
-    // new style: we only store the SHA-1 hashes of each sig, not the full block
-    static boolean signaturesMatch(ArrayList<byte[]> storedSigHashes, PackageInfo target) {
-        if (target == null) {
-            return false;
-        }
-
-        // If the target resides on the system partition, we allow it to restore
-        // data from the like-named package in a restore set even if the signatures
-        // do not match.  (Unlike general applications, those flashed to the system
-        // partition will be signed with the device's platform certificate, so on
-        // different phones the same system app will have different signatures.)
-        if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
-            if (MORE_DEBUG) Slog.v(TAG, "System app " + target.packageName + " - skipping sig check");
-            return true;
-        }
-
-        // Allow unsigned apps, but not signed on one device and unsigned on the other
-        // !!! TODO: is this the right policy?
-        Signature[] deviceSigs = target.signatures;
-        if (MORE_DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes
-                + " device=" + deviceSigs);
-        if ((storedSigHashes == null || storedSigHashes.size() == 0)
-                && (deviceSigs == null || deviceSigs.length == 0)) {
-            return true;
-        }
-        if (storedSigHashes == null || deviceSigs == null) {
-            return false;
-        }
-
-        // !!! TODO: this demands that every stored signature match one
-        // that is present on device, and does not demand the converse.
-        // Is this this right policy?
-        final int nStored = storedSigHashes.size();
-        final int nDevice = deviceSigs.length;
-
-        // hash each on-device signature
-        ArrayList<byte[]> deviceHashes = new ArrayList<byte[]>(nDevice);
-        for (int i = 0; i < nDevice; i++) {
-            deviceHashes.add(hashSignature(deviceSigs[i]));
-        }
-
-        // now ensure that each stored sig (hash) matches an on-device sig (hash)
-        for (int n = 0; n < nStored; n++) {
-            boolean match = false;
-            final byte[] storedHash = storedSigHashes.get(n);
-            for (int i = 0; i < nDevice; i++) {
-                if (Arrays.equals(storedHash, deviceHashes.get(i))) {
-                    match = true;
-                    break;
-                }
-            }
-            // match is false when no on-device sig matched one of the stored ones
-            if (!match) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    static byte[] hashSignature(Signature sig) {
-        try {
-            MessageDigest digest = MessageDigest.getInstance("SHA-256");
-            digest.update(sig.toByteArray());
-            return digest.digest();
-        } catch (NoSuchAlgorithmException e) {
-            Slog.w(TAG, "No SHA-256 algorithm found!");
-        }
-        return null;
-    }
-
     // Old style: directly match the stored vs on device signature blocks
     static boolean signaturesMatch(Signature[] storedSigs, PackageInfo target) {
         if (target == null) {
@@ -8173,7 +8129,7 @@
             }
 
             Metadata metaInfo = mPmAgent.getRestoredMetadata(packageName);
-            if (!signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
+            if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage)) {
                 Slog.w(TAG, "Signature mismatch restoring " + packageName);
                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
                         "Signature mismatch");
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index f197c1e..09f240f 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -205,7 +205,7 @@
                         PackageManager.GET_SIGNATURES);
                 homeInstaller = mPackageManager.getInstallerPackageName(home.getPackageName());
                 homeVersion = homeInfo.versionCode;
-                homeSigHashes = hashSignatureArray(homeInfo.signatures);
+                homeSigHashes = BackupUtils.hashSignatureArray(homeInfo.signatures);
             } catch (NameNotFoundException e) {
                 Slog.w(TAG, "Can't access preferred home info");
                 // proceed as though there were no preferred home set
@@ -222,7 +222,7 @@
             final boolean needHomeBackup = (homeVersion != mStoredHomeVersion)
                     || !Objects.equals(home, mStoredHomeComponent)
                     || (home != null
-                        && !BackupManagerService.signaturesMatch(mStoredHomeSigHashes, homeInfo));
+                        && !BackupUtils.signaturesMatch(mStoredHomeSigHashes, homeInfo));
             if (needHomeBackup) {
                 if (DEBUG) {
                     Slog.i(TAG, "Home preference changed; backing up new state " + home);
@@ -309,7 +309,7 @@
                     outputBuffer.reset();
                     outputBufferStream.writeInt(info.versionCode);
                     writeSignatureHashArray(outputBufferStream,
-                            hashSignatureArray(info.signatures));
+                            BackupUtils.hashSignatureArray(info.signatures));
 
                     if (DEBUG) {
                         Slog.v(TAG, "+ writing metadata for " + packName
@@ -432,18 +432,6 @@
         mRestoredSignatures = sigMap;
     }
 
-    private static ArrayList<byte[]> hashSignatureArray(Signature[] sigs) {
-        if (sigs == null) {
-            return null;
-        }
-
-        ArrayList<byte[]> hashes = new ArrayList<byte[]>(sigs.length);
-        for (Signature s : sigs) {
-            hashes.add(BackupManagerService.hashSignature(s));
-        }
-        return hashes;
-    }
-
     private static void writeSignatureHashArray(DataOutputStream out, ArrayList<byte[]> hashes)
             throws IOException {
         // the number of entries in the array
@@ -492,13 +480,8 @@
             }
 
             if (nonHashFound) {
-                ArrayList<byte[]> hashes =
-                        new ArrayList<byte[]>(sigs.size());
-                for (int i = 0; i < sigs.size(); i++) {
-                    Signature s = new Signature(sigs.get(i));
-                    hashes.add(BackupManagerService.hashSignature(s));
-                }
-                sigs = hashes;
+                // Replace with the hashes.
+                sigs = BackupUtils.hashSignatureArray(sigs);
             }
 
             return sigs;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 5b4a96d..a9ef1d6 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -4787,6 +4787,8 @@
                     "    Task id #" + task.taskId + "\n" +
                     "    mFullscreen=" + task.mFullscreen + "\n" +
                     "    mBounds=" + task.mBounds + "\n" +
+                    "    mMinimalWidth=" + task.mMinimalWidth + "\n" +
+                    "    mMinimalHeight=" + task.mMinimalHeight + "\n" +
                     "    mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
             if (printed) {
                 header = null;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index ffa3b5b..3d42047 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1224,7 +1224,8 @@
     // WiFi keeps an accumulated total of stats, unlike Bluetooth.
     // Keep the last WiFi stats so we can compute a delta.
     @GuardedBy("mExternalStatsLock")
-    private WifiActivityEnergyInfo mLastInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+    private WifiActivityEnergyInfo mLastInfo =
+            new WifiActivityEnergyInfo(0, 0, 0, new long[]{0}, 0, 0, 0);
 
     @GuardedBy("mExternalStatsLock")
     private WifiActivityEnergyInfo pullWifiEnergyInfoLocked() {
diff --git a/services/core/java/com/android/server/backup/BackupUtils.java b/services/core/java/com/android/server/backup/BackupUtils.java
new file mode 100644
index 0000000..e5d564d
--- /dev/null
+++ b/services/core/java/com/android/server/backup/BackupUtils.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.Signature;
+import android.util.Slog;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class BackupUtils {
+    private static final String TAG = "BackupUtils";
+
+    private static final boolean DEBUG = false; // STOPSHIP if true
+
+    public static boolean signaturesMatch(ArrayList<byte[]> storedSigHashes, PackageInfo target) {
+        if (target == null) {
+            return false;
+        }
+
+        // If the target resides on the system partition, we allow it to restore
+        // data from the like-named package in a restore set even if the signatures
+        // do not match.  (Unlike general applications, those flashed to the system
+        // partition will be signed with the device's platform certificate, so on
+        // different phones the same system app will have different signatures.)
+        if ((target.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+            if (DEBUG) Slog.v(TAG, "System app " + target.packageName + " - skipping sig check");
+            return true;
+        }
+
+        // Allow unsigned apps, but not signed on one device and unsigned on the other
+        // !!! TODO: is this the right policy?
+        Signature[] deviceSigs = target.signatures;
+        if (DEBUG) Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes
+                + " device=" + deviceSigs);
+        if ((storedSigHashes == null || storedSigHashes.size() == 0)
+                && (deviceSigs == null || deviceSigs.length == 0)) {
+            return true;
+        }
+        if (storedSigHashes == null || deviceSigs == null) {
+            return false;
+        }
+
+        // !!! TODO: this demands that every stored signature match one
+        // that is present on device, and does not demand the converse.
+        // Is this this right policy?
+        final int nStored = storedSigHashes.size();
+        final int nDevice = deviceSigs.length;
+
+        // hash each on-device signature
+        ArrayList<byte[]> deviceHashes = new ArrayList<byte[]>(nDevice);
+        for (int i = 0; i < nDevice; i++) {
+            deviceHashes.add(hashSignature(deviceSigs[i]));
+        }
+
+        // now ensure that each stored sig (hash) matches an on-device sig (hash)
+        for (int n = 0; n < nStored; n++) {
+            boolean match = false;
+            final byte[] storedHash = storedSigHashes.get(n);
+            for (int i = 0; i < nDevice; i++) {
+                if (Arrays.equals(storedHash, deviceHashes.get(i))) {
+                    match = true;
+                    break;
+                }
+            }
+            // match is false when no on-device sig matched one of the stored ones
+            if (!match) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    public static byte[] hashSignature(byte[] signature) {
+        try {
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+            digest.update(signature);
+            return digest.digest();
+        } catch (NoSuchAlgorithmException e) {
+            Slog.w(TAG, "No SHA-256 algorithm found!");
+        }
+        return null;
+    }
+
+    public static byte[] hashSignature(Signature signature) {
+        return hashSignature(signature.toByteArray());
+    }
+
+    public static ArrayList<byte[]> hashSignatureArray(Signature[] sigs) {
+        if (sigs == null) {
+            return null;
+        }
+
+        ArrayList<byte[]> hashes = new ArrayList<>(sigs.length);
+        for (Signature s : sigs) {
+            hashes.add(hashSignature(s));
+        }
+        return hashes;
+    }
+
+    public static ArrayList<byte[]> hashSignatureArray(List<byte[]> sigs) {
+        if (sigs == null) {
+            return null;
+        }
+
+        ArrayList<byte[]> hashes = new ArrayList<>(sigs.size());
+        for (byte[] s : sigs) {
+            hashes.add(hashSignature(s));
+        }
+        return hashes;
+    }
+}
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/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5263c37..6df36e4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2196,7 +2196,13 @@
     }
 
     private void removeUserState(final int userHandle) {
-        mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle);
+        try {
+            mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle);
+        } catch (IllegalStateException e) {
+            // This may be simply because the user was partially created.
+            Slog.i(LOG_TAG,
+                "Destroying key for user " + userHandle + " failed, continuing anyway", e);
+        }
         // Cleanup package manager settings
         mPm.cleanUpUser(this, userHandle);
 
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 2c15818..98d44ac 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -21,6 +21,7 @@
 
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
+import android.annotation.NonNull;
 import android.app.Service;
 import android.content.Context;
 import android.graphics.Canvas;
@@ -122,6 +123,12 @@
         }
     }
 
+    public void getMagnificationRegionsLocked(Region outMagnified, Region outAvailable) {
+        if (mDisplayMagnifier != null) {
+            mDisplayMagnifier.getMagnificationRegionsLocked(outMagnified, outAvailable);
+        }
+    }
+
     public void onRectangleOnScreenRequestedLocked(Rect rectangle) {
         if (mDisplayMagnifier != null) {
             mDisplayMagnifier.onRectangleOnScreenRequestedLocked(rectangle);
@@ -392,6 +399,10 @@
             return spec;
         }
 
+        public void getMagnificationRegionsLocked(Region outMagnified, Region outAvailable) {
+            mMagnifedViewport.getBoundsLocked(outMagnified, outAvailable);
+        }
+
         public void destroyLocked() {
             mMagnifedViewport.destroyWindow();
         }
@@ -413,6 +424,7 @@
             private final Matrix mTempMatrix = new Matrix();
 
             private final Region mMagnifiedBounds = new Region();
+            private final Region mAvailableBounds = new Region();
             private final Region mOldMagnifiedBounds = new Region();
             private final Region mOldAvailableBounds = new Region();
 
@@ -450,6 +462,12 @@
                 recomputeBoundsLocked();
             }
 
+            public void getBoundsLocked(@NonNull Region outMagnified,
+                    @NonNull Region outAvailable) {
+                outMagnified.set(mMagnifiedBounds);
+                outAvailable.set(mAvailableBounds);
+            }
+
             public void updateMagnificationSpecLocked(MagnificationSpec spec) {
                 if (spec != null) {
                     mMagnificationSpec.initialize(spec.scale, spec.offsetX, spec.offsetY);
@@ -469,14 +487,11 @@
                 final int screenWidth = mTempPoint.x;
                 final int screenHeight = mTempPoint.y;
 
-                Region magnifiedBounds = mMagnifiedBounds;
-                magnifiedBounds.set(0, 0, 0, 0);
-
-                Region availableBounds = mTempRegion1;
-                availableBounds.set(0, 0, screenWidth, screenHeight);
+                mMagnifiedBounds.set(0, 0, 0, 0);
+                mAvailableBounds.set(0, 0, screenWidth, screenHeight);
 
                 if (mCircularPath != null) {
-                    availableBounds.setPath(mCircularPath, availableBounds);
+                    mAvailableBounds.setPath(mCircularPath, mAvailableBounds);
                 }
 
                 Region nonMagnifiedBounds = mTempRegion4;
@@ -505,8 +520,8 @@
                         matrix.mapRect(windowFrame);
                         windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
                                 (int) windowFrame.right, (int) windowFrame.bottom);
-                        magnifiedBounds.op(windowBounds, Region.Op.UNION);
-                        magnifiedBounds.op(availableBounds, Region.Op.INTERSECT);
+                        mMagnifiedBounds.op(windowBounds, Region.Op.UNION);
+                        mMagnifiedBounds.op(mAvailableBounds, Region.Op.INTERSECT);
                     } else {
                         Region touchableRegion = mTempRegion3;
                         windowState.getTouchableRegion(touchableRegion);
@@ -518,12 +533,12 @@
                         windowBounds.set((int) windowFrame.left, (int) windowFrame.top,
                                 (int) windowFrame.right, (int) windowFrame.bottom);
                         nonMagnifiedBounds.op(windowBounds, Region.Op.UNION);
-                        windowBounds.op(magnifiedBounds, Region.Op.DIFFERENCE);
-                        availableBounds.op(windowBounds, Region.Op.DIFFERENCE);
+                        windowBounds.op(mMagnifiedBounds, Region.Op.DIFFERENCE);
+                        mAvailableBounds.op(windowBounds, Region.Op.DIFFERENCE);
                     }
 
                     Region accountedBounds = mTempRegion2;
-                    accountedBounds.set(magnifiedBounds);
+                    accountedBounds.set(mMagnifiedBounds);
                     accountedBounds.op(nonMagnifiedBounds, Region.Op.UNION);
                     accountedBounds.op(0, 0, screenWidth, screenHeight, Region.Op.INTERSECT);
 
@@ -539,15 +554,15 @@
 
                 visibleWindows.clear();
 
-                magnifiedBounds.op(mDrawBorderInset, mDrawBorderInset,
+                mMagnifiedBounds.op(mDrawBorderInset, mDrawBorderInset,
                         screenWidth - mDrawBorderInset, screenHeight - mDrawBorderInset,
                         Region.Op.INTERSECT);
 
-                final boolean magnifiedChanged = !mOldMagnifiedBounds.equals(magnifiedBounds);
-                final boolean availableChanged = !mOldAvailableBounds.equals(availableBounds);
+                final boolean magnifiedChanged = !mOldMagnifiedBounds.equals(mMagnifiedBounds);
+                final boolean availableChanged = !mOldAvailableBounds.equals(mAvailableBounds);
                 if (magnifiedChanged || availableChanged) {
                     if (magnifiedChanged) {
-                        mWindow.setBounds(magnifiedBounds);
+                        mWindow.setBounds(mMagnifiedBounds);
                         Rect dirtyRect = mTempRect1;
                         if (mFullRedrawNeeded) {
                             mFullRedrawNeeded = false;
@@ -557,23 +572,23 @@
                             mWindow.invalidate(dirtyRect);
                         } else {
                             Region dirtyRegion = mTempRegion3;
-                            dirtyRegion.set(magnifiedBounds);
+                            dirtyRegion.set(mMagnifiedBounds);
                             dirtyRegion.op(mOldMagnifiedBounds, Region.Op.UNION);
                             dirtyRegion.op(nonMagnifiedBounds, Region.Op.INTERSECT);
                             dirtyRegion.getBounds(dirtyRect);
                             mWindow.invalidate(dirtyRect);
                         }
 
-                        mOldMagnifiedBounds.set(magnifiedBounds);
+                        mOldMagnifiedBounds.set(mMagnifiedBounds);
                     }
 
                     if (availableChanged) {
-                        mOldAvailableBounds.set(availableBounds);
+                        mOldAvailableBounds.set(mAvailableBounds);
                     }
 
                     final SomeArgs args = SomeArgs.obtain();
-                    args.arg1 = Region.obtain(magnifiedBounds);
-                    args.arg2 = Region.obtain(availableBounds);
+                    args.arg1 = Region.obtain(mMagnifiedBounds);
+                    args.arg2 = Region.obtain(mAvailableBounds);
                     mHandler.obtainMessage(
                             MyHandler.MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED, args).sendToTarget();
                 }
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4e8f19e..1f03c04 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -498,7 +498,15 @@
                 return;
             }
 
-            out.set(mBounds);
+            if (!mFullscreen) {
+                // When minimizing the docked stack when going home, we don't adjust the task bounds
+                // so we need to intersect the task bounds with the stack bounds here.
+                mStack.getBounds(mTmpRect);
+                mTmpRect.intersect(mBounds);
+                out.set(mTmpRect);
+            } else {
+                out.set(mBounds);
+            }
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5771d69..5d13b3b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -10725,6 +10725,19 @@
         }
 
         @Override
+        public void getMagnificationRegions(@NonNull Region outMagnified,
+                @NonNull Region outAvailable) {
+            synchronized (mWindowMap) {
+                if (mAccessibilityController != null) {
+                    mAccessibilityController.getMagnificationRegionsLocked(
+                            outMagnified, outAvailable);
+                } else {
+                    throw new IllegalStateException("Magnification callbacks not set!");
+                }
+            }
+        }
+
+        @Override
         public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) {
             synchronized (mWindowMap) {
                 WindowState windowState = mWindowMap.get(windowToken);
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.
diff --git a/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
new file mode 100644
index 0000000..c016e61
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/backup/BackupUtilsTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.pm.backup;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageParser.Package;
+import android.content.pm.Signature;
+import android.test.AndroidTestCase;
+import android.test.MoreAsserts;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.backup.BackupUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+@SmallTest
+public class BackupUtilsTest extends AndroidTestCase {
+
+    private Signature[] genSignatures(String... signatures) {
+        final Signature[] sigs = new Signature[signatures.length];
+        for (int i = 0; i < signatures.length; i++){
+            sigs[i] = new Signature(signatures[i].getBytes());
+        }
+        return sigs;
+    }
+
+    private PackageInfo genPackage(String... signatures) {
+        final PackageInfo pi = new PackageInfo();
+        pi.packageName = "package";
+        pi.applicationInfo = new ApplicationInfo();
+        pi.signatures = genSignatures(signatures);
+
+        return pi;
+    }
+
+    public void testSignaturesMatch() {
+        final ArrayList<byte[]> stored1 = BackupUtils.hashSignatureArray(Arrays.asList(
+                "abc".getBytes()));
+        final ArrayList<byte[]> stored2 = BackupUtils.hashSignatureArray(Arrays.asList(
+                "abc".getBytes(), "def".getBytes()));
+
+        PackageInfo pi;
+
+        // False for null package.
+        assertFalse(BackupUtils.signaturesMatch(stored1, null));
+
+        // If it's a system app, signatures don't matter.
+        pi = genPackage("xyz");
+        pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+        assertTrue(BackupUtils.signaturesMatch(stored1, pi));
+
+        // Non system apps.
+        assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc")));
+
+        // Superset is okay.
+        assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("abc", "xyz")));
+        assertTrue(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "abc")));
+
+        assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz")));
+        assertFalse(BackupUtils.signaturesMatch(stored1, genPackage("xyz", "def")));
+
+        assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("def", "abc")));
+        assertTrue(BackupUtils.signaturesMatch(stored2, genPackage("x", "def", "abc", "y")));
+
+        // Subset is not okay.
+        assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("abc")));
+        assertFalse(BackupUtils.signaturesMatch(stored2, genPackage("def")));
+    }
+
+    public void testHashSignature() {
+        final byte[] sig1 = "abc".getBytes();
+        final byte[] sig2 = "def".getBytes();
+
+        final byte[] hash1a = BackupUtils.hashSignature(sig1);
+        final byte[] hash1b = BackupUtils.hashSignature(new Signature(sig1));
+
+        final byte[] hash2a = BackupUtils.hashSignature(sig2);
+        final byte[] hash2b = BackupUtils.hashSignature(new Signature(sig2));
+
+        assertEquals(32, hash1a.length);
+        MoreAsserts.assertEquals(hash1a, hash1b);
+
+        assertEquals(32, hash2a.length);
+        MoreAsserts.assertEquals(hash2a, hash2b);
+
+        assertFalse(Arrays.equals(hash1a, hash2a));
+
+        final ArrayList<byte[]> listA = BackupUtils.hashSignatureArray(Arrays.asList(
+                "abc".getBytes(), "def".getBytes()));
+
+        final ArrayList<byte[]> listB = BackupUtils.hashSignatureArray(new Signature[]{
+                new Signature("abc".getBytes()), new Signature("def".getBytes())});
+
+        assertEquals(2, listA.size());
+        assertEquals(2, listB.size());
+
+        MoreAsserts.assertEquals(hash1a, listA.get(0));
+        MoreAsserts.assertEquals(hash1a, listB.get(0));
+
+        MoreAsserts.assertEquals(hash2a, listA.get(1));
+        MoreAsserts.assertEquals(hash2a, listB.get(1));
+    }
+}
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 06851ee..1ce4ade 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -694,7 +694,7 @@
         if (mPreviousExtraKeys != null) {
             List<String> toRemove = new ArrayList<String>();
             for (String oldKey : mPreviousExtraKeys) {
-                if (!extras.containsKey(oldKey)) {
+                if (extras == null || !extras.containsKey(oldKey)) {
                     toRemove.add(oldKey);
                 }
             }
@@ -710,7 +710,9 @@
             mPreviousExtraKeys = new ArraySet<String>();
         }
         mPreviousExtraKeys.clear();
-        mPreviousExtraKeys.addAll(extras.keySet());
+        if (extras != null) {
+            mPreviousExtraKeys.addAll(extras.keySet());
+        }
     }
 
     /**
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 310c957..d83cdb8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -1887,7 +1887,7 @@
         if (mPreviousExtraKeys != null) {
             List<String> toRemove = new ArrayList<String>();
             for (String oldKey : mPreviousExtraKeys) {
-                if (!extras.containsKey(oldKey)) {
+                if (extras == null || !extras.containsKey(oldKey)) {
                     toRemove.add(oldKey);
                 }
             }
@@ -1902,7 +1902,9 @@
             mPreviousExtraKeys = new ArraySet<String>();
         }
         mPreviousExtraKeys.clear();
-        mPreviousExtraKeys.addAll(extras.keySet());
+        if (extras != null) {
+            mPreviousExtraKeys.addAll(extras.keySet());
+        }
     }
 
     /**
@@ -2317,7 +2319,7 @@
      */
     public void sendConnectionEvent(String event, Bundle extras) {
         for (Listener l : mListeners) {
-            l.onConnectionEvent(this, event, null);
+            l.onConnectionEvent(this, event, extras);
         }
     }
 }
diff --git a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
index 035317e..4c38c9b 100644
--- a/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
+++ b/wifi/java/android/net/wifi/WifiActivityEnergyInfo.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Arrays;
+
 /**
  * Record of energy and activity information from controller and
  * underlying wifi stack state. Timestamp the record with elapsed
@@ -44,6 +46,11 @@
     /**
      * @hide
      */
+    public long[] mControllerTxTimePerLevelMs;
+
+    /**
+     * @hide
+     */
     public long mControllerRxTimeMs;
 
     /**
@@ -62,10 +69,12 @@
     public static final int STACK_STATE_STATE_IDLE = 3;
 
     public WifiActivityEnergyInfo(long timestamp, int stackState,
-                                  long txTime, long rxTime, long idleTime, long energyUsed) {
+                                  long txTime, long[] txTimePerLevel, long rxTime, long idleTime,
+                                  long energyUsed) {
         mTimestamp = timestamp;
         mStackState = stackState;
         mControllerTxTimeMs = txTime;
+        mControllerTxTimePerLevelMs = txTimePerLevel;
         mControllerRxTimeMs = rxTime;
         mControllerIdleTimeMs = idleTime;
         mControllerEnergyUsed = energyUsed;
@@ -77,6 +86,7 @@
             + " timestamp=" + mTimestamp
             + " mStackState=" + mStackState
             + " mControllerTxTimeMs=" + mControllerTxTimeMs
+            + " mControllerTxTimePerLevelMs=" + Arrays.toString(mControllerTxTimePerLevelMs)
             + " mControllerRxTimeMs=" + mControllerRxTimeMs
             + " mControllerIdleTimeMs=" + mControllerIdleTimeMs
             + " mControllerEnergyUsed=" + mControllerEnergyUsed
@@ -89,11 +99,12 @@
             long timestamp = in.readLong();
             int stackState = in.readInt();
             long txTime = in.readLong();
+            long[] txTimePerLevel = in.createLongArray();
             long rxTime = in.readLong();
             long idleTime = in.readLong();
             long energyUsed = in.readLong();
             return new WifiActivityEnergyInfo(timestamp, stackState,
-                    txTime, rxTime, idleTime, energyUsed);
+                    txTime, txTimePerLevel, rxTime, idleTime, energyUsed);
         }
         public WifiActivityEnergyInfo[] newArray(int size) {
             return new WifiActivityEnergyInfo[size];
@@ -104,6 +115,7 @@
         out.writeLong(mTimestamp);
         out.writeInt(mStackState);
         out.writeLong(mControllerTxTimeMs);
+        out.writeLongArray(mControllerTxTimePerLevelMs);
         out.writeLong(mControllerRxTimeMs);
         out.writeLong(mControllerIdleTimeMs);
         out.writeLong(mControllerEnergyUsed);
@@ -128,6 +140,16 @@
     }
 
     /**
+     * @return tx time at power level provided in ms
+     */
+    public long getControllerTxTimeMillisAtLevel(int level) {
+        if (level < mControllerTxTimePerLevelMs.length) {
+            return mControllerTxTimePerLevelMs[level];
+        }
+        return 0;
+    }
+
+    /**
      * @return rx time in ms
      */
     public long getControllerRxTimeMillis() {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 06dea07..fb2bdd4 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -938,6 +938,15 @@
         private boolean mSeenInLastQualifiedNetworkSelection;
 
         /**
+         * Boolean indicating if we have ever successfully connected to this network.
+         *
+         * This value will be set to true upon a successful connection.
+         * This value will be set to false if a previous value was not stored in the config or if
+         * the credentials are updated (ex. a password change).
+         */
+        private boolean mHasEverConnected;
+
+        /**
          * set whether this network is visible in latest Qualified Network Selection
          * @param seen value set to candidate
          */
@@ -1027,7 +1036,18 @@
             return QUALITY_NETWORK_SELECTION_STATUS[mStatus];
         }
 
-        private NetworkSelectionStatus() {};
+        public void setHasEverConnected(boolean value) {
+            mHasEverConnected = value;
+        }
+
+        public boolean getHasEverConnected() {
+            return mHasEverConnected;
+        }
+
+        private NetworkSelectionStatus() {
+            // previously stored configs will not have this parameter, so we default to false.
+            mHasEverConnected = false;
+        };
 
         /**
          * @param reason specific error reason
@@ -1226,6 +1246,7 @@
             mNetworkSelectionBSSID = source.mNetworkSelectionBSSID;
             setConnectChoice(source.getConnectChoice());
             setConnectChoiceTimestamp(source.getConnectChoiceTimestamp());
+            setHasEverConnected(source.getHasEverConnected());
         }
 
         public void writeToParcel(Parcel dest) {
@@ -1244,6 +1265,7 @@
             } else {
                 dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
             }
+            dest.writeInt(getHasEverConnected() ? 1 : 0);
         }
 
         public void readFromParcel(Parcel in) {
@@ -1262,6 +1284,7 @@
                 setConnectChoice(null);
                 setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
             }
+            setHasEverConnected(in.readInt() != 0);
         }
     }
 
@@ -1389,6 +1412,8 @@
             sbuf.append(" connect choice set time: ").append(mNetworkSelectionStatus
                     .getConnectChoiceTimestamp());
         }
+        sbuf.append(" hasEverConnected: ")
+                .append(mNetworkSelectionStatus.getHasEverConnected()).append("\n");
 
         if (this.numAssociation > 0) {
             sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
diff --git a/wifi/java/android/net/wifi/WifiLinkLayerStats.java b/wifi/java/android/net/wifi/WifiLinkLayerStats.java
index 1de4fd8..edd400b 100644
--- a/wifi/java/android/net/wifi/WifiLinkLayerStats.java
+++ b/wifi/java/android/net/wifi/WifiLinkLayerStats.java
@@ -19,6 +19,8 @@
 import android.os.Parcelable;
 import android.os.Parcel;
 
+import java.util.Arrays;
+
 /**
  * A class representing link layer statistics collected over a Wifi Interface.
  */
@@ -101,6 +103,8 @@
     /** {@hide} */
     public int tx_time;
     /** {@hide} */
+    public int[] tx_time_per_level;
+    /** {@hide} */
     public int rx_time;
     /** {@hide} */
     public int on_time_scan;
@@ -141,9 +145,10 @@
                 .append(" lost=").append(Long.toString(this.lostmpdu_vo))
                 .append(" retries=").append(Long.toString(this.retries_vo)).append('\n');
         sbuf.append(" on_time : ").append(Integer.toString(this.on_time))
-                .append(" tx_time=").append(Integer.toString(this.tx_time))
                 .append(" rx_time=").append(Integer.toString(this.rx_time))
-                .append(" scan_time=").append(Integer.toString(this.on_time_scan)).append('\n');
+                .append(" scan_time=").append(Integer.toString(this.on_time_scan)).append('\n')
+                .append(" tx_time=").append(Integer.toString(this.tx_time))
+                .append(" tx_time_per_level=" + Arrays.toString(tx_time_per_level));
         return sbuf.toString();
     }
 
@@ -179,6 +184,7 @@
         dest.writeString(BSSID);
         dest.writeInt(on_time);
         dest.writeInt(tx_time);
+        dest.writeIntArray(tx_time_per_level);
         dest.writeInt(rx_time);
         dest.writeInt(on_time_scan);
     }
@@ -192,6 +198,7 @@
                 stats.BSSID = in.readString();
                 stats.on_time = in.readInt();
                 stats.tx_time = in.readInt();
+                stats.tx_time_per_level = in.createIntArray();
                 stats.rx_time = in.readInt();
                 stats.on_time_scan = in.readInt();
                 return stats;