Merge "use mskp extension to differentiate multi frame files."
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index c30a6f4..eb53b7c 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -121,8 +121,6 @@
 Landroid/bluetooth/IBluetoothPbap$Stub;->asInterface(Landroid/os/IBinder;)Landroid/bluetooth/IBluetoothPbap;
 Landroid/bluetooth/IBluetoothStateChangeCallback$Stub;-><init>()V
 Landroid/companion/ICompanionDeviceDiscoveryService$Stub;-><init>()V
-Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V
 Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
 Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -194,7 +192,6 @@
 Landroid/content/UndoManager;-><init>()V
 Landroid/database/IContentObserver$Stub;-><init>()V
 Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
-Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
 Landroid/database/sqlite/SQLiteConnectionPool;->$assertionsDisabled:Z
 Landroid/database/sqlite/SQLiteDatabase;->$assertionsDisabled:Z
 Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
@@ -723,9 +720,6 @@
 Lcom/android/internal/location/GpsNetInitiatedHandler;->mIsHexInput:Z
 Lcom/android/internal/location/ILocationProvider$Stub;-><init>()V
 Lcom/android/internal/location/ILocationProvider$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProvider;
-Lcom/android/internal/location/ILocationProvider;->sendExtraCommand(Ljava/lang/String;Landroid/os/Bundle;)V
-Lcom/android/internal/location/ILocationProvider;->setLocationProviderManager(Lcom/android/internal/location/ILocationProviderManager;)V
-Lcom/android/internal/location/ILocationProvider;->setRequest(Lcom/android/internal/location/ProviderRequest;Landroid/os/WorkSource;)V
 Lcom/android/internal/location/ILocationProviderManager$Stub;-><init>()V
 Lcom/android/internal/location/ILocationProviderManager$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/location/ILocationProviderManager;
 Lcom/android/internal/logging/MetricsLogger;-><init>()V
@@ -736,7 +730,6 @@
 Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
 Lcom/android/internal/policy/IKeyguardService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardService;
 Lcom/android/internal/policy/IKeyguardStateCallback$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/policy/IKeyguardStateCallback;
-Lcom/android/internal/preference/YesNoPreference;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
 Lcom/android/internal/R$anim;->fade_in:I
 Lcom/android/internal/R$array;->config_autoBrightnessLcdBacklightValues:I
 Lcom/android/internal/R$array;->config_autoBrightnessLevels:I
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
index 5f73e55..c9dc019 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
@@ -18,6 +18,8 @@
 
 /** @hide */
 interface ICompanionDeviceDiscoveryServiceCallback {
+    @UnsupportedAppUsage
     oneway void onDeviceSelected(String packageName, int userId, String deviceAddress);
+    @UnsupportedAppUsage
     oneway void onDeviceSelectionCancel();
 }
diff --git a/core/java/android/database/IContentObserver.aidl b/core/java/android/database/IContentObserver.aidl
index 22dc9fe..6235566 100644
--- a/core/java/android/database/IContentObserver.aidl
+++ b/core/java/android/database/IContentObserver.aidl
@@ -29,5 +29,6 @@
      * observed. selfUpdate is true if the update was caused by a call to
      * commit on the cursor that is being observed.
      */
+    @UnsupportedAppUsage
     oneway void onChange(boolean selfUpdate, in Uri uri, int userId);
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index cc8c182..68857da9 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -2337,6 +2337,12 @@
             final CaptureCallbackHolder holder =
                     CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
 
+            if (holder == null) {
+                Log.e(TAG, String.format("Receive capture error on unknown request ID %d",
+                        requestId));
+                return;
+            }
+
             final CaptureRequest request = holder.getRequest(subsequenceId);
 
             Runnable failureDispatch = null;
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index b377e8d..6165146 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -123,6 +123,7 @@
             IBinder binder = callback.asBinder();
             try {
                 Callback cb = new Callback(callback, cookie);
+                unregister(callback);
                 binder.linkToDeath(cb, 0);
                 mCallbacks.put(binder, cb);
                 return true;
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index a46580d..18d4d69 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -464,7 +464,9 @@
      * Note that the feature will continue to be supported on older versions of
      * Android as before.
      *
-     * This function does not have any effect.
+     * @deprecated In Android O and afterwards, this function does not have
+     * any effect, the form data will be saved to platform's autofill service
+     * if applicable.
      */
     @Deprecated
     public abstract  void setSaveFormData(boolean save);
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 5091eea..ad35633 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -42,6 +42,8 @@
 import android.view.animation.LinearInterpolator;
 import android.widget.RemoteViews.RemoteView;
 
+import com.android.internal.R;
+
 import java.lang.ref.WeakReference;
 
 @RemoteView
@@ -1241,14 +1243,40 @@
         info.setScrollable(getChildCount() > 1);
         if (isEnabled()) {
             if (getDisplayedChild() < getChildCount() - 1) {
-                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
+                if (mStackMode == ITEMS_SLIDE_UP) {
+                    info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_DOWN);
+                } else {
+                    info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_UP);
+                }
             }
             if (getDisplayedChild() > 0) {
-                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+                info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
+                if (mStackMode == ITEMS_SLIDE_UP) {
+                    info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_UP);
+                } else {
+                    info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_DOWN);
+                }
             }
         }
     }
 
+    private boolean goForward() {
+        if (getDisplayedChild() < getChildCount() - 1) {
+            showNext();
+            return true;
+        }
+        return false;
+    }
+
+    private boolean goBackward() {
+        if (getDisplayedChild() > 0) {
+            showPrevious();
+            return true;
+        }
+        return false;
+    }
+
     /** @hide */
     @Override
     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
