Merge "Add new job scheduler constraints for "battery not low"."
diff --git a/api/current.txt b/api/current.txt
index 1d58c28..22dbe7b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10105,10 +10105,12 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+    method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10647,6 +10649,9 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
+    method public android.content.ComponentName[] getChooserComponentNames();
+    method public android.os.PersistableBundle getChooserExtras();
+    method public android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -10659,6 +10664,7 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
+    method public boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -10671,9 +10677,11 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+    method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -14015,6 +14023,8 @@
 
   public class ArcShape extends android.graphics.drawable.shapes.RectShape {
     ctor public ArcShape(float, float);
+    method public final float getStartAngle();
+    method public final float getSweepAngle();
   }
 
   public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -22166,6 +22176,7 @@
     field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
     field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
     field public static final java.lang.String KEY_LANGUAGE = "language";
+    field public static final java.lang.String KEY_LATENCY = "latency";
     field public static final java.lang.String KEY_LEVEL = "level";
     field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
     field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -26132,8 +26143,6 @@
   public class DiscoverySession {
     method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
     method public void destroy();
-    method public static int getMaxSendRetryCount();
-    method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
 
@@ -36393,16 +36402,17 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
-    field public static final int SAVE_UI_TYPE_ADDRESS = 2; // 0x2
-    field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
-    field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
-    field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+    field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+    field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
   }
 
   public static final class SaveInfo.Builder {
     ctor public SaveInfo.Builder(int);
     method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
     method public android.service.autofill.SaveInfo build();
+    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
   }
 
 }
diff --git a/api/system-current.txt b/api/system-current.txt
index bdcfa6f..daf8cef 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10642,10 +10642,12 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+    method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -11269,6 +11271,9 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
+    method public android.content.ComponentName[] getChooserComponentNames();
+    method public android.os.PersistableBundle getChooserExtras();
+    method public android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -11281,6 +11286,7 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
+    method public boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -11293,9 +11299,11 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+    method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -14651,6 +14659,8 @@
 
   public class ArcShape extends android.graphics.drawable.shapes.RectShape {
     ctor public ArcShape(float, float);
+    method public final float getStartAngle();
+    method public final float getSweepAngle();
   }
 
   public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -23854,6 +23864,7 @@
     field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
     field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
     field public static final java.lang.String KEY_LANGUAGE = "language";
+    field public static final java.lang.String KEY_LATENCY = "latency";
     field public static final java.lang.String KEY_LEVEL = "level";
     field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
     field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -28717,8 +28728,6 @@
   public class DiscoverySession {
     method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
     method public void destroy();
-    method public static int getMaxSendRetryCount();
-    method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
 
@@ -39313,16 +39322,17 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
-    field public static final int SAVE_UI_TYPE_ADDRESS = 2; // 0x2
-    field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
-    field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
-    field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+    field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+    field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
   }
 
   public static final class SaveInfo.Builder {
     ctor public SaveInfo.Builder(int);
     method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
     method public android.service.autofill.SaveInfo build();
+    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index 8b4189a..e9dddc3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -10137,10 +10137,12 @@
     ctor public LauncherApps.ShortcutQuery();
     method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
     method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+    method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
     method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
     method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
     method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
     field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+    field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
     field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
     field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
     field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10683,6 +10685,9 @@
     method public int describeContents();
     method public android.content.ComponentName getActivity();
     method public java.util.Set<java.lang.String> getCategories();
+    method public android.content.ComponentName[] getChooserComponentNames();
+    method public android.os.PersistableBundle getChooserExtras();
+    method public android.content.IntentFilter[] getChooserIntentFilters();
     method public java.lang.CharSequence getDisabledMessage();
     method public android.os.PersistableBundle getExtras();
     method public java.lang.String getId();
@@ -10695,6 +10700,7 @@
     method public java.lang.CharSequence getShortLabel();
     method public android.os.UserHandle getUserHandle();
     method public boolean hasKeyFieldsOnly();
+    method public boolean isChooser();
     method public boolean isDeclaredInManifest();
     method public boolean isDynamic();
     method public boolean isEnabled();
@@ -10707,9 +10713,11 @@
 
   public static class ShortcutInfo.Builder {
     ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+    method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
     method public android.content.pm.ShortcutInfo build();
     method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
     method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+    method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
     method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -14053,6 +14061,8 @@
 
   public class ArcShape extends android.graphics.drawable.shapes.RectShape {
     ctor public ArcShape(float, float);
+    method public final float getStartAngle();
+    method public final float getSweepAngle();
   }
 
   public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -22262,6 +22272,7 @@
     field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
     field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
     field public static final java.lang.String KEY_LANGUAGE = "language";
+    field public static final java.lang.String KEY_LATENCY = "latency";
     field public static final java.lang.String KEY_LEVEL = "level";
     field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
     field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -26228,8 +26239,6 @@
   public class DiscoverySession {
     method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
     method public void destroy();
-    method public static int getMaxSendRetryCount();
-    method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
     method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
   }
 
@@ -36532,16 +36541,17 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
-    field public static final int SAVE_UI_TYPE_ADDRESS = 2; // 0x2
-    field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
-    field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
-    field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+    field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+    field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+    field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
   }
 
   public static final class SaveInfo.Builder {
     ctor public SaveInfo.Builder(int);
     method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
     method public android.service.autofill.SaveInfo build();
+    method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
   }
 
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3e9b987..7ee93d0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -38,6 +38,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetManager;
+import android.content.res.CompatResources;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -49,6 +50,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Environment;
@@ -1925,8 +1927,8 @@
             final int displayId = mDisplay != null
                     ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
 
-            c.mResources = createResources(mActivityToken, pi, displayId, null,
-                    getDisplayAdjustments(displayId).getCompatibilityInfo());
+            c.setResources(createResources(mActivityToken, pi, displayId, null,
+                    getDisplayAdjustments(displayId).getCompatibilityInfo()));
             if (c.mResources != null) {
                 return c;
             }
@@ -1962,8 +1964,8 @@
             final int displayId = mDisplay != null
                     ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
 
-            c.mResources = createResources(mActivityToken, pi, displayId, null,
-                    getDisplayAdjustments(displayId).getCompatibilityInfo());
+            c.setResources(createResources(mActivityToken, pi, displayId, null,
+                    getDisplayAdjustments(displayId).getCompatibilityInfo()));
             if (c.mResources != null) {
                 return c;
             }
@@ -1990,7 +1992,7 @@
         final int displayId = mDisplay != null
                 ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
 
-        context.mResources = ResourcesManager.getInstance().getResources(
+        context.setResources(ResourcesManager.getInstance().getResources(
                 mActivityToken,
                 mPackageInfo.getResDir(),
                 paths,
@@ -1999,7 +2001,7 @@
                 displayId,
                 null,
                 mPackageInfo.getCompatibilityInfo(),
-                classLoader);
+                classLoader));
         return context;
     }
 
@@ -2013,8 +2015,8 @@
                 mUser, mFlags, mClassLoader);
 
         final int displayId = mDisplay != null ? mDisplay.getDisplayId() : Display.DEFAULT_DISPLAY;
-        context.mResources = createResources(mActivityToken, mPackageInfo, displayId,
-                overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo());
+        context.setResources(createResources(mActivityToken, mPackageInfo, displayId,
+                overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo()));
         return context;
     }
 
@@ -2028,8 +2030,8 @@
                 mUser, mFlags, mClassLoader);
 
         final int displayId = display.getDisplayId();
-        context.mResources = createResources(mActivityToken, mPackageInfo, displayId, null,
-                getDisplayAdjustments(displayId).getCompatibilityInfo());
+        context.setResources(createResources(mActivityToken, mPackageInfo, displayId, null,
+                getDisplayAdjustments(displayId).getCompatibilityInfo()));
         context.mDisplay = display;
         return context;
     }
@@ -2136,7 +2138,7 @@
         LoadedApk packageInfo = new LoadedApk(mainThread);
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, 0,
                 null);
-        context.mResources = packageInfo.getResources();
+        context.setResources(packageInfo.getResources());
         context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                 context.mResourcesManager.getDisplayMetrics());
         return context;
@@ -2146,7 +2148,7 @@
         if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, 0,
                 null);
-        context.mResources = packageInfo.getResources();
+        context.setResources(packageInfo.getResources());
         return context;
     }
 
@@ -2185,7 +2187,7 @@
 
         // Create the base resources for which all configuration contexts for this Activity
         // will be rebased upon.
-        context.mResources = resourcesManager.createBaseActivityResources(activityToken,
+        context.setResources(resourcesManager.createBaseActivityResources(activityToken,
                 packageInfo.getResDir(),
                 splitDirs,
                 packageInfo.getOverlayDirs(),
@@ -2193,7 +2195,7 @@
                 displayId,
                 overrideConfiguration,
                 compatInfo,
-                classLoader);
+                classLoader));
         context.mDisplay = resourcesManager.getAdjustedDisplay(displayId,
                 context.getResources());
         return context;
@@ -2232,7 +2234,7 @@
         if (container != null) {
             mBasePackageName = container.mBasePackageName;
             mOpPackageName = container.mOpPackageName;
-            mResources = container.mResources;
+            setResources(container.mResources);
             mDisplay = container.mDisplay;
         } else {
             mBasePackageName = packageInfo.mPackageName;
@@ -2251,6 +2253,14 @@
         mContentResolver = new ApplicationContentResolver(this, mainThread, user);
     }
 
+    void setResources(Resources r) {
+        if (mPackageInfo.getTargetSdkVersion() < VERSION_CODES.O) {
+            mResources = new CompatResources(r, this);
+        } else {
+            mResources = r;
+        }
+    }
+
     void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
         mPackageInfo.installSystemApplicationInfo(info, classLoader);
     }
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index c08bd1d..41311eb 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -55,7 +55,8 @@
             String callingPackage, String packageName, int flags, in UserHandle user);
 
     ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
-            in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
+            in List shortcutIds, in ComponentName componentName, in Intent intent, int flags,
+            in UserHandle user);
     void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
             in UserHandle user);
     boolean startShortcut(String callingPackage, String packageName, String id,
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index d76d824..776492a 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -275,7 +275,18 @@
         @Deprecated
         public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
 
-        /** @hide */
+        /**
+         * Include chooser shortcuts in the result.
+         * STOPSHIP TODO: Unless explicitly requesting chooser fields, we should strip out chooser
+         *           relevant fields from the Shortcut. This should also be adequately documented.
+         */
+        public static final int FLAG_MATCH_CHOOSER = 1 << 4;
+
+        /**
+         * Does not retrieve CHOOSER only shortcuts.
+         * TODO: Add another flag for MATCH_ALL_PINNED
+         * @hide
+         */
         public static final int FLAG_MATCH_ALL_KINDS =
                 FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST;
 
@@ -308,6 +319,7 @@
                         FLAG_MATCH_DYNAMIC,
                         FLAG_MATCH_PINNED,
                         FLAG_MATCH_MANIFEST,
+                        FLAG_MATCH_CHOOSER,
                         FLAG_GET_KEY_FIELDS_ONLY,
                 })
         @Retention(RetentionPolicy.SOURCE)
@@ -324,6 +336,9 @@
         @Nullable
         ComponentName mActivity;
 
+        @Nullable
+        Intent mIntent;
+
         @QueryFlags
         int mQueryFlags;
 
@@ -368,6 +383,14 @@
         }
 
         /**
+         * If non-null, returns only shortcuts with intent filters that match this intent.
+         */
+        public ShortcutQuery setIntent(@Nullable Intent intent) {
+            mIntent = intent;
+            return this;
+        }
+
+        /**
          * Set query options.  At least one of the {@code MATCH} flags should be set.  Otherwise,
          * no shortcuts will be returned.
          *
@@ -681,7 +704,7 @@
         try {
             return mService.getShortcuts(mContext.getPackageName(),
                     query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
-                    query.mQueryFlags, user)
+                    query.mIntent, query.mQueryFlags, user)
                     .getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index f1f2683..d3d3c66 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,8 +21,10 @@
 import android.annotation.UserIdInt;
 import android.app.TaskStackBuilder;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -38,10 +40,12 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.MemInfoReader;
 import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 
@@ -95,6 +99,14 @@
     public static final int FLAG_MASKABLE_BITMAP = 1 << 9;
 
     /** @hide */
