Merge "Add Chromium ARC EventLogTags"
diff --git a/api/current.txt b/api/current.txt
index c3dbee0..05b2a0c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6344,6 +6344,7 @@
     method public java.util.List<java.lang.String> getDelegatedScopes(android.content.ComponentName, java.lang.String);
     method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
     method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
+    method public java.util.List<java.lang.String> getKeepUninstalledPackages(android.content.ComponentName);
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
     method public int getLockTaskFeatures(android.content.ComponentName);
     method public java.lang.String[] getLockTaskPackages(android.content.ComponentName);
@@ -6384,6 +6385,7 @@
     method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]);
     method public boolean hasGrantedPolicy(android.content.ComponentName, int);
     method public boolean installCaCert(android.content.ComponentName, byte[]);
+    method public boolean installExistingPackage(android.content.ComponentName, java.lang.String);
     method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String);
     method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean);
     method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean);
@@ -6434,6 +6436,7 @@
     method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>);
     method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
+    method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>);
     method public boolean setKeyguardDisabled(android.content.ComponentName, boolean);
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
     method public void setLockTaskFeatures(android.content.ComponentName, int);
@@ -6503,6 +6506,8 @@
     field public static final java.lang.String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall";
     field public static final java.lang.String DELEGATION_CERT_INSTALL = "delegation-cert-install";
     field public static final java.lang.String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app";
+    field public static final java.lang.String DELEGATION_INSTALL_EXISTING_PACKAGE = "delegation-install-existing-package";
+    field public static final java.lang.String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages";
     field public static final java.lang.String DELEGATION_PACKAGE_ACCESS = "delegation-package-access";
     field public static final java.lang.String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant";
     field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2
@@ -7006,11 +7011,14 @@
     field public static final java.lang.String HINT_LARGE = "large";
     field public static final java.lang.String HINT_LIST = "list";
     field public static final java.lang.String HINT_LIST_ITEM = "list_item";
+    field public static final java.lang.String HINT_MAX = "max";
     field public static final java.lang.String HINT_NO_TINT = "no_tint";
     field public static final java.lang.String HINT_PARTIAL = "partial";
     field public static final java.lang.String HINT_SELECTED = "selected";
     field public static final java.lang.String HINT_TITLE = "title";
+    field public static final java.lang.String SUBTYPE_COLOR = "color";
     field public static final java.lang.String SUBTYPE_MESSAGE = "message";
+    field public static final java.lang.String SUBTYPE_SLIDER = "slider";
     field public static final java.lang.String SUBTYPE_SOURCE = "source";
   }
 
@@ -7019,12 +7027,14 @@
     ctor public Slice.Builder(android.app.slice.Slice.Builder);
     method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice);
     method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice, java.lang.String);
-    method public android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...);
-    method public android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>);
+    method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...);
+    method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>);
     method public android.app.slice.Slice.Builder addHints(java.lang.String...);
     method public android.app.slice.Slice.Builder addHints(java.util.List<java.lang.String>);
     method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.lang.String...);
     method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.util.List<java.lang.String>);
+    method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.lang.String...);
+    method public android.app.slice.Slice.Builder addInt(int, java.lang.String, java.util.List<java.lang.String>);
     method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.util.List<java.lang.String>);
     method public android.app.slice.Slice.Builder addRemoteInput(android.app.RemoteInput, java.lang.String, java.lang.String...);
     method public android.app.slice.Slice.Builder addSubSlice(android.app.slice.Slice);