@@ -1260,17 +1288,25 @@
         }
         switch (action) {
             case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
-                if (getDisplayedChild() < getChildCount() - 1) {
-                    showNext();
-                    return true;
-                }
-            } return false;
+                return goForward();
+            }
             case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
-                if (getDisplayedChild() > 0) {
-                    showPrevious();
-                    return true;
+                return goBackward();
+            }
+            case R.id.accessibilityActionPageUp: {
+                if (mStackMode == ITEMS_SLIDE_UP) {
+                    return goBackward();
+                } else {
+                    return goForward();
                 }
-            } return false;
+            }
+            case R.id.accessibilityActionPageDown: {
+                if (mStackMode == ITEMS_SLIDE_UP) {
+                    return goForward();
+                } else {
+                    return goBackward();
+                }
+            }
         }
         return false;
     }
diff --git a/core/java/com/android/internal/preference/YesNoPreference.java b/core/java/com/android/internal/preference/YesNoPreference.java
index 7abf416..46d14a1 100644
--- a/core/java/com/android/internal/preference/YesNoPreference.java
+++ b/core/java/com/android/internal/preference/YesNoPreference.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.preference;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.os.Parcel;
@@ -40,6 +41,7 @@
         this(context, attrs, defStyleAttr, 0);
     }
 
+    @UnsupportedAppUsage
     public YesNoPreference(Context context, AttributeSet attrs) {
         this(context, attrs, com.android.internal.R.attr.yesNoPreferenceStyle);
     }
diff --git a/graphics/java/android/graphics/RectF.java b/graphics/java/android/graphics/RectF.java
index 3361fa2..1d294d5 100644
--- a/graphics/java/android/graphics/RectF.java
+++ b/graphics/java/android/graphics/RectF.java
@@ -27,7 +27,7 @@
 
 /**
  * RectF holds four float coordinates for a rectangle. The rectangle is
- * represented by the coordinates of its 4 edges (left, top, right bottom).
+ * represented by the coordinates of its 4 edges (left, top, right, bottom).
  * These fields can be accessed directly. Use width() and height() to retrieve
  * the rectangle's width and height. Note: most methods do not check to see that
  * the coordinates are sorted correctly (i.e. left <= right and top <= bottom).
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
index a571630..8ae972b 100644
--- a/location/java/com/android/internal/location/ILocationProvider.aidl
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -29,10 +29,13 @@
  */
 interface ILocationProvider {
 
+    @UnsupportedAppUsage
     oneway void setLocationProviderManager(in ILocationProviderManager manager);
 
+    @UnsupportedAppUsage
     oneway void setRequest(in ProviderRequest request, in WorkSource ws);
 
+    @UnsupportedAppUsage
     oneway void sendExtraCommand(String command, in Bundle extras);
 
     // --- deprecated and will be removed the future ---
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index c0a1b12..1d4d0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -103,10 +103,11 @@
         final boolean userSwitcherEnabled = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.USER_SWITCHER_ENABLED, 0) != 0;
 
-        if (!UserManager.supportsMultipleUsers()
-                || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)
+        // TODO(b/138661450) Move IPC calls to background
+        if (!userSwitcherEnabled
+                || !UserManager.supportsMultipleUsers()
                 || UserManager.isDeviceInDemoMode(mContext)
-                || !userSwitcherEnabled) {
+                || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index cb6cf74..6010b1dc 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -15,9 +15,6 @@
  */
 package com.android.server.audio;
 
-import static com.android.server.audio.AudioService.CONNECTION_STATE_CONNECTED;
-import static com.android.server.audio.AudioService.CONNECTION_STATE_DISCONNECTED;
-
 import android.annotation.NonNull;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
@@ -95,13 +92,28 @@
     /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) {
         mContext = context;
         mAudioService = service;
-        setupMessaging(context);
         mBtHelper = new BtHelper(this);
         mDeviceInventory = new AudioDeviceInventory(this);
 
+        init();
+    }
+
+    /** for test purposes only, inject AudioDeviceInventory */
+    AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service,
+                      @NonNull AudioDeviceInventory mockDeviceInventory) {
+        mContext = context;
+        mAudioService = service;
+        mBtHelper = new BtHelper(this);
+        mDeviceInventory = mockDeviceInventory;
+
+        init();
+    }
+
+    private void init() {
+        setupMessaging(mContext);
+
         mForcedUseForComm = AudioSystem.FORCE_NONE;
         mForcedUseForCommExt = mForcedUseForComm;
-
     }
 
     /*package*/ Context getContext() {
@@ -232,17 +244,42 @@
             mSupprNoisy = suppressNoisyIntent;
             mVolume = vol;
         }
+
+        // redefine equality op so we can match messages intended for this device
+        @Override
+        public boolean equals(Object o) {
+            return mDevice.equals(o);
+        }
     }
 
+
     /*package*/ void postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
             @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
             int profile, boolean suppressNoisyIntent, int a2dpVolume) {
         final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
                 suppressNoisyIntent, a2dpVolume);
 