+    public static final int FLAG_CHOOSER = 1 << 10;
+
+    /**
+     * TODO: Add FLAG_CHOOSER_INFO_OMITTED to reflect that chooser info was omitted in the Shortcut
+     *       due to the context in which it was retrieved.
+     * TODO: Add a FLAG_LAUNCHABLE to reflect whether or not the Shortcut has a launchable intent
+     * @hide
+     */
     @IntDef(flag = true,
             value = {
             FLAG_DYNAMIC,
@@ -107,6 +119,7 @@
             FLAG_STRINGS_RESOLVED,
             FLAG_IMMUTABLE,
             FLAG_MASKABLE_BITMAP,
+            FLAG_CHOOSER,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ShortcutFlags {}
@@ -201,6 +214,24 @@
     @Nullable
     private PersistableBundle[] mIntentPersistableExtrases;
 
+    /**
+     * If used in a chooser, extras that should be added into the intent passed through.
+     */
+    @Nullable
+    private PersistableBundle mChooserExtras;
+
+    /**
+     * Intent filters to be used if the shortcut is to be used in a chooser context.
+     */
+    @Nullable
+    private IntentFilter[] mChooserIntentFilters;
+
+    /**
+     * Component names corresponding to the above intent filters.
+     */
+    @Nullable
+    private ComponentName[] mChooserComponentNames;
+
     private int mRank;
 
     /**
@@ -250,6 +281,13 @@
         mDisabledMessageResId = b.mDisabledMessageResId;
         mCategories = cloneCategories(b.mCategories);
         mIntents = cloneIntents(b.mIntents);
+        if (b.mChooserIntentFilters != null) {
+            mChooserIntentFilters = b.mChooserIntentFilters.toArray(new IntentFilter[0]);
+        }
+        if (b.mChooserComponentNames != null) {
+            mChooserComponentNames = b.mChooserComponentNames.toArray(new ComponentName[0]);
+        }
+        mChooserExtras = b.mChooserExtras;
         fixUpIntentExtras();
         mRank = b.mRank;
         mExtras = b.mExtras;
@@ -330,8 +368,28 @@
         if (mTitle == null && mTitleResId == 0) {
             throw new IllegalArgumentException("Short label must be provided");
         }
-        Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
-        Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
+
+        // For a shortcut to be valid, there should either be an Intent, or a non-empty set of
+        // intent filters.
+        if (mIntents == null || mIntents.length == 0) {
+            Preconditions.checkNotNull(mChooserIntentFilters,
+                    "Intent must be provided if not a chooser target");
+            Preconditions.checkNotNull(mChooserComponentNames,
+                    "Intent must be provided if not a chooser target");
+        }
+
+        // If ChooserIntentFilter are provided, they should match the length of the provided
+        // component names.
+        if (mChooserIntentFilters != null) {
+            if (mChooserComponentNames == null
+                    || mChooserIntentFilters.length != mChooserComponentNames.length) {
+                throw new IllegalArgumentException("Inconsistent intent filters and "
+                        + "component names given");
+            }
+            if (mChooserIntentFilters.length == 0 || mChooserComponentNames.length == 0) {
+                throw new IllegalArgumentException("Empty intent filter and component names given");
+            }
+        }
     }
 
     /**
@@ -376,6 +434,10 @@
                 mDisabledMessageResName = source.mDisabledMessageResName;
                 mIconResName = source.mIconResName;
             }
+            // TODO: Omit these by default and add a new clone flag.
+            mChooserIntentFilters = source.mChooserIntentFilters;
+            mChooserComponentNames = source.mChooserComponentNames;
+            mChooserExtras = source.mChooserExtras;
         } else {
             // Set this bit.
             mFlags |= FLAG_KEY_FIELDS_ONLY;
@@ -503,6 +565,25 @@
     }
 
     /**
+     * Whether the shortcut has any intentFilter matching the passed in one.
+     * @hide
+     */
+    @VisibleForTesting
+    public boolean hasMatchingFilter(ContentResolver resolver, Intent intent) {
+        if (mChooserIntentFilters == null) {
+            return false;
+        }
+        for (IntentFilter filter : mChooserIntentFilters) {
+            int match = filter.match(resolver, intent, false, TAG);
+            if (match > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+    /**
      * Extract the entry name from a fully-donated resource name.
      * e.g. "com.android.app1:drawable/icon1" -> "icon1"
      * @hide
@@ -685,6 +766,15 @@
         if (source.mExtras != null) {
             mExtras = source.mExtras;
         }
+        if (source.mChooserExtras != null) {
+            mChooserExtras = source.mChooserExtras;
+        }
+        if (source.mChooserIntentFilters != null) {
+            mChooserIntentFilters = source.mChooserIntentFilters;
+        }
+        if (source.mChooserComponentNames != null) {
+            mChooserComponentNames = source.mChooserComponentNames;
+        }
     }
 
     /**
@@ -746,6 +836,12 @@
 
         private PersistableBundle mExtras;
 
+        private PersistableBundle mChooserExtras;
+
+        private List<IntentFilter> mChooserIntentFilters;
+
+        private List<ComponentName> mChooserComponentNames;
+
         /**
          * Old style constructor.
          * @hide
@@ -1032,6 +1128,40 @@
         }
 
         /**
+         * Extras that can be added which will be added to the Intent used to launch the app if
+         * launched from a chooser context.
+         */
+        @NonNull
+        public Builder setChooserExtras(@NonNull PersistableBundle extras) {
+            mChooserExtras = extras;
+            return this;
+        }
+
+        /**
+         * IntentFilters and the components that should resolve a match for a given chooser target.
+         * If multiple matches are found, the component corresponding to the closest match will be
+         * used.
+         *
+         * @param filter IntendFilter that if matched will have the intent forwarded to the given
+         *               component
+         * @param name The component that an intent that passes this filter will resolve to.
+         */
+        public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
+                @NonNull ComponentName name) {
+            Preconditions.checkNotNull(filter, "intent filter cannot be null");
+            Preconditions.checkNotNull(name, "component name cannot be null");
+
+            if (mChooserIntentFilters == null || mChooserComponentNames == null) {
+                mChooserIntentFilters = new ArrayList<>();
+                mChooserComponentNames = new ArrayList<>();
+            }
+
+            mChooserIntentFilters.add(filter);
+            mChooserComponentNames.add(name);
+            return this;
+        }
+
+        /**
          * Creates a {@link ShortcutInfo} instance.
          */
         @NonNull
@@ -1232,6 +1362,30 @@
     }
 
     /**
+     * Retrieve the extras that will be added in to any intent launched through the chooser.
+     */
+    @NonNull
+    public PersistableBundle getChooserExtras() {
+        return mChooserExtras;
+    }
+
+    /**
+     * Retrieve the list of intent filters for chooser targets.
+     */
+    @NonNull
+    public IntentFilter[] getChooserIntentFilters() {
+        return mChooserIntentFilters;
+    }
+
+    /**
+     * Retrieve the list of component names corresponding to the above intent filters.
+     */
+    @NonNull
+    public ComponentName[] getChooserComponentNames() {
+        return mChooserComponentNames;
+    }
+
+    /**
      * "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
      * {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
      *
@@ -1352,6 +1506,11 @@
         return hasFlags(FLAG_PINNED);
     }
 
+    /** Return whether a shortcut can be shown in the chooser. */
+    public boolean isChooser() {
+        return hasFlags(FLAG_CHOOSER);
+    }
+
     /**
      * Return whether a shortcut is static; that is, whether a shortcut is
      * published from AndroidManifest.xml.  If {@code true}, the shortcut is
@@ -1380,6 +1539,14 @@
         return isPinned() && !(isDynamic() || isManifestShortcut());
     }
 
+    /**
+     * @return true if pinned but neither static nor dynamic.
+     * @hide
+     */
+    public boolean isDynamicOrChooser() {
+        return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_CHOOSER);
+    }
+
     /** @hide */
     public boolean isOriginallyFromManifest() {
         return hasFlags(FLAG_IMMUTABLE);
@@ -1661,6 +1828,19 @@
                 mCategories.add(source.readString().intern());
             }
         }
+
+        // We put a placeholder empty array in to keep the parcelable order, but can do away with
+        // them at this point if they're empty.
+        mChooserComponentNames = source.readParcelableArray(cl, ComponentName.class);
+        if (mChooserComponentNames.length == 0) {
+            mChooserComponentNames = null;
+        }
+
+        mChooserIntentFilters = source.readParcelableArray(cl, IntentFilter.class);
+        if (mChooserIntentFilters.length == 0) {
+            mChooserIntentFilters = null;
+        }
+        mChooserExtras = source.readPersistableBundle(cl);
     }
 
     @Override
@@ -1707,6 +1887,17 @@
         } else {
             dest.writeInt(0);
         }
+        if (mChooserComponentNames != null) {
+            dest.writeParcelableArray(mChooserComponentNames, flags);
+        } else {
+            dest.writeParcelableArray(new ComponentName[0], flags);
+        }
+        if (mChooserIntentFilters != null) {
+            dest.writeParcelableArray(mChooserIntentFilters, flags);
+        } else {
+            dest.writeParcelableArray(new IntentFilter[0], flags);
+        }
+        dest.writePersistableBundle(mChooserExtras);
     }
 
     public static final Creator<ShortcutInfo> CREATOR =
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 87a6d4a..696fe81 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -44,8 +44,8 @@
             getShortcuts(int launcherUserId,
             @NonNull String callingPackage, long changedSince,
             @Nullable String packageName, @Nullable List<String> shortcutIds,
-            @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
-            int userId);
+            @Nullable ComponentName componentName, @Nullable Intent intent,
+            @ShortcutQuery.QueryFlags int flags, int userId);
 
     public abstract boolean
             isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
diff --git a/core/java/android/content/res/CompatResources.java b/core/java/android/content/res/CompatResources.java
new file mode 100644
index 0000000..15575fd
--- /dev/null
+++ b/core/java/android/content/res/CompatResources.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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 android.content.res;
+
+import android.annotation.ColorRes;
+import android.annotation.DrawableRes;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Version of resources generated for apps targeting <26.
+ * @hide
+ */
+public class CompatResources extends Resources {
+
+    private final WeakReference<Context> mContext;
+
+    public CompatResources(Resources base, Context context) {
+        super(base.getClassLoader());
+        setImpl(base.getImpl());
+        mContext = new WeakReference<>(context);
+    }
+
+    @Override
+    public Drawable getDrawable(@DrawableRes int id) throws NotFoundException {
+        return getDrawable(id, getTheme());
+    }
+
+    @Override
+    public Drawable getDrawableForDensity(@DrawableRes int id, int density)
+            throws NotFoundException {
+        return getDrawableForDensity(id, density, getTheme());
+    }
+
+    @Override
+    public int getColor(@ColorRes int id) throws NotFoundException {
+        return getColor(id, getTheme());
+    }
+
+    @Override
+    public ColorStateList getColorStateList(@ColorRes int id) throws NotFoundException {
+        return getColorStateList(id, getTheme());
+    }
+
+    private Theme getTheme() {
+        Context c = mContext.get();
+        return c != null ? c.getTheme() : null;
+    }
+}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index a241d1f..ba75c8b 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -188,7 +188,7 @@
             // Handle the the case where service didn't call setSavableIds() because it would
             // contain just the ids from the datasets.
             if (saveInfo == null && mDatasets != null) {
-                saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_UI_TYPE_GENERIC).build();
+                saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC).build();
             }
             if (saveInfo != null) {
                 saveInfo.addSavableIds(mDatasets);
@@ -324,7 +324,7 @@
                 throw new IllegalStateException("setSaveInfo() already called");
             }
             if (mSaveInfoBuilder == null) {
-                mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_UI_TYPE_GENERIC);
+                mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC);
             }
             mSaveInfoBuilder.addSavableIds(ids);
 
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 148bd24..096f28b 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -52,43 +52,44 @@
      * Type used on when the service can save the contents of an activity, but cannot describe what
      * the content is for.
      */
-    public static final int SAVE_UI_TYPE_GENERIC = 0;
+    public static final int SAVE_DATA_TYPE_GENERIC = 0;
 
     /**
-     * Type used when the {@link FillResponse} represents user credentials (such as username and
-     * password).
+     * Type used when the {@link FillResponse} represents user credentials that have a password.
      */
-    public static final int SAVE_UI_TYPE_CREDENTIALS = 1;
+    public static final int SAVE_DATA_TYPE_PASSWORD = 1;
+
 
     /**
      * Type used on when the {@link FillResponse} represents a physical address (such as street,
      * city, state, etc).
      */
-    public static final int SAVE_UI_TYPE_ADDRESS = 2;
+    public static final int SAVE_DATA_TYPE_ADDRESS = 2;
 
     /**
-     * Type used when the {@link FillResponse} represents a payment (such as credit card number
-     * and expiration date).
+     * Type used when the {@link FillResponse} represents a credit card.
      */
-    public static final int SAVE_UI_TYPE_PAYMENT = 3;
+    public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
 
-    private final @SaveUiType int mType;
+    private final @SaveDataType int mType;
     private ArraySet<AutoFillId> mSavableIds;
+    private final CharSequence mDescription;
 
     /** @hide */
     @IntDef({
-        SAVE_UI_TYPE_GENERIC,
-        SAVE_UI_TYPE_CREDENTIALS,
-        SAVE_UI_TYPE_ADDRESS,
-        SAVE_UI_TYPE_PAYMENT
+        SAVE_DATA_TYPE_GENERIC,
+        SAVE_DATA_TYPE_PASSWORD,
+        SAVE_DATA_TYPE_ADDRESS,
+        SAVE_DATA_TYPE_CREDIT_CARD
     })
     @Retention(RetentionPolicy.SOURCE)
-    public @interface SaveUiType {
+    public @interface SaveDataType {
     }
 
     private SaveInfo(Builder builder) {
         mType = builder.mType;
         mSavableIds = builder.mSavableIds;
+        mDescription = builder.mDescription;
     }
 
     /** @hide */
@@ -97,6 +98,16 @@
     }
 
     /** @hide */
+    public int getType() {
+        return mType;
+    }
+
+    /** @hide */
+    public CharSequence getDescription() {
+        return mDescription;
+    }
+
+    /** @hide */
     public void addSavableIds(@Nullable ArrayList<Dataset> datasets) {
         if (datasets != null) {
             for (Dataset dataset : datasets) {
@@ -120,27 +131,28 @@
      */
     public static final class Builder {
 
-        private final @SaveUiType int mType;
+        private final @SaveDataType int mType;
         private ArraySet<AutoFillId> mSavableIds;
+        private CharSequence mDescription;
         private boolean mDestroyed;
 
         /**
          * Creates a new builder.
          *
          * @param type the type of information the associated {@link FillResponse} represents. Must
-         * be {@link SaveInfo#SAVE_UI_TYPE_GENERIC}, {@link SaveInfo#SAVE_UI_TYPE_CREDENTIALS},
-         * {@link SaveInfo#SAVE_UI_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_UI_TYPE_PAYMENT};
-         * otherwise it will assume {@link SaveInfo#SAVE_UI_TYPE_GENERIC}.
+         * be {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
+         * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD};
+         * otherwise it will assume {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}.
          */
-        public Builder(@SaveUiType int type) {
+        public Builder(@SaveDataType int type) {
             switch (type) {
-                case SAVE_UI_TYPE_CREDENTIALS:
-                case SAVE_UI_TYPE_ADDRESS:
-                case SAVE_UI_TYPE_PAYMENT:
+                case SAVE_DATA_TYPE_PASSWORD:
+                case SAVE_DATA_TYPE_ADDRESS:
+                case SAVE_DATA_TYPE_CREDIT_CARD:
                     mType = type;
                     break;
                 default:
-                    mType = SAVE_UI_TYPE_GENERIC;
+                    mType = SAVE_DATA_TYPE_GENERIC;
             }
         }
 
@@ -169,6 +181,20 @@
         }
 
         /**
+         * Sets an optional description to be shown in the UI when the user is asked to save.
+         *
+         * <p>Typically, it describes how the data will be stored by the service, so it can help
+         * users to decide whether they can trust the service to save their data.
+         *
+         * @param description a succint description.
+         * @return This Builder.
+         */
+        public @NonNull Builder setDescription(@Nullable CharSequence description) {
+            mDescription = description;
+            return this;
+        }
+
+        /**
          * Builds a new {@link SaveInfo} instance.
          */
         public SaveInfo build() {
@@ -210,6 +236,7 @@
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mType);
         parcel.writeTypedArraySet(mSavableIds, flags);
+        parcel.writeCharSequence(mDescription);
     }
 
     public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
@@ -224,7 +251,7 @@
             for (int i = 0; i < savableIdsCount; i++) {
                 builder.addSavableIds(savableIds.valueAt(i));
             }
-
+            builder.setDescription(parcel.readCharSequence());
             return builder.build();
         }
 
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index df65659..79301aa 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -23,15 +23,21 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.IntentSender.SendIntentException;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LabeledIntent;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
 import android.database.DataSetObserver;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
@@ -356,6 +362,7 @@
             mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
         }
         mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
+        mChooserRowAdapter.updateRowScales();
         mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
         adapterView.setAdapter(mChooserRowAdapter);
         if (listView != null) {
@@ -842,7 +849,9 @@
                 return false;
             }
             intent.setComponent(mChooserTarget.getComponentName());
-            intent.putExtras(mChooserTarget.getIntentExtras());
+            if (mChooserTarget.getIntentExtras() != null) {
+                intent.putExtras(mChooserTarget.getIntentExtras());
+            }
 
             // Important: we will ignore the target security checks in ActivityManager
             // if and only if the ChooserTarget's target package is the same package
@@ -925,6 +934,8 @@
         private static final int MAX_SERVICE_TARGETS = 8;
         private static final int MAX_TARGETS_PER_SERVICE = 4;
 
+        private boolean mAreChooserShortcutsRetrieved;
+
         private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
         private final List<TargetInfo> mCallerTargets = new ArrayList<>();
         private boolean mShowServiceTargets;
@@ -1016,6 +1027,20 @@
             if (mServiceTargets != null) {
                 pruneServiceTargets();
             }
+
+            if (DEBUG) Log.d(TAG, "Adding pushed chooser targets");
+
+            if (!mAreChooserShortcutsRetrieved) {
+                LauncherApps launcherApps = getLauncherApps();
+                LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
+                query.setIntent(getTargetIntent());
+                query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_CHOOSER);
+                List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query, UserHandle.SYSTEM);
+                if (DEBUG) Log.d(TAG, "Adding " + shortcuts.size() + " chooser shortcuts");
+                addShortcuts(shortcuts);
+                mAreChooserShortcutsRetrieved = true;
+            }
+
             if (DEBUG) Log.d(TAG, "List built querying services");
             queryTargetServices(this);
         }
@@ -1041,6 +1066,7 @@
 
         public int getServiceTargetCount() {
             if (!mShowServiceTargets) {
+                if (DEBUG) Log.d("TAG", "Hiding service targets");
                 return 0;
             }
             return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
@@ -1132,6 +1158,71 @@
             notifyDataSetChanged();
         }
 