@@ -7040,10 +7050,11 @@
   public final class SliceItem implements android.os.Parcelable {
     method public int describeContents();
     method public android.app.PendingIntent getAction();
-    method public int getColor();
+    method public deprecated int getColor();
     method public java.lang.String getFormat();
     method public java.util.List<java.lang.String> getHints();
     method public android.graphics.drawable.Icon getIcon();
+    method public int getInt();
     method public android.app.RemoteInput getRemoteInput();
     method public android.app.slice.Slice getSlice();
     method public java.lang.String getSubType();
@@ -7053,8 +7064,9 @@
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.slice.SliceItem> CREATOR;
     field public static final java.lang.String FORMAT_ACTION = "action";
-    field public static final java.lang.String FORMAT_COLOR = "color";
+    field public static final deprecated java.lang.String FORMAT_COLOR = "color";
     field public static final java.lang.String FORMAT_IMAGE = "image";
+    field public static final java.lang.String FORMAT_INT = "int";
     field public static final java.lang.String FORMAT_REMOTE_INPUT = "input";
     field public static final java.lang.String FORMAT_SLICE = "slice";
     field public static final java.lang.String FORMAT_TEXT = "text";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ad21983..34cd67e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1321,9 +1321,15 @@
     public static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app";
 
     /**
+     * Delegation for installing existing packages. This scope grants access to the
+     * {@link #installExistingPackage} API.
+     */
+    public static final String DELEGATION_INSTALL_EXISTING_PACKAGE =
+            "delegation-install-existing-package";
+
+    /**
      * Delegation of management of uninstalled packages. This scope grants access to the
      * {@code #setKeepUninstalledPackages} and {@code #getKeepUninstalledPackages} APIs.
-     * @hide
      */
     public static final String DELEGATION_KEEP_UNINSTALLED_PACKAGES =
             "delegation-keep-uninstalled-packages";
@@ -6085,7 +6091,6 @@
      * @return List of package names to keep cached.
      * @see #setDelegatedScopes
      * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES
-     * @hide
      */
     public @Nullable List<String> getKeepUninstalledPackages(@Nullable ComponentName admin) {
         throwIfParentInstance("getKeepUninstalledPackages");
@@ -6113,7 +6118,6 @@
      * @throws SecurityException if {@code admin} is not a device owner.
      * @see #setDelegatedScopes
      * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES
-     * @hide
      */
     public void setKeepUninstalledPackages(@Nullable ComponentName admin,
             @NonNull List<String> packageNames) {
@@ -6591,6 +6595,37 @@
     }
 
     /**
+     * Install an existing package that has been installed in another user, or has been kept after
+     * removal via {@link #setKeepUninstalledPackages}.
+     * This function can be called by a device owner, profile owner or a delegate given
+     * the {@link #DELEGATION_INSTALL_EXISTING_PACKAGE} scope via {@link #setDelegatedScopes}.
+     * When called in a secondary user or managed profile, the user/profile must be affiliated with
+     * the device owner. See {@link #setAffiliationIds}.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName The package to be installed in the calling profile.
+     * @return {@code true} if the app is installed; {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of
+     * an affiliated user or profile.
+     * @see #setKeepUninstalledPackages
+     * @see #setDelegatedScopes
+     * @see #setAffiliationIds
+     * @see #DELEGATION_PACKAGE_ACCESS
+     */
+    public boolean installExistingPackage(@NonNull ComponentName admin, String packageName) {
+        throwIfParentInstance("installExistingPackage");
+        if (mService != null) {
+            try {
+                return mService.installExistingPackage(admin, mContext.getPackageName(),
+                        packageName);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by a device owner or profile owner to disable account management for a specific type
      * of account.
      * <p>
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index ff869d2..81da197 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -223,6 +223,7 @@
 
     void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName);
     int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent);
+    boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName);
 
     void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled);
     String[] getAccountTypesWithManagementDisabled();
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 807c47d..9b3b462 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -143,6 +143,11 @@
      * OS and should not be cached by apps.
      */
     public static final String HINT_PARTIAL     = "partial";
+    /**
+     * A hint representing that this item is the max value possible for the slice containing this.
+     * Used to indicate the maximum integer value for a {@link #SUBTYPE_SLIDER}.
+     */
+    public static final String HINT_MAX = "max";
 
     /**
      * Key to retrieve an extra added to an intent when a control is changed.
@@ -158,6 +163,14 @@
      * Subtype to tag the source (i.e. sender) of a {@link #SUBTYPE_MESSAGE}.
      */
     public static final String SUBTYPE_SOURCE = "source";
+    /**
+     * Subtype to tag an item as representing a color.
+     */
+    public static final String SUBTYPE_COLOR = "color";
+    /**
+     * Subtype to tag an item represents a slider.
+     */
+    public static final String SUBTYPE_SLIDER = "slider";
 
     private final SliceItem[] mItems;
     private final @SliceHint String[] mHints;
@@ -389,9 +402,31 @@
          * Add a color to the slice being constructed
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
+         * @deprecated will be removed once supportlib updates
          */
         public Builder addColor(int color, @Nullable String subType, @SliceHint String... hints) {
-            mItems.add(new SliceItem(color, SliceItem.FORMAT_COLOR, subType, hints));
+            mItems.add(new SliceItem(color, SliceItem.FORMAT_INT, subType, hints));
+            return this;
+        }
+
+        /**
+         * Add a color to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         * @deprecated will be removed once supportlib updates
+         */
+        public Builder addColor(int color, @Nullable String subType,
+                @SliceHint List<String> hints) {
+            return addColor(color, subType, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add a color to the slice being constructed
+         * @param subType Optional template-specific type information
+         * @see {@link SliceItem#getSubType()}
+         */
+        public Builder addInt(int value, @Nullable String subType, @SliceHint String... hints) {
+            mItems.add(new SliceItem(value, SliceItem.FORMAT_INT, subType, hints));
             return this;
         }
 
@@ -400,9 +435,9 @@
          * @param subType Optional template-specific type information
          * @see {@link SliceItem#getSubType()}
          */
-        public Builder addColor(int color, @Nullable String subType,
+        public Builder addInt(int value, @Nullable String subType,
                 @SliceHint List<String> hints) {
-            return addColor(color, subType, hints.toArray(new String[hints.size()]));
+            return addInt(value, subType, hints.toArray(new String[hints.size()]));
         }
 
         /**
diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java
index 743d6b7..5d04c3e 100644
--- a/core/java/android/app/slice/SliceItem.java
+++ b/core/java/android/app/slice/SliceItem.java
@@ -44,7 +44,7 @@
  * <li>{@link #FORMAT_TEXT}</li>
  * <li>{@link #FORMAT_IMAGE}</li>
  * <li>{@link #FORMAT_ACTION}</li>
- * <li>{@link #FORMAT_COLOR}</li>
+ * <li>{@link #FORMAT_INT}</li>
  * <li>{@link #FORMAT_TIMESTAMP}</li>
  * <li>{@link #FORMAT_REMOTE_INPUT}</li>
  *
@@ -62,7 +62,7 @@
             FORMAT_TEXT,
             FORMAT_IMAGE,
             FORMAT_ACTION,
-            FORMAT_COLOR,
+            FORMAT_INT,
             FORMAT_TIMESTAMP,
             FORMAT_REMOTE_INPUT,
     })
@@ -89,7 +89,12 @@
      */
     public static final String FORMAT_ACTION = "action";
     /**
-     * A {@link SliceItem} that contains a Color int.
+     * A {@link SliceItem} that contains an int.
+     */
+    public static final String FORMAT_INT = "int";
+    /**
+     * A {@link SliceItem} that contains an int.
+     * @deprecated to be removed
      */
     public static final String FORMAT_COLOR = "color";
     /**
@@ -159,7 +164,7 @@
      * <li>{@link #FORMAT_TEXT}</li>
      * <li>{@link #FORMAT_IMAGE}</li>
      * <li>{@link #FORMAT_ACTION}</li>
-     * <li>{@link #FORMAT_COLOR}</li>
+     * <li>{@link #FORMAT_INT}</li>
      * <li>{@link #FORMAT_TIMESTAMP}</li>
      * <li>{@link #FORMAT_REMOTE_INPUT}</li>
      * @see #getSubType() ()
@@ -216,7 +221,14 @@
     }
 
     /**
-     * @return The color held by this {@link #FORMAT_COLOR} SliceItem
+     * @return The color held by this {@link #FORMAT_INT} SliceItem
+     */
+    public int getInt() {
+        return (Integer) mObj;
+    }
+
+    /**
+     * @deprecated to be removed.
      */
     public int getColor() {
         return (Integer) mObj;
@@ -318,7 +330,7 @@
             case FORMAT_TEXT:
                 TextUtils.writeToParcel((CharSequence) obj, dest, flags);
                 break;
-            case FORMAT_COLOR:
+            case FORMAT_INT:
                 dest.writeInt((Integer) obj);
                 break;
             case FORMAT_TIMESTAMP:
@@ -339,7 +351,7 @@
                 return new Pair<>(
                         PendingIntent.CREATOR.createFromParcel(in),
                         Slice.CREATOR.createFromParcel(in));
-            case FORMAT_COLOR:
+            case FORMAT_INT:
                 return in.readInt();
             case FORMAT_TIMESTAMP:
                 return in.readLong();
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index 0c893b0..5a91e94 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -16,10 +16,14 @@
 
 package android.content.pm;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Overall information about the contents of a package.  This corresponds
  * to all of the information collected from AndroidManifest.xml.
@@ -330,8 +334,29 @@
     /** @hide */
     public int overlayPriority;
 
-    /** @hide */
-    public boolean isStaticOverlay;
+    /**
+     * Flag for use with {@link #mOverlayFlags}. Marks the overlay as static, meaning it cannot
+     * be enabled/disabled at runtime.
+     */
+    static final int FLAG_OVERLAY_STATIC = 1 << 1;
+
+    /**
+     * Flag for use with {@link #mOverlayFlags}. Marks the overlay as trusted (not 3rd party).
+     */
+    static final int FLAG_OVERLAY_TRUSTED = 1 << 2;
+
+    @IntDef(flag = true, prefix = "FLAG_OVERLAY_", value = {
+            FLAG_OVERLAY_STATIC,
+            FLAG_OVERLAY_TRUSTED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface OverlayFlags {}
+
+    /**
+     * Modifiers that affect the state of this overlay. See {@link #FLAG_OVERLAY_STATIC},
+     * {@link #FLAG_OVERLAY_TRUSTED}.
+     */
+    @OverlayFlags int mOverlayFlags;
 
     /**
      * The user-visible SDK version (ex. 26) of the framework against which the application claims
@@ -359,6 +384,23 @@
     public PackageInfo() {
     }
 
+    /**
+     * Returns true if the package is a valid Runtime Overlay package.
+     * @hide
+     */
+    public boolean isOverlayPackage() {
+        return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_TRUSTED) != 0;
+    }
+
+    /**
+     * Returns true if the package is a valid static Runtime Overlay package. Static overlays
+     * are not updatable outside of a system update and are safe to load in the system process.
+     * @hide
+     */
+    public boolean isStaticOverlayPackage() {
+        return overlayTarget != null && (mOverlayFlags & FLAG_OVERLAY_STATIC) != 0;
+    }
+
     @Override
     public String toString() {
         return "PackageInfo{"
@@ -410,8 +452,8 @@
         dest.writeString(restrictedAccountType);
         dest.writeString(requiredAccountType);
         dest.writeString(overlayTarget);
-        dest.writeInt(isStaticOverlay ? 1 : 0);
         dest.writeInt(overlayPriority);
+        dest.writeInt(mOverlayFlags);
         dest.writeInt(compileSdkVersion);
         dest.writeString(compileSdkVersionCodename);
     }
@@ -465,8 +507,8 @@
         restrictedAccountType = source.readString();
         requiredAccountType = source.readString();
         overlayTarget = source.readString();
-        isStaticOverlay = source.readInt() != 0;
         overlayPriority = source.readInt();
+        mOverlayFlags = source.readInt();
         compileSdkVersion = source.readInt();
         compileSdkVersionCodename = source.readString();
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 153c944..fb1b885 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -689,7 +689,15 @@
         pi.requiredAccountType = p.mRequiredAccountType;
         pi.overlayTarget = p.mOverlayTarget;
         pi.overlayPriority = p.mOverlayPriority;
-        pi.isStaticOverlay = p.mIsStaticOverlay;
+
+        if (p.mIsStaticOverlay) {
+            pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_STATIC;
+        }
+
+        if (p.mTrustedOverlay) {
+            pi.mOverlayFlags |= PackageInfo.FLAG_OVERLAY_TRUSTED;
+        }
+
         pi.compileSdkVersion = p.mCompileSdkVersion;
         pi.compileSdkVersionCodename = p.mCompileSdkVersionCodename;
         pi.firstInstallTime = firstInstallTime;
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index b31c7bc..1d66dc6d 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -342,7 +342,17 @@
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public ContextHubTransaction<Void> loadNanoApp(
             ContextHubInfo hubInfo, NanoAppBinary appBinary) {
-        throw new UnsupportedOperationException("TODO: Implement this");
+        ContextHubTransaction<Void> transaction =
+                new ContextHubTransaction<>(ContextHubTransaction.TYPE_LOAD_NANOAPP);
+        IContextHubTransactionCallback callback = createTransactionCallback(transaction);
+
+        try {
+            mService.loadNanoAppOnHub(hubInfo.getId(), callback, appBinary);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        return transaction;
     }
 
     /**
@@ -357,7 +367,17 @@
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public ContextHubTransaction<Void> unloadNanoApp(ContextHubInfo hubInfo, long nanoAppId) {
-        throw new UnsupportedOperationException("TODO: Implement this");
+        ContextHubTransaction<Void> transaction =
+                new ContextHubTransaction<>(ContextHubTransaction.TYPE_UNLOAD_NANOAPP);
+        IContextHubTransactionCallback callback = createTransactionCallback(transaction);
+
+        try {
+            mService.unloadNanoAppFromHub(hubInfo.getId(), callback, nanoAppId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        return transaction;
     }
 
     /**
@@ -401,7 +421,17 @@
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public ContextHubTransaction<List<NanoAppState>> queryNanoApps(ContextHubInfo hubInfo) {
-        throw new UnsupportedOperationException("TODO: Implement this");
+        ContextHubTransaction<List<NanoAppState>> transaction =
+                new ContextHubTransaction<>(ContextHubTransaction.TYPE_QUERY_NANOAPPS);
+        IContextHubTransactionCallback callback = createQueryCallback(transaction);
+
+        try {
+            mService.queryNanoApps(hubInfo.getId(), callback);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        return transaction;
     }
 
     /**
diff --git a/core/java/android/hardware/location/ContextHubTransaction.java b/core/java/android/hardware/location/ContextHubTransaction.java
index a8569ef..b808de3 100644
--- a/core/java/android/hardware/location/ContextHubTransaction.java
+++ b/core/java/android/hardware/location/ContextHubTransaction.java
@@ -72,7 +72,8 @@
             TRANSACTION_FAILED_PENDING,
             TRANSACTION_FAILED_AT_HUB,
             TRANSACTION_FAILED_TIMEOUT,
-            TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE})
+            TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE,
+            TRANSACTION_FAILED_HAL_UNAVAILABLE})
     public @interface Result {}
     public static final int TRANSACTION_SUCCESS = 0;
     /**
@@ -103,6 +104,10 @@
      * Failure mode when the transaction has failed internally at the service.
      */
     public static final int TRANSACTION_FAILED_SERVICE_INTERNAL_FAILURE = 7;
+    /**
+     * Failure mode when the Context Hub HAL was not available.
+     */
+    public static final int TRANSACTION_FAILED_HAL_UNAVAILABLE = 8;
 
     /**
      * A class describing the response for a ContextHubTransaction.
@@ -189,6 +194,30 @@
     }
 
     /**
+     * Converts a transaction type to a human-readable string
+     *
+     * @param type the type of a transaction
+     * @param upperCase {@code true} if upper case the first letter, {@code false} otherwise
+     * @return a string describing the transaction
+     */
+    public static String typeToString(@Type int type, boolean upperCase) {
+        switch (type) {
+            case ContextHubTransaction.TYPE_LOAD_NANOAPP:
+                return upperCase ? "Load" : "load";
+            case ContextHubTransaction.TYPE_UNLOAD_NANOAPP:
+                return upperCase ? "Unload" : "unload";
+            case ContextHubTransaction.TYPE_ENABLE_NANOAPP:
+                return upperCase ? "Enable" : "enable";
+            case ContextHubTransaction.TYPE_DISABLE_NANOAPP:
+                return upperCase ? "Disable" : "disable";
+            case ContextHubTransaction.TYPE_QUERY_NANOAPPS:
+                return upperCase ? "Query" : "query";
+            default:
+                return upperCase ? "Unknown" : "unknown";
+        }
+    }
+
+    /**
      * @return the type of the transaction
      */
     @Type
@@ -239,7 +268,7 @@
      * A transaction can be invalidated if the process owning the transaction is no longer active
      * and the reference to this object is lost.
      *
-     * This method or {@link #setCallbackOnCompletecan(ContextHubTransaction.Callback)} can only be
+     * This method or {@link #setCallbackOnComplete(ContextHubTransaction.Callback)} can only be
      * invoked once, or an IllegalStateException will be thrown.
      *
      * @param callback the callback to be invoked upon completion
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index 1bb7c8f..628ebc7 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -20,41 +20,56 @@
 import android.hardware.location.ContextHubInfo;
 import android.hardware.location.ContextHubMessage;
 import android.hardware.location.NanoApp;
+import android.hardware.location.NanoAppBinary;
 import android.hardware.location.NanoAppFilter;
 import android.hardware.location.NanoAppInstanceInfo;
 import android.hardware.location.IContextHubCallback;
 import android.hardware.location.IContextHubClient;
 import android.hardware.location.IContextHubClientCallback;
+import android.hardware.location.IContextHubTransactionCallback;
 
 /**
  * @hide
  */
 interface IContextHubService {
 
-    // register a callback to receive messages
+    // Registers a callback to receive messages
     int registerCallback(in IContextHubCallback callback);
 
     // Gets a list of available context hub handles
     int[] getContextHubHandles();
 
-    // Get the properties of a hub
+    // Gets the properties of a hub
     ContextHubInfo getContextHubInfo(int contextHubHandle);
 
-    // Load a nanoapp on a specified context hub
+    // Loads a nanoapp at the specified hub (old API)
     int loadNanoApp(int hubHandle, in NanoApp app);
 
-    // Unload a nanoapp instance
+    // Unloads a nanoapp given its instance ID (old API)
     int unloadNanoApp(int nanoAppInstanceHandle);
 
-    // get information about a nanoAppInstance
+    // Gets the NanoAppInstanceInfo of a nanoapp give its instance ID
     NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle);
 
-    // find all nanoApp instances matching some filter
+    // Finds all nanoApp instances matching some filter
     int[] findNanoAppOnHub(int hubHandle, in NanoAppFilter filter);
 
-    // send a message to a nanoApp
+    // Sends a message to a nanoApp
     int sendMessage(int hubHandle, int nanoAppHandle, in ContextHubMessage msg);
 
     // Creates a client to send and receive messages
     IContextHubClient createClient(in IContextHubClientCallback client, int contextHubId);
+
+    // Loads a nanoapp at the specified hub (new API)
+    void loadNanoAppOnHub(
+            int contextHubId, in IContextHubTransactionCallback transactionCallback,
+            in NanoAppBinary nanoAppBinary);
+
+    // Unloads a nanoapp on a specified context hub (new API)
+    void unloadNanoAppFromHub(
+            int contextHubId, in IContextHubTransactionCallback transactionCallback,
+            long nanoAppId);
+
+    // Queries for a list of nanoapps
+    void queryNanoApps(int contextHubId, in IContextHubTransactionCallback transactionCallback);
 }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 400b075..53ddd16 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -887,6 +887,7 @@
 
             if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE)
                     && mLineCount < mMaximumVisibleLineCount) {
+                measured = MeasuredText.buildForBidi(source, bufEnd, bufEnd, textDir, measured);
                 paint.getFontMetricsInt(fm);
                 v = out(source,
                         bufEnd, bufEnd, fm.ascent, fm.descent,
@@ -894,7 +895,7 @@
                         v,
                         spacingmult, spacingadd, null,
                         null, fm, 0,
-                        needMultiply, null, bufEnd,
+                        needMultiply, measured, bufEnd,
                         includepad, trackpad, addLastLineSpacing, null,
                         null, bufStart, ellipsize,
                         ellipsizedWidth, 0, paint, false);
@@ -912,7 +913,7 @@
     private int out(final CharSequence text, final int start, final int end, int above, int below,
             int top, int bottom, int v, final float spacingmult, final float spacingadd,
             final LineHeightSpan[] chooseHt, final int[] chooseHtv, final Paint.FontMetricsInt fm,
-            final int flags, final boolean needMultiply, @Nullable final MeasuredText measured,
+            final int flags, final boolean needMultiply, @NonNull final MeasuredText measured,
             final int bufEnd, final boolean includePad, final boolean trackPad,
             final boolean addLastLineLineSpacing, final char[] chs, final float[] widths,
             final int widthStart, final TextUtils.TruncateAt ellipsize, final float ellipsisWidth,
@@ -921,7 +922,7 @@
         final int off = j * mColumns;
         final int want = off + mColumns + TOP;
         int[] lines = mLines;
-        final int dir = (start == end) ? Layout.DIR_LEFT_TO_RIGHT : measured.getParagraphDir();
+        final int dir = measured.getParagraphDir();
 
         if (want >= lines.length) {
             final int[] grow = ArrayUtils.newUnpaddedIntArray(GrowingArrayUtils.growSize(want));
@@ -948,11 +949,7 @@
         lines[off + TAB] |= flags & TAB_MASK;
         lines[off + HYPHEN] = flags;
         lines[off + DIR] |= dir << DIR_SHIFT;
-        if (start == end) {
-            mLineDirections[j] = Layout.DIRS_ALL_LEFT_TO_RIGHT;
-        } else {
-            mLineDirections[j] = measured.getDirections(start - widthStart, end - widthStart);
-        }
+        mLineDirections[j] = measured.getDirections(start - widthStart, end - widthStart);
 
         final boolean firstLine = (j == 0);
         final boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6d4998b..129a255 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -142,10 +142,11 @@
     private static final boolean DEBUG_KEEP_SCREEN_ON = false || LOCAL_LOGV;
 
     /**
-     * Set to false if we do not want to use the multi threaded renderer. Note that by disabling
+     * Set to false if we do not want to use the multi threaded renderer even though
+     * threaded renderer (aka hardware renderering) is used. Note that by disabling
      * this, WindowCallbacks will not fire.
      */
-    private static final boolean USE_MT_RENDERER = true;
+    private static final boolean MT_RENDERER_AVAILABLE = true;
 
     /**
      * Set this system property to true to force the view hierarchy to render
@@ -302,6 +303,7 @@
     Rect mDirty;
     public boolean mIsAnimating;
 
+    private boolean mUseMTRenderer;
     private boolean mDragResizing;
     private boolean mInvalidateRootRequested;
     private int mResizeMode;
@@ -548,18 +550,14 @@
     }
 
     public void addWindowCallbacks(WindowCallbacks callback) {
-        if (USE_MT_RENDERER) {
-            synchronized (mWindowCallbacks) {
-                mWindowCallbacks.add(callback);
-            }
+        synchronized (mWindowCallbacks) {
+            mWindowCallbacks.add(callback);
         }
     }
 
     public void removeWindowCallbacks(WindowCallbacks callback) {
-        if (USE_MT_RENDERER) {
-            synchronized (mWindowCallbacks) {
-                mWindowCallbacks.remove(callback);
-            }
+        synchronized (mWindowCallbacks) {
+            mWindowCallbacks.remove(callback);
         }
     }
 
@@ -685,7 +683,17 @@
 
                 // If the application owns the surface, don't enable hardware acceleration
                 if (mSurfaceHolder == null) {
+                    // While this is supposed to enable only, it can effectively disable
+                    // the acceleration too.
                     enableHardwareAcceleration(attrs);
+                    final boolean useMTRenderer = MT_RENDERER_AVAILABLE
+                            && mAttachInfo.mThreadedRenderer != null;
+                    if (mUseMTRenderer != useMTRenderer) {
+                        // Shouldn't be resizing, as it's done only in window setup,
+                        // but end just in case.
+                        endDragResizing();
+                        mUseMTRenderer = useMTRenderer;
+                    }
                 }
 
                 boolean restore = false;
@@ -2088,7 +2096,7 @@
                         endDragResizing();
                     }
                 }
-                if (!USE_MT_RENDERER) {
+                if (!mUseMTRenderer) {
                     if (dragResizing) {
                         mCanvasOffsetX = mWinFrame.left;
                         mCanvasOffsetY = mWinFrame.top;
@@ -2726,8 +2734,10 @@
     @Override
     public void onPostDraw(DisplayListCanvas canvas) {
         drawAccessibilityFocusedDrawableIfNeeded(canvas);
-        for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
-            mWindowCallbacks.get(i).onPostDraw(canvas);
+        if (mUseMTRenderer) {
+            for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
+                mWindowCallbacks.get(i).onPostDraw(canvas);
+            }
         }
     }
 
@@ -3058,7 +3068,8 @@
                     return;
                 }
 
-                if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
+                if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset,
+                        scalingRequired, dirty, surfaceInsets)) {
                     return;
                 }
             }
@@ -3074,11 +3085,22 @@
      * @return true if drawing was successful, false if an error occurred
      */
     private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
-            boolean scalingRequired, Rect dirty) {
+            boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
 
         // Draw with software renderer.
         final Canvas canvas;
+
+        // We already have the offset of surfaceInsets in xoff, yoff and dirty region,
+        // therefore we need to add it back when moving the dirty region.
+        int dirtyXOffset = xoff;
+        int dirtyYOffset = yoff;
+        if (surfaceInsets != null) {
+            dirtyXOffset += surfaceInsets.left;
+            dirtyYOffset += surfaceInsets.top;
+        }
+
         try {
+            dirty.offset(-dirtyXOffset, -dirtyYOffset);
             final int left = dirty.left;
             final int top = dirty.top;
             final int right = dirty.right;
@@ -3105,6 +3127,8 @@
             // kill stuff (or ourself) for no reason.
             mLayoutRequested = true;    // ask wm for a new surface next time.
             return false;
+        } finally {
+            dirty.offset(dirtyXOffset, dirtyYOffset);  // Reset to the original value.
         }
 
         try {
@@ -6578,7 +6602,7 @@
 
         // Tell all listeners that we are resizing the window so that the chrome can get
         // updated as fast as possible on a separate thread,
-        if (mDragResizing) {
+        if (mDragResizing && mUseMTRenderer) {
             boolean fullscreen = frame.equals(backDropFrame);
             synchronized (mWindowCallbacks) {
                 for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
@@ -7828,9 +7852,11 @@
             Rect stableInsets, int resizeMode) {
         if (!mDragResizing) {
             mDragResizing = true;
-            for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
-                mWindowCallbacks.get(i).onWindowDragResizeStart(initialBounds, fullscreen,
-                        systemInsets, stableInsets, resizeMode);
+            if (mUseMTRenderer) {
+                for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
+                    mWindowCallbacks.get(i).onWindowDragResizeStart(
+                            initialBounds, fullscreen, systemInsets, stableInsets, resizeMode);
+                }
             }
             mFullRedrawNeeded = true;
         }
@@ -7842,8 +7868,10 @@
     private void endDragResizing() {
         if (mDragResizing) {
             mDragResizing = false;
-            for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
-                mWindowCallbacks.get(i).onWindowDragResizeEnd();
+            if (mUseMTRenderer) {
+                for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
+                    mWindowCallbacks.get(i).onWindowDragResizeEnd();
+                }
             }
             mFullRedrawNeeded = true;
         }
@@ -7851,19 +7879,21 @@
 
     private boolean updateContentDrawBounds() {
         boolean updated = false;
-        for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
-            updated |= mWindowCallbacks.get(i).onContentDrawn(
-                    mWindowAttributes.surfaceInsets.left,
-                    mWindowAttributes.surfaceInsets.top,
-                    mWidth, mHeight);
+        if (mUseMTRenderer) {
+            for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
+                updated |=
+                        mWindowCallbacks.get(i).onContentDrawn(mWindowAttributes.surfaceInsets.left,
+                                mWindowAttributes.surfaceInsets.top, mWidth, mHeight);
+            }
         }
         return updated | (mDragResizing && mReportNextDraw);
     }
 
     private void requestDrawWindow() {
-        if (mReportNextDraw) {
-            mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
+        if (!mUseMTRenderer) {
+            return;
         }
+        mWindowDrawCountDown = new CountDownLatch(mWindowCallbacks.size());
         for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) {
             mWindowCallbacks.get(i).onRequestDraw(mReportNextDraw);
         }
diff --git a/core/java/com/android/internal/widget/ButtonBarLayout.java b/core/java/com/android/internal/widget/ButtonBarLayout.java
index 6a0edef..82affe2 100644
--- a/core/java/com/android/internal/widget/ButtonBarLayout.java
+++ b/core/java/com/android/internal/widget/ButtonBarLayout.java
@@ -151,7 +151,7 @@
 
     private void setStacked(boolean stacked) {
         setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
-        setGravity(stacked ? Gravity.RIGHT : Gravity.BOTTOM);
+        setGravity(stacked ? Gravity.END : Gravity.BOTTOM);
 
         final View spacer = findViewById(R.id.spacer);
         if (spacer != null) {
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 460a0d7..564afeb 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -101,7 +101,8 @@
         SkIRect src = SkIRect::MakeWH(bitmap.width(), bitmap.height());
         lattice.fBounds = &src;
         NinePatchUtils::SetLatticeDivs(&lattice, *chunk, bitmap.width(), bitmap.height());
-        lattice.fFlags = nullptr;
+        lattice.fRectTypes = nullptr;
+        lattice.fColors = nullptr;
 
         SkRegion* region = nullptr;
         if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), lattice)) {
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index d3da21b..b9ff0a7 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -747,7 +747,7 @@
 
 static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray out)
 {
-    char buffer[1024];
+    char buffer[4096];
     size_t numFound = 0;
 
     if (out == NULL) {
diff --git a/libs/hwui/NinePatchUtils.h b/libs/hwui/NinePatchUtils.h
index 8f866f5..db9509f 100644
--- a/libs/hwui/NinePatchUtils.h
+++ b/libs/hwui/NinePatchUtils.h
@@ -53,10 +53,13 @@
     return xRects * yRects;
 }
 
-static inline void SetLatticeFlags(SkCanvas::Lattice* lattice, SkCanvas::Lattice::Flags* flags,
-                                   int numFlags, const Res_png_9patch& chunk) {
-    lattice->fFlags = flags;
-    sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::Flags));
+static inline void SetLatticeFlags(SkCanvas::Lattice* lattice,
+        SkCanvas::Lattice::RectType* flags, int numFlags, const Res_png_9patch& chunk,
+        SkColor* colors) {
+    lattice->fRectTypes = flags;
+    lattice->fColors = colors;
+    sk_bzero(flags, numFlags * sizeof(SkCanvas::Lattice::RectType));
+    sk_bzero(colors, numFlags * sizeof(SkColor));
 
     bool needPadRow = lattice->fYCount > 0 && 0 == lattice->fYDivs[0];
     bool needPadCol = lattice->fXCount > 0 && 0 == lattice->fXDivs[0];
@@ -65,6 +68,7 @@
     if (needPadRow) {
         // Skip flags for the degenerate first row of rects.
         flags += lattice->fXCount + 1;
+        colors += lattice->fXCount + 1;
         yCount--;
     }
 
@@ -75,20 +79,28 @@
             if (0 == x && needPadCol) {
                 // First rect of each column is degenerate, skip the flag.
                 flags++;
+                colors++;
                 continue;
             }
 
-            if (0 == chunk.getColors()[i++]) {
-                *flags = SkCanvas::Lattice::kTransparent_Flags;
+            uint32_t currentColor = chunk.getColors()[i++];
+            if (Res_png_9patch::TRANSPARENT_COLOR == currentColor) {
+                *flags = SkCanvas::Lattice::kTransparent;
+                setFlags = true;
+            } else if (Res_png_9patch::NO_COLOR != currentColor) {
+                *flags = SkCanvas::Lattice::kFixedColor;
+                *colors = currentColor;
                 setFlags = true;
             }
 
             flags++;
+            colors++;
         }
     }
 
     if (!setFlags) {
-        lattice->fFlags = nullptr;
+        lattice->fRectTypes = nullptr;
+        lattice->fColors = nullptr;
     }
 }
 
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index eb0d161..13e1ebe 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -699,7 +699,8 @@
     SkCanvas::Lattice lattice;
     NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
 
-    lattice.fFlags = nullptr;
+    lattice.fRectTypes = nullptr;
+    lattice.fColors = nullptr;
     int numFlags = 0;
     if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) {
         // We can expect the framework to give us a color for every distinct rect.
@@ -707,9 +708,10 @@
         numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
     }
 
-    SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags);
+    SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags);
+    SkAutoSTMalloc<25, SkColor> colors(numFlags);
     if (numFlags > 0) {
-        NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk);
+        NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
     }
 
     lattice.fBounds = nullptr;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 288d039..107890e 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -45,8 +45,7 @@
     if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
         sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
         LOG_ALWAYS_FATAL_IF(!glInterface.get());
-        grContext.reset(GrContext::Create(GrBackend::kOpenGL_GrBackend,
-                                          (GrBackendContext)glInterface.get()));
+        grContext = GrContext::MakeGL(std::move(glInterface));
     } else {
         grContext->resetContext();
     }
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 91b35c2..035cea3 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -218,7 +218,8 @@
     SkCanvas::Lattice lattice;
     NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
 
-    lattice.fFlags = nullptr;
+    lattice.fRectTypes = nullptr;
+    lattice.fColors = nullptr;
     int numFlags = 0;
     if (chunk.numColors > 0 && chunk.numColors == NinePatchUtils::NumDistinctRects(lattice)) {
         // We can expect the framework to give us a color for every distinct rect.
@@ -226,9 +227,10 @@
         numFlags = (lattice.fXCount + 1) * (lattice.fYCount + 1);
     }
 
-    SkAutoSTMalloc<25, SkCanvas::Lattice::Flags> flags(numFlags);
+    SkAutoSTMalloc<25, SkCanvas::Lattice::RectType> flags(numFlags);
+    SkAutoSTMalloc<25, SkColor> colors(numFlags);
     if (numFlags > 0) {
-        NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk);
+        NinePatchUtils::SetLatticeFlags(&lattice, flags.get(), numFlags, chunk, colors.get());
     }
 
     lattice.fBounds = nullptr;
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 5e89fae..907f2d2 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -53,13 +53,13 @@
     }
 }
 
-void CacheManager::reset(GrContext* context) {
-    if (context != mGrContext.get()) {
+void CacheManager::reset(sk_sp<GrContext> context) {
+    if (context != mGrContext) {
         destroy();
     }
 
     if (context) {
-        mGrContext = sk_ref_sp(context);
+        mGrContext = std::move(context);
         mGrContext->getResourceCacheLimits(&mMaxResources, nullptr);
         updateContextCacheSizes();
     }
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index d037045..7d73352 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -61,7 +61,7 @@
 
     CacheManager(const DisplayInfo& display);
 
-    void reset(GrContext* grContext);
+    void reset(sk_sp<GrContext> grContext);
     void destroy();
     void updateContextCacheSizes();
 
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 4df7caf..848c6a8 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -141,8 +141,9 @@
         GrContextOptions options;
         options.fDisableDistanceFieldPaths = true;
         mRenderThread.cacheManager().configureContext(&options);
-        mRenderThread.setGrContext(GrContext::Create(GrBackend::kOpenGL_GrBackend,
-                                                     (GrBackendContext)glInterface.get(), options));
+        sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
+        LOG_ALWAYS_FATAL_IF(!grContext.get());
+        mRenderThread.setGrContext(grContext);
     }
 }
 
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 20443ec..79dc09f 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -173,12 +173,12 @@
     return *mReadback;
 }
 
-void RenderThread::setGrContext(GrContext* context) {
+void RenderThread::setGrContext(sk_sp<GrContext> context) {
     mCacheManager->reset(context);
-    if (mGrContext.get()) {
+    if (mGrContext) {
         mGrContext->releaseResourcesAndAbandonContext();
     }
-    mGrContext.reset(context);
+    mGrContext = std::move(context);
 }
 
 int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 970537b..3aa5487 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -88,7 +88,7 @@
     const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; }
 
     GrContext* getGrContext() const { return mGrContext.get(); }
-    void setGrContext(GrContext* cxt);
+    void setGrContext(sk_sp<GrContext> cxt);
 
     CacheManager& cacheManager() { return *mCacheManager; }
     VulkanManager& vulkanManager() { return *mVkManager; }
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index a693e68..9d246ff 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -58,6 +58,7 @@
 
     mBackendContext.reset(GrVkBackendContext::Create(vkGetInstanceProcAddr, vkGetDeviceProcAddr,
                                                      &mPresentQueueIndex, canPresent));
+    LOG_ALWAYS_FATAL_IF(!mBackendContext.get());
 
     // Get all the addresses of needed vulkan functions
     VkInstance instance = mBackendContext->fInstance;
@@ -110,8 +111,9 @@
     GrContextOptions options;
     options.fDisableDistanceFieldPaths = true;
     mRenderThread.cacheManager().configureContext(&options);
-    mRenderThread.setGrContext(
-            GrContext::Create(kVulkan_GrBackend, (GrBackendContext)mBackendContext.get(), options));
+    sk_sp<GrContext> grContext(GrContext::MakeVulkan(mBackendContext, options));
+    LOG_ALWAYS_FATAL_IF(!grContext.get());
+    mRenderThread.setGrContext(grContext);
     DeviceInfo::initialize(mRenderThread.getGrContext()->caps()->maxRenderTargetSize());
 
     if (Properties::enablePartialUpdates && Properties::useBufferAge) {
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 21410ea..b4ca88c 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -24,7 +24,6 @@
 #define USE_SHARED_MEM_BUFFER
 
 #include <media/AudioTrack.h>
-#include <media/mediaplayer.h>
 #include "SoundPool.h"
 #include "SoundPoolThread.h"
 #include <media/AudioPolicyHelper.h>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index f563794..bab1e5e 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -32,6 +32,7 @@
             android:id="@+id/volume_dialog_content"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:layout_toStartOf="@id/expand"
             android:clipChildren="false"
             android:clipToPadding="false"
             android:orientation="vertical" >
@@ -44,54 +45,83 @@
                 <!-- volume rows added and removed here! :-) -->
             </LinearLayout>
 
-            <!-- special row for ringer mode -->
-            <RelativeLayout
-                android:id="@+id/ringer_mode"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:background="@drawable/rounded_bg_full"
-                android:clipChildren="false"
-                android:clipToPadding="false"
-                android:layout_margin="10dp">
 
-                <com.android.keyguard.AlphaOptimizedImageButton
-                    android:id="@+id/ringer_icon"
-                    style="@style/VolumeButtons"
-                    android:background="?android:selectableItemBackgroundBorderless"
-                    android:layout_width="@dimen/volume_button_size"
-                    android:layout_height="@dimen/volume_button_size"
-                    android:layout_alignParentStart="true"
-                    android:layout_centerVertical="true"
-                    android:soundEffectsEnabled="false" />
-
-                <TextView
-                    android:id="@+id/ringer_title"
-                    android:text="@string/stream_ring"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:ellipsize="end"
-                    android:maxLines="1"
-                    android:layout_alignParentStart="true"
-                    android:layout_centerVertical="true"
-                    android:layout_toEndOf="@+id/ringer_icon"
-                    android:layout_marginStart="64dp"
-                    android:textColor="?android:attr/colorControlNormal"
-                    android:textAppearance="?android:attr/textAppearanceSmall"
-                    android:paddingStart="@dimen/volume_row_header_padding_start" />
-
-                <TextView
-                    android:id="@+id/ringer_status"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:ellipsize="end"
-                    android:layout_alignParentEnd="true"
-                    android:layout_centerVertical="true"
-                    android:layout_marginEnd="14dp"
-                    android:maxLines="1"
-                    android:textColor="?android:attr/colorControlNormal"
-                    android:textAppearance="?android:attr/textAppearanceSmall" />
-
-            </RelativeLayout>
         </LinearLayout>
+        <LinearLayout
+            android:id="@+id/expand"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:layout_alignParentEnd="true"
+            android:layout_alignParentTop="true"
+            android:layout_marginEnd="@dimen/volume_expander_margin_end" >
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ellipsize="end"
+                android:maxLines="1"
+                android:textAppearance="@style/TextAppearance.Volume.Header" />
+            <com.android.keyguard.AlphaOptimizedImageButton
+                xmlns:android="http://schemas.android.com/apk/res/android"
+                xmlns:tools="http://schemas.android.com/tools"
+                android:id="@+id/volume_expand_button"
+                style="@style/VolumeButtons"
+                android:layout_width="@dimen/volume_button_size"
+                android:layout_height="@dimen/volume_button_size"
+                android:clickable="true"
+                android:soundEffectsEnabled="false"
+                android:src="@drawable/ic_volume_collapse_animation"
+                android:background="@drawable/ripple_drawable"
+                tools:ignore="RtlHardcoded" />
+        </LinearLayout>
+        <!-- special row for ringer mode -->
+        <RelativeLayout
+            android:id="@+id/ringer_mode"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@drawable/rounded_bg_full"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:layout_below="@id/volume_dialog_content"
+            android:layout_margin="10dp">
+
+            <com.android.keyguard.AlphaOptimizedImageButton
+                android:id="@+id/ringer_icon"
+                style="@style/VolumeButtons"
+                android:background="?android:selectableItemBackgroundBorderless"
+                android:layout_width="@dimen/volume_button_size"
+                android:layout_height="@dimen/volume_button_size"
+                android:layout_alignParentStart="true"
+                android:layout_centerVertical="true"
+                android:soundEffectsEnabled="false" />
+
+            <TextView
+                android:id="@+id/ringer_title"
+                android:text="@string/stream_ring"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ellipsize="end"
+                android:maxLines="1"
+                android:layout_alignParentStart="true"
+                android:layout_centerVertical="true"
+                android:layout_toEndOf="@+id/ringer_icon"
+                android:layout_marginStart="64dp"
+                android:textColor="?android:attr/colorControlNormal"
+                android:textAppearance="?android:attr/textAppearanceSmall"
+                android:paddingStart="@dimen/volume_row_header_padding_start" />
+
+            <TextView
+                android:id="@+id/ringer_status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ellipsize="end"
+                android:layout_alignParentEnd="true"
+                android:layout_centerVertical="true"
+                android:layout_marginEnd="14dp"
+                android:maxLines="1"
+                android:textColor="?android:attr/colorControlNormal"
+                android:textAppearance="?android:attr/textAppearanceSmall" />
+
+        </RelativeLayout>
     </RelativeLayout>
 </com.android.systemui.volume.VolumeUiLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 05fcbb0..168758f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -195,6 +195,10 @@
 
     public void transitionTo(ScrimState state, Callback callback) {
         if (state == mState) {
+            // Call the callback anyway, unless it's already enqueued
+            if (callback != null && mCallback != callback) {
+                callback.onFinished();
+            }
             return;
         } else if (DEBUG) {
             Log.d(TAG, "State changed to: " + state);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index c61b7e8..0cfad18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -656,7 +656,9 @@
                         + "mStatusBarKeyguardViewManager was null");
                 return;
             }
-            mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+            if (mKeyguardFadingAway) {
+                mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index dacd3d9..8504d8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -380,8 +380,6 @@
                 mStatusBar.fadeKeyguardWhilePulsing();
                 wakeAndUnlockDejank();
             } else {
-                mFingerprintUnlockController.startKeyguardFadingAway();
-                mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
                 boolean staying = mStatusBar.hideKeyguard();
                 if (!staying) {
                     mStatusBarWindowManager.setKeyguardFadingAway(true);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 3e70980..7959b72 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -29,11 +29,15 @@
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.TransitionDrawable;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 import android.os.Debug;
@@ -42,6 +46,8 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.provider.Settings.Global;
+import android.transition.AutoTransition;
+import android.transition.TransitionManager;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
@@ -66,6 +72,7 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.plugins.VolumeDialog;
 import com.android.systemui.plugins.VolumeDialogController;
@@ -97,7 +104,7 @@
     private CustomDialog mDialog;
     private ViewGroup mDialogView;
     private ViewGroup mDialogRowsView;
-    private ViewGroup mDialogContentView;
+    private ImageButton mExpandButton;
     private ImageButton mRingerIcon;
     private TextView mRingerStatus;
     private final List<VolumeRow> mRows = new ArrayList<>();
@@ -109,9 +116,10 @@
     private final Accessibility mAccessibility = new Accessibility();
     private final ColorStateList mActiveSliderTint;
     private final ColorStateList mInactiveSliderTint;
-    private VolumeUiLayout mHardwareLayout;
 
     private boolean mShowing;
+    private boolean mExpanded;
+    private boolean mExpandButtonAnimationRunning;
     private boolean mShowA11yStream;
 
     private int mActiveStream;
@@ -170,57 +178,57 @@
         mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast);
 
         mDialog.setContentView(R.layout.volume_dialog);
-        mDialog.setOnShowListener(new DialogInterface.OnShowListener() {
-            @Override
-            public void onShow(DialogInterface dialog) {
-                mDialogView.setTranslationY(-mDialogView.getHeight());
-                mDialogView.setAlpha(0);
-                mDialogView.animate()
-                        .alpha(1)
-                        .translationY(0)
-                        .setDuration(300)
-                        .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
-                        .withEndAction(() -> {
-                            mWindow.getDecorView().requestAccessibilityFocus();
-                        })
-                        .start();
-            }
+        mDialog.setOnShowListener(dialog -> {
+            mDialogView.setTranslationY(-mDialogView.getHeight());
+            mDialogView.setAlpha(0);
+            mDialogView.animate()
+                    .alpha(1)
+                    .translationY(0)
+                    .setDuration(300)
+                    .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator())
+                    .withEndAction(() -> {
+                        mWindow.getDecorView().requestAccessibilityFocus();
+                    })
+                    .start();
         });
         mDialogView = mDialog.findViewById(R.id.volume_dialog);
-        mDialogView.setOnHoverListener(new View.OnHoverListener() {
-            @Override
-            public boolean onHover(View v, MotionEvent event) {
-                int action = event.getActionMasked();
-                mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
-                        || (action == MotionEvent.ACTION_HOVER_MOVE);
-                rescheduleTimeoutH();
-                return true;
-            }
+        mDialogView.setOnHoverListener((v, event) -> {
+            int action = event.getActionMasked();
+            mHovering = (action == MotionEvent.ACTION_HOVER_ENTER)
+                    || (action == MotionEvent.ACTION_HOVER_MOVE);
+            rescheduleTimeoutH();
+            return true;
         });
-        mHardwareLayout = VolumeUiLayout.get(mDialogView);
-        mHardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
+        VolumeUiLayout hardwareLayout = VolumeUiLayout.get(mDialogView);
+        hardwareLayout.setOutsideTouchListener(view -> dismiss(DISMISS_REASON_TOUCH_OUTSIDE));
 
-        mDialogContentView = mDialog.findViewById(R.id.volume_dialog_content);
-        mDialogRowsView = mDialogContentView.findViewById(R.id.volume_dialog_rows);
-        mRingerIcon = mDialogContentView.findViewById(R.id.ringer_icon);
-        mRingerStatus = mDialogContentView.findViewById(R.id.ringer_status);
+        ViewGroup dialogContentView = mDialog.findViewById(R.id.volume_dialog_content);
+        mDialogRowsView = dialogContentView.findViewById(R.id.volume_dialog_rows);
+        mRingerIcon = mDialog.findViewById(R.id.ringer_icon);
+        mRingerStatus = mDialog.findViewById(R.id.ringer_status);
+
+        mExpanded = false;
+        mExpandButton = mDialogView.findViewById(R.id.volume_expand_button);
+        mExpandButton.setOnClickListener(mClickExpand);
+        mExpandButton.setVisibility(
+                AudioSystem.isSingleVolume(mContext) ? View.GONE : View.VISIBLE);
 
         if (mRows.isEmpty()) {
             addRow(AudioManager.STREAM_MUSIC,
-                    R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true);
+                    R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true);
             if (!AudioSystem.isSingleVolume(mContext)) {
                 addRow(AudioManager.STREAM_RING,
-                        R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, false);
+                        R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true, false);
                 addRow(AudioManager.STREAM_ALARM,
-                        R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, false);
+                        R.drawable.ic_volume_alarm, R.drawable.ic_volume_alarm_mute, true, false);
                 addRow(AudioManager.STREAM_VOICE_CALL,
-                        R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false);
+                        R.drawable.ic_volume_voice, R.drawable.ic_volume_voice, false, false);
                 addRow(AudioManager.STREAM_BLUETOOTH_SCO,
-                        R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false);
-                addRow(AudioManager.STREAM_SYSTEM,
-                        R.drawable.ic_volume_system, R.drawable.ic_volume_system_mute, false);
+                        R.drawable.ic_volume_bt_sco, R.drawable.ic_volume_bt_sco, false, false);
+                addRow(AudioManager.STREAM_SYSTEM, R.drawable.ic_volume_system,
+                        R.drawable.ic_volume_system_mute, false, false);
                 addRow(AudioManager.STREAM_ACCESSIBILITY, R.drawable.ic_volume_accessibility,
-                        R.drawable.ic_volume_accessibility, true);
+                        R.drawable.ic_volume_accessibility, true, false);
             }
         } else {
             addExistingRows();
@@ -249,14 +257,15 @@
         mHandler.sendEmptyMessage(H.RECHECK_ALL);
     }
 
-    private void addRow(int stream, int iconRes, int iconMuteRes, boolean important) {
-        addRow(stream, iconRes, iconMuteRes, important, false);
+    private void addRow(int stream, int iconRes, int iconMuteRes, boolean important,
+            boolean defaultStream) {
+        addRow(stream, iconRes, iconMuteRes, important, defaultStream, false);
     }
 
     private void addRow(int stream, int iconRes, int iconMuteRes, boolean important,
-            boolean dynamic) {
+            boolean defaultStream, boolean dynamic) {
         VolumeRow row = new VolumeRow();
-        initRow(row, stream, iconRes, iconMuteRes, important);
+        initRow(row, stream, iconRes, iconMuteRes, important, defaultStream);
         int rowSize;
         int viewSize;
         if (mShowA11yStream && dynamic && (rowSize = mRows.size()) > 1
@@ -274,7 +283,8 @@
         int N = mRows.size();
         for (int i = 0; i < N; i++) {
             final VolumeRow row = mRows.get(i);
-            initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important);
+            initRow(row, row.stream, row.iconRes, row.iconMuteRes, row.important,
+                    row.defaultStream);
             mDialogRowsView.addView(row.view);
             updateVolumeRowH(row);
         }
@@ -299,6 +309,7 @@
     public void dump(PrintWriter writer) {
         writer.println(VolumeDialogImpl.class.getSimpleName() + " state:");
         writer.print("  mShowing: "); writer.println(mShowing);
+        writer.print("  mExpanded: "); writer.println(mExpanded);
         writer.print("  mActiveStream: "); writer.println(mActiveStream);
         writer.print("  mDynamic: "); writer.println(mDynamic);
         writer.print("  mAutomute: "); writer.println(mAutomute);
@@ -317,11 +328,12 @@
 
     @SuppressLint("InflateParams")
     private void initRow(final VolumeRow row, final int stream, int iconRes, int iconMuteRes,
-            boolean important) {
+            boolean important, boolean defaultStream) {
         row.stream = stream;
         row.iconRes = iconRes;
         row.iconMuteRes = iconMuteRes;
         row.important = important;
+        row.defaultStream = defaultStream;
         row.view = mDialog.getLayoutInflater().inflate(R.layout.volume_dialog_row, null);
         row.view.setId(row.stream);
         row.view.setTag(row);
@@ -359,34 +371,31 @@
         row.icon = row.view.findViewById(R.id.volume_row_icon);
         row.icon.setImageResource(iconRes);
         if (row.stream != AudioSystem.STREAM_ACCESSIBILITY) {
-            row.icon.setOnClickListener(new OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState);
-                    mController.setActiveStream(row.stream);
-                    if (row.stream == AudioManager.STREAM_RING) {
-                        final boolean hasVibrator = mController.hasVibrator();
-                        if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
-                            if (hasVibrator) {
-                                mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
-                            } else {
-                                final boolean wasZero = row.ss.level == 0;
-                                mController.setStreamVolume(stream,
-                                        wasZero ? row.lastAudibleLevel : 0);
-                            }
+            row.icon.setOnClickListener(v -> {
+                Events.writeEvent(mContext, Events.EVENT_ICON_CLICK, row.stream, row.iconState);
+                mController.setActiveStream(row.stream);
+                if (row.stream == AudioManager.STREAM_RING) {
+                    final boolean hasVibrator = mController.hasVibrator();
+                    if (mState.ringerModeInternal == AudioManager.RINGER_MODE_NORMAL) {
+                        if (hasVibrator) {
+                            mController.setRingerMode(AudioManager.RINGER_MODE_VIBRATE, false);
                         } else {
-                            mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
-                            if (row.ss.level == 0) {
-                                mController.setStreamVolume(stream, 1);
-                            }
+                            final boolean wasZero = row.ss.level == 0;
+                            mController.setStreamVolume(stream,
+                                    wasZero ? row.lastAudibleLevel : 0);
                         }
                     } else {
-                        final boolean vmute = row.ss.level == row.ss.levelMin;
-                        mController.setStreamVolume(stream,
-                                vmute ? row.lastAudibleLevel : row.ss.levelMin);
+                        mController.setRingerMode(AudioManager.RINGER_MODE_NORMAL, false);
+                        if (row.ss.level == 0) {
+                            mController.setStreamVolume(stream, 1);
+                        }
                     }
-                    row.userAttempt = 0;  // reset the grace period, slider updates immediately
+                } else {
+                    final boolean vmute = row.ss.level == row.ss.levelMin;
+                    mController.setStreamVolume(stream,
+                            vmute ? row.lastAudibleLevel : row.ss.levelMin);
                 }
+                row.userAttempt = 0;  // reset the grace period, slider updates immediately
             });
         } else {
             row.icon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
@@ -450,6 +459,7 @@
     private int computeTimeoutH() {
         if (mAccessibility.mFeedbackEnabled) return 20000;
         if (mHovering) return 16000;
+        if (mExpanded) return 5000;
         if (mSafetyWarning != null) return 5000;
         return 3000;
     }
@@ -461,6 +471,8 @@
         mDialogView.animate().cancel();
         mShowing = false;
 
+        updateExpandedH(false /* expanding */, true /* dismissing */);
+
         mDialogView.setTranslationY(0);
         mDialogView.setAlpha(1);
         mDialogView.animate()
@@ -493,6 +505,76 @@
         }
     }
 
+    private void updateExpandedH(final boolean expanded, final boolean dismissing) {
+        if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded);
+
+        if (mExpanded == expanded) return;
+        mExpanded = expanded;
+        mExpandButtonAnimationRunning = isAttached();
+        updateExpandButtonH();
+        TransitionManager.endTransitions(mDialogView);
+        final VolumeRow activeRow = getActiveRow();
+        if (!dismissing) {
+            mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT);
+            TransitionManager.beginDelayedTransition(mDialogView, getTransition());
+        }
+        updateRowsH(activeRow);
+        rescheduleTimeoutH();
+    }
+
+    private AutoTransition getTransition() {
+        AutoTransition transition = new AutoTransition();
+        transition.setDuration(300);
+        transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+        return transition;
+    }
+
+    private void updateExpandButtonH() {
+        if (D.BUG) Log.d(TAG, "updateExpandButtonH");
+
+        mExpandButton.setClickable(!mExpandButtonAnimationRunning);
+        if (!(mExpandButtonAnimationRunning && isAttached())) {
+            final int res = mExpanded ? R.drawable.ic_volume_collapse_animation
+                    : R.drawable.ic_volume_expand_animation;
+            if (hasTouchFeature()) {
+                mExpandButton.setImageResource(res);
+            } else {
+                // if there is no touch feature, show the volume ringer instead
+                mExpandButton.setImageResource(R.drawable.ic_volume_ringer);
+                mExpandButton.setBackgroundResource(0);  // remove gray background emphasis
+            }
+            mExpandButton.setContentDescription(mContext.getString(mExpanded ?
+                    R.string.accessibility_volume_collapse : R.string.accessibility_volume_expand));
+        }
+        if (mExpandButtonAnimationRunning) {
+            final Drawable d = mExpandButton.getDrawable();
+            if (d instanceof AnimatedVectorDrawable) {
+                // workaround to reset drawable
+                final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d.getConstantState()
+                        .newDrawable();
+                mExpandButton.setImageDrawable(avd);
+                avd.start();
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        mExpandButtonAnimationRunning = false;
+                        updateExpandButtonH();
+                        rescheduleTimeoutH();
+                    }
+                }, 300);
+            }
+        }
+    }
+
+    private boolean isAttached() {
+        return mDialogView != null && mDialogView.isAttachedToWindow();
+    }
+
+    private boolean hasTouchFeature() {
+        final PackageManager pm = mContext.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN);
+    }
+
     private boolean shouldBeVisibleH(VolumeRow row, VolumeRow activeRow) {
         boolean isActive = row == activeRow;
         if (row.stream == AudioSystem.STREAM_ACCESSIBILITY) {
@@ -506,7 +588,7 @@
             return true;
         }
 
-        return row.important || isActive;
+        return row.defaultStream || isActive || (mExpanded && row.important);
     }
 
     private void updateRowsH(final VolumeRow activeRow) {
@@ -545,7 +627,7 @@
                     break;
                 case AudioManager.RINGER_MODE_NORMAL:
                 default:
-                    boolean muted = (mAutomute && ss.level == 0) || ss.muted ? true : false;
+                    boolean muted = (mAutomute && ss.level == 0) || ss.muted;
                     if (muted) {
                         mRingerStatus.setText(R.string.volume_ringer_status_silent);
                         mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
@@ -596,7 +678,7 @@
             mDynamic.put(stream, true);
             if (findRow(stream) == null) {
                 addRow(stream, R.drawable.ic_volume_remote, R.drawable.ic_volume_remote_mute, true,
-                        true);
+                        false, true);
             }
         }
 
@@ -843,6 +925,16 @@
         }
     }
 