-        // TODO add a check to try to remove unprocessed messages for the same device (the old
-        //      check didn't work), and  make sure it doesn't conflict with config change message
-        sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
+        // when receiving a request to change the connection state of a device, this last request
+        // is the source of truth, so cancel all previous requests
+        removeAllA2dpConnectionEvents(device);
+
+        sendLMsgNoDelay(
+                state == BluetoothProfile.STATE_CONNECTED
+                        ? MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION
+                        : MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
+                SENDMSG_QUEUE, info);
+    }
+
+    /** remove all previously scheduled connection and disconnection events for the given device */
+    private void removeAllA2dpConnectionEvents(@NonNull BluetoothDevice device) {
+        mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION,
+                device);
+        mBrokerHandler.removeMessages(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION,
+                device);
+        mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
+                device);
+        mBrokerHandler.removeMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
+                device);
     }
 
     private static final class HearingAidDeviceConnectionInfo {
@@ -430,13 +467,16 @@
         sendMsgNoDelay(MSG_BROADCAST_AUDIO_BECOMING_NOISY, SENDMSG_REPLACE);
     }
 
-    /*package*/ void postA2dpSinkConnection(int state,
+    /*package*/ void postA2dpSinkConnection(@AudioService.BtProfileConnectionState int state,
             @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
-        sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE,
+        sendILMsg(state == BluetoothA2dp.STATE_CONNECTED
+                        ? MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED
+                        : MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
+                SENDMSG_QUEUE,
                 state, btDeviceInfo, delay);
     }
 
-    /*package*/ void postA2dpSourceConnection(int state,
+    /*package*/ void postA2dpSourceConnection(@AudioService.BtProfileConnectionState int state,
             @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo, int delay) {
         sendILMsg(MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE, SENDMSG_QUEUE,
                 state, btDeviceInfo, delay);
@@ -522,25 +562,6 @@
         }
     }
 
-    @GuardedBy("mDeviceStateLock")
-    /*package*/ void handleSetA2dpSinkConnectionState(@BluetoothProfile.BtProfileState int state,
-                @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
-        final int intState = (state == BluetoothA2dp.STATE_CONNECTED)
-                ? CONNECTION_STATE_CONNECTED : CONNECTION_STATE_DISCONNECTED;
-        final int delay = mDeviceInventory.checkSendBecomingNoisyIntent(
-                    AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, intState,
-                    AudioSystem.DEVICE_NONE);
-        final String addr = btDeviceInfo == null ? "null" : btDeviceInfo.getBtDevice().getAddress();
-
-        if (AudioService.DEBUG_DEVICES) {
-            Log.d(TAG, "handleSetA2dpSinkConnectionState btDevice= " + btDeviceInfo
-                    + " state= " + state
-                    + " is dock: " + btDeviceInfo.getBtDevice().isBluetoothDock());
-        }
-        sendILMsg(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE, SENDMSG_QUEUE,
-                state, btDeviceInfo, delay);
-    }
-
     /*package*/ void postSetA2dpSourceConnectionState(@BluetoothProfile.BtProfileState int state,
             @NonNull BtHelper.BluetoothA2dpDeviceInfo btDeviceInfo) {
         final int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
@@ -575,8 +596,10 @@
 
     // must be called synchronized on mConnectedDevices
     /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
-        return mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE,
-                new BtHelper.BluetoothA2dpDeviceInfo(btDevice));
+        return (mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED,
+                        new BtHelper.BluetoothA2dpDeviceInfo(btDevice))
+                || mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED,
+                        new BtHelper.BluetoothA2dpDeviceInfo(btDevice)));
     }
 
     /*package*/ void setA2dpDockTimeout(String address, int a2dpCodec, int delayMs) {
@@ -711,7 +734,8 @@
                         mDeviceInventory.onReportNewRoutes();
                     }
                     break;
-                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
+                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
+                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.onSetA2dpSinkConnectionState(
                                 (BtHelper.BluetoothA2dpDeviceInfo) msg.obj, msg.arg1);
@@ -836,7 +860,8 @@
                         }
                     }
                     break;
