Merge "Allow setImeWindowStatus with null startInputToken"
diff --git a/Android.mk b/Android.mk
index 28adbca..7a8b1b7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -295,9 +295,9 @@
 	core/java/android/printservice/IPrintService.aidl \
 	core/java/android/printservice/IPrintServiceClient.aidl \
 	core/java/android/companion/ICompanionDeviceManager.aidl \
-	core/java/android/companion/ICompanionDeviceManagerService.aidl \
-	core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl \
-	core/java/android/companion/IOnAssociateCallback.aidl \
+	core/java/android/companion/ICompanionDeviceDiscoveryService.aidl \
+	core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl \
+	core/java/android/companion/IFindDeviceCallback.aidl \
 	core/java/android/service/dreams/IDreamManager.aidl \
 	core/java/android/service/dreams/IDreamService.aidl \
 	core/java/android/service/persistentdata/IPersistentDataBlockService.aidl \
diff --git a/api/current.txt b/api/current.txt
index a03ef38..7465c4d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -121,6 +121,7 @@
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
+    field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -139,6 +140,7 @@
     field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
     field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
     field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
+    field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND";
     field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
     field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
     field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
@@ -6572,6 +6574,7 @@
     method public int getTextStyle();
     method public int getTop();
     method public android.graphics.Matrix getTransformation();
+    method public java.lang.String getUrl();
     method public int getVisibility();
     method public int getWidth();
     method public boolean isAccessibilityFocused();
@@ -9224,7 +9227,7 @@
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
     field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
     field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
-    field public static final java.lang.String EXTRA_QUICK_VIEW_PLAIN = "android.intent.extra.QUICK_VIEW_PLAIN";
+    field public static final java.lang.String EXTRA_QUICK_VIEW_ADVANCED = "android.intent.extra.QUICK_VIEW_ADVANCED";
     field public static final java.lang.String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
@@ -22320,7 +22323,7 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
-    method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
     method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
     method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22348,6 +22351,7 @@
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
     method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22412,9 +22416,8 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