+        // TODO: Pushed targets need to be scored correctly
+        public void addShortcuts(List<ShortcutInfo> infos) {
+            for (ShortcutInfo info : infos) {
+                List<ChooserTarget> newTargets = new ArrayList<>();
+                final ComponentName cn = info.getActivity();
+                ActivityInfo ai;
+                ResolveInfo ri = new ResolveInfo();
+                if (cn != null) {
+                    try {
+                        ai = getPackageManager().getActivityInfo(cn, 0);
+                        ri.activityInfo = ai;
+                        UserManager userManager =
+                                (UserManager) getSystemService(Context.USER_SERVICE);
+                        ri.iconResourceId = ai.icon;
+                        ri.labelRes = ai.labelRes;
+                        ri.resolvePackageName = ai.packageName;
+                        ri.activityInfo.applicationInfo = new ApplicationInfo(
+                                ri.activityInfo.applicationInfo);
+                        ri.activityInfo.applicationInfo = ai.applicationInfo;
+                        ri.activityInfo.applicationInfo.uid = getUserId();
+                    } catch (PackageManager.NameNotFoundException ignored) {
+                        if (DEBUG) Log.d(TAG, "Package not found, skipping this shortcut");
+                        continue;
+                    }
+                }
+
+                DisplayResolveInfo resolveInfo = new DisplayResolveInfo(getTargetIntent(),
+                        ri,
+                        info.getShortLabel(),
+                        info.getLongLabel(),
+                        getTargetIntent());
+
+                int bestMatch = 0;
+                ComponentName bestComponent = null;
+                for (int i = 0; i < info.getChooserIntentFilters().length; i++) {
+                    int newMatch = info.getChooserIntentFilters()[i]
+                            .match(getContentResolver(), getTargetIntent(), false, TAG);
+                    if (DEBUG) Log.d(TAG, "A match was found with value: " + newMatch);
+                    if (newMatch > bestMatch) {
+                        bestMatch = newMatch;
+                        bestComponent = info.getChooserComponentNames()[i];
+                    }
+                }
+                if (bestMatch == 0) {
+                    Log.e(TAG, "Unexpectedly, no match was found for the provided chooser intent");
+                    return;
+                }
+
+                Bundle extrasToAdd =
+                        info.getChooserExtras() == null ? null: new Bundle(info.getChooserExtras());
+                if (DEBUG) Log.d(TAG, "Adding service target " + info.getShortLabel());
+                newTargets.add(new ChooserTarget(
+                        info.getShortLabel(),
+                        info.getIcon(),
+                        1,
+                        bestComponent,
+                        extrasToAdd));
+                addServiceResults(resolveInfo, newTargets);
+            }
+            if (mChooserRowAdapter != null) {
+                mChooserRowAdapter.updateRowScales();
+            }
+            setShowServiceTargets(true);
+        }
+
         /**
          * Set to true to reveal all service targets at once.
          */
@@ -1246,37 +1337,7 @@
                 @Override
                 public void onChanged() {
                     super.onChanged();
-                    final int rcount = getServiceTargetRowCount();
-                    if (mServiceTargetScale == null
-                            || mServiceTargetScale.length != rcount) {
-                        RowScale[] old = mServiceTargetScale;
-                        int oldRCount = old != null ? old.length : 0;
-                        mServiceTargetScale = new RowScale[rcount];
-                        if (old != null && rcount > 0) {
-                            System.arraycopy(old, 0, mServiceTargetScale, 0,
-                                    Math.min(old.length, rcount));
-                        }
-
-                        for (int i = rcount; i < oldRCount; i++) {
-                            old[i].cancelAnimation();
-                        }
-
-                        for (int i = oldRCount; i < rcount; i++) {
-                            final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
-                                    .setInterpolator(mInterpolator);
-                            mServiceTargetScale[i] = rs;
-                        }
-
-                        // Start the animations in a separate loop.
-                        // The process of starting animations will result in
-                        // binding views to set up initial values, and we must
-                        // have ALL of the new RowScale objects created above before
-                        // we get started.
-                        for (int i = oldRCount; i < rcount; i++) {
-                            mServiceTargetScale[i].startAnimation();
-                        }
-                    }
-
+                    updateRowScales();
                     notifyDataSetChanged();
                 }
 
@@ -1293,6 +1354,40 @@
             });
         }
 
+         void updateRowScales() {
+            final int rcount = getServiceTargetRowCount();
+            if (mServiceTargetScale == null
+                    || mServiceTargetScale.length != rcount) {
+                if (DEBUG) Log.d(TAG, "Row scales need adjusting to " + rcount + " rows.");
+                RowScale[] old = mServiceTargetScale;
+                int oldRCount = old != null ? old.length : 0;
+                mServiceTargetScale = new RowScale[rcount];
+                if (old != null && rcount > 0) {
+                    System.arraycopy(old, 0, mServiceTargetScale, 0,
+                            Math.min(old.length, rcount));
+                }
+
+                for (int i = rcount; i < oldRCount; i++) {
+                    old[i].cancelAnimation();
+                }
+
+                for (int i = oldRCount; i < rcount; i++) {
+                    final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
+                            .setInterpolator(mInterpolator);
+                    mServiceTargetScale[i] = rs;
+                }
+
+                // Start the animations in a separate loop.
+                // The process of starting animations will result in
+                // binding views to set up initial values, and we must
+                // have ALL of the new RowScale objects created above before
+                // we get started.
+                for (int i = oldRCount; i < rcount; i++) {
+                    mServiceTargetScale[i].startAnimation();
+                }
+            }
+        }
+
         private float getRowScale(int rowPosition) {
             final int start = getCallerTargetRowCount();
             final int end = start + getServiceTargetRowCount();
@@ -1563,6 +1658,10 @@
         }
     }
 
+    public LauncherApps getLauncherApps() {
+        return (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
+    }
+
     static class ServiceResultInfo {
         public final DisplayResolveInfo originalTarget;
         public final List<ChooserTarget> resultTargets;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b3ae891..054fad2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3489,7 +3489,7 @@
         <receiver android:name="com.android.server.updates.ApnDbInstallReceiver"
                 android:permission="android.permission.UPDATE_CONFIG">
             <intent-filter>
-                <action android:name="android.intent.action.UPDATE_APN_DB" />
+                <action android:name="com.android.internal.intent.action.UPDATE_APN_DB" />
                 <data android:scheme="content" android:host="*" android:mimeType="*/*" />
             </intent-filter>
         </receiver>
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index 40cce7b..9b90de6 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -15,7 +15,7 @@
 -->
 
 <ListView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/list"
+    android:id="@+id/autofill_dataset_picker"
     android:layout_width="wrap_content"
     android:layout_height="fill_parent"
     android:divider="?android:attr/listDivider"
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 8453cd3..dad9aad 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -16,6 +16,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/autofill_save"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:paddingStart="16dip"
@@ -39,6 +40,13 @@
             android:singleLine="true">
         </TextView>
 
+        <TextView
+            android:id="@+id/autofill_save_subtitle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:visibility="invisible">
+        </TextView>
+
         <Space
             android:layout_width="0dp"
             android:layout_height="0dp"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6abc009..b0c532c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4510,11 +4510,22 @@
     <!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
     <string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
 
-    <!-- Title for the auto-fill save dialog shown when the user entered savable text [CHAR LIMIT=NONE] -->
+    <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+         by an auto-fill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
     <string name="autofill_save_title">Save to <xliff:g id="label" example="MyPass">%1$s</xliff:g>?</string>
+    <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+         by an auto-fill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_title_with_type">Save <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to <xliff:g id="label" example="MyPass">%2$s</xliff:g>?</string>
     <!-- Label for the auto-fill save button [CHAR LIMIT=NONE] -->
     <string name="autofill_save_yes">Save</string>
     <!-- Label for the auto-fill cancel button [CHAR LIMIT=NONE] -->
     <string name="autofill_save_no">No thanks</string>
 
+    <!-- Label for the type of data being saved for auto-fill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_password">password</string>
+    <!-- Label for the type of data being saved for auto-fill when it represent an address (street, city, etc.) [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_address">address</string>
+    <!-- Label for the type of data being saved for auto-fill when it represents a credit card [CHAR LIMIT=NONE] -->
+    <string name="autofill_save_type_credit_card">credit card</string>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 49216d9..6995d9a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2838,12 +2838,17 @@
   <java-symbol type="layout" name="autofill_save"/>
   <java-symbol type="layout" name="autofill_dataset_picker"/>
   <java-symbol type="id" name="autofill_save_title" />
+  <java-symbol type="id" name="autofill_save_subtitle" />
   <java-symbol type="id" name="autofill_save_no" />
   <java-symbol type="id" name="autofill_save_yes" />
   <java-symbol type="id" name="autofill_save_close" />
   <java-symbol type="string" name="autofill_save_title" />
+  <java-symbol type="string" name="autofill_save_title_with_type" />
   <java-symbol type="string" name="autofill_save_yes" />
   <java-symbol type="string" name="autofill_save_no" />
+  <java-symbol type="string" name="autofill_save_type_password" />
+  <java-symbol type="string" name="autofill_save_type_address" />
+  <java-symbol type="string" name="autofill_save_type_credit_card" />
 
   <!-- Accessibility fingerprint gestures -->
   <java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 1080a9f..3dfecc6 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,6 +16,17 @@
 
 package com.android.internal.app;
 
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.SystemClock;
 import com.android.internal.R;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
 
@@ -48,25 +59,31 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 /**
  * Chooser activity instrumentation tests
  */
 @RunWith(AndroidJUnit4.class)
 public class ChooserActivityTest {
+    private Instrumentation instrumentation;
+
+    @Before
+    public void setUp() {
+        instrumentation = InstrumentationRegistry.getInstrumentation();
+        sOverrides.reset();
+    }
+
     @Rule
     public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
             new ActivityTestRule<>(ChooserWrapperActivity.class, false,
                     false);
 
-    @Before
-    public void cleanOverrideData() {
-        sOverrides.reset();
-    }
-
     @Test
     public void customTitle() throws InterruptedException {
         Intent sendIntent = createSendImageIntent();
@@ -235,7 +252,6 @@
             chosen[0] = targetInfo.getResolveInfo();
             return true;
         };
-
         // Make a stable copy of the components as the original list may be modified
         List<ResolvedComponentInfo> stableCopy =
                 createResolvedComponentsForTestWithOtherProfile(2);
@@ -324,6 +340,32 @@
         assertThat(chosen[0], is(toChoose));
     }
 
+    public void pushedChooserTarget() {
+        ResolveInfo[] chosen = new ResolveInfo[1];
+        sOverrides.onSafelyStartCallback = targetInfo -> {
+            chosen[0] = targetInfo.getResolveInfo();
+            return true;
+        };
+
+        setChooserShortcuts(1);
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+        Intent sendIntent = createSendImageIntent();
+        final ChooserWrapperActivity activity = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent, null));
+
+        waitForIdle();
+
+        onView(withText("short chooser label 0"))
+                .perform(click());
+        waitForIdle();
+        assertThat(chosen[0].resolvePackageName,
+                is(ResolverDataProvider.createActivityInfo(0).packageName));
+    }
+
     private Intent createSendImageIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
@@ -371,4 +413,48 @@
         }
         return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
     }
+
+    private void setChooserShortcuts(int numShortcuts) {
+        ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+        for (int i = 0; i < numShortcuts; i++) {
+           shortcuts.add(makeShortcut(i));
+        }
+        when(sOverrides.launcherApps.getShortcuts(
+                Mockito.isA(LauncherApps.ShortcutQuery.class),
+                Mockito.eq(UserHandle.SYSTEM)))
+                .thenReturn(shortcuts);
+    }
+
+    private ShortcutInfo makeShortcut(int i) {
+        try {
+            IntentFilter filter = new IntentFilter(Intent.ACTION_SEND, "image/jpeg");
+
+            ComponentName component = new ComponentName("foo.bar", "foo.bar" + ".MainActivity");
+            ShortcutInfo.Builder b = new ShortcutInfo.Builder(instrumentation.getContext(), "" + i)
+                    .setActivity(component)
+                    .setShortLabel("short chooser label " + i)
+                    .setLongLabel("long chooser label" + i)
+                    .setRank(i)
+                    .setIntent(createSendImageIntent())
+                    .setIcon(Icon.createWithResource(instrumentation.getContext(),
+                            android.R.drawable.ic_menu_add))
+                    .addChooserIntentFilter(
+                            filter,
+                            component);
+
+            sOverrides.createPackageManager = pm -> {
+                final PackageManager spied = spy(pm);
+                try {
+                    doAnswer(invocation -> ResolverDataProvider.createActivityInfo(i))
+                            .when(spied).getActivityInfo(
+                            Mockito.isA(ComponentName.class), Mockito.anyInt());
+                } catch (Exception e) {
+                    // this is ok, just not found
+                    e.printStackTrace();
+                }
+                return spied;
+            };
+            return b.build();
+        } catch (Exception e) {return null;}
+    }
 }
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index c446f3c..0dac260 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -18,6 +18,7 @@
 
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 
 import java.util.function.Function;
@@ -74,6 +75,11 @@
         return super.getPackageManager();
     }
 
+    @Override
+    public LauncherApps getLauncherApps() {
+        return sOverrides.launcherApps;
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
@@ -82,6 +88,7 @@
     static class OverrideData {
         @SuppressWarnings("Since15")
         public Function<PackageManager, PackageManager> createPackageManager;
+        public LauncherApps launcherApps;
         public Function<TargetInfo, Boolean> onSafelyStartCallback;
         public ResolverListController resolverListController;
         public Boolean isVoiceInteraction;
@@ -90,6 +97,7 @@
             onSafelyStartCallback = null;
             isVoiceInteraction = null;
             createPackageManager = null;
+            launcherApps = mock(LauncherApps.class);
             resolverListController = mock(ResolverListController.class);
         }
     }
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index fe82a93..a24b970 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -16,9 +16,11 @@
 
 package android.graphics.drawable;
 
+import android.annotation.NonNull;
 import android.content.pm.ActivityInfo.Config;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
+import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
@@ -31,10 +33,10 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.drawable.shapes.Shape;
-import android.content.res.Resources.Theme;
 import android.util.AttributeSet;
 
 import com.android.internal.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -69,7 +71,7 @@
  * @attr ref android.R.styleable#ShapeDrawable_height
  */
 public class ShapeDrawable extends Drawable {
-    private ShapeState mShapeState;
+    private @NonNull ShapeState mShapeState;
     private PorterDuffColorFilter mTintFilter;
     private boolean mMutated;
 
@@ -77,7 +79,7 @@
      * ShapeDrawable constructor.
      */
     public ShapeDrawable() {
-        this(new ShapeState(null), null);
+        this(new ShapeState(), null);
     }
 
     /**
@@ -86,7 +88,7 @@
      * @param s the Shape that this ShapeDrawable should be
      */
     public ShapeDrawable(Shape s) {
-        this(new ShapeState(null), null);
+        this(new ShapeState(), null);
 
         mShapeState.mShape = s;
     }
@@ -402,7 +404,7 @@
         }
 
         // Update local properties.
-        updateLocalState(r);
+        updateLocalState();
     }
 
     @Override
@@ -426,7 +428,7 @@
         }
 
         // Update local properties.