-                case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT: {
+                case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
+                case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION: {
                     final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
                     AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
                             "setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent "
@@ -887,7 +912,7 @@
     private static final int MSG_I_BROADCAST_BT_CONNECTION_STATE = 3;
     private static final int MSG_IIL_SET_FORCE_USE = 4;
     private static final int MSG_IIL_SET_FORCE_BT_A2DP_USE = 5;
-    private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE = 6;
+    private static final int MSG_TOGGLE_HDMI = 6;
     private static final int MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE = 7;
     private static final int MSG_IL_SET_HEARING_AID_CONNECTION_STATE = 8;
     private static final int MSG_BT_HEADSET_CNCT_FAILED = 9;
@@ -898,7 +923,6 @@
     private static final int MSG_II_SET_HEARING_AID_VOLUME = 14;
     private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15;
     private static final int MSG_I_DISCONNECT_BT_SCO = 16;
-    private static final int MSG_TOGGLE_HDMI = 17;
     private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE = 18;
     private static final int MSG_DISCONNECT_A2DP = 19;
     private static final int MSG_DISCONNECT_A2DP_SINK = 20;
@@ -908,25 +932,30 @@
     private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_A2DP_SINK = 24;
     private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEARING_AID = 25;
     private static final int MSG_L_BT_SERVICE_CONNECTED_PROFILE_HEADSET = 26;
+    private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED = 27;
+    private static final int MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED = 28;
     // process external command to (dis)connect an A2DP device
-    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
+    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION = 29;
+    private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION = 30;
     // process external command to (dis)connect a hearing aid device
-    private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
+    private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 31;
     // a ScoClient died in BtHelper
-    private static final int MSG_L_SCOCLIENT_DIED = 29;
+    private static final int MSG_L_SCOCLIENT_DIED = 32;
 
 
     private static boolean isMessageHandledUnderWakelock(int msgId) {
         switch(msgId) {
             case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
-            case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
+            case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
+            case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
             case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
             case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
             case MSG_IL_BTA2DP_DOCK_TIMEOUT:
             case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
             case MSG_TOGGLE_HDMI:
             case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
-            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
+            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_CONNECTION:
+            case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT_DISCONNECTION:
             case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
                 return true;
             default:
@@ -1007,7 +1036,8 @@
 
             switch (msg) {
                 case MSG_IL_SET_A2DP_SOURCE_CONNECTION_STATE:
-                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE:
+                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_CONNECTED:
+                case MSG_IL_SET_A2DP_SINK_CONNECTION_STATE_DISCONNECTED:
                 case MSG_IL_SET_HEARING_AID_CONNECTION_STATE:
                 case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
                 case MSG_IL_BTA2DP_DOCK_TIMEOUT:
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index a9a8ef2..90973a8 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -41,14 +41,16 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
 
 /**
  * Class to manage the inventory of all connected devices.
  * This class is thread-safe.
+ * (non final for mocking/spying)
  */
-public final class AudioDeviceInventory {
+public class AudioDeviceInventory {
 
     private static final String TAG = "AS.AudioDeviceInventory";
 
@@ -56,11 +58,7 @@
     // Key for map created from DeviceInfo.makeDeviceListKey()
     private final ArrayMap<String, DeviceInfo> mConnectedDevices = new ArrayMap<>();
 
-    private final @NonNull AudioDeviceBroker mDeviceBroker;
-
-    AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
-        mDeviceBroker = broker;
-    }
+    private @NonNull AudioDeviceBroker mDeviceBroker;
 
     // cache of the address of the last dock the device was connected to
     private String mDockAddress;
@@ -70,6 +68,20 @@
     final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers =
             new RemoteCallbackList<IAudioRoutesObserver>();
 
+    /*package*/ AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
+        mDeviceBroker = broker;
+    }
+
+    //-----------------------------------------------------------
+    /** for mocking only */
+    /*package*/ AudioDeviceInventory() {
+        mDeviceBroker = null;
+    }
+
+    /*package*/ void setDeviceBroker(@NonNull AudioDeviceBroker broker) {
+        mDeviceBroker = broker;
+    }
+
     //------------------------------------------------------------
     /**
      * Class to store info about connected devices.
@@ -146,8 +158,10 @@
         }
     }
 
+    // only public for mocking/spying
     @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
-    /*package*/ void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
+    @VisibleForTesting
+    public void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
             @AudioService.BtProfileConnectionState int state) {
         final BluetoothDevice btDevice = btInfo.getBtDevice();
         int a2dpVolume = btInfo.getVolume();
@@ -159,30 +173,40 @@
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             address = "";
         }
-        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
-                "A2DP sink connected: device addr=" + address + " state=" + state
-                        + " vol=" + a2dpVolume));
 
         final int a2dpCodec = btInfo.getCodec();
 
+        AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+                "A2DP sink connected: device addr=" + address + " state=" + state
+                        + " codec=" + a2dpCodec
+                        + " vol=" + a2dpVolume));
+
         synchronized (mConnectedDevices) {
             final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
                     btDevice.getAddress());
             final DeviceInfo di = mConnectedDevices.get(key);
             boolean isConnected = di != null;
 
-            if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
-                if (btDevice.isBluetoothDock()) {
-                    if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                        // introduction of a delay for transient disconnections of docks when
-                        // power is rapidly turned off/on, this message will be canceled if
-                        // we reconnect the dock under a preset delay
-                        makeA2dpDeviceUnavailableLater(address,
-                                AudioDeviceBroker.BTA2DP_DOCK_TIMEOUT_MS);
-                        // the next time isConnected is evaluated, it will be false for the dock
+            if (isConnected) {
+                if (state == BluetoothProfile.STATE_CONNECTED) {
+                    // device is already connected, but we are receiving a connection again,
+                    // it could be for a codec change
+                    if (a2dpCodec != di.mDeviceCodecFormat) {
+                        mDeviceBroker.postBluetoothA2dpDeviceConfigChange(btDevice);
                     }
                 } else {
-                    makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
+                    if (btDevice.isBluetoothDock()) {
+                        if (state == BluetoothProfile.STATE_DISCONNECTED) {
+                            // introduction of a delay for transient disconnections of docks when
+                            // power is rapidly turned off/on, this message will be canceled if
+                            // we reconnect the dock under a preset delay
+                            makeA2dpDeviceUnavailableLater(address,
+                                    AudioDeviceBroker.BTA2DP_DOCK_TIMEOUT_MS);
+                            // the next time isConnected is evaluated, it will be false for the dock
+                        }
+                    } else {
+                        makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
+                    }
                 }
             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
                 if (btDevice.isBluetoothDock()) {
@@ -282,11 +306,9 @@
                     + " event=" + BtHelper.a2dpDeviceEventToString(event)));
 
         synchronized (mConnectedDevices) {
-            //TODO original CL is not consistent between BluetoothDevice and BluetoothA2dpDeviceInfo
-            // for this type of message
             if (mDeviceBroker.hasScheduledA2dpSinkConnectionState(btDevice)) {
                 AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
-                        "A2dp config change ignored"));
+                        "A2dp config change ignored (scheduled connection change)"));
                 return;
             }
             final String key = DeviceInfo.makeDeviceListKey(
@@ -534,8 +556,10 @@
         return mCurAudioRoutes;
     }
 
+    // only public for mocking/spying
     @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