+    private final OnClickListener mClickExpand = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            mExpandButton.animate().cancel();
+            final boolean newExpand = !mExpanded;
+            Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand);
+            updateExpandedH(newExpand, false /* dismissing */);
+        }
+    };
+
     private final VolumeDialogController.Callbacks mControllerCallbackH
             = new VolumeDialogController.Callbacks() {
         @Override
@@ -898,8 +990,7 @@
 
         @Override
         public void onAccessibilityModeChanged(Boolean showA11yStream) {
-            boolean show = showA11yStream == null ? false : showA11yStream;
-            mShowA11yStream = show;
+            mShowA11yStream = showA11yStream == null ? false : showA11yStream;
             VolumeRow activeRow = getActiveRow();
             if (!mShowA11yStream && AudioManager.STREAM_ACCESSIBILITY == activeRow.stream) {
                 dismissH(Events.DISMISS_STREAM_GONE);
@@ -1100,6 +1191,7 @@
         private int iconRes;
         private int iconMuteRes;
         private boolean important;
+        private boolean defaultStream;
         private ColorStateList cachedSliderTint;
         private int iconState;  // from Events
         private ObjectAnimator anim;  // slider progress animation for non-touch-related updates
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index b9f695b..37dcaa8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -229,6 +229,15 @@
         verify(mWakeLock, times(1)).release();
     }
 
+    @Test
+    public void testCallbackInvokedOnSameStateTransition() {
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        mScrimController.finishAnimationsImmediately();
+        ScrimController.Callback callback = mock(ScrimController.Callback.class);
+        mScrimController.transitionTo(ScrimState.UNLOCKED, callback);
+        verify(callback, times(1)).onFinished();
+    }
+
     private void assertScrimTint(ScrimView scrimView, boolean tinted) {
         final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT;
         final String name = scrimView == mScrimInFront ? "front" : "back";
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 7bc63f0..fcb93d2 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -42,6 +42,7 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -491,7 +492,10 @@
         } catch (NameNotFoundException e) {
             throw new SecurityException("Could not verify UID for " + componentName);
         }
-        if (callingUid != packageUid) {
+        // TODO(b/70506888): allow all system UIDs to call it is too broad, we should call
+        // something like am.isActivityRunningInProcess(componentName, callingPid), but there is
+        // no such API yet.
+        if (callingUid != packageUid && Process.isApplicationUid(callingUid)) {
             final String[] packages = pm.getPackagesForUid(callingUid);
             final String callingPackage = packages != null ? packages[0] : "uid-" + callingUid;
             Slog.w(TAG, "App (package=" + callingPackage + ", UID=" + callingUid
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index dc35051..37f1dc4 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -889,7 +889,7 @@
 
     /**
      * Start a VR InputMethod that matches IME with package name of {@param component}.
-     * Note: This method is called from {@link VrManager}.
+     * Note: This method is called from {@link android.app.VrManager}.
      */
     private void startVrInputMethodNoCheck(@Nullable ComponentName component) {
         if (component == null) {
@@ -903,7 +903,7 @@
             for (InputMethodInfo info : mMethodList) {
                 if (TextUtils.equals(info.getPackageName(), packageName) && info.isVrOnly()) {
                     // set this is as current inputMethod without updating settings.
-                    setInputMethodEnabled(info.getId(), true);
+                    setInputMethodEnabledLocked(info.getId(), true);
                     setInputMethodLocked(info.getId(), NOT_A_SUBTYPE_ID);
                     break;
                 }
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 219bc61..36cacd7a 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -1149,8 +1149,10 @@
         public void forEachJob(JobStatusFunctor functor) {
             for (int uidIndex = mJobs.size() - 1; uidIndex >= 0; uidIndex--) {
                 ArraySet<JobStatus> jobs = mJobs.valueAt(uidIndex);
-                for (int i = jobs.size() - 1; i >= 0; i--) {
-                    functor.process(jobs.valueAt(i));
+                if (jobs != null) {
+                    for (int i = jobs.size() - 1; i >= 0; i--) {
+                        functor.process(jobs.valueAt(i));
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 4525a49..cd4bb14 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -742,6 +742,82 @@
         return mClientManager.registerClient(clientCallback, contextHubId);
     }
 
+    /**
+     * Loads a nanoapp binary at the specified Context hub.
+     *
+     * @param contextHubId the ID of the hub to load the binary
+     * @param transactionCallback the client-facing transaction callback interface
+     * @param nanoAppBinary the binary to load
+     *
+     * @throws RemoteException
+     */
+    @Override
+    public void loadNanoAppOnHub(
+            int contextHubId, IContextHubTransactionCallback transactionCallback,
+            NanoAppBinary nanoAppBinary) throws RemoteException {
+        checkPermissions();
+        if (!checkHalProxyAndContextHubId(
+                contextHubId, transactionCallback, ContextHubTransaction.TYPE_LOAD_NANOAPP)) {
+            return;
+        }
+        if (nanoAppBinary == null) {
+            Log.e(TAG, "NanoAppBinary cannot be null in loadNanoAppOnHub");
+            transactionCallback.onTransactionComplete(
+                    ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS);
+            return;
+        }
+
+        ContextHubServiceTransaction transaction = mTransactionManager.createLoadTransaction(
+                contextHubId, nanoAppBinary, transactionCallback);
+        addTransaction(transaction);
+    }
+
+    /**
+     * Unloads a nanoapp from the specified Context Hub.
+     *
+     * @param contextHubId the ID of the hub to unload the nanoapp
+     * @param transactionCallback the client-facing transaction callback interface
+     * @param nanoAppId the ID of the nanoapp to unload
+     *
+     * @throws RemoteException
+     */
+    @Override
+    public void unloadNanoAppFromHub(
+            int contextHubId, IContextHubTransactionCallback transactionCallback, long nanoAppId)
+            throws RemoteException {
+        checkPermissions();
+        if (!checkHalProxyAndContextHubId(
+                contextHubId, transactionCallback, ContextHubTransaction.TYPE_UNLOAD_NANOAPP)) {
+            return;
+        }
+
+        ContextHubServiceTransaction transaction = mTransactionManager.createUnloadTransaction(
+                contextHubId, nanoAppId, transactionCallback);
+        addTransaction(transaction);
+    }
+
+    /**
+     * Queries for a list of nanoapps from the specified Context hub.
+     *
+     * @param contextHubId the ID of the hub to query
+     * @param transactionCallback the client-facing transaction callback interface
+     *
+     * @throws RemoteException
+     */
+    @Override
+    public void queryNanoApps(int contextHubId, IContextHubTransactionCallback transactionCallback)
+            throws RemoteException {
+        checkPermissions();
+        if (!checkHalProxyAndContextHubId(
+                contextHubId, transactionCallback, ContextHubTransaction.TYPE_QUERY_NANOAPPS)) {
+            return;
+        }
+
+        ContextHubServiceTransaction transaction =
+                mTransactionManager.createQueryTransaction(contextHubId, transactionCallback);
+        addTransaction(transaction);
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -797,6 +873,42 @@
         return 0;
     }
 
+    /**
+     * Validates the HAL proxy state and context hub ID to see if we can start the transaction.
+     *
+     * @param contextHubId    the ID of the hub to start the transaction
+     * @param callback        the client transaction callback interface
+     * @param transactionType the type of the transaction
+     *
+     * @return {@code true} if mContextHubProxy and contextHubId is valid, {@code false} otherwise
+     */
+    private boolean checkHalProxyAndContextHubId(
+            int contextHubId, IContextHubTransactionCallback callback,
+            @ContextHubTransaction.Type int transactionType) {
+        if (mContextHubProxy == null) {
+            try {
+                callback.onTransactionComplete(
+                        ContextHubTransaction.TRANSACTION_FAILED_HAL_UNAVAILABLE);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException while calling onTransactionComplete", e);
+            }
+            return false;
+        }
+        if (!isValidContextHubId(contextHubId)) {
+            Log.e(TAG, "Cannot start "
+                    + ContextHubTransaction.typeToString(transactionType, false /* upperCase */)
+                    + " transaction for invalid hub ID " + contextHubId);
+            try {
+                callback.onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_BAD_PARAMS);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException while calling onTransactionComplete", e);
+            }
+            return false;
+        }
+
+        return true;
+    }
+
     private int addAppInstance(int hubHandle, int appInstanceHandle, long appId, int appVersion) {
         // App Id encodes vendor & version
         NanoAppInstanceInfo appInfo = new NanoAppInstanceInfo();
diff --git a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java
index a543daf..ce92f72 100644
--- a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java
+++ b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java
@@ -126,28 +126,9 @@
         return mIsComplete;
     }
 
-    /**
-     * @return the human-readable string of this transaction's type
-     */
-    private String getTransactionTypeString() {
-        switch (mTransactionType) {
-            case ContextHubTransaction.TYPE_LOAD_NANOAPP:
-                return "Load";
-            case ContextHubTransaction.TYPE_UNLOAD_NANOAPP:
-                return "Unload";
-            case ContextHubTransaction.TYPE_ENABLE_NANOAPP:
-                return "Enable";
-            case ContextHubTransaction.TYPE_DISABLE_NANOAPP:
-                return "Disable";
-            case ContextHubTransaction.TYPE_QUERY_NANOAPPS:
-                return "Query";
-            default:
-                return "Unknown";
-        }
-    }
-
     @Override
     public String toString() {
-        return getTransactionTypeString() + " transaction (ID = " + mTransactionId + ")";
+        return ContextHubTransaction.typeToString(mTransactionType, true /* upperCase */)
+                + " transaction (ID = " + mTransactionId + ")";
     }
 }
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 2940a6e..2041de6 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -370,10 +370,10 @@
                             false);
                     if (pi != null) {
                         mPackageManager.cachePackageInfo(packageName, userId, pi);
-                        if (!isOverlayPackage(pi)) {
-                            mImpl.onTargetPackageAdded(packageName, userId);
-                        } else {
+                        if (pi.isOverlayPackage()) {
                             mImpl.onOverlayPackageAdded(packageName, userId);
+                        } else {
+                            mImpl.onTargetPackageAdded(packageName, userId);
                         }
                     }
                 }
@@ -388,10 +388,10 @@
                             false);
                     if (pi != null) {
                         mPackageManager.cachePackageInfo(packageName, userId, pi);
-                        if (!isOverlayPackage(pi)) {
-                            mImpl.onTargetPackageChanged(packageName, userId);
-                        } else {
+                        if (pi.isOverlayPackage()) {
                             mImpl.onOverlayPackageChanged(packageName, userId);
+                        } else {
+                            mImpl.onTargetPackageChanged(packageName, userId);
                         }
                     }
                 }
@@ -404,10 +404,10 @@
                 synchronized (mLock) {
                     mPackageManager.forgetPackageInfo(packageName, userId);
                     final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
-                    if (oi == null) {
-                        mImpl.onTargetPackageUpgrading(packageName, userId);
-                    } else {
+                    if (oi != null) {
                         mImpl.onOverlayPackageUpgrading(packageName, userId);
+                    } else {
+                        mImpl.onTargetPackageUpgrading(packageName, userId);
                     }
                 }
             }
@@ -421,10 +421,10 @@
                             false);
                     if (pi != null) {
                         mPackageManager.cachePackageInfo(packageName, userId, pi);
-                        if (!isOverlayPackage(pi)) {
-                            mImpl.onTargetPackageUpgraded(packageName, userId);
-                        } else {
+                        if (pi.isOverlayPackage()) {
                             mImpl.onOverlayPackageUpgraded(packageName, userId);
+                        } else {
+                            mImpl.onTargetPackageUpgraded(packageName, userId);
                         }
                     }
                 }
@@ -437,10 +437,10 @@
                 synchronized (mLock) {
                     mPackageManager.forgetPackageInfo(packageName, userId);
                     final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
-                    if (oi == null) {
-                        mImpl.onTargetPackageRemoved(packageName, userId);
-                    } else {
+                    if (oi != null) {
                         mImpl.onOverlayPackageRemoved(packageName, userId);
+                    } else {
+                        mImpl.onTargetPackageRemoved(packageName, userId);
                     }
                 }
             }
@@ -668,10 +668,6 @@
         }
     };
 
-    private boolean isOverlayPackage(@NonNull final PackageInfo pi) {
-        return pi != null && pi.overlayTarget != null;
-    }
-
     private final class OverlayChangeListener
             implements OverlayManagerServiceImpl.OverlayChangeListener {
         @Override
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index db6e974..253d4f5 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -102,11 +102,11 @@
                 mSettings.init(overlayPackage.packageName, newUserId,
                         overlayPackage.overlayTarget,
                         overlayPackage.applicationInfo.getBaseCodePath(),
-                        overlayPackage.isStaticOverlay, overlayPackage.overlayPriority);
+                        overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
 
                 if (oi == null) {
                     // This overlay does not exist in our settings.
-                    if (overlayPackage.isStaticOverlay ||
+                    if (overlayPackage.isStaticOverlayPackage() ||
                             mDefaultOverlays.contains(overlayPackage.packageName)) {
                         // Enable this overlay by default.
                         if (DEBUG) {
@@ -255,8 +255,8 @@
                 mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
 
         mSettings.init(packageName, userId, overlayPackage.overlayTarget,
-                overlayPackage.applicationInfo.getBaseCodePath(), overlayPackage.isStaticOverlay,
-                overlayPackage.overlayPriority);
+                overlayPackage.applicationInfo.getBaseCodePath(),
+                overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority);
         try {
             if (updateState(targetPackage, overlayPackage, userId)) {
                 mListener.onOverlaysChanged(overlayPackage.overlayTarget, userId);
@@ -313,7 +313,7 @@
         }
 
         // Ignore static overlays.
-        if (overlayPackage.isStaticOverlay) {
+        if (overlayPackage.isStaticOverlayPackage()) {
             return false;
         }
 
@@ -363,7 +363,7 @@
                     continue;
                 }
 
-                if (disabledOverlayPackageInfo.isStaticOverlay) {
+                if (disabledOverlayPackageInfo.isStaticOverlayPackage()) {
                     // Don't touch static overlays.
                     continue;
                 }
@@ -388,7 +388,7 @@
 
     private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
         final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
-        if (overlayPackage == null || overlayPackage.isStaticOverlay) {
+        if (overlayPackage == null || overlayPackage.isStaticOverlayPackage()) {
             return false;
         }
         return true;
@@ -483,7 +483,8 @@
             throws OverlayManagerSettings.BadKeyException {
         // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers.
         if (targetPackage != null &&
-                !("android".equals(targetPackage.packageName) && overlayPackage.isStaticOverlay)) {
+                !("android".equals(targetPackage.packageName)
+                        && overlayPackage.isStaticOverlayPackage())) {
             mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
         }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 91ba87e..b946122 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -40,6 +40,7 @@
 import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL;
 import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL;
 import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP;
+import static android.app.admin.DevicePolicyManager.DELEGATION_INSTALL_EXISTING_PACKAGE;
 import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
@@ -296,7 +297,9 @@
         DELEGATION_ENABLE_SYSTEM_APP,
         DELEGATION_KEEP_UNINSTALLED_PACKAGES,
         DELEGATION_PACKAGE_ACCESS,
-        DELEGATION_PERMISSION_GRANT
+        DELEGATION_PERMISSION_GRANT,
+        DELEGATION_INSTALL_EXISTING_PACKAGE,
+        DELEGATION_KEEP_UNINSTALLED_PACKAGES
     };
 
     /**
@@ -8843,6 +8846,39 @@
     }
 
     @Override
+    public boolean installExistingPackage(ComponentName who, String callerPackage,
+            String packageName) {
+        synchronized (this) {
+            // Ensure the caller is a PO or an install existing package delegate
+            enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
+                    DELEGATION_INSTALL_EXISTING_PACKAGE);
+            final int callingUserId = mInjector.userHandleGetCallingUserId();
+            if (!isUserAffiliatedWithDeviceLocked(callingUserId)) {
+                throw new SecurityException("Admin " + who +
+                        " is neither the device owner or affiliated user's profile owner.");
+            }
+
+            final long id = mInjector.binderClearCallingIdentity();
+            try {
+                if (VERBOSE_LOG) {
+                    Slog.v(LOG_TAG, "installing " + packageName + " for "
+                            + callingUserId);
+                }
+
+                // Install the package.
+                return mIPackageManager.installExistingPackageAsUser(packageName, callingUserId,
+                        0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY)
+                        == PackageManager.INSTALL_SUCCEEDED;
+            } catch (RemoteException re) {
+                // shouldn't happen
+                return false;
+            } finally {
+                mInjector.binderRestoreCallingIdentity(id);
+            }
+        }
+    }
+
+    @Override
     public void setAccountManagementDisabled(ComponentName who, String accountType,
             boolean disabled) {
         if (!mHasFeature) {
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index d7b6142..942ea00 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -3342,6 +3342,12 @@
         public static final String APN = "apn";
 
         /**
+         * Prefix of Integrated Circuit Card Identifier.
+         * <P>Type: TEXT </P>
+         */
+        public static final String ICCID_PREFIX = "iccid_prefix";
+
+        /**
          * User facing carrier name.
          * <P>Type: TEXT </P>
          */