-        updateLocalState(t.getResources());
+        updateLocalState();
     }
 
     private void updateStateFromTypedArray(TypedArray a) {
@@ -447,10 +449,10 @@
         dither = a.getBoolean(R.styleable.ShapeDrawable_dither, dither);
         paint.setDither(dither);
 
-        setIntrinsicWidth((int) a.getDimension(
-                R.styleable.ShapeDrawable_width, state.mIntrinsicWidth));
-        setIntrinsicHeight((int) a.getDimension(
-                R.styleable.ShapeDrawable_height, state.mIntrinsicHeight));
+        state.mIntrinsicWidth = (int) a.getDimension(
+                R.styleable.ShapeDrawable_width, state.mIntrinsicWidth);
+        state.mIntrinsicHeight = (int) a.getDimension(
+                R.styleable.ShapeDrawable_height, state.mIntrinsicHeight);
 
         final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1);
         if (tintMode != -1) {
@@ -494,21 +496,8 @@
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            if (mShapeState.mPaint != null) {
-                mShapeState.mPaint = new Paint(mShapeState.mPaint);
-            } else {
-                mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-            }
-            if (mShapeState.mPadding != null) {
-                mShapeState.mPadding = new Rect(mShapeState.mPadding);
-            } else {
-                mShapeState.mPadding = new Rect();
-            }
-            try {
-                mShapeState.mShape = mShapeState.mShape.clone();
-            } catch (CloneNotSupportedException e) {
-                return null;
-            }
+            mShapeState = new ShapeState(mShapeState);
+            updateLocalState();
             mMutated = true;
         }
         return this;
@@ -525,12 +514,13 @@
     /**
      * Defines the intrinsic properties of this ShapeDrawable's Shape.
      */