-    /*package*/ void setBluetoothA2dpDeviceConnectionState(
+    @VisibleForTesting
+    public void setBluetoothA2dpDeviceConnectionState(
             @NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
             int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume) {
         int delay;
@@ -544,9 +568,12 @@
         }
         synchronized (mConnectedDevices) {
             if (profile == BluetoothProfile.A2DP && !suppressNoisyIntent) {
-                int intState = (state == BluetoothA2dp.STATE_CONNECTED) ? 1 : 0;
+                @AudioService.ConnectionState int asState =
+                        (state == BluetoothA2dp.STATE_CONNECTED)
+                                ? AudioService.CONNECTION_STATE_CONNECTED
+                                : AudioService.CONNECTION_STATE_DISCONNECTED;
                 delay = checkSendBecomingNoisyIntentInt(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
-                        intState, musicDevice);
+                        asState, musicDevice);
             } else {
                 delay = 0;
             }
@@ -785,7 +812,7 @@
                 return 0;
             }
             mDeviceBroker.postBroadcastBecomingNoisy();
-            delay = 1000;
+            delay = AudioService.BECOMING_NOISY_DELAY_MS;
         }
 
         return delay;
@@ -943,4 +970,21 @@
             intent.putExtra(AudioManager.EXTRA_MAX_CHANNEL_COUNT, maxChannels);
         }
     }
+
+    //----------------------------------------------------------
+    // For tests only
+
+    /**
+     * Check if device is in the list of connected devices
+     * @param device
+     * @return true if connected
+     */
+    @VisibleForTesting
+    public boolean isA2dpDeviceConnected(@NonNull BluetoothDevice device) {
+        final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                device.getAddress());
+        synchronized (mConnectedDevices) {
+            return (mConnectedDevices.get(key) != null);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 7458bee..5bc2261 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -128,6 +128,7 @@
 import android.widget.Toast;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
 import com.android.server.EventLogTags;
@@ -190,6 +191,13 @@
     private static final int UNMUTE_STREAM_DELAY = 350;
 
     /**
+     * Delay before disconnecting a device that would cause BECOMING_NOISY intent to be sent,
+     * to give a chance to applications to pause.
+     */
+    @VisibleForTesting
+    public static final int BECOMING_NOISY_DELAY_MS = 1000;
+
+    /**
      * Only used in the result from {@link #checkForRingerModeChange(int, int, int)}
      */
     private static final int FLAG_ADJUST_VOLUME = 1;
@@ -3950,7 +3958,9 @@
                 || adjust == AudioManager.ADJUST_TOGGLE_MUTE;
     }
 