-  public static abstract class MediaPlayer.OnDrmConfigCallback {
-    ctor public MediaPlayer.OnDrmConfigCallback();
-    method public void onDrmConfig(android.media.MediaPlayer);
+  public static abstract interface MediaPlayer.OnDrmConfigListener {
+    method public abstract void onDrmConfig(android.media.MediaPlayer);
   }
 
   public static abstract interface MediaPlayer.OnDrmInfoListener {
@@ -44111,6 +44114,7 @@
     field public static final int AXIS_RX = 12; // 0xc
     field public static final int AXIS_RY = 13; // 0xd
     field public static final int AXIS_RZ = 14; // 0xe
+    field public static final int AXIS_SCROLL = 26; // 0x1a
     field public static final int AXIS_SIZE = 3; // 0x3
     field public static final int AXIS_THROTTLE = 19; // 0x13
     field public static final int AXIS_TILT = 25; // 0x19
@@ -45661,6 +45665,7 @@
     method public abstract void setTextLines(int[], int[]);
     method public abstract void setTextStyle(float, int, int, int);
     method public abstract void setTransformation(android.graphics.Matrix);
+    method public abstract void setUrl(java.lang.String);
     method public abstract void setVisibility(int);
     field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
   }
@@ -47337,7 +47342,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
diff --git a/api/system-current.txt b/api/system-current.txt
index 406d51c..25b393c 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -211,6 +211,7 @@
     field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
     field public static final java.lang.String RETRIEVE_WINDOW_CONTENT = "android.permission.RETRIEVE_WINDOW_CONTENT";
     field public static final java.lang.String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
+    field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND";
     field public static final java.lang.String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
@@ -248,6 +249,7 @@
     field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
     field public static final java.lang.String UPDATE_LOCK = "android.permission.UPDATE_LOCK";
     field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY";
+    field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND";
     field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
     field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
     field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
@@ -6809,6 +6811,7 @@
     method public int getTextStyle();
     method public int getTop();
     method public android.graphics.Matrix getTransformation();
+    method public java.lang.String getUrl();
     method public int getVisibility();
     method public int getWidth();
     method public boolean isAccessibilityFocused();
@@ -9668,7 +9671,7 @@
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
     field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
     field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
-    field public static final java.lang.String EXTRA_QUICK_VIEW_PLAIN = "android.intent.extra.QUICK_VIEW_PLAIN";
+    field public static final java.lang.String EXTRA_QUICK_VIEW_ADVANCED = "android.intent.extra.QUICK_VIEW_ADVANCED";
     field public static final java.lang.String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
@@ -23963,7 +23966,7 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
-    method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
     method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
     method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -23991,6 +23994,7 @@
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
     method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -24055,9 +24059,8 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
-  public static abstract class MediaPlayer.OnDrmConfigCallback {
-    ctor public MediaPlayer.OnDrmConfigCallback();
-    method public void onDrmConfig(android.media.MediaPlayer);
+  public static abstract interface MediaPlayer.OnDrmConfigListener {
+    method public abstract void onDrmConfig(android.media.MediaPlayer);
   }
 
   public static abstract interface MediaPlayer.OnDrmInfoListener {
@@ -47549,6 +47552,7 @@
     field public static final int AXIS_RX = 12; // 0xc
     field public static final int AXIS_RY = 13; // 0xd
     field public static final int AXIS_RZ = 14; // 0xe
+    field public static final int AXIS_SCROLL = 26; // 0x1a
     field public static final int AXIS_SIZE = 3; // 0x3
     field public static final int AXIS_THROTTLE = 19; // 0x13
     field public static final int AXIS_TILT = 25; // 0x19
@@ -49099,6 +49103,7 @@
     method public abstract void setTextLines(int[], int[]);
     method public abstract void setTextStyle(float, int, int, int);
     method public abstract void setTransformation(android.graphics.Matrix);
+    method public abstract void setUrl(java.lang.String);
     method public abstract void setVisibility(int);
     field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
   }
@@ -50778,7 +50783,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
diff --git a/api/test-current.txt b/api/test-current.txt
index 1be19ed..2c2831f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -121,6 +121,7 @@
     field public static final java.lang.String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES";
     field public static final deprecated java.lang.String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES";
     field public static final java.lang.String RESTRICTED_VR_ACCESS = "android.permission.RESTRICTED_VR_ACCESS";
+    field public static final java.lang.String RUN_IN_BACKGROUND = "android.permission.RUN_IN_BACKGROUND";
     field public static final java.lang.String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE";
     field public static final java.lang.String SEND_SMS = "android.permission.SEND_SMS";
     field public static final java.lang.String SET_ALARM = "com.android.alarm.permission.SET_ALARM";
@@ -139,6 +140,7 @@
     field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
     field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
     field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
+    field public static final java.lang.String USE_DATA_IN_BACKGROUND = "android.permission.USE_DATA_IN_BACKGROUND";
     field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
     field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
     field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
@@ -6595,6 +6597,7 @@
     method public int getTextStyle();
     method public int getTop();
     method public android.graphics.Matrix getTransformation();
+    method public java.lang.String getUrl();
     method public int getVisibility();
     method public int getWidth();
     method public boolean isAccessibilityFocused();
@@ -9250,7 +9253,7 @@
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
     field public static final java.lang.String EXTRA_PROCESS_TEXT = "android.intent.extra.PROCESS_TEXT";
     field public static final java.lang.String EXTRA_PROCESS_TEXT_READONLY = "android.intent.extra.PROCESS_TEXT_READONLY";
-    field public static final java.lang.String EXTRA_QUICK_VIEW_PLAIN = "android.intent.extra.QUICK_VIEW_PLAIN";
+    field public static final java.lang.String EXTRA_QUICK_VIEW_ADVANCED = "android.intent.extra.QUICK_VIEW_ADVANCED";
     field public static final java.lang.String EXTRA_QUIET_MODE = "android.intent.extra.QUIET_MODE";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REFERRER_NAME = "android.intent.extra.REFERRER_NAME";
@@ -22413,7 +22416,7 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
-    method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public void prepareDrm(java.util.UUID) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
     method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
     method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
@@ -22441,6 +22444,7 @@
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnDrmConfigListener(android.media.MediaPlayer.OnDrmConfigListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
     method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
     method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
@@ -22505,9 +22509,8 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
-  public static abstract class MediaPlayer.OnDrmConfigCallback {
-    ctor public MediaPlayer.OnDrmConfigCallback();
-    method public void onDrmConfig(android.media.MediaPlayer);
+  public static abstract interface MediaPlayer.OnDrmConfigListener {
+    method public abstract void onDrmConfig(android.media.MediaPlayer);
   }
 
   public static abstract interface MediaPlayer.OnDrmInfoListener {
@@ -44418,6 +44421,7 @@
     field public static final int AXIS_RX = 12; // 0xc
     field public static final int AXIS_RY = 13; // 0xd
     field public static final int AXIS_RZ = 14; // 0xe
+    field public static final int AXIS_SCROLL = 26; // 0x1a
     field public static final int AXIS_SIZE = 3; // 0x3
     field public static final int AXIS_THROTTLE = 19; // 0x13
     field public static final int AXIS_TILT = 25; // 0x19
@@ -45973,6 +45977,7 @@
     method public abstract void setTextLines(int[], int[]);
     method public abstract void setTextStyle(float, int, int, int);
     method public abstract void setTransformation(android.graphics.Matrix);
+    method public abstract void setUrl(java.lang.String);
     method public abstract void setVisibility(int);
     field public static final int AUTO_FILL_FLAG_SANITIZED = 1; // 0x1
   }
@@ -47651,7 +47656,7 @@
 
   public final class TextClassificationManager {
     method public java.util.List<android.view.textclassifier.TextLanguage> detectLanguages(java.lang.CharSequence);
-    method public synchronized android.view.textclassifier.TextClassifier getDefaultTextClassifier();
+    method public android.view.textclassifier.TextClassifier getDefaultTextClassifier();
   }
 
   public final class TextClassificationResult {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index fb927e9..6dd31a8 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -357,7 +357,8 @@
     public static final String OPSTR_INSTANT_APP_START_FOREGROUND
             = "android:instant_app_start_foreground";
 
-    private static final int[] RUNTIME_PERMISSIONS_OPS = {
+    private static final int[] RUNTIME_AND_APPOP_PERMISSIONS_OPS = {
+            // RUNTIME PERMISSIONS
             // Contacts
             OP_READ_CONTACTS,
             OP_WRITE_CONTACTS,
@@ -392,7 +393,13 @@
             // Camera
             OP_CAMERA,
             // Body sensors
-            OP_BODY_SENSORS
+            OP_BODY_SENSORS,
+
+            // APPOP PERMISSIONS
+            OP_ACCESS_NOTIFICATIONS,
+            OP_SYSTEM_ALERT_WINDOW,
+            OP_WRITE_SETTINGS,
+            OP_REQUEST_INSTALL_PACKAGES,
     };
 
     /**
@@ -926,9 +933,9 @@
             AppOpsManager.MODE_ALLOWED,  // OP_RUN_IN_BACKGROUND
             AppOpsManager.MODE_ALLOWED,  // OP_AUDIO_ACCESSIBILITY_VOLUME
             AppOpsManager.MODE_ALLOWED,
-            AppOpsManager.MODE_DEFAULT, // OP_REQUEST_INSTALL_PACKAGES
+            AppOpsManager.MODE_DEFAULT,  // OP_REQUEST_INSTALL_PACKAGES
             AppOpsManager.MODE_ALLOWED,  // OP_ENTER_PICTURE_IN_PICTURE_ON_HIDE
-            AppOpsManager.MODE_DEFAULT, // OP_INSTANT_APP_START_FOREGROUND
+            AppOpsManager.MODE_DEFAULT,  // OP_INSTANT_APP_START_FOREGROUND
     };
 
     /**
@@ -1018,7 +1025,7 @@
     /**
      * Mapping from a permission to the corresponding app op.
      */
-    private static HashMap<String, Integer> sRuntimePermToOp = new HashMap<>();
+    private static HashMap<String, Integer> sPermToOp = new HashMap<>();
 
     static {
         if (sOpToSwitch.length != _NUM_OP) {
@@ -1058,9 +1065,9 @@
                 sOpStrToOp.put(sOpToString[i], i);
             }
         }
-        for (int op : RUNTIME_PERMISSIONS_OPS) {
+        for (int op : RUNTIME_AND_APPOP_PERMISSIONS_OPS) {
             if (sOpPerms[op] != null) {
-                sRuntimePermToOp.put(sOpPerms[op], op);
+                sPermToOp.put(sOpPerms[op], op);
             }
         }
     }
@@ -1112,12 +1119,12 @@
 
     /**
      * Retrieve the app op code for a permission, or null if there is not one.
-     * This API is intended to be used for mapping runtime permissions to the
-     * corresponding app op.
+     * This API is intended to be used for mapping runtime or appop permissions
+     * to the corresponding app op.
      * @hide
      */
     public static int permissionToOpCode(String permission) {
-        Integer boxedOpCode = sRuntimePermToOp.get(permission);
+        Integer boxedOpCode = sPermToOp.get(permission);
         return boxedOpCode != null ? boxedOpCode : OP_NONE;
     }
 
@@ -1462,7 +1469,7 @@
      * @return The app op associated with the permission or null.
      */
     public static String permissionToOp(String permission) {
-        final Integer opCode = sRuntimePermToOp.get(permission);
+        final Integer opCode = sPermToOp.get(permission);
         if (opCode == null) {
             return null;
         }
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 6591fc9..8d385db 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -17,13 +17,13 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
-import android.view.ViewStructure;
 import android.view.ViewRootImpl;
+import android.view.ViewStructure;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.view.autofill.AutoFillId;
 import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
-import android.view.autofill.AutoFillId;
 
 import java.util.ArrayList;
 
@@ -579,6 +579,7 @@
         static final int FLAGS_HAS_EXTRAS = 0x00400000;
         static final int FLAGS_HAS_ID = 0x00200000;
         static final int FLAGS_HAS_CHILDREN = 0x00100000;
+        static final int FLAGS_HAS_URL = 0x00080000;
         static final int FLAGS_ALL_CONTROL = 0xfff00000;
 
         int mFlags;
@@ -587,6 +588,7 @@
         CharSequence mContentDescription;
 
         ViewNodeText mText;
+        String mUrl;
         Bundle mExtras;
 
         ViewNode[] mChildren;
@@ -651,6 +653,9 @@
             if ((flags&FLAGS_HAS_TEXT) != 0) {
                 mText = new ViewNodeText(in, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0);
             }
+            if ((flags&FLAGS_HAS_URL) != 0) {
+                mUrl = in.readString();
+            }
             if ((flags&FLAGS_HAS_EXTRAS) != 0) {
                 mExtras = in.readBundle();
             }
@@ -704,6 +709,9 @@
                     flags |= FLAGS_HAS_COMPLEX_TEXT;
                 }
             }
+            if (mUrl != null) {
+                flags |= FLAGS_HAS_URL;
+            }
             if (mExtras != null) {
                 flags |= FLAGS_HAS_EXTRAS;
             }
@@ -760,6 +768,9 @@
             if ((flags&FLAGS_HAS_TEXT) != 0) {
                 mText.writeToParcel(out, (flags&FLAGS_HAS_COMPLEX_TEXT) == 0, writeSensitive);
             }
+            if ((flags&FLAGS_HAS_URL) != 0) {
+                out.writeString(mUrl);
+            }
             if ((flags&FLAGS_HAS_EXTRAS) != 0) {
                 out.writeBundle(mExtras);
             }
@@ -1040,6 +1051,20 @@
         }
 
         /**
+         * Returns the URL represented by this node.
+         *
+         * <p>Typically used in 2 categories of nodes:
+         *
+         * <ol>
+         * <li>Root node (containing the URL of the HTML page)
+         * <li>Child nodes that represent hyperlinks (contains the hyperlink URL).
+         * </ol>
+         */
+        public String getUrl() {
+            return mUrl;
+        }
+
+        /**
          * Returns any text associated with the node that is displayed to the user, or null
          * if there is none.
          */
@@ -1486,6 +1511,11 @@
         public void setSanitized(boolean sanitized) {
             mNode.mSanitized = sanitized;
         }
+
+        @Override
+        public void setUrl(String url) {
+            mNode.mUrl = url;
+        }
     }
 
     /** @hide */
@@ -1583,6 +1613,10 @@
             Log.i(TAG, prefix + "  Text color fg: #" + Integer.toHexString(node.getTextColor())
                     + ", bg: #" + Integer.toHexString(node.getTextBackgroundColor()));
         }
+        CharSequence url = node.getUrl();
+        if (url != null) {
+            Log.i(TAG, prefix + "  URL: " + url);
+        }
         String hint = node.getHint();
         if (hint != null) {
             Log.i(TAG, prefix + "  Hint: " + hint);
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index b379c7c..c0c1a4d 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -29,12 +29,10 @@
 /**
  * System level service for managing companion devices
  *
- * Usage:
- * To obtain an instance call
- * {@link Context#getSystemService}({@link Context#COMPANION_DEVICE_SERVICE})
- *
- * Then, call {@link #associate} to initiate the flow of associating current package
- * with a device selected by user
+ * <p>To obtain an instance call {@link Context#getSystemService}({@link
+ * Context#COMPANION_DEVICE_SERVICE}) Then, call {@link #associate(AssociationRequest,
+ * Callback, Handler)} to initiate the flow of associating current package with a
+ * device selected by user.</p>
  *
  * @see AssociationRequest
  */
@@ -47,6 +45,14 @@
     public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
 
     /**
+     * The package name of the companion device discovery component.
+     *
+     * @hide
+     */
+    public static final String COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME =
+            "com.android.companiondevicemanager";
+
+    /**
      * A callback to receive once at least one suitable device is found, or the search failed
      * (e.g. timed out)
      */
@@ -81,13 +87,20 @@
     /**
      * Associate this app with a companion device, selected by user
      *
-     * Once at least one appropriate device is found, {@code callback} will be called with a
+     * <p>Once at least one appropriate device is found, {@code callback} will be called with a
      * {@link PendingIntent} that can be used to show the list of available devices for the user
      * to select.
      * It should be started for result (i.e. using
      * {@link android.app.Activity#startIntentSenderForResult}), as the resulting
      * {@link android.content.Intent} will contain extra {@link #EXTRA_DEVICE}, with the selected
-     * device. (e.g. {@link android.bluetooth.BluetoothDevice})
+     * device. (e.g. {@link android.bluetooth.BluetoothDevice})</p>
+     *
+     * <p>If your app needs to be excluded from battery optimizations (run in the background)
+     * or to have unrestricted data access (use data in the background) you can declare that
+     * you use the {@link android.Manifest.permission#RUN_IN_BACKGROUND} and {@link
+     * android.Manifest.permission#USE_DATA_IN_BACKGROUND} respectively. Note that these
+     * special capabilities have a negative effect on the device's battery and user's data
+     * usage, therefore you should requested them when absolutely necessary.</p>
      *
      * @param request specific details about this request
      * @param callback will be called once there's at least one device found for user to choose from
@@ -106,17 +119,16 @@
         try {
             mService.associate(
                     request,
-                    new IOnAssociateCallback.Stub() {
-
+                    new IFindDeviceCallback.Stub() {
                         @Override
-                        public void onSuccess(PendingIntent launcher) throws RemoteException {
+                        public void onSuccess(PendingIntent launcher) {
                             finalHandler.post(() -> {
                                 callback.onDeviceFound(launcher.getIntentSender());
                             });
                         }
 
                         @Override
-                        public void onFailure(CharSequence reason) throws RemoteException {
+                        public void onFailure(CharSequence reason) {
                             finalHandler.post(() -> callback.onFailure(reason));
                         }
                     },
diff --git a/core/java/android/companion/ICompanionDeviceManagerService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
similarity index 71%
rename from core/java/android/companion/ICompanionDeviceManagerService.aidl
rename to core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index ff2a7eb..4d77963 100644
--- a/core/java/android/companion/ICompanionDeviceManagerService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -17,13 +17,14 @@
 package android.companion;
 
 import android.companion.AssociationRequest;
-import android.companion.IOnAssociateCallback;
-
+import android.companion.ICompanionDeviceDiscoveryServiceCallback;
+import android.companion.IFindDeviceCallback;
 
 /** @hide */
-interface ICompanionDeviceManagerService {
+interface ICompanionDeviceDiscoveryService {
     void startDiscovery(
         in AssociationRequest request,
-        in IOnAssociateCallback callback,
-        in String callingPackage);
+        in String callingPackage,
+        in IFindDeviceCallback findCallback,
+        in ICompanionDeviceDiscoveryServiceCallback serviceCallback);
 }
diff --git a/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
similarity index 81%
rename from core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
rename to core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
index c9dd345..7af708e 100644
--- a/core/java/android/companion/ICompanionDeviceManagerServiceCallback.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
@@ -16,9 +16,7 @@
 
 package android.companion;
 
-import android.bluetooth.BluetoothDevice;
-
 /** @hide */
-interface ICompanionDeviceManagerServiceCallback {
-    void onDeviceSelected(in BluetoothDevice device);
+interface ICompanionDeviceDiscoveryServiceCallback {
+    void onDeviceSelected(String packageName, int userId);
 }
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 065e31b..1d30ada 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -16,7 +16,7 @@
 
 package android.companion;
 
-import android.companion.IOnAssociateCallback;
+import android.companion.IFindDeviceCallback;
 import android.companion.AssociationRequest;
 
 /**
@@ -26,8 +26,8 @@
  */
 interface ICompanionDeviceManager {
     void associate(in AssociationRequest request,
-        in IOnAssociateCallback callback,
-        in String callingPackage); //TODO int userId?
+        in IFindDeviceCallback callback,
+        in String callingPackage);
 
     //TODO add these
 //    boolean haveNotificationAccess(String packageName);
diff --git a/core/java/android/companion/IOnAssociateCallback.aidl b/core/java/android/companion/IFindDeviceCallback.aidl
similarity index 95%
rename from core/java/android/companion/IOnAssociateCallback.aidl
rename to core/java/android/companion/IFindDeviceCallback.aidl
index 4867eadd..919e1519 100644
--- a/core/java/android/companion/IOnAssociateCallback.aidl
+++ b/core/java/android/companion/IFindDeviceCallback.aidl
@@ -19,7 +19,7 @@
 import android.app.PendingIntent;
 
 /** @hide */
-interface IOnAssociateCallback {
+interface IFindDeviceCallback {
     void onSuccess(in PendingIntent launcher);
     void onFailure(in CharSequence reason);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 028a7bcf..b0505ac 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -669,13 +669,14 @@
      * preview. {@link #getClipData} contains an optional list of content URIs
      * if there is more than one item to preview. {@link #EXTRA_INDEX} is an
      * optional index of the URI in the clip data to show first.
-     * If {@link #EXTRA_QUICK_VIEW_PLAIN} is true, then the quick viewer should show
-     * basic UI without any extra features other than quick viewing the passed items.
-     * Especially, the quick viewer should not let users open the passed files
-     * in other apps, which includes sharing, opening, editing, printing, etc in the
-     * plain mode.
+     * <p>By default quick viewers are supposed to be lightweight and focus on
+     * previewing the content only. They should not expose features such as printing,
+     * opening in an external app, deleting, rotating, casting, etc.
+     * However, if {@link #EXTRA_QUICK_VIEW_ADVANCED} is true, then the quick viewer
+     * may show advanced UI which includes convenience actions suitable for the passed
+     * Uris.
      * <p>Output: nothing.
-     * @see #EXTRA_QUICK_VIEW_HIDE_DEFAULT_ACTIONS
+     * @see #EXTRA_QUICK_VIEW_ADVANCED
      * @see #EXTRA_INDEX
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -4413,19 +4414,15 @@
     public static final String EXTRA_INDEX = "android.intent.extra.INDEX";
 
     /**
-     * Shows a plain quick viewer UI which doesn't provide any extra features other than
-     * quick viewing the items.
-     *
-     * <p>Especially, the quick viewer should not let users open the quick viewed files
-     * in other apps, which includes sharing, opening, editing, printing, etc.
-     *
-     * <p>This feature is optional, and may not be handled by all quick viewers.
+     * Tells the quick viewer to show additional UI actions suitable for the passed Uris,
+     * such as opening in other apps, sharing, opening, editing, printing, deleting,
+     * casting, etc.
      *
      * <p>The value is boolean. By default false.
      * @see ACTION_QUICK_VIEW
      */
-    public static final String EXTRA_QUICK_VIEW_PLAIN =
-            "android.intent.extra.QUICK_VIEW_PLAIN";
+    public static final String EXTRA_QUICK_VIEW_ADVANCED =
+            "android.intent.extra.QUICK_VIEW_ADVANCED";
 
     /**
      * Optional boolean extra indicating whether quiet mode has been switched on or off.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index acb1d07..719a957 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2998,8 +2998,8 @@
      *
      * This function behaves identically to the non-timedout version, but if a suitable
      * network is not found within the given time (in milliseconds) the
-     * {@link NetworkCallback#unavailable} callback is called.  The request must
-     * still be released normally by calling {@link unregisterNetworkCallback(NetworkCallback)}.
+     * {@link NetworkCallback#onUnavailable()} callback is called.  The request must
+     * still be released normally by calling {@link #unregisterNetworkCallback(NetworkCallback)}.
      *
      * <p>This method requires the caller to hold either the
      * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission
@@ -3011,10 +3011,7 @@
      *                        the callbacks must not be shared - they uniquely specify
      *                        this request.
      * @param timeoutMs The time in milliseconds to attempt looking for a suitable network
-     *                  before {@link NetworkCallback#unavailable} is called.
-     *
-     * TODO: Make timeouts work and then unhide this method.
-     *
+     *                  before {@link NetworkCallback#onUnavailable()} is called.
      * @hide
      */
     public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
@@ -3024,13 +3021,6 @@
     }
 
     /**
-     * The maximum number of milliseconds the framework will look for a suitable network
-     * during a timeout-equiped call to {@link requestNetwork}.
-     * {@hide}
-     */
-    public final static int MAX_NETWORK_REQUEST_TIMEOUT_MS = 100 * 60 * 1000;
-
-    /**
      * The lookup key for a {@link Network} object included with the intent after
      * successfully finding a network for the applications request.  Retrieve it with
      * {@link android.content.Intent#getParcelableExtra(String)}.
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 11b9606..ee8eed1 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -348,8 +348,8 @@
             if (msg.what == UPDATE_SLIDER) {
                 if (mSeekBar != null) {
                     mLastProgress = msg.arg1;
-                    mLastAudibleStreamVolume = Math.abs(msg.arg2);
-                    final boolean muted = msg.arg2 < 0;
+                    mLastAudibleStreamVolume = msg.arg2;
+                    final boolean muted = ((Boolean)msg.obj).booleanValue();
                     if (muted != mMuted) {
                         mMuted = muted;
                         if (mCallback != null) {
@@ -362,8 +362,7 @@
         }
 
         public void postUpdateSlider(int volume, int lastAudibleVolume, boolean mute) {
-            final int arg2 = lastAudibleVolume * (mute ? -1 : 1);
-            obtainMessage(UPDATE_SLIDER, volume, arg2).sendToTarget();
+            obtainMessage(UPDATE_SLIDER, volume, lastAudibleVolume, new Boolean(mute)).sendToTarget();
         }
     }
 
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index b6d720d..83810b0 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -164,6 +164,8 @@
 
     public static int VARIATION_SELECTOR_16 = 0xFE0F;
 
+    public static int CANCEL_TAG = 0xE007F;
+
     // Returns true if the given code point is regional indicator symbol.
     public static boolean isRegionalIndicatorSymbol(int codepoint) {
         return 0x1F1E6 <= codepoint && codepoint <= 0x1F1FF;
@@ -188,4 +190,13 @@
     public static boolean isKeycapBase(int codePoint) {
         return ('0' <= codePoint && codePoint <= '9') || codePoint == '#' || codePoint == '*';
     }
+
+    /**
+     * Returns true if the character can be a part of tag_spec in emoji tag sequence.
+     *
+     * Note that 0xE007F (CANCEL TAG) is not included.
+     */
+    public static boolean isTagSpecChar(int codePoint) {
+        return 0xE0020 <= codePoint && codePoint <= 0xE007E;
+    }
 }
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index 90559dc..5f0a46d 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -145,8 +145,11 @@
         // The number of following RIS code points is even.
         final int STATE_EVEN_NUMBERED_RIS = 11;
 
+        // The offset is in emoji tag sequence.
+        final int STATE_IN_TAG_SEQUENCE = 12;
+
         // The state machine has been stopped.
-        final int STATE_FINISHED = 12;
+        final int STATE_FINISHED = 13;
 
         int deleteCharCount = 0;  // Char count to be deleted by backspace.
         int lastSeenVSCharCount = 0;  // Char count of previous variation selector.
@@ -173,6 +176,8 @@
                         state = STATE_BEFORE_KEYCAP;
                     } else if (Emoji.isEmoji(codePoint)) {
                         state = STATE_BEFORE_EMOJI;
+                    } else if (codePoint == Emoji.CANCEL_TAG) {
+                        state = STATE_IN_TAG_SEQUENCE;
                     } else {
                         state = STATE_FINISHED;
                     }
@@ -275,6 +280,20 @@
                         state = STATE_FINISHED;
                     }
                     break;
+                case STATE_IN_TAG_SEQUENCE:
+                    if (Emoji.isTagSpecChar(codePoint)) {
+                        deleteCharCount += 2; /* Char count of emoji tag spec character. */
+                        // Keep the same state.
+                    } else if (Emoji.isEmoji(codePoint)) {
+                        deleteCharCount += Character.charCount(codePoint);
+                        state = STATE_FINISHED;
+                    } else {
+                        // Couldn't find tag_base character. Delete the last tag_term character.
+                        deleteCharCount = 2;  // for U+E007F
+                        state = STATE_FINISHED;
+                    }
+                    // TODO: Need handle emoji variation selectors. Issue 35224297
+                    break;
                 default:
                     throw new IllegalArgumentException("state " + state + " is unknown");
             }
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 2129039..5f55bdc 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1008,7 +1008,6 @@
      * </p>
      *
      * @see #getAxisValue(int, int)
-     * {@hide}
      */
     public static final int AXIS_SCROLL = 26;
 
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index cc19539..9ce23e6 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -25,7 +25,8 @@
 
 /**
  * Container for storing additional per-view data generated by {@link View#onProvideStructure
- * View.onProvideStructure}.
+ * View.onProvideStructure} and {@link View#onProvideAutoFillStructure
+ * View.onProvideAutoFillStructure}.
  */
 public abstract class ViewStructure {
 
@@ -33,7 +34,9 @@
      * Flag used when adding virtual views for auto-fill, it indicates the contents of the view
      * (such as * {@link android.app.assist.AssistStructure.ViewNode#getText()} and
      * {@link android.app.assist.AssistStructure.ViewNode#getAutoFillValue()})
-     * can be passed to the {@link android.service.autofill.AutoFillService}.
+     * can be passed to the {@link
+     * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+     * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)} call.
      */
     public static final int AUTO_FILL_FLAG_SANITIZED = 0x1;
 
@@ -275,7 +278,7 @@
      *
      * @param index child index
      * @param virtualId id identifying the virtual child inside the custom view.
-     * @param flags currently {@code 0}.
+     * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
      */
     // TODO(b/33197203, b/33802548): add CTS/unit test
     public abstract ViewStructure newChild(int index, int virtualId, int flags);
@@ -296,7 +299,7 @@
      *
      * @param index child index
      * @param virtualId id identifying the virtual child inside the custom view.
-     * @param flags currently {@code 0}.
+     * @param flags currently {@code 0} or {@link #AUTO_FILL_FLAG_SANITIZED}.
      */
     // TODO(b/33197203, b/33802548): add CTS/unit test
     public abstract ViewStructure asyncNewChild(int index, int virtualId, int flags);
@@ -335,4 +338,17 @@
 
     /** @hide */
     public abstract AutoFillId getAutoFillId();
+
+    /**
+     * Sets the URL represented by this node.
+     *
+     * <p>Typically used in the following situations:
+     *
+     * <ol>
+     * <li>In a {@link android.app.assist.AssistStructure.WindowNode#getRootViewNode()}, to set up
+     * the main URL of an HTML page.
+     * <li>On child nodes represening hyperlinks.
+     * </ol>
+     */
+    public abstract void setUrl(String url);
 }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 0b5a1b7..310cbc7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -584,6 +584,7 @@
             OsConstants.CAP_NET_RAW,
             OsConstants.CAP_SYS_MODULE,
             OsConstants.CAP_SYS_NICE,
+            OsConstants.CAP_SYS_PTRACE,
             OsConstants.CAP_SYS_RESOURCE,
             OsConstants.CAP_SYS_TIME,
             OsConstants.CAP_SYS_TTY_CONFIG,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cd02fbb..97fbfa5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1813,6 +1813,22 @@
         android:description="@string/permdesc_systemAlertWindow"
         android:protectionLevel="signature|preinstalled|appop|pre23|development" />
 
+    <!-- Allows an app to run in the background.
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.RUN_IN_BACKGROUND"
+        android:label="@string/permlab_runInBackground"
+        android:description="@string/permdesc_runInBackground"
+        android:protectionLevel="signature" />
+
+    <!-- Allows an app to use data in the background.
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.USE_DATA_IN_BACKGROUND"
+        android:label="@string/permlab_useDataInBackground"
+        android:description="@string/permdesc_useDataInBackground"
+        android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
     <!-- ================================== -->
@@ -2996,7 +3012,7 @@
          any metadata and intents attached.
          @hide -->
     <permission android:name="android.permission.ACCESS_NOTIFICATIONS"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged|appop" />
 
     <!-- Marker permission for applications that wish to access notification policy.
          <p>Protection level: normal
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 72a2e43..fcb0e08 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1286,6 +1286,16 @@
         <item>com.android.networkrecommendation</item>
     </string-array>
 
+    <!-- The package name of the default network recommendation app.
+         A network recommendation provider must:
+             * Be granted the SCORE_NETWORKS permission.
+             * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
+               protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
+
+         This must be set to a valid network recommendation app.
+     -->
+    <string name="config_defaultNetworkRecommendationProviderPackage" translatable="false">com.android.networkrecommendation</string>
+
     <!-- Whether to enable Hardware FLP overlay which allows Hardware FLP to be
          replaced by an app at run-time. When disabled, only the
          config_hardwareFlpPackageName package will be searched for Hardware Flp,
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2309866..8faa76c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -816,6 +816,16 @@
     <string name="permdesc_systemAlertWindow">This app can appear on top of other apps or other parts of the screen. This may interfere with normal app usage and change the way that other apps appear.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_runInBackground">run in the background</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_runInBackground">This app can run in the background. This may drain battery faster.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_useDataInBackground">use data in the background</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_useDataInBackground">This app can use data in the background. This may increase data usage.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_persistentActivity">make app always run</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_persistentActivity" product="tablet">Allows the app to make parts of itself persistent in memory.  This can limit memory available to other apps slowing down the tablet.</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1324e38..0d63a1e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2790,6 +2790,7 @@
 
   <!-- Network Recommendation -->
   <java-symbol type="array" name="config_networkRecommendationPackageNames" />
+  <java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" />
 
   <!-- Whether allow 3rd party apps on internal storage. -->
   <java-symbol type="bool" name="config_allow3rdPartyAppOnInternal" />
diff --git a/core/tests/coretests/src/android/text/method/BackspaceTest.java b/core/tests/coretests/src/android/text/method/BackspaceTest.java
index a260e94..864b48a 100644
--- a/core/tests/coretests/src/android/text/method/BackspaceTest.java
+++ b/core/tests/coretests/src/android/text/method/BackspaceTest.java
@@ -37,23 +37,12 @@
     // Sync the state to the TextView and call onKeyDown with KEYCODE_DEL key event.
     // Then update the state to the result of TextView.
     private void backspace(final EditorState state, int modifiers) {
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mTextView.setText(state.mText, BufferType.EDITABLE);
-                mTextView.setKeyListener(mKeyListener);
-                mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        assertTrue(mTextView.hasWindowFocus());
+        mTextView.setText(state.mText, BufferType.EDITABLE);
+        mTextView.setKeyListener(mKeyListener);
+        mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
 
         final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_DEL, modifiers);
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
 
         state.mText = mTextView.getText();
         state.mSelectionStart = mTextView.getSelectionStart();
@@ -247,6 +236,51 @@
         state.assertEquals("U+1F1FA U+1F1F8 |");
         backspace(state, 0);
         state.assertEquals("|");
+
+        // Incomplete sequence. (no tag_term: U+E007E)
+        state.setByString("'a' U+1F3F4 U+E0067 'b' |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+1F3F4 U+E0067 |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+1F3F4 |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
+
+        // No tag_base
+        state.setByString("'a' U+E0067 U+E007F 'b' |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+E0067 U+E007F |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+E0067 |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
+
+        // Isolated tag chars
+        state.setByString("'a' U+E0067 U+E0067 'b' |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+E0067 U+E0067 |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+E0067 |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
+
+        // Isolated tab term.
+        state.setByString("'a' U+E007F U+E007F 'b' |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+E007F U+E007F |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+E007F |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
+
+        // Immediate tag_term after tag_base
+        state.setByString("'a' U+1F3F4 U+E007F U+1F3F4 U+E007F 'b' |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+1F3F4 U+E007F U+1F3F4 U+E007F |");
+        backspace(state, 0);
+        state.assertEquals("'a' U+1F3F4 U+E007F |");
+        backspace(state, 0);
+        state.assertEquals("'a' |");
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
index 1990fd0..839d380 100644
--- a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -37,23 +37,12 @@
     // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
     // Then update the state to the result of TextView.
     private void forwardDelete(final EditorState state, int modifiers) {
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mTextView.setText(state.mText, BufferType.EDITABLE);
-                mTextView.setKeyListener(mKeyListener);
-                mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
-        assertTrue(mTextView.hasWindowFocus());
+        mTextView.setText(state.mText, BufferType.EDITABLE);
+        mTextView.setKeyListener(mKeyListener);
+        mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
 
         final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
-            }
-        });
-        mInstrumentation.waitForIdleSync();
+        mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
 
         state.mText = mTextView.getText();
         state.mSelectionStart = mTextView.getSelectionStart();
@@ -186,6 +175,46 @@
         state.assertEquals("| U+1F1FA");
         forwardDelete(state, 0);
         state.assertEquals("|");
+
+        // Incomplete sequence. (no tag_term:U+E007E)
+        state.setByString("| 'a' U+1F3F4 U+E0067 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3F4 U+E0067 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'b'");
+
+        // No tag_base
+        state.setByString("| 'a' U+E0067 U+E007F 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'b'");
+
+        // Isolated tag chars
+        state.setByString("| 'a' U+E0067 U+E0067 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'b'");
+
+        // Isolated tag base.
+        state.setByString("| 'a' U+1F3F4 U+1F3F4 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3F4 U+1F3F4 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3F4 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'b'");
+
+        // Isolated tab term.
+        state.setByString("| 'a' U+E007F U+E007F 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'b'");
+
+        // Immediate tag_term after tag_base
+        state.setByString("| 'a' U+1F3F4 U+E007F U+1F3F4 U+E007F 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3F4 U+E007F U+1F3F4 U+E007F 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| U+1F3F4 U+E007F 'b'");
+        forwardDelete(state, 0);
+        state.assertEquals("| 'b'");
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java b/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
index 4b4e7af..f005d7b 100644
--- a/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
+++ b/core/tests/coretests/src/android/text/method/KeyListenerTestCase.java
@@ -17,41 +17,26 @@
 package android.text.method;
 
 import android.app.Instrumentation;
-import android.test.ActivityInstrumentationTestCase2;
-import android.text.format.DateUtils;
+import android.test.InstrumentationTestCase;
 import android.view.KeyEvent;
 import android.widget.EditText;
-import android.widget.TextViewActivity;
 
 import com.android.frameworks.coretests.R;
 
-public abstract class KeyListenerTestCase extends
-        ActivityInstrumentationTestCase2<TextViewActivity> {
+public abstract class KeyListenerTestCase extends InstrumentationTestCase {
 
-    protected TextViewActivity mActivity;
     protected Instrumentation mInstrumentation;
     protected EditText mTextView;
 
     public KeyListenerTestCase() {
-        super(TextViewActivity.class);
     }
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
-        mActivity = getActivity();
         mInstrumentation = getInstrumentation();
-        mTextView = (EditText) mActivity.findViewById(R.id.textview);
-
-        mActivity.runOnUiThread(new Runnable() {
-            public void run() {
-                // Ensure that the screen is on for this test.
-                mTextView.setKeepScreenOn(true);
-            }
-        });
-
-        assertTrue(mActivity.waitForWindowFocus(5 * DateUtils.SECOND_IN_MILLIS));
+        mTextView = new EditText(mInstrumentation.getContext());
     }
 
     protected static KeyEvent getKey(int keycode, int metaState) {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 85c3c1c..5008a5f 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -640,6 +640,8 @@
     private UUID mDrmUUID;
     private final Object mDrmLock = new Object();
     private DrmInfo mDrmInfo;
+    private MediaDrm mDrmObj;
+    private byte[] mDrmSessionId;
     private boolean mDrmInfoResolved;
     private boolean mActiveDrmScheme;
     private boolean mDrmConfigAllowed;
@@ -1960,6 +1962,7 @@
         mOnSubtitleDataListener = null;
 
         // Modular DRM clean up
+        mOnDrmConfigListener = null;
         mOnDrmInfoHandlerDelegate = null;
         mOnDrmPreparedHandlerDelegate = null;
         resetDrmState();
@@ -3171,7 +3174,7 @@
                         onDrmInfoHandlerDelegate.notifyClient(drmInfo);
                     }
                 } else {
-                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj NONE; UNEXPECTED" + msg.obj);
+                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + msg.obj);
                 }
                 return;
 
@@ -3846,17 +3849,34 @@
      * and setDrmPropertyString.
      *
      */
-    public static abstract class OnDrmConfigCallback
+    public interface OnDrmConfigListener
     {
         /**
          * Called to give the app the opportunity to configure DRM before the session is created
          *
          * @param mp the {@code MediaPlayer} associated with this callback
          */
-        public void onDrmConfig(MediaPlayer mp) {}
+        public void onDrmConfig(MediaPlayer mp);
     }
 
     /**
+     * Register a callback to be invoked for configuration of the DRM object before
+     * the session is created.
+     * The callback will be invoked synchronously half-way into the execution
+     * of {@link #prepareDrm(UUID uuid)}.
+     *
+     * @param listener the callback that will be run
+     */
+    public void setOnDrmConfigListener(OnDrmConfigListener listener)
+    {
+        synchronized (mDrmLock) {
+            mOnDrmConfigListener = listener;
+        } // synchronized
+    }
+
+    private OnDrmConfigListener mOnDrmConfigListener;
+
+    /**
      * Interface definition of a callback to be invoked when the
      * DRM info becomes available
      */
@@ -4053,13 +4073,11 @@
         return drmInfo;
     }
 
-    private native void _prepareDrm(@NonNull byte[] uuid, int mode)
-            throws UnsupportedSchemeException, ResourceBusyException, NotProvisionedException;
 
     /**
      * Prepares the DRM for the current source
      * <p>
-     * If {@code OnDrmConfigCallback} is registered, it will be called half-way into
+     * If {@code OnDrmConfigListener} is registered, it will be called half-way into
      * preparation to allow configuration of the DRM properties before opening the
      * DRM session. Note that the callback is called synchronously in the thread that called
      * {@code prepareDrm}. It should be used only for a series of {@code getDrmPropertyString}
@@ -4087,10 +4105,12 @@
      * @throws ResourceBusyException       if required DRM resources are in use
      * @throws ProvisioningErrorException  if provisioning is required but an attempt failed
      */
-    public void prepareDrm(@NonNull UUID uuid, OnDrmConfigCallback configCallback)
+    public void prepareDrm(@NonNull UUID uuid)
             throws UnsupportedSchemeException,
                    ResourceBusyException, ProvisioningErrorException
     {
+        Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigListener: " + mOnDrmConfigListener);
+
         boolean allDoneWithoutProvisioning = false;
         // get a snapshot as we'll use them outside the lock
         OnDrmPreparedHandlerDelegate onDrmPreparedHandlerDelegate = null;
@@ -4099,58 +4119,46 @@
 
             // only allowing if tied to a protected source; might releax for releasing offline keys
             if (mDrmInfo == null) {
-                final String msg = String.format("prepareDrm(%s): Wrong usage: " +
-                                                 "The player must be prepared and DRM " +
-                                                 "info be retrieved before this call.", uuid);
+                final String msg = "prepareDrm(): Wrong usage: The player must be prepared and " +
+                        "DRM info be retrieved before this call.";
                 Log.e(TAG, msg);
                 throw new IllegalStateException(msg);
             }
 
             if (mActiveDrmScheme) {
-                final String msg = String.format("prepareDrm(%s): Wrong usage: There is already " +
-                                                 "an active DRM scheme with %s.", uuid, mDrmUUID);
+                final String msg = "prepareDrm(): Wrong usage: There is already " +
+                        "an active DRM scheme with " + mDrmUUID;
                 Log.e(TAG, msg);
                 throw new IllegalStateException(msg);
             }
 
             if (mPrepareDrmInProgress) {
-                final String msg = String.format("prepareDrm(%s): Wrong usage: There is already " +
-                                                 "a pending prepareDrm call.", uuid);
+                final String msg = "prepareDrm(): Wrong usage: There is already " +
+                        "a pending prepareDrm call.";
                 Log.e(TAG, msg);
                 throw new IllegalStateException(msg);
             }
 
             if (mDrmProvisioningInProgress) {
-                final String msg = String.format("prepareDrm(%s): Unexpectd: Provisioning is " +
-                                                 "already in progress.", uuid);
+                final String msg = "prepareDrm(): Unexpectd: Provisioning is already in progress.";
                 Log.e(TAG, msg);
                 throw new IllegalStateException(msg);
             }
 
+            // shouldn't need this; just for safeguard
+            cleanDrmObj();
+
             mPrepareDrmInProgress = true;
             // local copy while the lock is held
             onDrmPreparedHandlerDelegate = mOnDrmPreparedHandlerDelegate;
 
-            if (configCallback != null) {
-                try {
-                    boolean allowOpenSession = false;   // just pre-openSession
-                    _prepareDrm(getByteArrayFromUUID(uuid), allowOpenSession ? 1 : 0);
-                } catch (IllegalStateException e) {
-                    final String msg = String.format("prepareDrm(): Wrong usage: The player must " +
-                                                     "be in prepared state to call prepareDrm().");
-                    Log.e(TAG, msg);
-                    throw new IllegalStateException(msg);
-                } catch (NotProvisionedException e) {   // the pre-config step won't raise this
-                    final String msg = String.format("prepareDrm: Unexpected " +
-                                                     "NotProvisionedException here.");
-                    Log.e(TAG, msg);
-                    throw new ProvisioningErrorException(msg);
-                } catch (Exception e) {
-                    Log.w(TAG, String.format("prepareDrm: Exception %s", e));
-                    throw e;
-                } finally {
-                    mPrepareDrmInProgress = false;
-                }
+            try {
+                // only creating the DRM object to allow pre-openSession configuration
+                prepareDrm_createDrmStep(uuid);
+            } catch (Exception e) {
+                Log.w(TAG, "prepareDrm(): Exception ", e);
+                mPrepareDrmInProgress = false;
+                throw e;
             }
 
             mDrmConfigAllowed = true;
@@ -4158,51 +4166,55 @@
 
 
         // call the callback outside the lock
-        if (configCallback != null)  {
-            configCallback.onDrmConfig(this);
+        if (mOnDrmConfigListener != null)  {
+            mOnDrmConfigListener.onDrmConfig(this);
         }
 
         synchronized (mDrmLock) {
             mDrmConfigAllowed = false;
+            boolean earlyExit = false;
 
             try {
-                boolean allowOpenSession = true;    // all in
-                _prepareDrm(getByteArrayFromUUID(uuid), allowOpenSession ? 1 : 0);
+                prepareDrm_openSessionStep(uuid);
 
                 mDrmUUID = uuid;
                 mActiveDrmScheme = true;
 
-                mPrepareDrmInProgress = false;
-
                 allDoneWithoutProvisioning = true;
             } catch (IllegalStateException e) {
-                final String msg = String.format("prepareDrm(%s): Wrong usage: The player must be" +
-                                                 " in prepared state to call prepareDrm().", uuid);
+                final String msg = "prepareDrm(): Wrong usage: The player must be " +
+                        "in the prepared state to call prepareDrm().";
                 Log.e(TAG, msg);
+                earlyExit = true;
                 throw new IllegalStateException(msg);
             } catch (NotProvisionedException e) {
-                Log.w(TAG, String.format("prepareDrm: NotProvisionedException"));
+                Log.w(TAG, "prepareDrm: NotProvisionedException");
 
-                // handle provisioning internally
+                // handle provisioning internally; it'll reset mPrepareDrmInProgress
                 boolean result = HandleProvisioninig(uuid);
 
                 // if blocking mode, we're already done;
                 // if non-blocking mode, we attempted to launch background provisioning
                 if (result == false) {
-                    final String msg =
-                                String.format("prepareDrm: Provisioning was required but failed.");
+                    final String msg = "prepareDrm: Provisioning was required but failed.";
                     Log.e(TAG, msg);
+                    earlyExit = true;
                     throw new ProvisioningErrorException(msg);
                 }
-
                 // nothing else to do;
                 // if blocking or non-blocking, HandleProvisioninig does the re-attempt & cleanup
             } catch (Exception e) {
-                Log.w(TAG, String.format("prepareDrm: Exception %s", e));
+                Log.e(TAG, "prepareDrm: Exception " + e);
+                earlyExit = true;
                 throw e;
             } finally {
-                mPrepareDrmInProgress = false;
-            }
+                if (!mDrmProvisioningInProgress) {// if early exit other than provisioning exception
+                    mPrepareDrmInProgress = false;
+                }
+                if (earlyExit) {    // cleaning up object if didn't succeed
+                    cleanDrmObj();
+                }
+            } // finally
         }   // synchronized
 
 
@@ -4225,25 +4237,33 @@
     public void releaseDrm()
             throws NoDrmSchemeException
     {
+        Log.v(TAG, "releaseDrm:");
+
         synchronized (mDrmLock) {
             if (!mActiveDrmScheme) {
-                Log.e(TAG, String.format("releaseDrm(%s): No active DRM scheme to release."));
+                Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
                 throw new NoDrmSchemeException("releaseDrm: No active DRM scheme to release.");
-            } else {
+            }
+
+            try {
+                // we don't have the player's state in this layer. The below call raises
+                // exception if we're in a non-stopped/idle state.
+
+                // for cleaning native/mediaserver crypto object
                 _releaseDrm();
 
+                // for cleaning client-side MediaDrm object; only called if above has succeeded
+                cleanDrmObj();
+
                 mActiveDrmScheme = false;
+            } catch (Exception e) {
+                Log.w(TAG, "releaseDrm: Exception ", e);
+                throw e;
             }
         }   // synchronized
     }
 
 
-    @NonNull
-    private native MediaDrm.KeyRequest _getKeyRequest(@NonNull byte[] scope,
-            @Nullable String mimeType, @MediaDrm.KeyType int keyType,
-            @Nullable Map<String, String> optionalParameters)
-            throws NotProvisionedException;
-
     /**
      * A key request/response exchange occurs between the app and a license server
      * to obtain or release keys used to decrypt encrypted content.
@@ -4284,20 +4304,42 @@
             @MediaDrm.KeyType int keyType, @Nullable Map<String, String> optionalParameters)
             throws NoDrmSchemeException
     {
+        Log.v(TAG, "getKeyRequest: " +
+                " scope: " + scope + " mimeType: " + mimeType +
+                " keyType: " + keyType + " optionalParameters: " + optionalParameters);
+
         synchronized (mDrmLock) {
             if (!mActiveDrmScheme) {
-                Log.e(TAG, String.format("getKeyRequest NoDrmSchemeException"));
+                Log.e(TAG, "getKeyRequest NoDrmSchemeException");
                 throw new NoDrmSchemeException("getKeyRequest: Has to set a DRM scheme first.");
             }
 
             try {
-                return _getKeyRequest(scope, mimeType, keyType, optionalParameters);
+                byte[] scopeOut = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
+                                  mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
+                                  scope;          // keySetId for KEY_TYPE_RELEASE
+
+                byte[] initData = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
+                                  scope :         // initData for KEY_TYPE_STREAMING/OFFLINE
+                                  null;           // not used for KEY_TYPE_RELEASE
+
+                HashMap<String, String> hmapOptionalParameters =
+                                                (optionalParameters != null) ?
+                                                new HashMap<String, String>(optionalParameters) :
+                                                null;
+
+                MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scopeOut, initData, mimeType,
+                                                              keyType, hmapOptionalParameters);
+                Log.v(TAG, "getKeyRequest:   --> request: " + request);
+
+                return request;
+
             } catch (NotProvisionedException e) {
-                Log.w(TAG, String.format("getKeyRequest NotProvisionedException: " +
-                                         "Unexpected. Shouldn't have reached here."));
+                Log.w(TAG, "getKeyRequest NotProvisionedException: " +
+                        "Unexpected. Shouldn't have reached here.");
                 throw new IllegalStateException("getKeyRequest: Unexpected provisioning error.");
             } catch (Exception e) {
-                Log.w(TAG, String.format("getKeyRequest Exception %s", e));
+                Log.w(TAG, "getKeyRequest Exception " + e);
                 throw e;
             }
 
@@ -4305,10 +4347,6 @@
     }
 
 
-    @Nullable
-    private native byte[] _provideKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
-            throws DeniedByServerException;
-
     /**
      * A key response is received from the license server by the app, then it is
      * provided to the DRM engine plugin using provideKeyResponse. When the
@@ -4331,25 +4369,41 @@
     public byte[] provideKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
             throws NoDrmSchemeException, DeniedByServerException
     {
+        Log.v(TAG, "provideKeyResponse: keySetId: " + keySetId + " response: " + response);
+
         synchronized (mDrmLock) {
 
             if (!mActiveDrmScheme) {
-                Log.e(TAG, String.format("getKeyRequest NoDrmSchemeException"));
+                Log.e(TAG, "getKeyRequest NoDrmSchemeException");
                 throw new NoDrmSchemeException("getKeyRequest: Has to set a DRM scheme first.");
             }
 
             try {
-                return _provideKeyResponse(keySetId, response);
+                byte[] scope = (keySetId == null) ?
+                                mDrmSessionId :     // sessionId for KEY_TYPE_STREAMING/OFFLINE
+                                keySetId;           // keySetId for KEY_TYPE_RELEASE
+
+                byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
+
+                Log.v(TAG, "provideKeyResponse: keySetId: " + keySetId + " response: " + response +
+                        " --> " + keySetResult);
+
+
+                return keySetResult;
+
+            } catch (NotProvisionedException e) {
+                Log.w(TAG, "provideKeyResponse NotProvisionedException: " +
+                        "Unexpected. Shouldn't have reached here.");
+                throw new IllegalStateException("provideKeyResponse: " +
+                        "Unexpected provisioning error.");
             } catch (Exception e) {
-                Log.w(TAG, String.format("provideKeyResponse Exception %s", e));
+                Log.w(TAG, "provideKeyResponse Exception " + e);
                 throw e;
             }
         }   // synchronized
     }
 
 
-    private native void _restoreKeys(@NonNull byte[] keySetId);
-
     /**
      * Restore persisted offline keys into a new session.  keySetId identifies the
      * keys to load, obtained from a prior call to {@link #provideKeyResponse}.
@@ -4359,17 +4413,19 @@
     public void restoreKeys(@NonNull byte[] keySetId)
             throws NoDrmSchemeException
     {
+        Log.v(TAG, "restoreKeys: keySetId: " + keySetId);
+
         synchronized (mDrmLock) {
 
             if (!mActiveDrmScheme) {
-                Log.w(TAG, String.format("restoreKeys NoDrmSchemeException"));
+                Log.w(TAG, "restoreKeys NoDrmSchemeException");
                 throw new NoDrmSchemeException("restoreKeys: Has to set a DRM scheme first.");
             }
 
             try {
-                _restoreKeys(keySetId);
+                mDrmObj.restoreKeys(mDrmSessionId, keySetId);
             } catch (Exception e) {
-                Log.w(TAG, String.format("restoreKeys Exception %s", e));
+                Log.w(TAG, "restoreKeys Exception " + e);
                 throw e;
             }
 
@@ -4377,9 +4433,6 @@
     }
 
 
-    @NonNull
-    private native String _getDrmPropertyString(@NonNull String propertyName);
-
     /**
      * Read a DRM engine plugin String property value, given the property name string.
      * <p>
@@ -4393,26 +4446,29 @@
     public String getDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName)
             throws NoDrmSchemeException
     {
+        Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName);
+
         String value;
         synchronized (mDrmLock) {
 
             if (!mActiveDrmScheme && !mDrmConfigAllowed) {
-                Log.w(TAG, String.format("getDrmPropertyString NoDrmSchemeException"));
+                Log.w(TAG, "getDrmPropertyString NoDrmSchemeException");
                 throw new NoDrmSchemeException("getDrmPropertyString: Has to prepareDrm() first.");
             }
 
             try {
-                value = _getDrmPropertyString(propertyName);
+                value = mDrmObj.getPropertyString(propertyName);
             } catch (Exception e) {
-                Log.w(TAG, String.format("getDrmPropertyString Exception %s", e));
+                Log.w(TAG, "getDrmPropertyString Exception " + e);
                 throw e;
             }
         }   // synchronized
 
+        Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName + " --> value: " + value);
+
         return value;
     }
 
-    private native void _setDrmPropertyString(@NonNull String propertyName, @NonNull String value);
 
     /**
      * Set a DRM engine plugin String property value.
@@ -4428,17 +4484,19 @@
                                      @NonNull String value)
             throws NoDrmSchemeException
     {
+        Log.v(TAG, "setDrmPropertyString: propertyName: " + propertyName + " value: " + value);
+
         synchronized (mDrmLock) {
 
             if ( !mActiveDrmScheme && !mDrmConfigAllowed ) {
-                Log.w(TAG, String.format("setDrmPropertyString NoDrmSchemeException"));
+                Log.w(TAG, "setDrmPropertyString NoDrmSchemeException");
                 throw new NoDrmSchemeException("setDrmPropertyString: Has to prepareDrm() first.");
             }
 
             try {
-                _setDrmPropertyString(propertyName, value);
+                mDrmObj.setPropertyString(propertyName, value);
             } catch ( Exception e ) {
-                Log.w(TAG, String.format("setDrmPropertyString Exception %s", e));
+                Log.w(TAG, "setDrmPropertyString Exception " + e);
                 throw e;
             }
         }   // synchronized
@@ -4605,8 +4663,47 @@
         }
     }
 
+
+    private native void _prepareDrm(@NonNull byte[] uuid, @NonNull byte[] drmSessionId);
+
         // Modular DRM helpers
 
+    private void prepareDrm_createDrmStep(@NonNull UUID uuid)
+            throws UnsupportedSchemeException {
+        Log.v(TAG, "prepareDrm_createDrmStep: UUID: " + uuid);
+
+        try {
+            mDrmObj = new MediaDrm(uuid);
+            Log.v(TAG, "prepareDrm_createDrmStep: Created mDrmObj=" + mDrmObj);
+        } catch (Exception e) { // UnsupportedSchemeException
+            Log.e(TAG, "prepareDrm_createDrmStep: MediaDrm failed with " + e);
+            throw e;
+        }
+    }
+
+    private void prepareDrm_openSessionStep(@NonNull UUID uuid)
+            throws NotProvisionedException, ResourceBusyException {
+        Log.v(TAG, "prepareDrm_openSessionStep: uuid: " + uuid);
+
+        // TODO: don't need an open session for a future specialKeyReleaseDrm mode but we should do
+        // it anyway so it raises provisioning error if needed. We'd rather handle provisioning
+        // at prepareDrm/openSession rather than getKeyRequest/provideKeyResponse
+        try {
+            mDrmSessionId = mDrmObj.openSession();
+            Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId);
+
+            // Sending it down to native/mediaserver to create the crypto object
+            // This call could simply fail due to bad player state, e.g., after start().
+            _prepareDrm(getByteArrayFromUUID(uuid), mDrmSessionId);
+            Log.v(TAG, "prepareDrm_openSessionStep: _prepareDrm/Crypto succeeded");
+
+        } catch (Exception e) { //ResourceBusyException, NotProvisionedException
+            Log.e(TAG, "prepareDrm_openSessionStep: open/crypto failed with " + e);
+            throw e;
+        }
+
+    }
+
     private class ProvisioningThread extends Thread
     {
         public static final int TIMEOUT_MS = 60000;
@@ -4633,7 +4730,7 @@
             urlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
             this.uuid = uuid;
 
-            Log.v(TAG, String.format("HandleProvisioninig: Thread is initialised url: %s", urlStr));
+            Log.v(TAG, "HandleProvisioninig: Thread is initialised url: " + urlStr);
             return this;
         }
 
@@ -4653,30 +4750,27 @@
                     connection.connect();
                     response = Streams.readFully(connection.getInputStream());
 
-                    Log.v(TAG, String.format("HandleProvisioninig: Thread run response %d %s",
-                                             response.length, response));
+                    Log.v(TAG, "HandleProvisioninig: Thread run: response " +
+                            response.length + " " + response);
                 } catch (Exception e) {
-                    Log.w(TAG, String.format("HandleProvisioninig: Thread run connect %s url: %s",
-                                             e, url));
+                    Log.w(TAG, "HandleProvisioninig: Thread run: connect " + e + " url: " + url);
                 } finally {
                     connection.disconnect();
                 }
             } catch (Exception e)   {
-                Log.w(TAG, String.format("HandleProvisioninig: Thread run openConnection %s", e));
+                Log.w(TAG, "HandleProvisioninig: Thread run: openConnection " + e);
             }
 
             if (response != null) {
                 try {
-                    MediaDrm drm = new MediaDrm(uuid);
-                    drm.provideProvisionResponse(response);
-                    drm.release();
-                    Log.v(TAG, String.format("HandleProvisioninig: Thread run " +
-                                             "newDrm+provideProvisionResponse SUCCEEDED!"));
+                    mDrmObj.provideProvisionResponse(response);
+                    Log.v(TAG, "HandleProvisioninig: Thread run: " +
+                            "provideProvisionResponse SUCCEEDED!");
 
                     provisioningSucceeded = true;
                 } catch (Exception e)   {
-                    Log.w(TAG, String.format("HandleProvisioninig: Thread run " +
-                                             "newDrm+provideProvisionResponse %s", e));
+                    Log.w(TAG, "HandleProvisioninig: Thread run: " +
+                            "provideProvisionResponse " + e);
                 }
             }
 
@@ -4690,7 +4784,10 @@
                     }
                     mediaPlayer.mDrmProvisioningInProgress = false;
                     mediaPlayer.mPrepareDrmInProgress = false;
-                }
+                    if (!succeeded) {
+                        cleanDrmObj();  // cleaning up if it hasn't gone through while in the lock
+                    }
+                } // synchronized
 
                 // calling the callback outside the lock
                 onDrmPreparedHandlerDelegate.notifyClient(succeeded);
@@ -4702,6 +4799,9 @@
                 }
                 mediaPlayer.mDrmProvisioningInProgress = false;
                 mediaPlayer.mPrepareDrmInProgress = false;
+                if (!succeeded) {
+                    cleanDrmObj();  // cleaning up if it hasn't gone through
+                }
             }
 
             finished = true;
@@ -4714,24 +4814,18 @@
         // the lock is already held by the caller
 
         if (mDrmProvisioningInProgress) {
-            Log.e(TAG, String.format("HandleProvisioninig: Unexpected mDrmProvisioningInProgress"));
+            Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress");
             return false;
         }
 
-        MediaDrm.ProvisionRequest provReq = null;
-        try {
-            MediaDrm drm = new MediaDrm(uuid);
-            provReq = drm.getProvisionRequest();
-            drm.release();
-        } catch (Exception e) {
-            Log.e(TAG, String.format("HandleProvisioninig: getProvisionRequest failed with %s", e));
+        MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
+        if (provReq == null) {
+            Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null.");
             return false;
         }
 
-        Log.v(TAG, String.format("HandleProvisioninig provReq: data %s  url %s",
-                                 (provReq != null) ? provReq.getData() : "-",
-                                 (provReq != null) ? provReq.getDefaultUrl() : "://")
-              );
+        Log.v(TAG, "HandleProvisioninig provReq " +
+                " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
 
         // networking in a background thread
         mDrmProvisioningInProgress = true;
@@ -4749,7 +4843,7 @@
             try {
                 mDrmProvisioningThread.join();
             } catch (Exception e) {
-                Log.w(TAG, String.format("HandleProvisioninig: Thread.join Exception %s", e));
+                Log.w(TAG, "HandleProvisioninig: Thread.join Exception " + e);
             }
             result = mDrmProvisioningThread.succeeded();
             // no longer need the thread
@@ -4761,19 +4855,21 @@
 
     private boolean resumePrepareDrm(UUID uuid)
     {
+        Log.v(TAG, "resumePrepareDrm: uuid: " + uuid);
+
         // mDrmLock is guaranteed to be held
         boolean success = false;
         try {
-            boolean allowOpenSession = true;  // resuming
-            _prepareDrm(getByteArrayFromUUID(uuid),  allowOpenSession ? 1 : 0);
+            // resuming
+            prepareDrm_openSessionStep(uuid);
 
             mDrmUUID = uuid;
             mActiveDrmScheme = true;
 
             success = true;
         } catch (Exception e) {
-            Log.w(TAG, String.format("HandleProvisioninig: " +
-                                     "Thread run _prepareDrm resume failed with %s", e));
+            Log.w(TAG, "HandleProvisioninig: Thread run _prepareDrm resume failed with " + e);
+            // mDrmObj clean up is done by the caller
         }
 
         return success;
@@ -4782,6 +4878,12 @@
     private void resetDrmState()
     {
         synchronized (mDrmLock) {
+            Log.v(TAG, "resetDrmState: " +
+                    " mDrmInfo=" + mDrmInfo +
+                    " mDrmProvisioningThread=" + mDrmProvisioningThread +
+                    " mPrepareDrmInProgress=" + mPrepareDrmInProgress +
+                    " mActiveDrmScheme=" + mActiveDrmScheme);
+
             mDrmInfoResolved = false;
             mDrmInfo = null;
 
@@ -4791,15 +4893,33 @@
                     mDrmProvisioningThread.join();
                 }
                 catch (InterruptedException e) {
-                    Log.w(TAG, String.format("resetDrmState: ProvThread.join Exception %s", e));
+                    Log.w(TAG, "resetDrmState: ProvThread.join Exception " + e);
                 }
                 mDrmProvisioningThread = null;
             }
 
             mPrepareDrmInProgress = false;
+            mActiveDrmScheme = false;
+
+            cleanDrmObj();
         }   // synchronized
     }
 
+    private void cleanDrmObj()
+    {
+        // the caller holds mDrmLock
+        Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId);
+
+        if (mDrmSessionId != null)    {
+            mDrmObj.closeSession(mDrmSessionId);
+            mDrmSessionId = null;
+        }
+        if (mDrmObj != null) {
+            mDrmObj.release();
+            mDrmObj = null;
+        }
+    }
+
     private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
         long msb = uuid.getMostSignificantBits();
         long lsb = uuid.getLeastSignificantBits();
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c941766..636727e 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -58,86 +58,20 @@
 #include "android_util_Binder.h"
 
 // Modular DRM begin
-#include <media/drm/DrmAPI.h>
-
 #define FIND_CLASS(var, className) \
 var = env->FindClass(className); \
 LOG_FATAL_IF(! (var), "Unable to find class " className);
 
-#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
-LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
-
 #define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
 var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
 LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
 
-#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
-var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
-LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
-
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-struct RequestFields {
-    jfieldID data;
-    jfieldID defaultUrl;
-    jfieldID requestType;
-};
-
-struct HashmapFields {
-    jmethodID init;
-    jmethodID get;
-    jmethodID put;
-    jmethodID entrySet;
-};
-
-struct SetFields {
-    jmethodID iterator;
-};
-
-struct IteratorFields {
-    jmethodID next;
-    jmethodID hasNext;
-};
-
-struct EntryFields {
-    jmethodID getKey;
-    jmethodID getValue;
-};
-
-struct KeyTypes {
-    jint kKeyTypeStreaming;
-    jint kKeyTypeOffline;
-    jint kKeyTypeRelease;
-};
-
-static KeyTypes gKeyTypes;
-
-struct KeyRequestTypes {
-    jint kKeyRequestTypeInitial;
-    jint kKeyRequestTypeRenewal;
-    jint kKeyRequestTypeRelease;
-};
-
-static KeyRequestTypes gKeyRequestTypes;
-
 struct StateExceptionFields {
     jmethodID init;
     jclass classId;
 };
 
-struct drm_fields_t {
-    RequestFields keyRequest;
-    HashmapFields hashmap;
-    SetFields set;
-    IteratorFields iterator;
-    EntryFields entry;
-    StateExceptionFields stateException;
-    jclass stringClassId;
-};
-
-static drm_fields_t gFields;
-
+static StateExceptionFields gStateExceptionFields;
 // Modular DRM end
 
 // ----------------------------------------------------------------------------
@@ -1041,50 +975,14 @@
     gBufferingParamsFields.init(env);
 
     // Modular DRM
-    FIND_CLASS(clazz, "android/media/MediaDrm");
-    if (clazz) {
-        jfieldID field;
-        GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
-        gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
-        GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
-        gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
-        GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
-        gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
-
-        env->DeleteLocalRef(clazz);
-    } else {
-        ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
-              "get clazz android/media/MediaDrm");
-    }
-
-    FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
-    if (clazz) {
-        GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
-        GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
-        GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
-
-        jfieldID field;
-        GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
-        gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
-        GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
-        gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
-        GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
-        gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
-
-        env->DeleteLocalRef(clazz);
-    } else {
-        ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
-              "get clazz android/media/MediaDrm$KeyRequest");
-    }
-
     FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
     if (clazz) {
-        GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
-        gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+        GET_METHOD_ID(gStateExceptionFields.init, clazz, "<init>", "(ILjava/lang/String;)V");
+        gStateExceptionFields.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
 
         env->DeleteLocalRef(clazz);
     } else {
-        ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
+        ALOGE("JNI android_media_MediaPlayer_native_init couldn't "
               "get clazz android/media/MediaDrm$MediaDrmStateException");
     }
 
@@ -1315,8 +1213,8 @@
 {
     ALOGE("Illegal DRM state exception: %s (%d)", msg, err);
 
-    jobject exception = env->NewObject(gFields.stateException.classId,
-            gFields.stateException.init, static_cast<int>(err),
+    jobject exception = env->NewObject(gStateExceptionFields.classId,
+            gStateExceptionFields.init, static_cast<int>(err),
             env->NewStringUTF(msg));
     env->Throw(static_cast<jthrowable>(exception));
 }
@@ -1393,18 +1291,6 @@
     return false;
 }
 
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector)
-{
-    size_t length = vector.size();
-    jbyteArray result = env->NewByteArray(length);
-    if (result != NULL) {
-        env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
-    }
-    return result;
-}
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
 static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray)
 {
     Vector<uint8_t> vector;
@@ -1414,74 +1300,8 @@
     return vector;
 }
 
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static String8 JStringToString8(JNIEnv *env, jstring const &jstr)
-{
-    String8 result;
-
-    const char *s = env->GetStringUTFChars(jstr, NULL);
-    if (s) {
-        result = s;
-        env->ReleaseStringUTFChars(jstr, s);
-    }
-    return result;
-}
-
-// TODO: investigate if these can be shared with their MediaDrm counterparts
-static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env,
-                                             jobject &hashMap, bool* pIsOK)
-{
-    jclass clazz = gFields.stringClassId;
-    KeyedVector<String8, String8> keyedVector;
-    *pIsOK = true;
-
-    jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
-    if (entrySet) {
-        jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
-        if (iterator) {
-            jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
-            while (hasNext) {
-                jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
-                if (entry) {
-                    jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
-                    if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
-                        jniThrowException(env, "java/lang/IllegalArgumentException",
-                                          "HashMap key is not a String");
-                        env->DeleteLocalRef(entry);
-                        *pIsOK = false;
-                        break;
-                    }
-                    jstring jkey = static_cast<jstring>(obj);
-
-                    obj = env->CallObjectMethod(entry, gFields.entry.getValue);
-                    if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
-                        jniThrowException(env, "java/lang/IllegalArgumentException",
-                                          "HashMap value is not a String");
-                        env->DeleteLocalRef(entry);
-                        *pIsOK = false;
-                        break;
-                    }
-                    jstring jvalue = static_cast<jstring>(obj);
-
-                    String8 key = JStringToString8(env, jkey);
-                    String8 value = JStringToString8(env, jvalue);
-                    keyedVector.add(key, value);
-
-                    env->DeleteLocalRef(jkey);
-                    env->DeleteLocalRef(jvalue);
-                    hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
-                }
-                env->DeleteLocalRef(entry);
-            }
-            env->DeleteLocalRef(iterator);
-        }
-        env->DeleteLocalRef(entrySet);
-    }
-    return keyedVector;
-}
-
 static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz,
-                    jbyteArray uuidObj, jint mode)
+                    jbyteArray uuidObj, jbyteArray drmSessionIdObj)
 {
     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
     if (mp == NULL) {
@@ -1504,13 +1324,23 @@
         return;
     }
 
-    status_t err = mp->prepareDrm(uuid.array(), mode);
+    Vector<uint8_t> drmSessionId = JByteArrayToVector(env, drmSessionIdObj);
+
+    if (drmSessionId.size() == 0) {
+        jniThrowException(
+                          env,
+                          "java/lang/IllegalArgumentException",
+                          "empty drmSessionId");
+        return;
+    }
+
+    status_t err = mp->prepareDrm(uuid.array(), drmSessionId);
     if (err != OK) {
         if (err == INVALID_OPERATION) {
             jniThrowException(
                               env,
                               "java/lang/IllegalStateException",
-                              "The player is not prepared yet.");
+                              "The player must be in prepared state.");
         } else if (err == ERROR_DRM_CANNOT_HANDLE) {
             jniThrowException(
                               env,
@@ -1536,211 +1366,10 @@
             jniThrowException(
                               env,
                               "java/lang/IllegalStateException",
-                              "The player is not prepared yet.");
+                              "Can not release DRM in an active player state.");
         }
     }
 }
-
-static jobject android_media_MediaPlayer_getKeyRequest(JNIEnv *env, jobject thiz, jbyteArray jscope,
-                       jstring jmimeType, jint jkeyType, jobject joptParams)
-{
-    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return NULL;
-    }
-
-    Vector<uint8_t> scope;
-    if (jscope != NULL) {
-        scope = JByteArrayToVector(env, jscope);
-    }
-
-    String8 mimeType;
-    if (jmimeType != NULL) {
-        mimeType = JStringToString8(env, jmimeType);
-    }
-
-    DrmPlugin::KeyType keyType;
-    if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
-        keyType = DrmPlugin::kKeyType_Streaming;
-    } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
-        keyType = DrmPlugin::kKeyType_Offline;
-    } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
-        keyType = DrmPlugin::kKeyType_Release;
-    } else {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
-        return NULL;
-    }
-
-    KeyedVector<String8, String8> optParams;
-    if (joptParams != NULL) {
-        bool isOK;
-        optParams = HashMapToKeyedVector(env, joptParams, &isOK);
-        if (!isOK) {
-            return NULL;
-        }
-    }
-
-    Vector<uint8_t> request;
-    String8 defaultUrl;
-    DrmPlugin::KeyRequestType keyRequestType;
-    status_t err = mp->getKeyRequest(scope, mimeType, keyType, optParams, request, defaultUrl,
-                           keyRequestType);
-
-    if (throwDrmExceptionAsNecessary(env, err, "Failed to get key request")) {
-        return NULL;
-    }
-
-    ALOGV("JNI getKeyRequest err %d  request %d  url %s  keyReqType %d",
-          err, (int)request.size(), defaultUrl.string(), (int)keyRequestType);
-
-    // Fill out return obj
-    jclass clazz;
-    FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
-
-    jobject keyObj = NULL;
-
-    if (clazz) {
-        keyObj = env->AllocObject(clazz);
-        jbyteArray jrequest = VectorToJByteArray(env, request);
-        env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
-
-        jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
-        env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
-
-        switch (keyRequestType) {
-        case DrmPlugin::kKeyRequestType_Initial:
-            env->SetIntField(keyObj, gFields.keyRequest.requestType,
-                         gKeyRequestTypes.kKeyRequestTypeInitial);
-            break;
-        case DrmPlugin::kKeyRequestType_Renewal:
-            env->SetIntField(keyObj, gFields.keyRequest.requestType,
-                         gKeyRequestTypes.kKeyRequestTypeRenewal);
-            break;
-        case DrmPlugin::kKeyRequestType_Release:
-            env->SetIntField(keyObj, gFields.keyRequest.requestType,
-                         gKeyRequestTypes.kKeyRequestTypeRelease);
-            break;
-        default:
-            throwDrmStateException(env, "MediaPlayer/DRM plugin failure: unknown "
-                    "key request type", ERROR_DRM_UNKNOWN);
-            break;
-        }
-    }
-
-    return keyObj;
-}
-
-static jbyteArray android_media_MediaPlayer_provideKeyResponse(JNIEnv *env, jobject thiz,
-                          jbyteArray jreleaseKeySetId, jbyteArray jresponse)
-{
-    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return NULL;
-    }
-
-    if (jresponse == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "key response is null");
-        return NULL;
-    }
-
-    Vector<uint8_t> releaseKeySetId;
-    if (jreleaseKeySetId != NULL) {
-        releaseKeySetId = JByteArrayToVector(env, jreleaseKeySetId);
-    }
-
-    Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
-    Vector<uint8_t> keySetId;
-
-    status_t err = mp->provideKeyResponse(releaseKeySetId, response, keySetId);
-
-    if (throwDrmExceptionAsNecessary(env, err, "Failed to handle key response")) {
-        return NULL;
-    }
-    return VectorToJByteArray(env, keySetId);
-}
-
-static void android_media_MediaPlayer_restoreKeys(JNIEnv *env, jobject thiz, jbyteArray jkeySetId)
-{
-     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
-     if (mp == NULL) {
-         jniThrowException(env, "java/lang/IllegalStateException", NULL);
-         return;
-     }
-
-    if (jkeySetId == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
-        return;
-    }
-
-    Vector<uint8_t> keySetId;
-    keySetId = JByteArrayToVector(env, jkeySetId);
-
-    status_t err = mp->restoreKeys(keySetId);
-
-    ALOGV("JNI restoreKeys err %d ", err);
-    throwDrmExceptionAsNecessary(env, err, "Failed to restore keys");
-}
-
-static jstring android_media_MediaPlayer_getDrmPropertyString(JNIEnv *env, jobject thiz,
-                       jstring jname)
-{
-    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return NULL;
-    }
-
-    if (jname == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException",
-                "property name String is null");
-        return NULL;
-    }
-
-    String8 name = JStringToString8(env, jname);
-    String8 value;
-
-    status_t err = mp->getDrmPropertyString(name, value);
-
-    ALOGV("JNI getPropertyString err %d", err);
-
-    if (throwDrmExceptionAsNecessary(env, err, "Failed to get property")) {
-        return NULL;
-    }
-
-    return env->NewStringUTF(value.string());
-}
-
-static void android_media_MediaPlayer_setDrmPropertyString(JNIEnv *env, jobject thiz,
-                    jstring jname, jstring jvalue)
-{
-    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
-    if (mp == NULL) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return;
-    }
-
-    if (jname == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException",
-                "property name String is null");
-        return;
-    }
-
-    if (jvalue == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException",
-                "property value String is null");
-        return;
-    }
-
-    String8 name = JStringToString8(env, jname);
-    String8 value = JStringToString8(env, jvalue);
-
-    status_t err = mp->setDrmPropertyString(name, value);
-
-    ALOGV("JNI setPropertyString err %d", err);
-    throwDrmExceptionAsNecessary(env, err, "Failed to set property");
-}
 // Modular DRM end
 // ----------------------------------------------------------------------------
 
@@ -1802,14 +1431,8 @@
                             "(I)Landroid/media/VolumeShaper$State;",
                                                                 (void *)android_media_MediaPlayer_getVolumeShaperState},
     // Modular DRM
-    { "_prepareDrm", "([BI)V",                                  (void *)android_media_MediaPlayer_prepareDrm },
+    { "_prepareDrm", "([B[B)V",                                 (void *)android_media_MediaPlayer_prepareDrm },
     { "_releaseDrm", "()V",                                     (void *)android_media_MediaPlayer_releaseDrm },
-    { "_getKeyRequest", "([BLjava/lang/String;ILjava/util/Map;)" "Landroid/media/MediaDrm$KeyRequest;",
-        (void *)android_media_MediaPlayer_getKeyRequest },
-    { "_provideKeyResponse", "([B[B)[B",                        (void *)android_media_MediaPlayer_provideKeyResponse },
-    { "_getDrmPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_MediaPlayer_getDrmPropertyString },
-    { "_setDrmPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_setDrmPropertyString },
-    { "_restoreKeys", "([B)V",                                  (void *)android_media_MediaPlayer_restoreKeys },
 };
 
 // This function only registers the native methods
diff --git a/obex/javax/obex/ServerSession.java b/obex/javax/obex/ServerSession.java
index acee5dd..3831cf7 100644
--- a/obex/javax/obex/ServerSession.java
+++ b/obex/javax/obex/ServerSession.java
@@ -658,6 +658,11 @@
          */
         byte[] sendData = new byte[totalLength];
         int maxRxLength = ObexHelper.getMaxRxPacketSize(mTransport);
+        if (maxRxLength > mMaxPacketLength) {
+            if(V) Log.v(TAG,"Set maxRxLength to min of maxRxServrLen:" + maxRxLength +
+                    " and MaxNegotiated from Client: " + mMaxPacketLength);
+            maxRxLength = mMaxPacketLength;
+        }
         sendData[0] = (byte)code;
         sendData[1] = length[2];
         sendData[2] = length[3];
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index 8a970da..25127ef 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -33,7 +33,6 @@
 import android.widget.ListView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
-import android.widget.Toast;
 
 public class DeviceChooserActivity extends Activity {
 
@@ -129,12 +128,9 @@
     }
 
     protected void onPairTapped(BluetoothDevice selectedDevice) {
+        getService().onDeviceSelected();
         setResult(RESULT_OK,
                 new Intent().putExtra(CompanionDeviceManager.EXTRA_DEVICE, selectedDevice));
         finish();
     }
-
-    private void toast(String msg) {
-        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
-    }
 }
\ No newline at end of file
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index ccbee2a..11c722d 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -32,16 +32,15 @@
 import android.bluetooth.le.ScanResult;
 import android.bluetooth.le.ScanSettings;
 import android.companion.AssociationRequest;
-import android.companion.BluetoothDeviceFilterUtils;
 import android.companion.BluetoothLEDeviceFilter;
-import android.companion.ICompanionDeviceManagerService;
-import android.companion.IOnAssociateCallback;
+import android.companion.ICompanionDeviceDiscoveryService;
+import android.companion.ICompanionDeviceDiscoveryServiceCallback;
+import android.companion.IFindDeviceCallback;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Color;
-import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -70,21 +69,25 @@
     List<BluetoothDevice> mDevicesFound;
     BluetoothDevice mSelectedDevice;
     DevicesAdapter mDevicesAdapter;
-    IOnAssociateCallback mCallback;
+    IFindDeviceCallback mFindCallback;
+    ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
     String mCallingPackage;
 
-    private final ICompanionDeviceManagerService mBinder =
-            new ICompanionDeviceManagerService.Stub() {
+    private final ICompanionDeviceDiscoveryService mBinder =
+            new ICompanionDeviceDiscoveryService.Stub() {
         @Override
         public void startDiscovery(AssociationRequest request,
-                IOnAssociateCallback callback,
-                String callingPackage) throws RemoteException {
+                String callingPackage,
+                IFindDeviceCallback findCallback,
+                ICompanionDeviceDiscoveryServiceCallback serviceCallback) {
             if (DEBUG) {
                 Log.i(LOG_TAG,
-                        "startDiscovery() called with: filter = [" + request + "], callback = ["
-                                + callback + "]");
+                        "startDiscovery() called with: filter = [" + request
+                                + "], findCallback = [" + findCallback + "]"
+                                + "], serviceCallback = [" + serviceCallback + "]");
             }
-            mCallback = callback;
+            mFindCallback = findCallback;
+            mServiceCallback = serviceCallback;
             mCallingPackage = callingPackage;
             DeviceDiscoveryService.this.startDiscovery(request);
         }
@@ -171,6 +174,14 @@
         return super.onUnbind(intent);
     }
 
+    public void onDeviceSelected() {
+        try {
+            mServiceCallback.onDeviceSelected(mCallingPackage, getUserId());
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Error reporting selected device");
+        }
+    }
+
     private void stopScan() {
         if (DEBUG) Log.i(LOG_TAG, "stopScan() called");
         mBluetoothAdapter.cancelDiscovery();
@@ -205,7 +216,7 @@
     //TODO also, on timeout -> call onFailure
     private void onReadyToShowUI() {
         try {
-            mCallback.onSuccess(PendingIntent.getActivity(
+            mFindCallback.onSuccess(PendingIntent.getActivity(
                     this, 0,
                     new Intent(this, DeviceChooserActivity.class),
                     PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 499b6ae..136f17e 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -227,7 +227,4 @@
 
     <!--  default setting for Settings.System.END_BUTTON_BEHAVIOR : END_BUTTON_BEHAVIOR_SLEEP -->
     <integer name="def_end_button_behavior">0x2</integer>
-
-    <!--Default settings for network recommendations. -->
-    <string name="def_network_recommendations_package" translatable="false">com.android.networkrecommendation</string>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index edcb9b5..d5787e6 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3182,24 +3182,7 @@
                 }
 
                 if (currentVersion == 138) {
-                    // Version 139: Applying the default to NETWORK_RECOMMENDATIONS_PACKAGE
-                    if (userId == UserHandle.USER_SYSTEM) {
-                        final SettingsState globalSettings = getGlobalSettingsLocked();
-                        final String defaultAppPackage = getContext().getResources()
-                                .getString(R.string.def_network_recommendations_package);
-
-                        // Set the network recommendations package name
-                        globalSettings.insertSettingLocked(
-                                Global.NETWORK_RECOMMENDATIONS_PACKAGE,
-                                defaultAppPackage, null, true,
-                                SettingsState.SYSTEM_PACKAGE_NAME);
-
-                        // Clear the scorer setting since it's no longer needed.
-                        globalSettings.insertSettingLocked(
-                                Global.NETWORK_SCORER_APP,
-                                null, null, true,
-                                SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
+                    // Version 139: Removed.
                     currentVersion = 139;
                 }
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d4c7c7a..2e115ab 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -154,8 +154,8 @@
             android:name=".BugreportReceiver"
             android:permission="android.permission.DUMP">
             <intent-filter>
-                <action android:name="android.intent.action.BUGREPORT_STARTED" />
-                <action android:name="android.intent.action.BUGREPORT_FINISHED" />
+                <action android:name="com.android.internal.intent.action.BUGREPORT_STARTED" />
+                <action android:name="com.android.internal.intent.action.BUGREPORT_FINISHED" />
             </intent-filter>
         </receiver>
 
@@ -163,7 +163,7 @@
             android:name=".RemoteBugreportReceiver"
             android:permission="android.permission.DUMP">
             <intent-filter>
-                <action android:name="android.intent.action.REMOTE_BUGREPORT_FINISHED" />
+                <action android:name="com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED" />
             </intent-filter>
         </receiver>
 
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 17d0a09..12d0c03 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -133,10 +133,12 @@
     private static final String AUTHORITY = "com.android.shell";
 
     // External intents sent by dumpstate.
-    static final String INTENT_BUGREPORT_STARTED = "android.intent.action.BUGREPORT_STARTED";
-    static final String INTENT_BUGREPORT_FINISHED = "android.intent.action.BUGREPORT_FINISHED";
+    static final String INTENT_BUGREPORT_STARTED =
+            "com.android.internal.intent.action.BUGREPORT_STARTED";
+    static final String INTENT_BUGREPORT_FINISHED =
+            "com.android.internal.intent.action.BUGREPORT_FINISHED";
     static final String INTENT_REMOTE_BUGREPORT_FINISHED =
-            "android.intent.action.REMOTE_BUGREPORT_FINISHED";
+            "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
 
     // Internal intents used on notification actions.
     static final String INTENT_BUGREPORT_CANCEL = "android.intent.action.BUGREPORT_CANCEL";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 3648a06..cb4306f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -462,6 +462,7 @@
         updateBackgroundForGroupState();
         updateClickAndFocus();
         if (mNotificationParent != null) {
+            setOverrideTintColor(NO_COLOR, 0.0f);
             mNotificationParent.updateBackgroundForGroupState();
         }
         updateIconVisibilities();
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 36dee49..8d2f0c3 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3416,6 +3416,19 @@
     // ACTION: Settings advanced button is expanded
     ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND = 834;
 
+    // ACTION: Logs the number of times the saved network evaluator was used to
+    // recommend a wifi network
+    WIFI_NETWORK_RECOMMENDATION_SAVED_NETWORK_EVALUATOR = 835;
+
+    // ACTION: Logs the number of times the recommended network evaluator was
+    // used to recommend a wifi network
+    WIFI_NETWORK_RECOMMENDATION_RECOMMENDED_NETWORK_EVALUATOR = 836;
+
+    // ACTION: Logs the number of times a recommended network was resulted in a
+    // successful connection
+    // VALUE: true if the connection was successful, false if the connection failed
+    WIFI_NETWORK_RECOMMENDATION_CONNECTION_SUCCESS = 837;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 13e6ae0..8fbc520 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2400,14 +2400,19 @@
         }
         final long oldToken = Binder.clearCallingIdentity();
         try {
+            List<Integer> operationsToCancel = new ArrayList<>();
             synchronized (mCurrentOpLock) {
                 for (int i = 0; i < mCurrentOperations.size(); i++) {
                     Operation op = mCurrentOperations.valueAt(i);
                     int token = mCurrentOperations.keyAt(i);
                     if (op.type == OP_TYPE_BACKUP) {
-                        handleCancel(token, true /* cancelAll */);
+                        operationsToCancel.add(token);
                     }
                 }
+
+                for (Integer token : operationsToCancel) {
+                    handleCancel(token, true /* cancelAll */);
+                }
             }
 
             // We don't want the backup jobs to kick in any time soon.
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 719a64e..fe0b840 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4166,7 +4166,7 @@
         }
         ensureRequestableCapabilities(networkCapabilities);
 
-        if (timeoutMs < 0 || timeoutMs > ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS) {
+        if (timeoutMs < 0) {
             throw new IllegalArgumentException("Bad timeout specified");
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a73eb18..c2c24b3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -556,7 +556,7 @@
 
     // Intent sent when remote bugreport collection has been completed
     private static final String INTENT_REMOTE_BUGREPORT_FINISHED =
-            "android.intent.action.REMOTE_BUGREPORT_FINISHED";
+            "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
 
     // Used to indicate that an app transition should be animated.
     static final boolean ANIMATE = true;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 1b19382..082b6b5 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -22,7 +22,6 @@
 import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -47,7 +46,6 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
 import static android.os.Build.VERSION_CODES.HONEYCOMB;
 import static android.os.Build.VERSION_CODES.O;
@@ -85,7 +83,6 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
@@ -290,8 +287,8 @@
     /**
      * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
      */
-    private final Configuration mTmpGlobalConfig = new Configuration();
-    private final Configuration mTmpTaskConfig = new Configuration();
+    private final Configuration mTmpConfig1 = new Configuration();
+    private final Configuration mTmpConfig2 = new Configuration();
 
     private static String startingWindowStateToString(int state) {
         switch (state) {
@@ -1975,13 +1972,13 @@
         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                 "Ensuring correct configuration: " + this);
 
-        // Short circuit: if the two configurations are equal (the common case), then there is
-        // nothing to do.
-        final Configuration newGlobalConfig = service.getGlobalConfiguration();
-        final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
-        if (mLastReportedConfiguration.equals(newGlobalConfig)
-                && mLastReportedOverrideConfiguration.equals(newTaskMergedOverrideConfig)
-                && !forceNewConfig) {
+        // Short circuit: if the two full configurations are equal (the common case), then there is
+        // nothing to do.  We test the full configuration instead of the global and merged override
+        // configurations because there are cases (like moving a task to the pinned stack) where
+        // the combine configurations are equal, but would otherwise differ in the override config
+        mTmpConfig1.setTo(mLastReportedConfiguration);
+        mTmpConfig1.updateFrom(mLastReportedOverrideConfiguration);
+        if (task.getConfiguration().equals(mTmpConfig1) && !forceNewConfig) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Configuration unchanged in " + this);
             return true;
@@ -1997,14 +1994,16 @@
 
         // Okay we now are going to make this activity have the new config.
         // But then we need to figure out how it needs to deal with that.
-        mTmpGlobalConfig.setTo(mLastReportedConfiguration);
-        mTmpTaskConfig.setTo(mLastReportedOverrideConfiguration);
+        final Configuration newGlobalConfig = service.getGlobalConfiguration();
+        final Configuration newTaskMergedOverrideConfig = task.getMergedOverrideConfiguration();
+        mTmpConfig1.setTo(mLastReportedConfiguration);
+        mTmpConfig2.setTo(mLastReportedOverrideConfiguration);
         mLastReportedConfiguration.setTo(newGlobalConfig);
         mLastReportedOverrideConfiguration.setTo(newTaskMergedOverrideConfig);
 
         int taskChanges = getTaskConfigurationChanges(this, newTaskMergedOverrideConfig,
-                mTmpTaskConfig);
-        final int changes = mTmpGlobalConfig.diff(newGlobalConfig) | taskChanges;
+                mTmpConfig2);
+        final int changes = mTmpConfig1.diff(newGlobalConfig) | taskChanges;
         if (changes == 0 && !forceNewConfig) {
             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                     "Configuration no differences in " + this);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7c24604..f75ce25 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2507,7 +2507,7 @@
                 if (!next.hasBeenLaunched) {
                     next.hasBeenLaunched = true;
                 } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
-                        mStackSupervisor.isFrontStack(lastStack)) {
+                        mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
                     next.showStartingWindow(null /* prev */, false /* newTask */,
                             false /* taskSwitch */);
                 }
@@ -4354,7 +4354,7 @@
         // If we have a watcher, preflight the move before committing to it.  First check
         // for *other* available tasks, but if none are available, then try again allowing the
         // current task to be selected.
-        if (mStackSupervisor.isFrontStack(this) && mService.mController != null) {
+        if (mStackSupervisor.isFrontStackOnDisplay(this) && mService.mController != null) {
             ActivityRecord next = topRunningActivityLocked(null, taskId);
             if (next == null) {
                 next = topRunningActivityLocked(null, 0);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 95734a4..4a29872 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -624,11 +624,6 @@
         return stack == mFocusedStack;
     }
 
-    /** The top most stack. */
-    boolean isFrontStack(ActivityStack stack) {
-        return isFrontOfStackList(stack, mHomeStack.mStacks);
-    }
-
     /** The top most stack on its display. */
     boolean isFrontStackOnDisplay(ActivityStack stack) {
         return isFrontOfStackList(stack, stack.mActivityContainer.mActivityDisplay.mStacks);
@@ -1103,13 +1098,21 @@
         }
 
         // Look in other non-focused and non-home stacks.
-        final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
-        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
-            final ActivityStack stack = stacks.get(stackNdx);
-            if (stack != focusedStack && isFrontStack(stack) && stack.isFocusable()) {
-                r = stack.topRunningActivityLocked();
-                if (r != null) {
-                    return r;
+        mWindowManager.getDisplaysInFocusOrder(mTmpOrderedDisplayIds);
+
+        for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
+            final int displayId = mTmpOrderedDisplayIds.get(i);
+            final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
+            if (stacks == null) {
+                continue;
+            }
+            for (int j = stacks.size() - 1; j >= 0; --j) {
+                final ActivityStack stack = stacks.get(j);
+                if (stack != focusedStack && isFrontStackOnDisplay(stack) && stack.isFocusable()) {
+                    r = stack.topRunningActivityLocked();
+                    if (r != null) {
+                        return r;
+                    }
                 }
             }
         }
@@ -2676,7 +2679,7 @@
         // In some cases the focused stack isn't the front stack. E.g. pinned stack.
         // Whenever we are moving the top activity from the front stack we want to make sure to move
         // the stack to the front.
-        final boolean wasFront = isFrontStack(prevStack)
+        final boolean wasFront = isFrontStackOnDisplay(prevStack)
                 && (prevStack.topRunningActivityLocked() == r);
 
         if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 520d4ee..f8645d6 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -35,7 +35,6 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
-import android.graphics.GraphicBuffer;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Debug;
@@ -52,6 +51,7 @@
 import com.android.internal.util.XmlUtils;
 
 import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.StackWindowController;
 import com.android.server.wm.TaskWindowContainerController;
 import com.android.server.wm.TaskWindowContainerListener;
 
@@ -278,7 +278,6 @@
     private final Rect mTmpStableBounds = new Rect();
     private final Rect mTmpNonDecorBounds = new Rect();
     private final Rect mTmpRect = new Rect();
-    private final Rect mTmpRect2 = new Rect();
 
     // Last non-fullscreen bounds the task was launched in or resized to.
     // The information is persisted and used to determine the appropriate stack to launch the
@@ -1838,66 +1837,38 @@
         return !mTmpConfig.equals(newConfig);
     }
 
-    private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
-                                        boolean overrideWidth, boolean overrideHeight) {
-        mTmpRect2.set(inInsetBounds);
-        mService.mWindowManager.subtractNonDecorInsets(mTmpRect2);
-        int leftInset = mTmpRect2.left - inInsetBounds.left;
-        int topInset = mTmpRect2.top - inInsetBounds.top;
-        int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
-        int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
-        inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
-    }
-
-    private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds,
-                                      boolean overrideWidth, boolean overrideHeight) {
-        mTmpRect2.set(inInsetBounds);
-        mService.mWindowManager.subtractStableInsets(mTmpRect2);
-        int leftInset = mTmpRect2.left - inInsetBounds.left;
-        int topInset = mTmpRect2.top - inInsetBounds.top;
-        int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
-        int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
-        inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
-    }
-
     /** Clears passed config and fills it with new override values. */
     private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
             boolean overrideWidth, boolean overrideHeight) {
         mTmpNonDecorBounds.set(bounds);
         mTmpStableBounds.set(bounds);
 
-        final Configuration parentConfig = getParent().getConfiguration();
         config.unset();
+        final Configuration parentConfig = getParent().getConfiguration();
         final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
-        final boolean isFloatingTask = mStack != null && StackId.tasksAreFloating(mStack.mStackId);
-        if (isFloatingTask) {
-            // Floating tasks should not be resized to the screen's bounds.
-            config.screenWidthDp = (int) (mTmpStableBounds.width() / density);
-            config.screenHeightDp = (int) (mTmpStableBounds.height() / density);
-        } else {
-            // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen area,
-            // i.e. the screen area without the system bars.
-            // Additionally task dimensions should not be bigger than its parents dimensions.
-            subtractNonDecorInsets(mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
-                    overrideWidth, overrideHeight);
-            subtractStableInsets(mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
-                    overrideWidth, overrideHeight);
-            config.screenWidthDp = Math.min(
-                    (int) (mTmpStableBounds.width() / density), parentConfig.screenWidthDp);
-            config.screenHeightDp = Math.min(
-                    (int) (mTmpStableBounds.height() / density), parentConfig.screenHeightDp);
-        }
 
         // TODO: Orientation?
         config.orientation = (config.screenWidthDp <= config.screenHeightDp)
                 ? Configuration.ORIENTATION_PORTRAIT
                 : Configuration.ORIENTATION_LANDSCAPE;
+        if (mStack != null) {
+            final StackWindowController stackController = mStack.getWindowContainerController();
+            stackController.adjustConfigurationForBounds(bounds, insetBounds,
+                    mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
+                    config, parentConfig);
+        } else {
+            // No stack, give some default values
+            config.smallestScreenWidthDp =
+                    mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
+            config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
+            Slog.wtf(TAG, "Expected stack when caclulating override config");
+        }
 
         // For calculating screen layout, we need to use the non-decor inset screen area for the
         // calculation for compatibility reasons, i.e. screen area without system bars that could
         // never go away in Honeycomb.
-        final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
-        final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
+        final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
+        final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
         // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
         // calculation with partial default.
         final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
@@ -1905,8 +1876,6 @@
         final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
         config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
 
-        config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
-                insetBounds != null ? insetBounds : bounds);
     }
 
     /**
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 17b005d..8bc72de 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -481,12 +481,6 @@
         public void onLost(Network network) {
             releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
         }
-
-        @Override
-        public void onUnavailable() {
-            // timeout, it was not possible to establish the required connection
-            releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
-        }
     };
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -877,8 +871,7 @@
         NetworkRequest request = requestBuilder.build();
         mConnMgr.requestNetwork(
                 request,
-                mSuplConnectivityCallback,
-                ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS);
+                mSuplConnectivityCallback);
     }
 
     private void handleReleaseSuplConnection(int agpsDataConnStatus) {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 98177fe..407262b 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -93,7 +93,6 @@
     private final SessionManagerImpl mSessionManagerImpl;
     private final MediaSessionStack mPriorityStack;
 
-    private final ArrayList<MediaSessionRecord> mAllSessions = new ArrayList<MediaSessionRecord>();
     private final SparseArray<UserRecord> mUserRecords = new SparseArray<UserRecord>();
     private final ArrayList<SessionsListenerRecord> mSessionsListeners
             = new ArrayList<SessionsListenerRecord>();
@@ -145,7 +144,8 @@
 
     public void updateSession(MediaSessionRecord record) {
         synchronized (mLock) {
-            if (!mAllSessions.contains(record)) {
+            UserRecord user = mUserRecords.get(record.getUserId());
+            if (user == null || !user.mSessions.contains(record)) {
                 Log.d(TAG, "Unknown session updated. Ignoring.");
                 return;
             }
@@ -171,7 +171,8 @@
     public void onSessionPlaystateChange(MediaSessionRecord record, int oldState, int newState) {
         boolean updateSessions = false;
         synchronized (mLock) {
-            if (!mAllSessions.contains(record)) {
+            UserRecord user = mUserRecords.get(record.getUserId());
+            if (user == null || !user.mSessions.contains(record)) {
                 Log.d(TAG, "Unknown session changed playback state. Ignoring.");
                 return;
             }
@@ -184,7 +185,8 @@
 
     public void onSessionPlaybackTypeChanged(MediaSessionRecord record) {
         synchronized (mLock) {
-            if (!mAllSessions.contains(record)) {
+            UserRecord user = mUserRecords.get(record.getUserId());
+            if (user == null || !user.mSessions.contains(record)) {
                 Log.d(TAG, "Unknown session changed playback type. Ignoring.");
                 return;
             }
@@ -318,7 +320,6 @@
         }
 
         mPriorityStack.removeSession(session);
-        mAllSessions.remove(session);
 
         try {
             session.getCallback().asBinder().unlinkToDeath(session, 0);
@@ -455,7 +456,6 @@
             throw new RuntimeException("Media Session owner died prematurely.", e);
         }
 
-        mAllSessions.add(session);
         mPriorityStack.addSession(session, mCurrentUserIdList.contains(userId));
         user.addSessionLocked(session);
 
@@ -1087,16 +1087,10 @@
 
             synchronized (mLock) {
                 pw.println(mSessionsListeners.size() + " sessions listeners.");
-                int count = mAllSessions.size();
-                pw.println(count + " Sessions:");
-                for (int i = 0; i < count; i++) {
-                    mAllSessions.get(i).dump(pw, "");
-                    pw.println();
-                }
                 mPriorityStack.dump(pw, "");
 
                 pw.println("User Records:");
-                count = mUserRecords.size();
+                int count = mUserRecords.size();
                 for (int i = 0; i < count; i++) {
                     UserRecord user = mUserRecords.get(mUserRecords.keyAt(i));
                     user.dumpLocked(pw, "");
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 9da94b3..06b6f66 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.app.DownloadManager;
 import android.app.admin.DevicePolicyManager;
+import android.companion.CompanionDeviceManager;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -673,6 +674,16 @@
                     && doesPackageSupportRuntimePermissions(storageManagerPckg)) {
                 grantRuntimePermissionsLPw(storageManagerPckg, STORAGE_PERMISSIONS, true, userId);
             }
+
+            // Companion devices
+            PackageParser.Package companionDeviceDiscoveryPackage = getSystemPackageLPr(
+                    CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME);
+            if (companionDeviceDiscoveryPackage != null
+                    && doesPackageSupportRuntimePermissions(companionDeviceDiscoveryPackage)) {
+                grantRuntimePermissionsLPw(companionDeviceDiscoveryPackage,
+                        LOCATION_PERMISSIONS, true, userId);
+            }
+
             mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
         }
     }
diff --git a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
index b704eb1..3c73c88 100644
--- a/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/TzDataInstallReceiver.java
@@ -20,7 +20,7 @@
 
 import java.io.File;
 import java.io.IOException;
-import libcore.tzdata.update2.TimeZoneBundleInstaller;
+import libcore.tzdata.update2.TimeZoneDistroInstaller;
 
 /**
  * An install receiver responsible for installing timezone data updates.
@@ -34,14 +34,14 @@
     private static final String UPDATE_DIR_NAME = TZ_DATA_DIR.getPath() + "/updates/";
     private static final String UPDATE_METADATA_DIR_NAME = "metadata/";
     private static final String UPDATE_VERSION_FILE_NAME = "version";
-    private static final String UPDATE_CONTENT_FILE_NAME = "tzdata_bundle.zip";
+    private static final String UPDATE_CONTENT_FILE_NAME = "tzdata_distro.zip";
 
-    private final TimeZoneBundleInstaller installer;
+    private final TimeZoneDistroInstaller installer;
 
     public TzDataInstallReceiver() {
         super(UPDATE_DIR_NAME, UPDATE_CONTENT_FILE_NAME, UPDATE_METADATA_DIR_NAME,
                 UPDATE_VERSION_FILE_NAME);
-        installer = new TimeZoneBundleInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR);
+        installer = new TimeZoneDistroInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 0a92a81..75a79fd 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -152,11 +152,6 @@
     int getSmallestWidthDpForBounds(Rect bounds) {
         final DisplayInfo di = mDisplayContent.getDisplayInfo();
 
-        // If the bounds are fullscreen, return the value of the fullscreen configuration
-        if (bounds == null || (bounds.left == 0 && bounds.top == 0
-                && bounds.right == di.logicalWidth && bounds.bottom == di.logicalHeight)) {
-            return mDisplayContent.getConfiguration().smallestScreenWidthDp;
-        }
         final int baseDisplayWidth = mDisplayContent.mBaseDisplayWidth;
         final int baseDisplayHeight = mDisplayContent.mBaseDisplayHeight;
         int minWidth = Integer.MAX_VALUE;
@@ -185,7 +180,7 @@
                     mTmpRect2.width(), mTmpRect2.height(), getContentWidth());
             mService.mPolicy.getStableInsetsLw(rotation, mTmpRect2.width(), mTmpRect2.height(),
                     mTmpRect3);
-            mService.subtractInsets(mTmpRect2, mTmpRect3, mTmpRect);
+            mService.intersectDisplayInsetBounds(mTmpRect2, mTmpRect3, mTmpRect);
             minWidth = Math.min(mTmpRect.width(), minWidth);
         }
         return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 36d07e0..142f69a 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+
+import android.app.ActivityManager.StackId;
 import android.app.RemoteAction;
 import android.content.res.Configuration;
 import android.graphics.Rect;
@@ -24,6 +27,8 @@
 import android.os.Message;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.DisplayInfo;
+
 import com.android.server.UiThread;
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -48,6 +53,12 @@
 
     private final H mHandler;
 
+    // Temp bounds only used in adjustConfigurationForBounds()
+    private final Rect mTmpRect = new Rect();
+    private final Rect mTmpStableInsets = new Rect();
+    private final Rect mTmpNonDecorInsets = new Rect();
+    private final Rect mTmpDisplayBounds = new Rect();
+
     public StackWindowController(int stackId, StackWindowListener listener,
             int displayId, boolean onTop, Rect outBounds) {
         this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance());
@@ -289,6 +300,107 @@
         }
     }
 
+    /**
+     * Adjusts the screen size in dp's for the {@param config} for the given params.
+     */
+    public void adjustConfigurationForBounds(Rect bounds, Rect insetBounds,
+            Rect nonDecorBounds, Rect stableBounds, boolean overrideWidth,
+            boolean overrideHeight, float density, Configuration config,
+            Configuration parentConfig) {
+        synchronized (mWindowMap) {
+            final TaskStack stack = mContainer;
+            final DisplayContent displayContent = stack.getDisplayContent();
+            final DisplayInfo di = displayContent.getDisplayInfo();
+
+            // Get the insets and display bounds
+            mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                    mTmpStableInsets);
+            mService.mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                    mTmpNonDecorInsets);
+            mTmpDisplayBounds.set(0, 0, di.logicalWidth, di.logicalHeight);
+
+            int width;
+            int height;
+            if (StackId.tasksAreFloating(mStackId)) {
+                // Floating tasks should not be resized to the screen's bounds.
+
+                if (bounds.width() == mTmpDisplayBounds.width() &&
+                        bounds.height() == mTmpDisplayBounds.height()) {
+                    // If the bounds we are animating is the same as the fullscreen stack
+                    // dimensions, then apply the same inset calculations that we normally do for
+                    // the fullscreen stack, without intersecting it with the display bounds
+                    stableBounds.inset(mTmpStableInsets);
+                    nonDecorBounds.inset(mTmpNonDecorInsets);
+                }
+                width = (int) (stableBounds.width() / density);
+                height = (int) (stableBounds.height() / density);
+            } else {
+                // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
+                // area, i.e. the screen area without the system bars.
+                // Additionally task dimensions should not be bigger than its parents dimensions.
+                // The non decor inset are areas that could never be removed in Honeycomb. See
+                // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
+                intersectDisplayBoundsExcludeInsets(nonDecorBounds,
+                        insetBounds != null ? insetBounds : bounds, mTmpNonDecorInsets,
+                        mTmpDisplayBounds, overrideWidth, overrideHeight);
+                intersectDisplayBoundsExcludeInsets(stableBounds,
+                        insetBounds != null ? insetBounds : bounds, mTmpStableInsets,
+                        mTmpDisplayBounds, overrideWidth, overrideHeight);
+                width = Math.min((int) (stableBounds.width() / density),
+                        parentConfig.screenWidthDp);
+                height = Math.min((int) (stableBounds.height() / density),
+                        parentConfig.screenHeightDp);
+            }
+
+            config.screenWidthDp = width;
+            config.screenHeightDp = height;
+            config.smallestScreenWidthDp = getSmallestWidthForTaskBounds(
+                    insetBounds != null ? insetBounds : bounds, density);
+        }
+    }
+
+    /**
+     * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
+     * inset areas.
+     *
+     * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
+     */
+    private void intersectDisplayBoundsExcludeInsets(Rect inOutBounds, Rect inInsetBounds,
+            Rect stableInsets, Rect displayBounds, boolean overrideWidth, boolean overrideHeight) {
+        mTmpRect.set(inInsetBounds);
+        mService.intersectDisplayInsetBounds(displayBounds, stableInsets, mTmpRect);
+        int leftInset = mTmpRect.left - inInsetBounds.left;
+        int topInset = mTmpRect.top - inInsetBounds.top;
+        int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect.right;
+        int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect.bottom;
+        inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
+    }
+
+    /**
+     * Calculates the smallest width for a task given the {@param bounds}.
+     *
+     * @return the smallest width to be used in the Configuration, in dips
+     */
+    private int getSmallestWidthForTaskBounds(Rect bounds, float density) {
+        final DisplayContent displayContent = mContainer.getDisplayContent();
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+
+        if (bounds == null || (bounds.width() == displayInfo.logicalWidth &&
+                bounds.height() == displayInfo.logicalHeight)) {
+            // If the bounds are fullscreen, return the value of the fullscreen configuration
+            return displayContent.getConfiguration().smallestScreenWidthDp;
+        } else if (StackId.tasksAreFloating(mStackId)) {
+            // For floating tasks, calculate the smallest width from the bounds of the task
+            return (int) (Math.min(bounds.width(), bounds.height()) / density);
+        } else {
+            // Iterating across all screen orientations, and return the minimum of the task
+            // width taking into account that the bounds might change because the snap algorithm
+            // snaps to a different value
+            return displayContent.getDockedDividerController()
+                    .getSmallestWidthDpForBounds(bounds);
+        }
+    }
+
     void requestResize(Rect bounds) {
         mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget();
     }
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index b09d699..b9429f4 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1476,7 +1476,10 @@
 
     @Override
     public void getFullScreenBounds(Rect bounds) {
-        getDisplayContent().getContentRect(bounds);
+        // This is currently only used for the pinned stack animation when leaving PiP
+        // (see {@link BoundsAnimationController}), and in that case we need to animate this back
+        // to the full bounds to match the fullscreen stack
+        getDisplayContent().getLogicalDisplayRect(bounds);
     }
 
     public boolean hasMovementAnimations() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 78568fc..5653113 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6146,6 +6146,7 @@
      * Get an array with display ids ordered by focus priority - last items should be given
      * focus first. Sparse array just maps position to displayId.
      */
+    // TODO: Maintain display list in focus order in ActivityManager and remove this call.
     public void getDisplaysInFocusOrder(SparseIntArray displaysInFocusOrder) {
         synchronized(mWindowMap) {
             mRoot.getDisplaysInFocusOrder(displaysInFocusOrder);
@@ -7543,63 +7544,12 @@
         }
     }
 
-    private void getNonDecorInsetsLocked(Rect outInsets) {
-        final DisplayInfo di = getDefaultDisplayInfoLocked();
-        mPolicy.getNonDecorInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight, outInsets);
-    }
-
-    /**
-     * Intersects the specified {@code inOutBounds} with the display frame that excludes the stable
-     * inset areas.
-     *
-     * @param inOutBounds The inOutBounds to subtract the stable inset areas from.
-     */
-    public void subtractStableInsets(Rect inOutBounds) {
-        synchronized (mWindowMap) {
-            getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect2);
-            final DisplayInfo di = getDefaultDisplayInfoLocked();
-            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
-            subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
-        }
-    }
-
-    /**
-     * Intersects the specified {@code inOutBounds} with the display frame that excludes
-     * areas that could never be removed in Honeycomb. See
-     * {@link WindowManagerPolicy#getNonDecorInsetsLw}.
-     *
-     * @param inOutBounds The inOutBounds to subtract the inset areas from.
-     */
-    public void subtractNonDecorInsets(Rect inOutBounds) {
-        synchronized (mWindowMap) {
-            getNonDecorInsetsLocked(mTmpRect2);
-            final DisplayInfo di = getDefaultDisplayInfoLocked();
-            mTmpRect.set(0, 0, di.logicalWidth, di.logicalHeight);
-            subtractInsets(mTmpRect, mTmpRect2, inOutBounds);
-        }
-    }
-
-    void subtractInsets(Rect display, Rect insets, Rect inOutBounds) {
+    void intersectDisplayInsetBounds(Rect display, Rect insets, Rect inOutBounds) {
         mTmpRect3.set(display);
         mTmpRect3.inset(insets);
         inOutBounds.intersect(mTmpRect3);
     }
 
-    /**
-     * Calculates the smallest width for a task given the {@param bounds}. It does that by iterating
-     * across all screen orientations, and returns the minimum of the task width taking into account
-     * that the bounds might change because the snap algorithm snaps to a different value.
-     *
-     * @return the smallest width to be used in the Configuration, in dips
-     */
-    public int getSmallestWidthForTaskBounds(Rect bounds) {
-        synchronized (mWindowMap) {
-            // TODO(multi-display): Use correct display content here
-            return getDefaultDisplayContentLocked().getDockedDividerController()
-                    .getSmallestWidthDpForBounds(bounds);
-        }
-    }
-
     MousePositionTracker mMousePositionTracker = new MousePositionTracker();
 
     private static class MousePositionTracker implements PointerEventListener {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 83e209d..31c8261 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -35,6 +35,7 @@
 import android.os.IIncidentManager;
 import android.os.Looper;
 import android.os.PowerManager;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
@@ -236,6 +237,8 @@
 
     private static final String START_SENSOR_SERVICE = "StartSensorService";
     private Future<?> mSensorServiceStart;
+    private Future<?> mZygotePreload;
+
 
     /**
      * Start the sensor service. This is a blocking call and can take time.
@@ -688,6 +691,26 @@
         }
 
         try {
+            final String SECONDARY_ZYGOTE_PRELOAD = "SecondaryZygotePreload";
+            // We start the preload ~1s before the webview factory preparation, to
+            // ensure that it completes before the 32 bit relro process is forked
+            // from the zygote. In the event that it takes too long, the webview
+            // RELRO process will block, but it will do so without holding any locks.
+            mZygotePreload = SystemServerInitThreadPool.get().submit(() -> {
+                try {
+                    Slog.i(TAG, SECONDARY_ZYGOTE_PRELOAD);
+                    BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
+                            SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+                    traceLog.traceBegin(SECONDARY_ZYGOTE_PRELOAD);
+                    if (!Process.zygoteProcess.preloadDefault(Build.SUPPORTED_32_BIT_ABIS[0])) {
+                        Slog.e(TAG, "Unable to preload default resources");
+                    }
+                    traceLog.traceEnd();
+                } catch (Exception ex) {
+                    Slog.e(TAG, "Exception preloading default resources", ex);
+                }
+            }, SECONDARY_ZYGOTE_PRELOAD);
+
             traceBeginAndSlog("StartKeyAttestationApplicationIdProviderService");
             ServiceManager.addService("sec_key_att_app_id_provider",
                     new KeyAttestationApplicationIdProviderService(context));
@@ -1615,6 +1638,8 @@
                     BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
                             SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
                     traceLog.traceBegin(WEBVIEW_PREPARATION);
+                    ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");
+                    mZygotePreload = null;
                     mWebViewUpdateService.prepareWebViewInSystemServer();
                     traceLog.traceEnd();
                 }, WEBVIEW_PREPARATION);
diff --git a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
index 9824c1d..9ac8295 100644
--- a/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
+++ b/services/print/java/com/android/server/print/CompanionDeviceManagerService.java
@@ -19,20 +19,28 @@
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
-import android.app.PendingIntent;
+import android.Manifest;
 import android.companion.AssociationRequest;
+import android.companion.CompanionDeviceManager;
+import android.companion.ICompanionDeviceDiscoveryService;
+import android.companion.ICompanionDeviceDiscoveryServiceCallback;
 import android.companion.ICompanionDeviceManager;
-import android.companion.ICompanionDeviceManagerService;
-import android.companion.IOnAssociateCallback;
+import android.companion.IFindDeviceCallback;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.NetworkPolicyManager;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.IDeviceIdleController;
 import android.os.RemoteException;
-import android.util.Log;
+import android.os.ServiceManager;
+import android.util.Slog;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.server.SystemService;
 
 //TODO move to own package!
@@ -40,7 +48,8 @@
 public class CompanionDeviceManagerService extends SystemService {
 
     private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
-            "com.android.companiondevicemanager", ".DeviceDiscoveryService");
+            CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
+            ".DeviceDiscoveryService");
 
     private static final boolean DEBUG = false;
     private static final String LOG_TAG = "CompanionDeviceManagerService";
@@ -58,14 +67,13 @@
     }
 
     class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
-
         @Override
         public void associate(
                 AssociationRequest request,
-                IOnAssociateCallback callback,
-                String callingPackage) throws RemoteException {
+                IFindDeviceCallback callback,
+                String callingPackage) {
             if (DEBUG) {
-                Log.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
+                Slog.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
                         + ", callingPackage = " + callingPackage + ")");
             }
             checkNotNull(request);
@@ -85,23 +93,24 @@
 
     private ServiceConnection getServiceConnection(
             final AssociationRequest<?> request,
-            final IOnAssociateCallback callback,
+            final IFindDeviceCallback findDeviceCallback,
             final String callingPackage) {
         return new ServiceConnection() {
             @Override
             public void onServiceConnected(ComponentName name, IBinder service) {
                 if (DEBUG) {
-                    Log.i(LOG_TAG,
+                    Slog.i(LOG_TAG,
                             "onServiceConnected(name = " + name + ", service = "
                                     + service + ")");
                 }
                 try {
-                    ICompanionDeviceManagerService.Stub
+                    ICompanionDeviceDiscoveryService.Stub
                             .asInterface(service)
                             .startDiscovery(
                                     request,
-                                    getCallback(callingPackage, callback),
-                                    callingPackage);
+                                    callingPackage,
+                                    findDeviceCallback,
+                                    getServiceCallback());
                 } catch (RemoteException e) {
                     throw new RuntimeException(e);
                 }
@@ -109,39 +118,50 @@
 
             @Override
             public void onServiceDisconnected(ComponentName name) {
-                if (DEBUG) Log.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
+                if (DEBUG) Slog.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
             }
         };
     }
 
-    private IOnAssociateCallback.Stub getCallback(
-            String callingPackage,
-            IOnAssociateCallback propagateTo) {
-        return new IOnAssociateCallback.Stub() {
-
+    private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() {
+        return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
             @Override
-            public void onSuccess(PendingIntent launcher)
-                    throws RemoteException {
-                if (DEBUG) Log.i(LOG_TAG, "onSuccess(launcher = " + launcher + ")");
-                recordSpecialPriviledgesForPackage(callingPackage);
-                propagateTo.onSuccess(launcher);
-            }
-
-            @Override
-            public void onFailure(CharSequence reason) throws RemoteException {
-                if (DEBUG) Log.i(LOG_TAG, "onFailure()");
-                propagateTo.onFailure(reason);
+            public void onDeviceSelected(String packageName, int userId) {
+                grantSpecialAccessPermissionsIfNeeded(packageName, userId);
             }
         };
     }
 
-    void recordSpecialPriviledgesForPackage(String priviledgedPackage) {
-        //TODO Show dialog before recording notification access
-//        final SettingStringHelper setting =
-//                new SettingStringHelper(
-//                        getContext().getContentResolver(),
-//                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-//                        Binder.getCallingUid());
-//        setting.write(ColonDelimitedSet.OfStrings.add(setting.read(), priviledgedPackage));
+    private void grantSpecialAccessPermissionsIfNeeded(String packageName, int userId) {
+        final long identity = Binder.clearCallingIdentity();
+        final PackageInfo packageInfo;
+        try {
+            packageInfo = getContext().getPackageManager().getPackageInfoAsUser(
+                    packageName, PackageManager.GET_PERMISSIONS, userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.e(LOG_TAG, "Error granting special access permissions to package:"
+                    + packageName, e);
+            return;
+        }
+        try {
+            if (ArrayUtils.contains(packageInfo.requestedPermissions,
+                    Manifest.permission.RUN_IN_BACKGROUND)) {
+                IDeviceIdleController idleController = IDeviceIdleController.Stub.asInterface(
+                        ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
+                try {
+                    idleController.addPowerSaveWhitelistApp(packageName);
+                } catch (RemoteException e) {
+                    /* ignore - local call */
+                }
+            }
+            if (ArrayUtils.contains(packageInfo.requestedPermissions,
+                    Manifest.permission.USE_DATA_IN_BACKGROUND)) {
+                NetworkPolicyManager.from(getContext()).addUidPolicy(
+                        packageInfo.applicationInfo.uid,
+                        NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
index d71cc6f..6e3a8e8 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
@@ -50,6 +50,7 @@
 import android.util.DisplayMetrics;
 import android.util.LruCache;
 import android.util.TypedValue;
+import android.view.DisplayAdjustments;
 import android.view.ViewGroup.LayoutParams;
 
 import java.io.File;
@@ -71,7 +72,8 @@
             DisplayMetrics metrics,
             Configuration config,
             LayoutlibCallback layoutlibCallback) {
-        Resources resources = new Resources(assets, metrics, config);
+        Resources resources = new Resources(Resources_Delegate.class.getClassLoader());
+        resources.setImpl(new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()));
         resources.mContext = context;
         resources.mLayoutlibCallback = layoutlibCallback;
         return Resources.mSystem = resources;
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
index bae2dc0c..8ebfc65 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java
@@ -132,7 +132,11 @@
 
     @Override
     public Integer getResourceId(ResourceType type, String name) {
-        return mResources.get(type).get(name);
+        Map<String, Integer> resName2Id = mResources.get(type);
+        if (resName2Id == null) {
+            return null;
+        }
+        return resName2Id.get(name);
     }
 
     @Override
diff --git a/tools/layoutlib/create/create.iml b/tools/layoutlib/create/create.iml
index 368b46b..ac97502 100644
--- a/tools/layoutlib/create/create.iml
+++ b/tools/layoutlib/create/create.iml
@@ -12,9 +12,9 @@
     <orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="module-library">
-      <library name="asm-5.0">
+      <library name="asm-5.2">
         <CLASSES>
-          <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-5.0.jar!/" />
+          <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-5.2.jar!/" />
         </CLASSES>
         <JAVADOC />
         <SOURCES>