-    final static class ShapeState extends ConstantState {
-        int[] mThemeAttrs;
+    static final class ShapeState extends ConstantState {
+        final @NonNull Paint mPaint;
+
         @Config int mChangingConfigurations;
-        Paint mPaint;
+        int[] mThemeAttrs;
         Shape mShape;
-        ColorStateList mTint = null;
+        ColorStateList mTint;
         Mode mTintMode = DEFAULT_TINT_MODE;
         Rect mPadding;
         int mIntrinsicWidth;
@@ -538,21 +528,43 @@
         int mAlpha = 255;
         ShaderFactory mShaderFactory;
 
-        ShapeState(ShapeState orig) {
-            if (orig != null) {
-                mThemeAttrs = orig.mThemeAttrs;
-                mPaint = orig.mPaint;
-                mShape = orig.mShape;
-                mTint = orig.mTint;
-                mTintMode = orig.mTintMode;
-                mPadding = orig.mPadding;
-                mIntrinsicWidth = orig.mIntrinsicWidth;
-                mIntrinsicHeight = orig.mIntrinsicHeight;
-                mAlpha = orig.mAlpha;
-                mShaderFactory = orig.mShaderFactory;
-            } else {
-                mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        /**
+         * Constructs a new ShapeState.
+         */
+        ShapeState() {
+            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        }
+
+        /**
+         * Constructs a new ShapeState that contains a deep copy of the
+         * specified ShapeState.
+         *
+         * @param orig the state to create a deep copy of
+         */
+        ShapeState(@NonNull ShapeState orig) {
+            mChangingConfigurations = orig.mChangingConfigurations;
+            mPaint = new Paint(orig.mPaint);
+            mThemeAttrs = orig.mThemeAttrs;
+            if (mShape != null) {
+                try {
+                    mShape = orig.mShape.clone();
+                } catch (CloneNotSupportedException e) {
+                    // Well, at least we tried.
+                    mShape = orig.mShape;
+                }
             }
+            mTint = orig.mTint;
+            mTintMode = orig.mTintMode;
+            if (orig.mPadding != null) {
+                mPadding = new Rect(orig.mPadding);
+            }
+            mIntrinsicWidth = orig.mIntrinsicWidth;
+            mIntrinsicHeight = orig.mIntrinsicHeight;
+            mAlpha = orig.mAlpha;
+
+            // We don't have any way to clone a shader factory, so hopefully
+            // this class doesn't contain any local state.
+            mShaderFactory = orig.mShaderFactory;
         }
 
         @Override
@@ -585,7 +597,7 @@
     private ShapeDrawable(ShapeState state, Resources res) {
         mShapeState = state;
 
-        updateLocalState(res);
+        updateLocalState();
     }
 
     /**
@@ -593,7 +605,7 @@
      * after significant state changes, e.g. from the One True Constructor and
      * after inflating or applying a theme.
      */
-    private void updateLocalState(Resources res) {
+    private void updateLocalState() {
         mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode);
     }
 
@@ -617,8 +629,4 @@
          */
         public abstract Shader resize(int width, int height);
     }
-
-    // other subclass could wack the Shader's localmatrix based on the
-    // resize params (e.g. scaletofit, etc.). This could be used to scale
-    // a bitmap to fill the bounds without needing any other special casing.
 }
diff --git a/graphics/java/android/graphics/drawable/shapes/ArcShape.java b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
index c4b239f..85ba0a9 100644
--- a/graphics/java/android/graphics/drawable/shapes/ArcShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
@@ -21,31 +21,47 @@
 import android.graphics.Paint;
 
 /**
- * Creates an arc shape. The arc shape starts at a specified
- * angle and sweeps clockwise, drawing slices of pie.
- * The arc can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * the ArcShape to a {@link android.graphics.drawable.ShapeDrawable}.
+ * Creates an arc shape. The arc shape starts at a specified angle and sweeps
+ * clockwise, drawing slices of pie.
+ * <p>
+ * The arc can be drawn to a {@link Canvas} with its own
+ * {@link #draw(Canvas, Paint)} method, but more graphical control is available
+ * if you instead pass the ArcShape to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
  */
 public class ArcShape extends RectShape {
-    private float mStart;
-    private float mSweep;
-    
+    private final float mStartAngle;
+    private final float mSweepAngle;
+
     /**
-     * ArcShape constructor. 
-     * 
+     * ArcShape constructor.
+     *
      * @param startAngle the angle (in degrees) where the arc begins
-     * @param sweepAngle the sweep angle (in degrees). Anything equal to or 
+     * @param sweepAngle the sweep angle (in degrees). Anything equal to or
      *                   greater than 360 results in a complete circle/oval.
      */
     public ArcShape(float startAngle, float sweepAngle) {
-        mStart = startAngle;
-        mSweep = sweepAngle;
+        mStartAngle = startAngle;
+        mSweepAngle = sweepAngle;
     }
-    
+
+    /**
+     * @return the angle (in degrees) where the arc begins
+     */
+    public final float getStartAngle() {
+        return mStartAngle;
+    }
+
+    /**
+     * @return the sweep angle (in degrees)
+     */
+    public final float getSweepAngle() {
+        return mSweepAngle;
+    }
+
     @Override
     public void draw(Canvas canvas, Paint paint) {
-        canvas.drawArc(rect(), mStart, mSweep, true, paint);
+        canvas.drawArc(rect(), mStartAngle, mSweepAngle, true, paint);
     }
 
     @Override
@@ -53,5 +69,10 @@
         // Since we don't support concave outlines, arc shape does not attempt
         // to provide an outline.
     }
+
+    @Override
+    public ArcShape clone() throws CloneNotSupportedException {
+        return (ArcShape) super.clone();
+    }
 }
 
diff --git a/graphics/java/android/graphics/drawable/shapes/OvalShape.java b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
index c9473f0..fb87d28 100644
--- a/graphics/java/android/graphics/drawable/shapes/OvalShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
@@ -22,7 +22,8 @@
 import android.graphics.RectF;
 
 /**
- * Defines an oval shape. 
+ * Defines an oval shape.
+ * <p>
  * The oval can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the OvalShape to a {@link android.graphics.drawable.ShapeDrawable}.
@@ -42,5 +43,10 @@
         outline.setOval((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
                 (int) Math.floor(rect.right), (int) Math.floor(rect.bottom));
     }
+
+    @Override
+    public OvalShape clone() throws CloneNotSupportedException {
+        return (OvalShape) super.clone();
+    }
 }
 
diff --git a/graphics/java/android/graphics/drawable/shapes/PathShape.java b/graphics/java/android/graphics/drawable/shapes/PathShape.java
index 30b7347..ce5552b 100644
--- a/graphics/java/android/graphics/drawable/shapes/PathShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/PathShape.java
@@ -16,41 +16,44 @@
 
 package android.graphics.drawable.shapes;
 
+import android.annotation.NonNull;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
 
 /**
  * Creates geometric paths, utilizing the {@link android.graphics.Path} class.
+ * <p>
  * The path can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the PathShape to a {@link android.graphics.drawable.ShapeDrawable}.
  */
 public class PathShape extends Shape {
-    private Path    mPath;
-    private float   mStdWidth;
-    private float   mStdHeight;
-    
-    private float   mScaleX;    // cached from onResize
-    private float   mScaleY;    // cached from onResize
-    
+    private final float mStdWidth;
+    private final float mStdHeight;
+
+    private Path mPath;
+
+    private float mScaleX; // cached from onResize
+    private float mScaleY; // cached from onResize
+
     /**
      * PathShape constructor.
-     * 
-     * @param path       a Path that defines the geometric paths for this shape
-     * @param stdWidth   the standard width for the shape. Any changes to the 
-     *                   width with resize() will result in a width scaled based
-     *                   on the new width divided by this width.
-     * @param stdHeight  the standard height for the shape. Any changes to the 
-     *                   height with resize() will result in a height scaled based
-     *                   on the new height divided by this height.
+     *
+     * @param path a Path that defines the geometric paths for this shape
+     * @param stdWidth the standard width for the shape. Any changes to the
+     *                 width with resize() will result in a width scaled based
+     *                 on the new width divided by this width.
+     * @param stdHeight the standard height for the shape. Any changes to the
+     *                  height with resize() will result in a height scaled based
+     *                  on the new height divided by this height.
      */
-    public PathShape(Path path, float stdWidth, float stdHeight) {
+    public PathShape(@NonNull Path path, float stdWidth, float stdHeight) {
         mPath = path;
         mStdWidth = stdWidth;
         mStdHeight = stdHeight;
     }
-    
+
     @Override
     public void draw(Canvas canvas, Paint paint) {
         canvas.save();
@@ -58,7 +61,7 @@
         canvas.drawPath(mPath, paint);
         canvas.restore();
     }
-    
+
     @Override
     protected void onResize(float width, float height) {
         mScaleX = width / mStdWidth;
@@ -67,7 +70,7 @@
 
     @Override
     public PathShape clone() throws CloneNotSupportedException {
-        PathShape shape = (PathShape) super.clone();
+        final PathShape shape = (PathShape) super.clone();
         shape.mPath = new Path(mPath);
         return shape;
     }
diff --git a/graphics/java/android/graphics/drawable/shapes/RectShape.java b/graphics/java/android/graphics/drawable/shapes/RectShape.java
index 04cf293..e339a21 100644
--- a/graphics/java/android/graphics/drawable/shapes/RectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RectShape.java
@@ -23,6 +23,7 @@
 
 /**
  * Defines a rectangle shape.
+ * <p>
  * The rectangle can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the RectShape to a {@link android.graphics.drawable.ShapeDrawable}.
diff --git a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
index e5253b8..f5cbb24 100644
--- a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable.shapes;
 
+import android.annotation.Nullable;
 import android.graphics.Canvas;
 import android.graphics.Outline;
 import android.graphics.Paint;
@@ -24,40 +25,41 @@
 
 /**
  * Creates a rounded-corner rectangle. Optionally, an inset (rounded) rectangle
- * can be included (to make a sort of "O" shape). 
+ * can be included (to make a sort of "O" shape).
+ * <p>
  * The rounded rectangle can be drawn to a Canvas with its own draw() method,
  * but more graphical control is available if you instead pass
  * the RoundRectShape to a {@link android.graphics.drawable.ShapeDrawable}.
  */
 public class RoundRectShape extends RectShape {
     private float[] mOuterRadii;
-    private RectF   mInset;
+    private RectF mInset;
     private float[] mInnerRadii;
     
     private RectF mInnerRect;
-    private Path  mPath;    // this is what we actually draw
+    private Path mPath; // this is what we actually draw
     
     /**
      * RoundRectShape constructor.
+     * <p>
      * Specifies an outer (round)rect and an optional inner (round)rect.
      *
      * @param outerRadii An array of 8 radius values, for the outer roundrect. 
-     *                   The first two floats are for the 
-     *                   top-left corner (remaining pairs correspond clockwise). 
-     *                   For no rounded corners on the outer rectangle, 
-     *                   pass null.
-     * @param inset      A RectF that specifies the distance from the inner 
-     *                   rect to each side of the outer rect. 
-     *                   For no inner, pass null.
+     *                   The first two floats are for the top-left corner
+     *                   (remaining pairs correspond clockwise). For no rounded
+     *                   corners on the outer rectangle, pass {@code null}.
+     * @param inset A RectF that specifies the distance from the inner
+     *              rect to each side of the outer rect. For no inner, pass
+     *              {@code null}.
      * @param innerRadii An array of 8 radius values, for the inner roundrect.
-     *                   The first two floats are for the 
-     *                   top-left corner (remaining pairs correspond clockwise). 
-     *                   For no rounded corners on the inner rectangle, 
-     *                   pass null.
-     *                   If inset parameter is null, this parameter is ignored. 
+     *                   The first two floats are for the top-left corner
+     *                   (remaining pairs correspond clockwise). For no rounded
+     *                   corners on the inner rectangle, pass {@code null}. If
+     *                   inset parameter is {@code null}, this parameter is
+     *                   ignored.
      */
-    public RoundRectShape(float[] outerRadii, RectF inset,
-                          float[] innerRadii) {
+    public RoundRectShape(@Nullable float[] outerRadii, @Nullable RectF inset,
+            @Nullable float[] innerRadii) {
         if (outerRadii != null && outerRadii.length < 8) {
             throw new ArrayIndexOutOfBoundsException("outer radii must have >= 8 values");
         }
@@ -97,8 +99,7 @@
 
         final RectF rect = rect();
         outline.setRoundRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
-                (int) Math.floor(rect.right), (int) Math.floor(rect.bottom),
-                radius);
+                (int) Math.floor(rect.right), (int) Math.floor(rect.bottom), radius);
     }
 
     @Override
@@ -128,7 +129,7 @@
 
     @Override
     public RoundRectShape clone() throws CloneNotSupportedException {
-        RoundRectShape shape = (RoundRectShape) super.clone();
+        final RoundRectShape shape = (RoundRectShape) super.clone();
         shape.mOuterRadii = mOuterRadii != null ? mOuterRadii.clone() : null;
         shape.mInnerRadii = mInnerRadii != null ? mInnerRadii.clone() : null;
         shape.mInset = new RectF(mInset);
diff --git a/graphics/java/android/graphics/drawable/shapes/Shape.java b/graphics/java/android/graphics/drawable/shapes/Shape.java
index eab8666..30b28f3 100644
--- a/graphics/java/android/graphics/drawable/shapes/Shape.java
+++ b/graphics/java/android/graphics/drawable/shapes/Shape.java
@@ -23,21 +23,25 @@
 
 /**
  * Defines a generic graphical "shape."
- * Any Shape can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * it to a {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Any Shape can be drawn to a Canvas with its own draw() method, but more
+ * graphical control is available if you instead pass it to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Custom Shape classes must implement {@link #clone()} and return an instance
+ * of the custom Shape class.
  */
 public abstract class Shape implements Cloneable {
     private float mWidth;
     private float mHeight;
-    
+
     /**
      * Returns the width of the Shape.
      */
     public final float getWidth() {
         return mWidth;
     }
-    
+
     /**
      * Returns the height of the Shape.
      */
@@ -46,9 +50,10 @@
     }
 
     /**
-     * Draw this shape into the provided Canvas, with the provided Paint.
+     * Draws this shape into the provided Canvas, with the provided Paint.
+     * <p>
      * Before calling this, you must call {@link #resize(float,float)}.
-     * 
+     *
      * @param canvas the Canvas within which this shape should be drawn
      * @param paint  the Paint object that defines this shape's characteristics
      */
@@ -56,8 +61,9 @@
 
     /**
      * Resizes the dimensions of this shape.
+     * <p>
      * Must be called before {@link #draw(Canvas,Paint)}.
-     * 
+     *
      * @param width the width of the shape (in pixels)
      * @param height the height of the shape (in pixels)
      */
@@ -74,30 +80,34 @@
             onResize(width, height);
         }
     }
-    
+
     /**
      * Checks whether the Shape is opaque.
-     * Default impl returns true. Override if your subclass can be opaque.
-     * 
-     * @return true if any part of the drawable is <em>not</em> opaque. 
+     * <p>
+     * Default impl returns {@code true}. Override if your subclass can be
+     * opaque.
+     *
+     * @return true if any part of the drawable is <em>not</em> opaque.
      */
     public boolean hasAlpha() {
         return true;
     }
-    
+
     /**
      * Callback method called when {@link #resize(float,float)} is executed.
-     * 
+     *
      * @param width the new width of the Shape
      * @param height the new height of the Shape
      */
     protected void onResize(float width, float height) {}
 
     /**
-     * Compute the Outline of the shape and return it in the supplied Outline
-     * parameter. The default implementation does nothing and {@code outline} is not changed.
+     * Computes the Outline of the shape and return it in the supplied Outline
+     * parameter. The default implementation does nothing and {@code outline}
+     * is not changed.
      *
-     * @param outline The Outline to be populated with the result. Should not be null.
+     * @param outline the Outline to be populated with the result. Must be
+     *                non-{@code null}.
      */
     public void getOutline(@NonNull Outline outline) {}
 
@@ -105,5 +115,4 @@
     public Shape clone() throws CloneNotSupportedException {
         return (Shape) super.clone();
     }
-
 }
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 4791cf0..e77c00b 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -53,6 +53,7 @@
  *         time-interval between key frames.
  *         Float support added in {@link android.os.Build.VERSION_CODES#N_MR1}</td></tr>
  * <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
+ * <tr><td>{@link #KEY_LATENCY}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
  * <tr><td>{@link #KEY_MAX_WIDTH}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution width</td></tr>
  * <tr><td>{@link #KEY_MAX_HEIGHT}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution height</td></tr>
  * <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>encoder in surface-mode
@@ -577,6 +578,18 @@
     public static final String KEY_LEVEL = "level";
 
     /**
+    * An optional key describing the desired encoder latency in frames. This is an optional
+    * parameter that applies only to video encoders. If encoder supports it, it should ouput
+    * at least one output frame after being queued the specified number of frames. This key
+    * is ignored if the video encoder does not support the latency feature. Use the output
+    * format to verify that this feature was enabled and the actual value used by the encoder.
+    * <p>
+    * If the key is not specified, the default latency will be implenmentation specific.
+    * The associated value is an integer.
+    */
+    public static final String KEY_LATENCY = "latency";
+
+    /**
      * A key describing the desired clockwise rotation on an output surface.
      * This key is only used when the codec is configured using an output surface.
      * The associated value is an integer, representing degrees. Supported values
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index aacce91..832b297 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -68,44 +68,46 @@
 
  <h4>Metadata Track</h4>
  <p>
-  Metadata is usefule in carrying extra information that correlated with video or audio to
-  facilate offline processing, e.g. gyro signals from the sensor. Meatadata track is only
-  supported in MP4 format. When adding a metadata track, track's mime format must start with
-  prefix "application/", e.g. "applicaton/gyro". Metadata's format/layout will be defined by
-  the application. The generated MP4 file uses TextMetaDataSampleEntry defined in section 12.3.3.2
-  of the ISOBMFF to signal the metadata's mime format. When using {@link android.media.MediaExtractor}
-  to extract the file with metadata track, the mime format of the metadata will be extracted into
-  {@link android.media.MediaFormat}.
+  Per-frame metadata is useful in carrying extra information that correlated with video or audio to
+  facilitate offline processing, e.g. gyro signals from the sensor could help video stabilization when
+  doing offline processing. Metaadata track is only supported in MP4 container. When adding a new
+  metadata track, track's mime format must start with prefix "application/", e.g. "applicaton/gyro".
+  Metadata's format/layout will be defined by the application. Writing metadata is nearly the same as
+  writing video/audio data except that the data will not be from mediacodec. Application just needs
+  to pass the bytebuffer that contains the metadata and also the associated timestamp to the
+  {@link #writeSampleData} api. The timestamp must be in the same time base as video and audio. The
+  generated MP4 file uses TextMetaDataSampleEntry defined in section 12.3.3.2 of the ISOBMFF to signal
+  the metadata's mime format. When using{@link android.media.MediaExtractor} to extract the file with
+  metadata track, the mime format of the metadata will be extracted into {@link android.media.MediaFormat}.
 
  <pre class=prettyprint>
    MediaMuxer muxer = new MediaMuxer("temp.mp4", OutputFormat.MUXER_OUTPUT_MPEG_4);
-   // More often, the MediaFormat will be retrieved from MediaCodec.getOutputFormat()
-   // or MediaExtractor.getTrackFormat().
+   // SetUp Video/Audio Tracks.
    MediaFormat audioFormat = new MediaFormat(...);
    MediaFormat videoFormat = new MediaFormat(...);
+   int audioTrackIndex = muxer.addTrack(audioFormat);
+   int videoTrackIndex = muxer.addTrack(videoFormat);
 
    // Setup Metadata Track
    MediaFormat metadataFormat = new MediaFormat(...);
    metadataFormat.setString(KEY_MIME, "application/gyro");
-
-   int audioTrackIndex = muxer.addTrack(audioFormat);
-   int videoTrackIndex = muxer.addTrack(videoFormat);
    int metadataTrackIndex = muxer.addTrack(metadataFormat);
-   ByteBuffer inputBuffer = ByteBuffer.allocate(bufferSize);
-   boolean finished = false;
-   BufferInfo bufferInfo = new BufferInfo();
 
    muxer.start();
-   while(!finished) {
-     // getInputBuffer() will fill the inputBuffer with one frame of encoded
-     // sample from either MediaCodec or MediaExtractor, set isAudioSample to
-     // true when the sample is audio data, set up all the fields of bufferInfo,
-     // and return true if there are no more samples.
-     finished = getInputBuffer(inputBuffer, sampleType, bufferInfo);
-     if (!finished) {
-       int currentTrackIndex = getTrackIndex(sampleType);
-       muxer.writeSampleData(currentTrackIndex, inputBuffer, bufferInfo);
-     }
+   while(..) {
+       // Allocate bytebuffer and write gyro data(x,y,z) into it.
+       ByteBuffer metaData = ByteBuffer.allocate(bufferSize);
+       metaData.putFloat(x);
+       metaData.putFloat(y);
+       metaData.putFloat(z);
+       BufferInfo metaInfo = new BufferInfo();
+       // Associate this metadata with the video frame by setting
+       // the same timestamp as the video frame.
+       metaInfo.presentationTimeUs = currentVideoTrackTimeUs;
+       metaInfo.offset = 0;
+       metaInfo.flags = 0;
+       metaInfo.size = bufferSize;
+       muxer.writeSampleData(metadataTrackIndex, metaData, metaInfo);
    };
    muxer.stop();
    muxer.release();
diff --git a/native/android/Android.mk b/native/android/Android.mk
index 1c1ff82..57f996c 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -19,6 +19,7 @@
     net.c \
     obb.cpp \
     sensor.cpp \
+    sharedmem.cpp \
     storage_manager.cpp \
     trace.cpp \
 
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index f9e8fda..e2623d4 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -186,6 +186,9 @@
     ASensor_getType;
     ASensor_getVendor;
     ASensor_isWakeUpSensor; # introduced=21
+    ASharedMemory_create; # introduced=26
+    ASharedMemory_getSize; # introduced=26
+    ASharedMemory_setProt; # introduced=26
     AStorageManager_delete;
     AStorageManager_getMountedObbPath;
     AStorageManager_isObbMounted;
diff --git a/native/android/sharedmem.cpp b/native/android/sharedmem.cpp
new file mode 100644
index 0000000..9d029dfa
--- /dev/null
+++ b/native/android/sharedmem.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <android/sharedmem.h>
+#include <cutils/ashmem.h>
+#include <utils/Errors.h>
+
+int ASharedMemory_create(const char *name, size_t size) {
+    if (size == 0) {
+        return android::BAD_VALUE;
+    }
+    return ashmem_create_region(name, size);
+}
+
+size_t ASharedMemory_getSize(int fd) {
+    return ashmem_valid(fd) ? ashmem_get_size_region(fd) : 0;
+}
+
+int ASharedMemory_setProt(int fd, int prot) {
+    return ashmem_set_prot_region(fd, prot);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 26ca3d4..6fe581e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -89,15 +89,15 @@
             new ConcurrentHashMap<String, ScanResult>(32);
     private static final long MAX_SCAN_RESULT_AGE_MS = 15000;
 
-    private static final String KEY_NETWORKINFO = "key_networkinfo";
-    private static final String KEY_WIFIINFO = "key_wifiinfo";
-    private static final String KEY_SCANRESULT = "key_scanresult";
-    private static final String KEY_SSID = "key_ssid";
-    private static final String KEY_SECURITY = "key_security";
-    private static final String KEY_PSKTYPE = "key_psktype";
-    private static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
-    private static final String KEY_CONFIG = "key_config";
-    private static final AtomicInteger sLastId = new AtomicInteger(0);
+    static final String KEY_NETWORKINFO = "key_networkinfo";
+    static final String KEY_WIFIINFO = "key_wifiinfo";
+    static final String KEY_SCANRESULT = "key_scanresult";
+    static final String KEY_SSID = "key_ssid";
+    static final String KEY_SECURITY = "key_security";
+    static final String KEY_PSKTYPE = "key_psktype";
+    static final String KEY_SCANRESULTCACHE = "key_scanresultcache";
+    static final String KEY_CONFIG = "key_config";
+    static final AtomicInteger sLastId = new AtomicInteger(0);
 
     /**
      * These values are matched in string arrays -- changes must be kept in sync
@@ -114,6 +114,8 @@
 
     public static final int SIGNAL_LEVELS = 4;
 
+    static final int UNREACHABLE_RSSI = Integer.MAX_VALUE;
+
     private final Context mContext;
 
     private String ssid;
@@ -125,7 +127,7 @@
 
     private WifiConfiguration mConfig;
 
-    private int mRssi = Integer.MAX_VALUE;
+    private int mRssi = UNREACHABLE_RSSI;
     private long mSeen = 0;
 
     private WifiInfo mInfo;
@@ -214,6 +216,21 @@
         this.mRankingScore = that.mRankingScore;
     }
 
+    /**
+    * Returns a negative integer, zero, or a positive integer if this AccessPoint is less than,
+    * equal to, or greater than the other AccessPoint.
+    *
+    * Sort order rules for AccessPoints:
+    *   1. Active before inactive
+    *   2. Reachable before unreachable
+    *   3. Saved before unsaved
+    *   4. (Internal only) Network ranking score
+    *   5. Stronger signal before weaker signal
+    *   6. SSID alphabetically
+    *
+    * Note that AccessPoints with a signal are usually also Reachable,
+    * and will thus appear before unreachable saved AccessPoints.
+    */
     @Override
     public int compareTo(@NonNull AccessPoint other) {
         // Active one goes first.
@@ -221,18 +238,16 @@
         if (!isActive() && other.isActive()) return 1;
 
         // Reachable one goes before unreachable one.
-        if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
-        if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
+        if (isReachable() && !other.isReachable()) return -1;
+        if (!isReachable() && other.isReachable()) return 1;
 
         // Configured (saved) one goes before unconfigured one.
-        if (networkId != WifiConfiguration.INVALID_NETWORK_ID
-                && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
-        if (networkId == WifiConfiguration.INVALID_NETWORK_ID
-                && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
+        if (isSaved() && !other.isSaved()) return -1;
+        if (!isSaved() && other.isSaved()) return 1;
 
         // Higher scores go before lower scores
-        if (mRankingScore != other.mRankingScore) {
-            return (mRankingScore > other.mRankingScore) ? -1 : 1;
+        if (getRankingScore() != other.getRankingScore()) {
+            return (getRankingScore() > other.getRankingScore()) ? -1 : 1;
         }
 
         // Sort by signal strength, bucketed by level
@@ -242,7 +257,7 @@
             return difference;
         }
         // Sort by ssid.
-        return ssid.compareToIgnoreCase(other.ssid);
+        return getSsidStr().compareToIgnoreCase(other.getSsidStr());
     }
 
     @Override
@@ -355,7 +370,7 @@
     }
 
     public int getLevel() {
-        if (mRssi == Integer.MAX_VALUE) {
+        if (!isReachable()) {
             return -1;
         }
         return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
@@ -531,7 +546,7 @@
             }
         } else if (config != null && config.getNetworkSelectionStatus().isNotRecommended()) {
             summary.append(mContext.getString(R.string.wifi_disabled_by_recommendation_provider));
-        } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range
+        } else if (!isReachable()) { // Wifi out of range
             summary.append(mContext.getString(R.string.wifi_not_in_range));
         } else { // In range, not disabled.
             if (config != null) { // Is saved network
@@ -874,6 +889,11 @@
         return mBadge;
     }
 
+    /** Return true if the current RSSI is reachable, and false otherwise. */
+    boolean isReachable() {
+        return mRssi != UNREACHABLE_RSSI;
+    }
+
     public static String getSummary(Context context, String ssid, DetailedState state,
             boolean isEphemeral, String passpointProvider) {
         if (state == DetailedState.CONNECTED && ssid == null) {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 6481f4d..ec0190c 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -15,9 +15,8 @@
  */
 package com.android.settingslib.wifi;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -39,6 +38,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
+import java.util.Collections;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -59,12 +59,12 @@
         final AccessPoint ap = new AccessPoint(InstrumentationRegistry.getTargetContext(), bundle);
         final CharSequence ssid = ap.getSsid();
 
-        assertTrue(ssid instanceof SpannableString);
+        assertThat(ssid instanceof SpannableString).isTrue();
 
         TtsSpan[] spans = ((SpannableString) ssid).getSpans(0, TEST_SSID.length(), TtsSpan.class);
 
-        assertEquals(1, spans.length);
-        assertEquals(TtsSpan.TYPE_TELEPHONE, spans[0].getType());
+        assertThat(spans.length).isEqualTo(1);
+        assertThat(spans[0].getType()).isEqualTo(TtsSpan.TYPE_TELEPHONE);
     }
 
     @Test
@@ -80,11 +80,11 @@
         originalAccessPoint.update(configuration, wifiInfo, networkInfo);
         AccessPoint copy = new AccessPoint(mContext, originalAccessPoint);
 
-        assertEquals(originalAccessPoint.getSsid().toString(), copy.getSsid().toString());
-        assertEquals(originalAccessPoint.getBssid(), copy.getBssid());
-        assertSame(originalAccessPoint.getConfig(), copy.getConfig());
-        assertEquals(originalAccessPoint.getSecurity(), copy.getSecurity());
-        assertTrue(originalAccessPoint.compareTo(copy) == 0);
+        assertThat(originalAccessPoint.getSsid().toString()).isEqualTo(copy.getSsid().toString());
+        assertThat(originalAccessPoint.getBssid()).isEqualTo(copy.getBssid());
+        assertThat(originalAccessPoint.getConfig()).isEqualTo(copy.getConfig());
+        assertThat(originalAccessPoint.getSecurity()).isEqualTo(copy.getSecurity());
+        assertThat(originalAccessPoint.compareTo(copy) == 0).isTrue();
     }
 
     @Test
@@ -101,11 +101,93 @@
 
         bundle.putParcelableArrayList("key_scanresultcache", scanResults);
         AccessPoint original = new AccessPoint(mContext, bundle);
-        assertEquals(4, original.getRssi());
+        assertThat(original.getRssi()).isEqualTo(4);
         AccessPoint copy = new AccessPoint(mContext, createWifiConfiguration());
-        assertEquals(Integer.MIN_VALUE, copy.getRssi());
+        assertThat(copy.getRssi()).isEqualTo(Integer.MIN_VALUE);
         copy.copyFrom(original);
-        assertEquals(original.getRssi(), copy.getRssi());
+        assertThat(original.getRssi()).isEqualTo(copy.getRssi());
+    }
+
+    @Test
+    public void testCompareTo_GivesActiveBeforeInactive() {
+        AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+        AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+
+        assertSortingWorks(activeAp, inactiveAp);
+    }
+
+    @Test
+    public void testCompareTo_GivesReachableBeforeUnreachable() {
+        AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+        AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+
+        assertSortingWorks(nearAp, farAp);
+    }
+
+    @Test
+    public void testCompareTo_GivesSavedBeforeUnsaved() {
+        AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+        AccessPoint notSavedAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+
+        assertSortingWorks(savedAp, notSavedAp);
+    }
+
+    //TODO: add tests for mRankingScore sort order if ranking is exposed
+
+    @Test
+    public void testCompareTo_GivesHighLevelBeforeLowLevel() {
+        final int highLevel = AccessPoint.SIGNAL_LEVELS - 1;
+        final int lowLevel = 1;
+        assertThat(highLevel).isGreaterThan(lowLevel);
+
+        AccessPoint strongAp = new TestAccessPointBuilder(mContext).setLevel(highLevel).build();
+        AccessPoint weakAp = new TestAccessPointBuilder(mContext).setLevel(lowLevel).build();
+
+        assertSortingWorks(strongAp, weakAp);
+    }
+
+    @Test
+    public void testCompareTo_GivesSsidAlphabetically() {
+
+        final String firstName = "AAAAAA";
+        final String secondName = "zzzzzz";
+
+        AccessPoint firstAp = new TestAccessPointBuilder(mContext).setSsid(firstName).build();
+        AccessPoint secondAp = new TestAccessPointBuilder(mContext).setSsid(secondName).build();
+
+        assertThat(firstAp.getSsidStr().compareToIgnoreCase(secondAp.getSsidStr()) < 0).isTrue();
+        assertSortingWorks(firstAp, secondAp);
+    }
+
+    @Test
+    public void testCompareTo_AllSortingRulesCombined() {
+
+        AccessPoint active = new TestAccessPointBuilder(mContext).setActive(true).build();
+        AccessPoint reachableAndMinLevel = new TestAccessPointBuilder(mContext)
+                .setReachable(true).build();
+        AccessPoint saved = new TestAccessPointBuilder(mContext).setSaved(true).build();
+        AccessPoint highLevelAndReachable = new TestAccessPointBuilder(mContext)
+                .setLevel(AccessPoint.SIGNAL_LEVELS - 1).build();
+        AccessPoint firstName = new TestAccessPointBuilder(mContext).setSsid("a").build();
+        AccessPoint lastname = new TestAccessPointBuilder(mContext).setSsid("z").build();
+
+        ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+        points.add(lastname);
+        points.add(firstName);
+        points.add(highLevelAndReachable);
+        points.add(saved);
+        points.add(reachableAndMinLevel);
+        points.add(active);
+
+        Collections.sort(points);
+        assertThat(points.indexOf(active)).isLessThan(points.indexOf(reachableAndMinLevel));
+        assertThat(points.indexOf(reachableAndMinLevel)).isLessThan(points.indexOf(saved));
+        // note: the saved AP will not appear before highLevelAndReachable,
+        // because all APs with a signal level are reachable,
+        // and isReachable() takes higher sorting precedence than isSaved().
+        assertThat(points.indexOf(saved)).isLessThan(points.indexOf(firstName));
+        assertThat(points.indexOf(highLevelAndReachable)).isLessThan(points.indexOf(firstName));
+        assertThat(points.indexOf(firstName)).isLessThan(points.indexOf(lastname));
     }
 
     private WifiConfiguration createWifiConfiguration() {
@@ -115,4 +197,85 @@
         configuration.networkId = 123;
         return configuration;
     }
+
+    /**
+    * Assert that the first AccessPoint appears after the second AccessPoint
+    * once sorting has been completed.
+    */
+    private void assertSortingWorks(AccessPoint first, AccessPoint second) {
+
+        ArrayList<AccessPoint> points = new ArrayList<AccessPoint>();
+
+        // add in reverse order so we can tell that sorting actually changed something
+        points.add(second);
+        points.add(first);
+        Collections.sort(points);
+        assertWithMessage(
+                String.format("After sorting: second AccessPoint should have higher array index "
+                    + "than the first, but found indicies second '%s' and first '%s'.",
+                    points.indexOf(second), points.indexOf(first)))
+            .that(points.indexOf(second)).isGreaterThan(points.indexOf(first));
+    }
+
+    @Test
+    public void testBuilder_setActive() {
+        AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build();
+        assertThat(activeAp.isActive()).isTrue();
+
+        AccessPoint inactiveAp = new TestAccessPointBuilder(mContext).setActive(false).build();
+        assertThat(inactiveAp.isActive()).isFalse();
+    }
+
+    @Test
+    public void testBuilder_setReachable() {
+        AccessPoint nearAp = new TestAccessPointBuilder(mContext).setReachable(true).build();
+        assertThat(nearAp.isReachable()).isTrue();
+
+        AccessPoint farAp = new TestAccessPointBuilder(mContext).setReachable(false).build();
+        assertThat(farAp.isReachable()).isFalse();
+    }
+
+    @Test
+    public void testBuilder_setSaved() {
+        AccessPoint savedAp = new TestAccessPointBuilder(mContext).setSaved(true).build();
+        assertThat(savedAp.isSaved()).isTrue();
+
+        AccessPoint newAp = new TestAccessPointBuilder(mContext).setSaved(false).build();
+        assertThat(newAp.isSaved()).isFalse();
+    }
+
+    @Test
+    public void testBuilder_setLevel() {
+        AccessPoint testAp;
+
+        for (int i = 0; i < AccessPoint.SIGNAL_LEVELS; i++) {
+            testAp = new TestAccessPointBuilder(mContext).setLevel(i).build();
+            assertThat(testAp.getLevel()).isEqualTo(i);
+        }
+
+        // numbers larger than the max level should be set to max
+        testAp = new TestAccessPointBuilder(mContext).setLevel(AccessPoint.SIGNAL_LEVELS).build();
+        assertThat(testAp.getLevel()).isEqualTo(AccessPoint.SIGNAL_LEVELS - 1);
+
+        // numbers less than 0 should give level 0
+        testAp = new TestAccessPointBuilder(mContext).setLevel(-100).build();
+        assertThat(testAp.getLevel()).isEqualTo(0);
+    }
+
+    @Test
+    public void testBuilder_settingReachableAfterLevelDoesNotAffectLevel() {
+        int level = 1;
+        assertThat(level).isLessThan(AccessPoint.SIGNAL_LEVELS - 1);
+
+        AccessPoint testAp =
+                new TestAccessPointBuilder(mContext).setLevel(level).setReachable(true).build();
+        assertThat(testAp.getLevel()).isEqualTo(level);
+    }
+
+    @Test
+    public void testBuilder_setSsid() {
+        String name = "AmazingSsid!";
+        AccessPoint namedAp = new TestAccessPointBuilder(mContext).setSsid(name).build();
+        assertThat(namedAp.getSsidStr()).isEqualTo(name);
+    }
 }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
new file mode 100644
index 0000000..665c439
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/TestAccessPointBuilder.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2017 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.settingslib.wifi;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+
+/**
+* Build and return a valid AccessPoint.
+*
+* Only intended for testing the AccessPoint class;
+* AccessPoints were designed to only be populated
+* by the mechanisms of scan results and wifi configurations.
+*/
+public class TestAccessPointBuilder {
+    // match the private values in WifiManager
+    private static final int MIN_RSSI = -100;
+    private static final int MAX_RSSI = -55;
+
+    // set some sensible defaults
+    private int mRssi = AccessPoint.UNREACHABLE_RSSI;
+    private int networkId = WifiConfiguration.INVALID_NETWORK_ID;
+    private String ssid = "TestSsid";
+    private NetworkInfo mNetworkInfo = null;
+
+    Context mContext;
+
+    public TestAccessPointBuilder(Context context) {
+        mContext = context;
+    }
+
+    public AccessPoint build() {
+        Bundle bundle = new Bundle();
+
+        WifiConfiguration wifiConig = new WifiConfiguration();
+        wifiConig.networkId = networkId;
+
+        bundle.putString(AccessPoint.KEY_SSID, ssid);
+        bundle.putParcelable(AccessPoint.KEY_CONFIG, wifiConig);
+        bundle.putParcelable(AccessPoint.KEY_NETWORKINFO, mNetworkInfo);
+        AccessPoint ap = new AccessPoint(mContext, bundle);
+        ap.setRssi(mRssi);
+        return ap;
+    }
+
+    public TestAccessPointBuilder setActive(boolean active) {
+        if (active) {
+            mNetworkInfo = new NetworkInfo(
+                ConnectivityManager.TYPE_DUMMY,
+                ConnectivityManager.TYPE_DUMMY,
+                "TestNetwork",
+                "TestNetwork");
+        } else {
+            mNetworkInfo = null;
+        }
+        return this;
+    }
+
+    /**
+    * Set the signal level.
+    * Side effect: if this AccessPoint was previously unreachable,
+    * setting the level will also make it reachable.
+    */
+    public TestAccessPointBuilder setLevel(int level) {
+        int outputRange = AccessPoint.SIGNAL_LEVELS - 1;
+
+        if (level > outputRange) {
+            level = outputRange;
+        } else if (level < 0) {
+            level = 0;
+        }
+
+        int inputRange = MAX_RSSI - MIN_RSSI;
+
+        // calculate the rssi required to get the level we want.
+        // this is a rearrangement of the formula from WifiManager.calculateSignalLevel()
+        mRssi = (int)((float)(level * inputRange) / (float)outputRange) + MIN_RSSI;
+        return this;
+    }
+
+    /**
+    * Set whether the AccessPoint is reachable.
+    * Side effect: if the signal level was not previously set,
+    * making an AccessPoint reachable will set the signal to the minimum level.
+    */
+    public TestAccessPointBuilder setReachable(boolean reachable) {
+        if (reachable) {
+            // only override the mRssi if it hasn't been set yet
+            if (mRssi == AccessPoint.UNREACHABLE_RSSI) {
+                mRssi = MIN_RSSI;
+            }
+        } else {
+            mRssi = AccessPoint.UNREACHABLE_RSSI;
+        }
+        return this;
+    }
+
+    public TestAccessPointBuilder setSaved(boolean saved){
+        if (saved) {
+             networkId = 1;
+        } else {
+             networkId = WifiConfiguration.INVALID_NETWORK_ID;
+        }
+        return this;
+    }
+
+    public TestAccessPointBuilder setSsid(String newSsid) {
+        ssid = newSsid;
+        return this;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 02b0113..e0dac09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -197,6 +197,7 @@
                     bm.getHeight() - thumbnailData.insets.top - thumbnailData.insets.bottom);
             mThumbnailData = thumbnailData;
             updateThumbnailMatrix();
+            updateThumbnailPaintFilter();
         } else {
             mBitmapShader = null;
             mDrawPaint.setShader(null);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 7e9cbca..bfc6e83 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -743,8 +743,9 @@
                         Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
                                 + state.mAutoFillValue);
                     }
-                    getUiForShowing().showSaveUi(mInfo.getServiceInfo()
-                            .loadLabel(mContext.getPackageManager()));
+                    getUiForShowing().showSaveUi(
+                            mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
+                            saveInfo);
                     return;
                 }
             }
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index cc0baa3..949a80c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -24,6 +24,7 @@
 import android.os.IBinder;
 import android.service.autofill.Dataset;
 import android.service.autofill.FillResponse;
+import android.service.autofill.SaveInfo;
 import android.text.TextUtils;
 import android.view.autofill.AutoFillId;
 import android.widget.Toast;
@@ -172,13 +173,13 @@
     /**
      * Shows the UI asking the user to save for auto-fill.
      */
-    public void showSaveUi(@NonNull CharSequence providerLabel) {
+    public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
         mHandler.post(() -> {
             if (!hasCallback()) {
                 return;
             }
             hideAllUiThread();
-            mSaveUi = new SaveUi(mContext, providerLabel,
+            mSaveUi = new SaveUi(mContext, providerLabel, info,
                     new SaveUi.OnSaveListener() {
                 @Override
                 public void onSave() {
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index b7215d6..afe93c7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -20,6 +20,7 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.os.Handler;
+import android.service.autofill.SaveInfo;
 import android.text.format.DateUtils;
 import android.view.Gravity;
 import android.view.Window;
@@ -50,15 +51,41 @@
 
     private boolean mDestroyed;
 
-    SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel,
+    SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
             @NonNull OnSaveListener listener) {
         mListener = listener;
 
         final LayoutInflater inflater = LayoutInflater.from(context);
         final View view = inflater.inflate(R.layout.autofill_save, null);
 
-        final TextView title = (TextView) view.findViewById(R.id.autofill_save_title);
-        title.setText(context.getString(R.string.autofill_save_title, providerLabel));
+        final TextView titleView = (TextView) view.findViewById(R.id.autofill_save_title);
+        final String type;
+
+        switch(info.getType()) {
+            case SaveInfo.SAVE_DATA_TYPE_PASSWORD:
+                type = context.getString(R.string.autofill_save_type_password);
+                break;
+            case SaveInfo.SAVE_DATA_TYPE_ADDRESS:
+                type = context.getString(R.string.autofill_save_type_address);
+                break;
+            case SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD:
+                type = context.getString(R.string.autofill_save_type_credit_card);
+                break;
+            default:
+                type = null;
+        }
+
+        final String title = (type == null)
+                ? context.getString(R.string.autofill_save_title, providerLabel)
+                : context.getString(R.string.autofill_save_title_with_type, type, providerLabel);
+
+        titleView.setText(title);
+        final CharSequence subTitle = info.getDescription();
+        if (subTitle != null) {
+            final TextView subTitleView = (TextView) view.findViewById(R.id.autofill_save_subtitle);
+            subTitleView.setText(subTitle);
+            subTitleView.setVisibility(View.VISIBLE);
+        }
 
         final View noButton = view.findViewById(R.id.autofill_save_no);
         noButton.setOnClickListener((v) -> mListener.onCancel());
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c11131a..71bfa64 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -442,8 +442,8 @@
 
         @Override
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
-                String packageName, List shortcutIds, ComponentName componentName, int flags,
-                UserHandle targetUser) {
+                String packageName, List shortcutIds, ComponentName componentName, Intent intent,
+                int flags, UserHandle targetUser) {
             ensureShortcutPermission(callingPackage);
             if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
                     || !isUserEnabled(targetUser)) {
@@ -454,11 +454,17 @@
                         "To query by shortcut ID, package name must also be set");
             }
 
+            if ((flags & ShortcutQuery.FLAG_MATCH_CHOOSER) == 0
+                    && intent != null) {
+                throw new IllegalArgumentException("Supplied an intent in the query, but did "
+                        + "not request chooser targets");
+            }
+
             // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
             return new ParceledListSlice<>((List<ShortcutInfo>)
                     mShortcutServiceInternal.getShortcuts(getCallingUserId(),
                             callingPackage, changedSince, packageName, shortcutIds,
-                            componentName, flags, targetUser.getIdentifier()));
+                            componentName, intent, flags, targetUser.getIdentifier()));
         }
 
         @Override
@@ -906,6 +912,7 @@
                                         cookie.packageName,
                                         /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
                                         /* component= */ null,
+                                        /* intent= */ null,
                                         ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
                                         | ShortcutQuery.FLAG_GET_ALL_KINDS
                                         , userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f1b4a70..116c0a3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11711,7 +11711,8 @@
             if (!whitelisted) {
                 Slog.w(TAG, "Privileged permission " + perm + " for package "
                         + pkg.packageName + " - not in privapp-permissions whitelist");
-                if (!mSystemReady) {
+                // Only report violations for apps on system image
+                if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
                     if (mPrivappPermissionsViolations == null) {
                         mPrivappPermissionsViolations = new ArraySet<>();
                     }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 570259b..ac98ab9 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -20,6 +20,7 @@
 import android.annotation.UserIdInt;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageInfo;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
@@ -31,6 +32,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.pm.ShortcutService.ShortcutOperation;
@@ -68,6 +70,9 @@
     private static final String TAG_EXTRAS = "extras";
     private static final String TAG_SHORTCUT = "shortcut";
     private static final String TAG_CATEGORIES = "categories";
+    private static final String TAG_CHOOSER_EXTRAS = "chooser-extras";
+    private static final String TAG_CHOOSER_INTENT_FILTERS = "chooser-intent-filters";
+    private static final String TAG_CHOOSER_COMPONENT_NAMES = "chooser-component-names";
 
     private static final String ATTR_NAME = "name";
     private static final String ATTR_CALL_COUNT = "call-count";
@@ -91,6 +96,7 @@
     private static final String ATTR_ICON_RES_ID = "icon-res";
     private static final String ATTR_ICON_RES_NAME = "icon-resname";
     private static final String ATTR_BITMAP_PATH = "bitmap-path";
+    private static final String ATTR_COMPONENT_NAMES = "component-names";
 
     private static final String NAME_CATEGORIES = "categories";
 
@@ -200,7 +206,7 @@
         if (shortcut != null) {
             mShortcutUser.mService.removeIcon(getPackageUserId(), shortcut);
             shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
-                    | ShortcutInfo.FLAG_MANIFEST);
+                    | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CHOOSER);
         }
         return shortcut;
     }
@@ -226,7 +232,7 @@
         Preconditions.checkArgument(newShortcut.isEnabled(),
                 "add/setDynamicShortcuts() cannot publish disabled shortcuts");
 
-        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+        addCorrectDynamicFlags(newShortcut);
 
         final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
 
@@ -250,6 +256,17 @@
         addShortcutInner(newShortcut);
     }
 
+    // TODO: Sample code & JavaDoc for ShortcutManager needs updating to reflect the fact that
+    //       Chooser shortcuts are not always dynamic.
+    public void addCorrectDynamicFlags(@NonNull ShortcutInfo shortcut) {
+        if (shortcut.getIntent() != null) {
+            shortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+        }
+        if (!ArrayUtils.isEmpty(shortcut.getChooserIntentFilters())) {
+            shortcut.addFlags(ShortcutInfo.FLAG_CHOOSER);
+        }
+    }
+
     /**
      * Remove all shortcuts that aren't pinned nor dynamic.
      */
@@ -282,11 +299,11 @@
         boolean changed = false;
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
-            if (si.isDynamic()) {
+            if (si.isDynamic() || si.isChooser()) {
                 changed = true;
 
                 si.setTimestamp(now);
-                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+                si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER);
                 si.setRank(0); // It may still be pinned, so clear the rank.
             }
         }
@@ -355,7 +372,8 @@
         if (oldShortcut.isPinned()) {
 
             oldShortcut.setRank(0);
-            oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
+            oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST
+                    | ShortcutInfo.FLAG_CHOOSER);
             if (disable) {
                 oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
             }
@@ -1116,8 +1134,8 @@
                     // Don't adjust ranks for manifest shortcuts.
                     continue;
                 }