-    /*package*/ boolean isInCommunication() {
+    /** only public for mocking/spying, do not call outside of AudioService */
+    @VisibleForTesting
+    public boolean isInCommunication() {
         boolean IsInCall = false;
 
         TelecomManager telecomManager =
@@ -4119,7 +4129,9 @@
         return false;
     }
 
-    /*package*/ int getDeviceForStream(int stream) {
+    /** only public for mocking/spying, do not call outside of AudioService */
+    @VisibleForTesting
+    public int getDeviceForStream(int stream) {
         int device = getDevicesForStream(stream);
         if ((device & (device - 1)) != 0) {
             // Multiple device selection is either:
@@ -4164,7 +4176,9 @@
         }
     }
 
-    /*package*/ void postObserveDevicesForAllStreams() {
+    /** only public for mocking/spying, do not call outside of AudioService */
+    @VisibleForTesting
+    public void postObserveDevicesForAllStreams() {
         sendMsg(mAudioHandler,
                 MSG_OBSERVE_DEVICES_FOR_ALL_STREAMS,
                 SENDMSG_QUEUE, 0 /*arg1*/, 0 /*arg2*/, null /*obj*/,
@@ -4275,7 +4289,9 @@
             AudioSystem.DEVICE_OUT_ALL_USB |
             AudioSystem.DEVICE_OUT_HDMI;
 
-    /*package*/ void postAccessoryPlugMediaUnmute(int newDevice) {
+    /** only public for mocking/spying, do not call outside of AudioService */
+    @VisibleForTesting
+    public void postAccessoryPlugMediaUnmute(int newDevice) {
         sendMsg(mAudioHandler, MSG_ACCESSORY_PLUG_MEDIA_UNMUTE, SENDMSG_QUEUE,
                 newDevice, 0, null, 0);
     }
@@ -4825,7 +4841,9 @@
         }
     }
 
-    /*package*/ void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
+    /** only public for mocking/spying, do not call outside of AudioService */
+    @VisibleForTesting
+    public void postSetVolumeIndexOnDevice(int streamType, int vssVolIndex, int device,
                                                 String caller) {
         sendMsg(mAudioHandler,
                 MSG_SET_DEVICE_STREAM_VOLUME,
@@ -5183,7 +5201,9 @@
      * @return true if there is currently a registered dynamic mixing policy that affects media
      * and is not a render + loopback policy
      */
-    /*package*/ boolean hasMediaDynamicPolicy() {
+    // only public for mocking/spying
+    @VisibleForTesting
+    public boolean hasMediaDynamicPolicy() {
         synchronized (mAudioPolicies) {
             if (mAudioPolicies.isEmpty()) {
                 return false;
@@ -5516,7 +5536,9 @@
         return mMediaFocusControl.getFocusRampTimeMs(focusGain, attr);
     }
 
-    /*package*/ boolean hasAudioFocusUsers() {
+    /** only public for mocking/spying, do not call outside of AudioService */
+    @VisibleForTesting
+    public boolean hasAudioFocusUsers() {
         return mMediaFocusControl.hasAudioFocusUsers();
     }
 
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 1a63f8f..9f1a6bd 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -139,6 +139,12 @@
         public int getCodec() {
             return mCodec;
         }
+
+        // redefine equality op so we can match messages intended for this device
+        @Override
+        public boolean equals(Object o) {
+            return mBtDevice.equals(o);
+        }
     }
 
     // A2DP device events
@@ -441,9 +447,9 @@
             return;
         }
         final BluetoothDevice btDevice = deviceList.get(0);
-        final @BluetoothProfile.BtProfileState int state = mA2dp.getConnectionState(btDevice);
-        mDeviceBroker.handleSetA2dpSinkConnectionState(
-                state, new BluetoothA2dpDeviceInfo(btDevice));
+        // the device is guaranteed CONNECTED
+        mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(btDevice,
+                BluetoothA2dp.STATE_CONNECTED, BluetoothProfile.A2DP_SINK, true, -1);
     }
 
     /*package*/ synchronized void onA2dpSinkProfileConnected(BluetoothProfile profile) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 4957eed..73d160d 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -772,7 +772,6 @@
                     case WifiManager.WIFI_AP_STATE_FAILED:
                     default:
                         disableWifiIpServingLocked(ifname, curState);
-                        mEntitlementMgr.stopProvisioningIfNeeded(TETHERING_WIFI);
                         break;
                 }
             }
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 984f22f..c712431 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -281,20 +281,7 @@
         mAbortIdleOptimization.set(false);
 
         long lowStorageThreshold = getLowStorageThreshold(context);
-        // Optimize primary apks.
-        int result = optimizePackages(pm, pkgs, lowStorageThreshold,
-            /*isForPrimaryDex=*/ true);
-        if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
-            return result;
-        }
-        if (supportSecondaryDex()) {
-            result = reconcileSecondaryDexFiles(pm.getDexManager());
-            if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
-                return result;
-            }
-            result = optimizePackages(pm, pkgs, lowStorageThreshold,
-                /*isForPrimaryDex=*/ false);
-        }
+        int result = idleOptimizePackages(pm, pkgs, lowStorageThreshold);
         return result;
     }
 
@@ -342,11 +329,20 @@
         return 0;
     }
 
-    private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
-            long lowStorageThreshold, boolean isForPrimaryDex) {
+    private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+            long lowStorageThreshold) {
         ArraySet<String> updatedPackages = new ArraySet<>();
 
         try {
+            final boolean supportSecondaryDex = supportSecondaryDex();
+
+            if (supportSecondaryDex) {
+                int result = reconcileSecondaryDexFiles(pm.getDexManager());
+                if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
+                    return result;
+                }
+            }
+
             // Only downgrade apps when space is low on device.
             // Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
             // up disk before user hits the actual lowStorageThreshold.
@@ -359,43 +355,61 @@
                         pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
                 Log.d(TAG, "Unsused Packages " +  String.join(",", unusedPackages));
 
-                for (String pkg : unusedPackages) {
-                    int abortCode = abortIdleOptimizations(/*lowStorageThreshold*/ -1);
-                    if (abortCode != OPTIMIZE_CONTINUE) {
-                        // Should be aborted by the scheduler.
-                        return abortCode;
-                    }
-                    if (downgradePackage(pm, pkg, isForPrimaryDex)) {
-                        updatedPackages.add(pkg);
-                    }
-                }
-
                 if (!unusedPackages.isEmpty()) {
+                    for (String pkg : unusedPackages) {
+                        int abortCode = abortIdleOptimizations(/*lowStorageThreshold*/ -1);
+                        if (abortCode != OPTIMIZE_CONTINUE) {
+                            // Should be aborted by the scheduler.
+                            return abortCode;
+                        }
+                        if (downgradePackage(pm, pkg, /*isForPrimaryDex*/ true)) {
+                            updatedPackages.add(pkg);
+                        }
+                        if (supportSecondaryDex) {
+                            downgradePackage(pm, pkg, /*isForPrimaryDex*/ false);
+                        }
+                    }
+
                     pkgs = new ArraySet<>(pkgs);
                     pkgs.removeAll(unusedPackages);
                 }
             }
 
-            for (String pkg : pkgs) {
-                int abortCode = abortIdleOptimizations(lowStorageThreshold);
-                if (abortCode != OPTIMIZE_CONTINUE) {
-                    // Either aborted by the scheduler or no space left.
-                    return abortCode;
-                }
-
-                boolean dexOptPerformed = optimizePackage(pm, pkg, isForPrimaryDex);
-                if (dexOptPerformed) {
-                    updatedPackages.add(pkg);
-                }
+            int primaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
+                    /*isForPrimaryDex*/ true, updatedPackages);
+            if (primaryResult != OPTIMIZE_PROCESSED) {
+                return primaryResult;
             }
 
-            return OPTIMIZE_PROCESSED;
+            if (!supportSecondaryDex) {
+                return OPTIMIZE_PROCESSED;
+            }
+
+            int secondaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
+                    /*isForPrimaryDex*/ false, updatedPackages);
+            return secondaryResult;
         } finally {
             // Always let the pinner service know about changes.
             notifyPinService(updatedPackages);
         }
     }
 
+    private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+            long lowStorageThreshold, boolean isForPrimaryDex, ArraySet<String> updatedPackages) {
+        for (String pkg : pkgs) {
+            int abortCode = abortIdleOptimizations(lowStorageThreshold);
+            if (abortCode != OPTIMIZE_CONTINUE) {
+                // Either aborted by the scheduler or no space left.
+                return abortCode;
+            }
+
+            boolean dexOptPerformed = optimizePackage(pm, pkg, isForPrimaryDex);
+            if (dexOptPerformed) {
+                updatedPackages.add(pkg);
+            }
+        }
+        return OPTIMIZE_PROCESSED;
+    }
 
     /**
      * Try to downgrade the package to a smaller compilation filter.
diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java
index a374e14..231168e 100644
--- a/services/core/java/com/android/server/pm/ProtectedPackages.java
+++ b/services/core/java/com/android/server/pm/ProtectedPackages.java
@@ -92,6 +92,9 @@
         if (mDeviceOwnerUserId == userId) {
             return mDeviceOwnerPackage;
         }
+        if (mProfileOwnerPackages == null) {
+            return null;
+        }
         return mProfileOwnerPackages.get(userId);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 421fd28..8fb23a4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2006,6 +2006,7 @@
 
             int attrChanges = 0;
             int flagChanges = 0;
+            int privateFlagChanges = 0;
             if (attrs != null) {
                 displayPolicy.adjustWindowParamsLw(win, attrs, pid, uid);
                 // if they don't have the permission, mask out the status bar bits
@@ -2034,6 +2035,7 @@
                 }
 
                 flagChanges = win.mAttrs.flags ^ attrs.flags;
+                privateFlagChanges = win.mAttrs.privateFlags ^ attrs.privateFlags;
                 attrChanges = win.mAttrs.copyFrom(attrs);
                 if ((attrChanges & (WindowManager.LayoutParams.LAYOUT_CHANGED
                         | WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
@@ -2050,7 +2052,7 @@
                             win.getDisplayContent().getDisplayId());
                 }
 
-                if ((flagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
+                if ((privateFlagChanges & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != 0) {
                     updateNonSystemOverlayWindowsVisibilityIfNeeded(
                             win, win.mWinAnimator.getShown());
                 }
@@ -7543,7 +7545,7 @@
             return;
         }
         final boolean systemAlertWindowsHidden = !mHidingNonSystemOverlayWindows.isEmpty();
-        if (surfaceShown) {
+        if (surfaceShown && win.hideNonSystemOverlayWindowsWhenVisible()) {
             if (!mHidingNonSystemOverlayWindows.contains(win)) {
                 mHidingNonSystemOverlayWindows.add(win);
             }
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 01f2f6b..c1bbb30 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -69,6 +69,7 @@
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
     <uses-permission android:name="android.permission.HARDWARE_TEST"/>
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
 
     <!-- Uses API introduced in O (26) -->
     <uses-sdk android:minSdkVersion="1"
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
new file mode 100644
index 0000000..5c2ad94
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.audio;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class AudioDeviceBrokerTest {
+
+    private static final String TAG = "AudioDeviceBrokerTest";
+    private static final int MAX_MESSAGE_HANDLING_DELAY_MS = 100;
+
+    private Context mContext;
+    // the actual class under test
+    private AudioDeviceBroker mAudioDeviceBroker;
+
+    @Mock private AudioService mMockAudioService;
+    @Spy private AudioDeviceInventory mSpyDevInventory;
+
+    private BluetoothDevice mFakeBtDevice;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getTargetContext();
+
+        mMockAudioService = mock(AudioService.class);
+        mSpyDevInventory = spy(new AudioDeviceInventory());
+        mAudioDeviceBroker = new AudioDeviceBroker(mContext, mMockAudioService, mSpyDevInventory);
+        mSpyDevInventory.setDeviceBroker(mAudioDeviceBroker);
+
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        mFakeBtDevice = adapter.getRemoteDevice("00:01:02:03:04:05");
+        Assert.assertNotNull("invalid null BT device", mFakeBtDevice);
+    }
+
+    @After
+    public void tearDown() throws Exception { }
+
+    @Test
+    public void testSetUpAndTearDown() { }
+
+    /**
+     * Verify call to postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent() for connection
+     * calls into AudioDeviceInventory with the right params
+     * @throws Exception
+     */
+    @Test
+    public void testPostA2dpDeviceConnectionChange() throws Exception {
+        Log.i(TAG, "testPostA2dpDeviceConnectionChange");
+        Assert.assertNotNull("invalid null BT device", mFakeBtDevice);
+
+        mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1);
+        Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
+        verify(mSpyDevInventory, times(1)).setBluetoothA2dpDeviceConnectionState(
+                any(BluetoothDevice.class),
+                ArgumentMatchers.eq(BluetoothProfile.STATE_CONNECTED) /*state*/,
+                ArgumentMatchers.eq(BluetoothProfile.A2DP) /*profile*/,
+                ArgumentMatchers.eq(true) /*suppressNoisyIntent*/, anyInt() /*musicDevice*/,
+                ArgumentMatchers.eq(1) /*a2dpVolume*/
+        );
+    }
+
+    /**
+     * Verify call to postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent() for
+     *    connection > pause > disconnection > connection
+     * keeps the device connected
+     * @throws Exception
+     */
+    @Test
+    public void testA2dpDeviceConnectionDisconnectionConnectionChange() throws Exception {
+        Log.i(TAG, "testA2dpDeviceConnectionDisconnectionConnectionChange");
+
+        doTestConnectionDisconnectionReconnection(0);
+    }
+
+    /**
+     * Verify device disconnection and reconnection within the BECOMING_NOISY window
+     * @throws Exception
+     */
+    @Test
+    public void testA2dpDeviceReconnectionWithinBecomingNoisyDelay() throws Exception {
+        Log.i(TAG, "testA2dpDeviceReconnectionWithinBecomingNoisyDelay");
+
+        doTestConnectionDisconnectionReconnection(AudioService.BECOMING_NOISY_DELAY_MS / 2);
+    }
+
+    private void doTestConnectionDisconnectionReconnection(int delayAfterDisconnection)
+            throws Exception {
+        when(mMockAudioService.getDeviceForStream(AudioManager.STREAM_MUSIC))
+                .thenReturn(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+        when(mMockAudioService.isInCommunication()).thenReturn(false);
+        when(mMockAudioService.hasMediaDynamicPolicy()).thenReturn(false);
+        when(mMockAudioService.hasAudioFocusUsers()).thenReturn(false);
+
+        // first connection
+        mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 1);
+        Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
+
+        // disconnection
+        mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice,
+                BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.A2DP, false, -1);
+        if (delayAfterDisconnection > 0) {
+            Thread.sleep(delayAfterDisconnection);
+        }
+
+        // reconnection
+        mAudioDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(mFakeBtDevice,
+                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, true, 2);
+        Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS);
+
+        // Verify disconnection has been cancelled and we're seeing two connections attempts,
+        // with the device connected at the end of the test
+        verify(mSpyDevInventory, times(2)).onSetA2dpSinkConnectionState(
+                any(BtHelper.BluetoothA2dpDeviceInfo.class),
+                ArgumentMatchers.eq(BluetoothProfile.STATE_CONNECTED));
+        Assert.assertTrue("Mock device not connected",
+                mSpyDevInventory.isA2dpDeviceConnected(mFakeBtDevice));
+    }
+}
diff --git a/startop/view_compiler/dex_layout_compiler.cc b/startop/view_compiler/dex_layout_compiler.cc
index c68793d..8febfb7 100644
--- a/startop/view_compiler/dex_layout_compiler.cc
+++ b/startop/view_compiler/dex_layout_compiler.cc
@@ -23,25 +23,6 @@
 
 using android::base::StringPrintf;
 