-                // At this point, it must be dynamic.
-                if (!si.isDynamic()) {
+                // At this point, it must be dynamic or a chooser.
+                if (!si.isDynamicOrChooser()) {
                     s.wtf("Non-dynamic shortcut found.");
                     continue;
                 }
@@ -1294,7 +1312,7 @@
             ShortcutService.writeAttr(out, ATTR_FLAGS,
                     si.getFlags() &
                             ~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
-                            | ShortcutInfo.FLAG_DYNAMIC));
+                            | ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER));
         } else {
             // When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
             // as dynamic.
@@ -1317,15 +1335,36 @@
         }
         final Intent[] intentsNoExtras = si.getIntentsNoExtras();
         final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
-        final int numIntents = intentsNoExtras.length;
-        for (int i = 0; i < numIntents; i++) {
-            out.startTag(null, TAG_INTENT);
-            ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
-            ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
-            out.endTag(null, TAG_INTENT);
+        if (intentsNoExtras != null) {
+            final int numIntents = intentsNoExtras.length;
+            for (int i = 0; i < numIntents; i++) {
+                out.startTag(null, TAG_INTENT);
+                ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+                ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+                out.endTag(null, TAG_INTENT);
+            }
+        }
+        ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+
+        ShortcutService.writeTagExtra(out, TAG_CHOOSER_EXTRAS, si.getChooserExtras());
+
+        final IntentFilter[] intentFilters = si.getChooserIntentFilters();
+        if (intentFilters != null) {
+            for (int i = 0; i < intentFilters.length; i++) {
+                out.startTag(null, TAG_CHOOSER_INTENT_FILTERS);
+                intentFilters[i].writeToXml(out);
+                out.endTag(null, TAG_CHOOSER_INTENT_FILTERS);
+            }
         }
 
-        ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+        final ComponentName[] componentNames = si.getChooserComponentNames();
+        if (componentNames != null) {
+            for (int i = 0; i < componentNames.length; i++) {
+                out.startTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+                ShortcutService.writeAttr(out, ATTR_COMPONENT_NAMES, componentNames[i]);
+                out.endTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+            }
+        }
 
         out.endTag(null, TAG_SHORTCUT);
     }
@@ -1398,6 +1437,9 @@
         String iconResName;
         String bitmapPath;
         ArraySet<String> categories = null;
+        PersistableBundle chooserExtras;
+        List<IntentFilter> chooserIntentFilters = new ArrayList<>();
+        List<ComponentName> chooserComponentNames = new ArrayList<>();
 
         id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
         activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -1458,6 +1500,18 @@
                         }
                     }
                     continue;
+                case TAG_CHOOSER_EXTRAS:
+                    chooserExtras = PersistableBundle.restoreFromXml(parser);
+                    continue;
+                case TAG_CHOOSER_COMPONENT_NAMES:
+                    chooserComponentNames.add(ShortcutService.parseComponentNameAttribute(parser,
+                            ATTR_ACTIVITY));
+                    continue;
+                case TAG_CHOOSER_INTENT_FILTERS:
+                    IntentFilter toAdd = new IntentFilter();
+                    toAdd.readFromXml(parser);
+                    chooserIntentFilters.add(toAdd);
+                    continue;
             }
             throw ShortcutService.throwForInvalidTag(depth, tag);
         }
@@ -1551,10 +1605,10 @@
         // Verify each shortcut's status.
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
-            if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned())) {
+            if (!(si.isDeclaredInManifest() || si.isDynamicOrChooser() || si.isPinned())) {
                 failed = true;
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
-                        + " is not manifest, dynamic or pinned.");
+                        + " is not manifest, dynamic, chooser or pinned.");
             }
             if (si.isDeclaredInManifest() && si.isDynamic()) {
                 failed = true;
@@ -1596,6 +1650,11 @@
                 Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
                         + " has a dummy target activity");
             }
+            if (si.getIntent() == null && !si.isChooser()) {
+                failed = true;
+                Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+                        + " has a null intent, but is not a chooser");
+            }
         }
 
         if (failed) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 057e781..74eb340 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -27,6 +27,7 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -64,6 +65,7 @@
 import android.os.Handler;
 import android.os.LocaleList;
 import android.os.Looper;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
 import android.os.Process;
@@ -1750,6 +1752,7 @@
             ps.clearAllImplicitRanks();
             assignImplicitRanks(newShortcuts);
 
+            // TODO: Consider removing Chooser fields. If so, the FLAG_CHOOSER should be removed
             for (int i = 0; i < size; i++) {
                 final ShortcutInfo source = newShortcuts.get(i);
                 fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
@@ -1789,6 +1792,13 @@
                 if (replacingIcon || source.hasStringResources()) {
                     fixUpShortcutResourceNamesAndValues(target);
                 }
+
+                // While updating, we keep the dynamic flag as it previously was, but refresh the
+                // chooser flag.
+                // TODO: If we support clearing Chooser fields, we should also remove the flag.
+                if (target.getChooserIntentFilters() != null) {
+                    target.addFlags(ShortcutInfo.FLAG_CHOOSER);
+                }
             }
 
             // Lastly, adjust the ranks.
@@ -1852,6 +1862,7 @@
         return true;
     }
 
+    // TODO: Ensure non-launchable shortcuts can not be pinned
     @Override
     public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
             IntentSender resultIntent, int userId) {
@@ -2007,7 +2018,7 @@
 
             return getShortcutsWithQueryLocked(
                     packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
-                    ShortcutInfo::isDynamic);
+                    ShortcutInfo::isDynamicOrChooser);
         }
     }
 
@@ -2200,6 +2211,14 @@
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
+            // For the chooser, we just check is the system is calling.
+            // STOPSHIP: We need to implement a new permission here rather than this terrible check.
+            //           The packageName check is to try to distinguish between when an actual
+            //           launcher is making the call, and when it's the system.
+            if (isCallerSystem() && packageName.equals("android")) {
+                return true;
+            }
+
             final ShortcutUser user = getUserShortcutsLocked(userId);
 
             // Always trust the cached component.
@@ -2372,7 +2391,7 @@
         public List<ShortcutInfo> getShortcuts(int launcherUserId,
                 @NonNull String callingPackage, long changedSince,
                 @Nullable String packageName, @Nullable List<String> shortcutIds,
-                @Nullable ComponentName componentName,
+                @Nullable ComponentName componentName, @Nullable Intent intent,
                 int queryFlags, int userId) {
             final ArrayList<ShortcutInfo> ret = new ArrayList<>();
 
@@ -2394,13 +2413,13 @@
                 if (packageName != null) {
                     getShortcutsInnerLocked(launcherUserId,
                             callingPackage, packageName, shortcutIds, changedSince,
-                            componentName, queryFlags, userId, ret, cloneFlag);
+                            componentName, intent, queryFlags, userId, ret, cloneFlag);
                 } else {
                     final List<String> shortcutIdsF = shortcutIds;
                     getUserShortcutsLocked(userId).forAllPackages(p -> {
                         getShortcutsInnerLocked(launcherUserId,
                                 callingPackage, p.getPackageName(), shortcutIdsF, changedSince,
-                                componentName, queryFlags, userId, ret, cloneFlag);
+                                componentName, intent, queryFlags, userId, ret, cloneFlag);
                     });
                 }
             }
@@ -2409,7 +2428,7 @@
 
         private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
                 @Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
-                @Nullable ComponentName componentName, int queryFlags,
+                @Nullable ComponentName componentName, Intent intent, int queryFlags,
                 int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
             final ArraySet<String> ids = shortcutIds == null ? null
                     : new ArraySet<>(shortcutIds);
@@ -2434,6 +2453,15 @@
                                 return false;
                             }
                         }
+                        if (intent != null
+                                && !si.hasMatchingFilter(mContext.getContentResolver(), intent)) {
+                            return false;
+                        }
+
+                        if (((queryFlags & ShortcutQuery.FLAG_MATCH_CHOOSER) != 0)
+                                && si.isChooser()) {
+                            return true;
+                        }
                         if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
                                 && si.isDynamic()) {
                             return true;
diff --git a/services/core/jni/com_android_server_vr_VrManagerService.cpp b/services/core/jni/com_android_server_vr_VrManagerService.cpp
index e06e051..9052697 100644
--- a/services/core/jni/com_android_server_vr_VrManagerService.cpp
+++ b/services/core/jni/com_android_server_vr_VrManagerService.cpp
@@ -38,7 +38,7 @@
         return;
     }
 
-    gVr = IVr::getService("vr");
+    gVr = IVr::getService();
     if (gVr == nullptr) {
         ALOGW("%s: Could not open IVr interface", __FUNCTION__);
         return;
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 100338e..1b59d72 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -34,6 +34,7 @@
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -1324,20 +1325,23 @@
     protected ShortcutInfo makeShortcut(String id) {
         return makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
     }
 
     @Deprecated // Title was renamed to short label.
     protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
         return makeShortcut(
                 id, title, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
     }
 
     protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
         return makeShortcut(
                 id, shortLabel, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
     }
 
     /**
@@ -1346,7 +1350,8 @@
     protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
         final ShortcutInfo s = makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
         s.setTimestamp(timestamp);
         return s;
     }
@@ -1358,7 +1363,8 @@
             ComponentName activity) {
         final ShortcutInfo s = makeShortcut(
                 id, "Title-" + id, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
         s.setTimestamp(timestamp);
         return s;
     }
@@ -1369,7 +1375,27 @@
     protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
         return makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, icon,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+    }
+
+    protected ShortcutInfo makeChooserShortcut(String id, int i, boolean includeIntent) {
+        List<IntentFilter> filters = new ArrayList<>();
+        List<ComponentName> componentNames = new ArrayList<>();
+        for(int j = 0; j < i; j++) {
+            final IntentFilter filter = new IntentFilter();
+            filter.addAction("view");
+            filters.add(filter);
+
+            componentNames.add(new ComponentName("xxxx", "yy" + i));
+        }
+        Intent intent = null;
+        if (includeIntent) {
+            intent = makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class);
+        }
+        return makeShortcut(
+                id, "Title-" + id, /* activity =*/ null, /* icon */ null,
+                intent, /* rank =*/ 0, filters, componentNames);
     }
 
     protected ShortcutInfo makePackageShortcut(String packageName, String id) {
@@ -1378,7 +1404,8 @@
         setCaller(packageName);
         ShortcutInfo s = makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
         setCaller(origCaller); // restore the caller
 
         return s;
@@ -1402,39 +1429,52 @@
     protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
         return makeShortcut(
                 id, "Title-" + id, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
     }
 
     protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
         return makeShortcut(
                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
-                intent, /* rank =*/ 0);
+                intent, /* rank =*/ 0, /* chooserFilters =*/ null,
+                /* chooserComponentNames =*/ null);
+
     }
 
     protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
             String title) {
         return makeShortcut(
                 id, title, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+                /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
     }
 
     protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
             int rank) {
         return makeShortcut(
                 id, "Title-" + id, activity, /* icon =*/ null,
-                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
+                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank,
+                /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
     }
 
     /**
      * Make a shortcut with details.
      */
     protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
-            Icon icon, Intent intent, int rank) {
+            Icon icon, Intent intent, int rank, @Nullable List<IntentFilter> chooserFilters,
+            @Nullable List<ComponentName> chooserComponentNames) {
         final ShortcutInfo.Builder  b = new ShortcutInfo.Builder(mClientContext, id)
                 .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
                 .setShortLabel(title)
-                .setRank(rank)
-                .setIntent(intent);
+                .setRank(rank);
+        if (intent != null) {
+            b.setIntent(intent);
+        }
+        if (chooserFilters != null) {
+            for (int i = 0; i < chooserFilters.size(); i++) {
+                b.addChooserIntentFilter(chooserFilters.get(i), chooserComponentNames.get(i));
+            }
+        }
         if (icon != null) {
             b.setIcon(icon);
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index e4d92ba..94ff07f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.pm;
 
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllChooser;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDisabled;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
@@ -256,7 +257,9 @@
                 icon1,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
-                /* weight */ 10);
+                /* weight */ 10,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
 
         final ShortcutInfo si2 = makeShortcut(
                 "shortcut2",
@@ -264,14 +267,18 @@
                 /* activity */ null,
                 icon2,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                /* weight */ 12);
+                /* weight */ 12,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
         final ShortcutInfo si3 = makeShortcut(
                 "shortcut3",
                 "Title 3",
                 /* activity */ null,
                 icon3,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                /* weight */ 13);
+                /* weight */ 13,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
 
         assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
         assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -982,8 +989,10 @@
                     makeShortcut("s2"),
                     makeShortcut("s3"),
                     makeShortcut("s4"),
-                    makeShortcut("s5")
-            )));
+                    makeShortcut("s5"),
+                    makeChooserShortcut("s6", 2, true),
+                    makeChooserShortcut("s7", 2, true),
+                    makeChooserShortcut("s8", 1, true))));
         });
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
@@ -991,11 +1000,13 @@
                     makeShortcut("s2"),
                     makeShortcut("s3"),
                     makeShortcut("s4"),