-void LayoutValidationVisitor::VisitStartTag(const std::u16string& name) {
-  if (0 == name.compare(u"merge")) {
-    message_ = "Merge tags are not supported";
-    can_compile_ = false;
-  }
-  if (0 == name.compare(u"include")) {
-    message_ = "Include tags are not supported";
-    can_compile_ = false;
-  }
-  if (0 == name.compare(u"view")) {
-    message_ = "View tags are not supported";
-    can_compile_ = false;
-  }
-  if (0 == name.compare(u"fragment")) {
-    message_ = "Fragment tags are not supported";
-    can_compile_ = false;
-  }
-}
-
 DexViewBuilder::DexViewBuilder(dex::MethodBuilder* method)
     : method_{method},
       context_{dex::Value::Parameter(0)},
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index cd79f37..ce21112 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2328,6 +2328,13 @@
     public static final String KEY_RTT_DOWNGRADE_SUPPORTED_BOOL = "rtt_downgrade_supported_bool";
 
     /**
+     * Indicates if the TTY HCO and VCO options should be hidden in the accessibility menu
+     * if the device is capable of RTT.
+     * @hide
+     */
+    public static final String KEY_HIDE_TTY_HCO_VCO_WITH_RTT_BOOL = "hide_tty_hco_vco_with_rtt";
+
+    /**
      * The flag to disable the popup dialog which warns the user of data charges.
      * @hide
      */
@@ -3406,6 +3413,7 @@
         sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
         sDefaults.putBoolean(KEY_RTT_SUPPORTED_BOOL, false);
         sDefaults.putBoolean(KEY_TTY_SUPPORTED_BOOL, true);
+        sDefaults.putBoolean(KEY_HIDE_TTY_HCO_VCO_WITH_RTT_BOOL, false);
         sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true);
         sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index cdf4c93..aa7e21a 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -340,6 +340,19 @@
      */
     public static final int MEDIA_TIMEOUT = 77;
 
+    /**
+     * Indicates that an emergency call cannot be placed over WFC because the service is not
+     * available in the current location.
+     * @hide
+     */
+    public static final int EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE = 78;
+
+    /**
+     * Indicates that WiFi calling service is not available in the current location.
+     * @hide
+     */
+    public static final int WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 79;
+
     //*********************************************************************************************
     // When adding a disconnect type:
     // 1) Update toString() with the newly added disconnect type.
@@ -510,6 +523,10 @@
             return "OTASP_PROVISIONING_IN_PROCESS";
         case MEDIA_TIMEOUT:
             return "MEDIA_TIMEOUT";
+        case EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE:
+            return "EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE";
+        case WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION:
+            return "WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION";
         default:
             return "INVALID: " + cause;
         }
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index a478606..20aba4d 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -871,6 +871,19 @@
      */
     public static final int CODE_REJECT_ONGOING_CS_CALL = 1621;
 
+    /**
+     * An attempt was made to place an emergency call over WFC when emergency services is not
+     * currently available in the current location.
+     * @hide
+     */
+    public static final int CODE_EMERGENCY_CALL_OVER_WFC_NOT_AVAILABLE = 1622;
+
+    /**
+     * Indicates that WiFi calling service is not available in the current location.
+     * @hide
+     */
+    public static final int CODE_WFC_SERVICE_NOT_AVAILABLE_IN_THIS_LOCATION = 1623;
+
     /*
      * OEM specific error codes. To be used by OEMs when they don't want to reveal error code which
      * would be replaced by ERROR_UNSPECIFIED.