-                    makeShortcut("s5")
-            )));
+                    makeShortcut("s5"),
+                    makeChooserShortcut("s6", 2, true),
+                    makeChooserShortcut("s7", 2, true),
+                    makeChooserShortcut("s8", 1, true))));
         });
         runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
-            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3", "s6"),
                     getCallingUser());
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
                     getCallingUser());
@@ -1008,19 +1019,20 @@
             mManager.removeDynamicShortcuts(list("s1"));
             mManager.removeDynamicShortcuts(list("s3"));
             mManager.removeDynamicShortcuts(list("s5"));
+            mManager.removeDynamicShortcuts(list("s7"));
         });
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s3", "s4", "s5");
+                    "s3", "s4", "s5", "s6", "s7", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
-                    "s2", "s3");
+                    "s2", "s3", "s6");
         });
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s2", "s4");
+                    "s2", "s4", "s6", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
                     "s4", "s5");
@@ -1057,10 +1069,10 @@
         runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s3", "s4", "s5");
+                    "s3", "s4", "s5", "s6", "s7", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
-                    "s2", "s3");
+                    "s2", "s3", "s6");
 
             ShortcutInfo s = getCallerShortcut("s2");
             assertTrue(s.hasIconResource());
@@ -1076,7 +1088,7 @@
         runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
             assertShortcutIds(assertAllDynamic(
                     mManager.getDynamicShortcuts()),
-                    "s2", "s4");
+                    "s2", "s4", "s6", "s8");
             assertShortcutIds(assertAllPinned(
                     mManager.getPinnedShortcuts()),
                     "s4", "s5");
@@ -1173,7 +1185,46 @@
         });
     }
 
-    // === Test for launcher side APIs ===
+    public void testUpdateShortcuts_chooser() {
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertTrue(mManager.setDynamicShortcuts(list(
+                    makeShortcut("s1"),
+                    makeChooserShortcut("s2", 2, false),
+                    makeChooserShortcut("s3", 2, false)
+            )));
+
+            assertFalse(getCallerShortcut("s1").isChooser());
+            assertTrue(getCallerShortcut("s2").isChooser());
+            assertTrue(getCallerShortcut("s3").isChooser());
+
+            ShortcutInfo s = getCallerShortcut("s1");
+            assertNull(s.getChooserIntentFilters());
+            assertNull(s.getChooserComponentNames());
+
+            assertTrue(getCallerShortcut("s1").isDynamic());
+            assertFalse(getCallerShortcut("s2").isDynamic());
+            assertFalse(getCallerShortcut("s3").isDynamic());
+
+
+            // Replace 2 with a chooser shortcut
+            mManager.updateShortcuts(list(makeChooserShortcut("s1", 2, true)));
+
+            s = getCallerShortcut("s1");
+            assertEquals(2, s.getChooserIntentFilters().length);
+            assertEquals(2, s.getChooserComponentNames().length);
+
+            assertShortcutIds(assertAllChooser(
+                    mManager.getDynamicShortcuts()),
+                    "s1", "s2", "s3");
+
+            assertTrue(getCallerShortcut("s1").isDynamic());
+            assertFalse(getCallerShortcut("s2").isDynamic());
+            assertFalse(getCallerShortcut("s3").isDynamic());
+        });
+    }
+
+
+            // === Test for launcher side APIs ===
 
     public void testGetShortcuts() {
 
@@ -1484,15 +1535,17 @@
                 /* icon =*/ null,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
-                /* weight */ 10);
+                        /* weight */ 10, /* chooserFilter=*/ null,
+                        /* chooserComponentNames=*/ null);
 
         final ShortcutInfo s1_2 = makeShortcut(
-                "s2",
-                "Title 2",
+                "s2", "Title 2",
                 /* activity */ null,
                 /* icon =*/ null,
                 makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                /* weight */ 12);
+                /* weight */ 12,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
 
         assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
         dumpsysOnLogcat();
@@ -1505,7 +1558,9 @@
                 /* icon =*/ null,
                 makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
                         "key1", "val1", "nest", makeBundle("key", 123)),
-                /* weight */ 10);
+                /* weight */ 10,
+                /* chooserFilter=*/ null,
+                /* chooserComponentNames=*/ null);
         assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
         dumpsysOnLogcat();
 
@@ -2674,10 +2729,12 @@
             final ShortcutInfo s1_2 = makeShortcut(
                     "s2",
                     "Title 2",
-            /* activity */ null,
-            /* icon =*/ null,
+                    /* activity */ null,
+                    /* icon =*/ null,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-            /* rank */ 12);
+                    /* rank */ 12,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
 
             final ShortcutInfo s1_3 = makeShortcut("s3");
 
@@ -2692,7 +2749,9 @@
                     /* icon =*/ null,
                     makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
                             "key1", "val1", "nest", makeBundle("key", 123)),
-                    /* weight */ 10);
+                    /* weight */ 10,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
             assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
         });
 
@@ -3110,7 +3169,9 @@
                     icon1,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                             "key1", "val1", "nest", makeBundle("key", 123)),
-                        /* weight */ 10);
+                        /* weight */ 10,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
 
             final ShortcutInfo si2 = makeShortcut(
                     "s2",
@@ -3118,7 +3179,9 @@
                         /* activity */ null,
                     icon2,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                        /* weight */ 12);
+                        /* weight */ 12,
+                    /* chooserFilter=*/ null,
+                    /* chooserComponentNames=*/ null);
 
             assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
@@ -3136,8 +3199,8 @@
                     makeComponent(ShortcutActivity.class),
                     icon1,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
-                            "key1", "val1", "nest", makeBundle("key", 123)),
-                        /* weight */ 10);
+                            "key1", "val1", "nest", makeBundle("key", 123)), /* weight */ 10,
+                            /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
 
             final ShortcutInfo si2 = makeShortcut(
                     "s2",
@@ -3145,7 +3208,8 @@
                         /* activity */ null,
                     icon2,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                        /* weight */ 12);
+                        /* weight */ 12, /* chooserFilter=*/ null,
+                        /* chooserComponentNames=*/ null);
 
             assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
@@ -3167,7 +3231,8 @@
                     icon1,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
                             "key1", "val1", "nest", makeBundle("key", 123)),
-                        /* weight */ 10);
+                            /* weight */ 10, /* chooserFilter=*/ null,
+                            /* chooserComponentNames=*/ null);
 
             final ShortcutInfo si2 = makeShortcut(
                     "s2",
@@ -3175,7 +3240,8 @@
                         /* activity */ null,
                     icon2,
                     makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
-                        /* weight */ 12);
+                            /* weight */ 12, /* chooserFilter=*/ null,
+                            /* chooserComponentNames=*/ null);
 
             assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
 
@@ -6800,10 +6866,12 @@
             mManager.setDynamicShortcuts(list(
                     makeShortcut("ms1", "title1",
                             new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
-                    /* icon */ null, new Intent("action1"), /* rank */ 0),
+                            /* icon */ null, new Intent("action1"), /* rank */ 0,
+                            /* chooserFilter=*/ null, /* chooserComponentNames=*/ null),
                     makeShortcut("ms2", "title2",
                             new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
-                    /* icon */ null, new Intent("action1"), /* rank */ 0)));
+                            /* icon */ null, new Intent("action1"), /* rank */ 0, /* chooserFilter=*/ null,
+                            /* chooserComponentNames=*/ null)));
         });
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 28ec4fd..c54fa02 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -34,6 +34,7 @@
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
 import android.graphics.BitmapFactory;
@@ -93,11 +94,6 @@
 
         assertExpectException(
                 RuntimeException.class,
-                "intents cannot contain null",
-                () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
-
-        assertExpectException(
-                RuntimeException.class,
                 "action must be set",
                 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
 
@@ -142,6 +138,19 @@
                 "disabledMessage cannot be empty",
                 () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
 
+
+        assertExpectException(
+                RuntimeException.class,
+                "component name cannot be null",
+                () -> new ShortcutInfo.Builder(getTestContext(), "id")
+                        .addChooserIntentFilter(new IntentFilter(Intent.ACTION_SEND), null));
+
+        assertExpectException(
+                RuntimeException.class,
+                "intent filter cannot be null",
+                () -> new ShortcutInfo.Builder(getTestContext(), "id")
+                        .addChooserIntentFilter(null, new ComponentName("xxx", "s")));
+
         assertExpectException(NullPointerException.class, "action must be set",
                 () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
 
@@ -240,6 +249,10 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
 
         si = new ShortcutInfo.Builder(getTestContext())
                 .setId("id")
@@ -252,6 +265,8 @@
                 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         si.addFlags(ShortcutInfo.FLAG_PINNED);
         si.setBitmapPath("abc");
@@ -282,6 +297,12 @@
         assertEquals(null, si.getTextResName());
         assertEquals(0, si.getDisabledMessageResourceId());
         assertEquals(null, si.getDisabledMessageResName());
+
+        assertEquals(1, si.getChooserIntentFilters().length);
+        assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+        assertEquals(1, si.getChooserComponentNames().length);
+        assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+        assertEquals(1, si.getChooserExtras().getInt("l"));
     }
 
     public void testShortcutInfoParcel_resId() {
@@ -290,6 +311,10 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
 
         si = new ShortcutInfo.Builder(getTestContext())
                 .setId("id")
@@ -302,6 +327,8 @@
                 .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         si.addFlags(ShortcutInfo.FLAG_PINNED);
         si.setBitmapPath("abc");
@@ -338,6 +365,11 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
+
         ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
                 .setId("id")
                 .setActivity(new ComponentName("a", "b"))
@@ -349,6 +381,8 @@
                 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         sorig.addFlags(ShortcutInfo.FLAG_PINNED);
         sorig.setBitmapPath("abc");
@@ -378,6 +412,12 @@
         assertEquals(456, si.getIconResourceId());
         assertEquals("string/r456", si.getIconResName());
 
+        assertEquals(1, si.getChooserIntentFilters().length);
+        assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+        assertEquals(1, si.getChooserComponentNames().length);
+        assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+        assertEquals(1, si.getChooserExtras().getInt("l"));
+
         si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
 
         assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -445,6 +485,10 @@
 
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
         ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
                 .setId("id")
                 .setActivity(new ComponentName("a", "b"))
@@ -456,6 +500,8 @@
                 .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
                 .setRank(123)
                 .setExtras(pb)
+                .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+                .setChooserExtras(pb2)
                 .build();
         sorig.addFlags(ShortcutInfo.FLAG_PINNED);
         sorig.setBitmapPath("abc");
@@ -488,6 +534,12 @@
         assertEquals(456, si.getIconResourceId());
         assertEquals("string/r456", si.getIconResName());
 
+        assertEquals(1, si.getChooserIntentFilters().length);
+        assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+        assertEquals(1, si.getChooserComponentNames().length);
+        assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+        assertEquals(1, si.getChooserExtras().getInt("l"));
+
         si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
 
         assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -603,6 +655,10 @@
     public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
         PersistableBundle pb = new PersistableBundle();
         pb.putInt("k", 1);
+        IntentFilter chooserFilter = new IntentFilter();
+        chooserFilter.addAction(Intent.ACTION_VIEW);
+        PersistableBundle pb2 = new PersistableBundle();
+        pb2.putInt("l", 1);
         ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
                 .setId("id")
                 .setActivity(new ComponentName("a", "b"))
@@ -714,12 +770,12 @@
         assertEquals(999, si.getRank());
 
 
-        PersistableBundle pb2 = new PersistableBundle();
-        pb2.putInt("x", 99);
+        PersistableBundle pb3 = new PersistableBundle();
+        pb3.putInt("x", 99);
 
         si = sorig.clone(/* flags=*/ 0);
         si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
-                .setExtras(pb2).build());
+                .setExtras(pb3).build());
         assertEquals("text", si.getText());
         assertEquals(99, si.getExtras().getInt("x"));
     }
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index ea45bd1..fd335c3 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -508,6 +508,13 @@
         return actualShortcuts;
     }
 
+    public static List<ShortcutInfo> assertAllChooser(List<ShortcutInfo> actualShortcuts) {
+        for (ShortcutInfo s : actualShortcuts) {
+            assertTrue("ID " + s.getId(), s.isChooser());
+        }
+        return actualShortcuts;
+    }
+
     public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
         for (ShortcutInfo s : actualShortcuts) {
             assertTrue("ID " + s.getId(), s.isPinned());
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index dc8dfba..bcaac6e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -270,7 +270,7 @@
      * Used in OMA-DM applications.
      */
     public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION
-            = "android.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
+            = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
 
     /**
      * Broadcast Action: A "secret code" has been entered in the dialer. Secret codes are
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index adf189b..57b98e9 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -31,8 +31,7 @@
  * {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This
  * class provides functionality common to both publish and subscribe discovery sessions:
  * <ul>
- *     <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or
- *     {@link #sendMessage(PeerHandle, int, byte[], int)} methods.
+ *     <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])}.
  *     <li>Creating a network-specifier when requesting a Aware connection:
  *     {@link #createNetworkSpecifier(PeerHandle, byte[])}.
  * </ul>
@@ -62,6 +61,8 @@
      * {@link #sendMessage(PeerHandle, int, byte[], int)}.
      *
      * @return Maximum retry count when sending messages.
+     *
+     * @hide
      */
     public static int getMaxSendRetryCount() {
         return MAX_SEND_RETRY_COUNT;
@@ -163,6 +164,8 @@
      *            or MAC level) retries should be attempted if there is no ACK from the receiver
      *            (note: no retransmissions are attempted in other failure cases). A value of 0
      *            indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
+     *
+     * @hide
      */
     public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
             @Nullable byte[] message, int retryCount) {
@@ -195,8 +198,6 @@
      * The peer will get a callback indicating a message was received using
      * {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
      * byte[])}.
-     * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)}
-     * with a {@code retryCount} of 0.
      *
      * @param peerHandle The peer's handle for the message. Must be a result of an
      * {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 33da182..9645b1d 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -124,10 +124,9 @@
     }
 
     /**
-     * Called when message transmission fails - when no ACK is received from the peer.
-     * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
-     * the {@link DiscoverySession#sendMessage(PeerHandle, int,
-     * byte[], int)} method) - this event is received after all retries are exhausted.
+     * Called when message transmission initiated with
+     * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} fails. E.g. when no ACK is
+     * received from the peer.
      * <p>
      * Note that either this callback or
      * {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
@@ -141,9 +140,7 @@
 
     /**
      * Called when a message is received from a discovery session peer - in response to the
-     * peer's {@link DiscoverySession#sendMessage(PeerHandle, int,
-     * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle,
-     * int, byte[], int)}.
+     * peer's {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}.
      *
      * @param peerHandle An opaque handle to the peer matching our discovery operation.
      * @param message A byte array containing the message.