Merge "Do not translate "Wi-Fi calling" for VF DE" into oc-dr1-dev
diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
index 633dd97..e31cb53 100644
--- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/WifiCommand.java
@@ -51,6 +51,10 @@
             if (validCommand) {
                 IWifiManager wifiMgr
                         = IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE));
+                if (wifiMgr == null) {
+                    System.err.println("Wi-Fi service is not ready");
+                    return;
+                }
                 try {
                     wifiMgr.setWifiEnabled("com.android.shell", flag);
                 }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 77ce65b..be9e809 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -672,36 +672,33 @@
             entry.tag = left.tag[i];
             entry.metered = left.metered[i];
             entry.roaming = left.roaming[i];
+            entry.rxBytes = left.rxBytes[i];
+            entry.rxPackets = left.rxPackets[i];
+            entry.txBytes = left.txBytes[i];
+            entry.txPackets = left.txPackets[i];
+            entry.operations = left.operations[i];
 
             // find remote row that matches, and subtract
             final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
                     entry.metered, entry.roaming, i);
-            if (j == -1) {
-                // newly appearing row, return entire value
-                entry.rxBytes = left.rxBytes[i];
-                entry.rxPackets = left.rxPackets[i];
-                entry.txBytes = left.txBytes[i];
-                entry.txPackets = left.txPackets[i];
-                entry.operations = left.operations[i];
-            } else {
-                // existing row, subtract remote value
-                entry.rxBytes = left.rxBytes[i] - right.rxBytes[j];
-                entry.rxPackets = left.rxPackets[i] - right.rxPackets[j];
-                entry.txBytes = left.txBytes[i] - right.txBytes[j];
-                entry.txPackets = left.txPackets[i] - right.txPackets[j];
-                entry.operations = left.operations[i] - right.operations[j];
+            if (j != -1) {
+                // Found matching row, subtract remote value.
+                entry.rxBytes -= right.rxBytes[j];
+                entry.rxPackets -= right.rxPackets[j];
+                entry.txBytes -= right.txBytes[j];
+                entry.txPackets -= right.txPackets[j];
+                entry.operations -= right.operations[j];
+            }
 
-                if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
-                        || entry.txPackets < 0 || entry.operations < 0) {
-                    if (observer != null) {
-                        observer.foundNonMonotonic(left, i, right, j, cookie);
-                    }
-                    entry.rxBytes = Math.max(entry.rxBytes, 0);
-                    entry.rxPackets = Math.max(entry.rxPackets, 0);
-                    entry.txBytes = Math.max(entry.txBytes, 0);
-                    entry.txPackets = Math.max(entry.txPackets, 0);
-                    entry.operations = Math.max(entry.operations, 0);
+            if (entry.isNegative()) {
+                if (observer != null) {
+                    observer.foundNonMonotonic(left, i, right, j, cookie);
                 }
+                entry.rxBytes = Math.max(entry.rxBytes, 0);
+                entry.rxPackets = Math.max(entry.rxPackets, 0);
+                entry.txBytes = Math.max(entry.txBytes, 0);
+                entry.txPackets = Math.max(entry.txPackets, 0);
+                entry.operations = Math.max(entry.operations, 0);
             }
 
             result.addValues(entry);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 6ec755b..794b3ba 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1460,7 +1460,7 @@
             user = mService.createUser(name, flags);
             // TODO: Keep this in sync with
             // UserManagerService.LocalService.createUserEvenWhenDisallowed
-            if (user != null && !user.isAdmin()) {
+            if (user != null && !user.isAdmin() && !user.isDemo()) {
                 mService.setUserRestriction(DISALLOW_SMS, true, user.id);
                 mService.setUserRestriction(DISALLOW_OUTGOING_CALLS, true, user.id);
             }
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 401cac8..02b6185 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -323,6 +323,20 @@
     }
 
     /**
+     * Sets if the source is important for accessibility.
+     *
+     * @param importantForAccessibility True if the source is important for accessibility,
+     *                                  false otherwise.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     * @hide
+     */
+    public void setImportantForAccessibility(boolean importantForAccessibility) {
+        enforceNotSealed();
+        setBooleanProperty(PROPERTY_IMPORTANT_FOR_ACCESSIBILITY, importantForAccessibility);
+    }
+
+    /**
      * Gets the number of items that can be visited.
      *
      * @return The number of items.
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 3505c29..c123a80 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -52,9 +52,64 @@
 import java.util.Objects;
 
 /**
- * App entry point to the Autofill Framework.
+ * The {@link AutofillManager} provides ways for apps and custom views to integrate with the
+ * Autofill Framework lifecycle.
  *
- * <p>It is safe to call into this from any thread.
+ * <p>The autofill lifecycle starts with the creation of an autofill context associated with an
+ * activity context; the autofill context is created when one of the following methods is called for
+ * the first time in an activity context, and the current user has an enabled autofill service:
+ *
+ * <ul>
+ *   <li>{@link #notifyViewEntered(View)}
+ *   <li>{@link #notifyViewEntered(View, int, Rect)}
+ *   <li>{@link #requestAutofill(View)}
+ * </ul>
+ *
+ * <p>Tipically, the context is automatically created when the first view of the activity is
+ * focused because {@code View.onFocusChanged()} indirectly calls
+ * {@link #notifyViewEntered(View)}. App developers can call {@link #requestAutofill(View)} to
+ * explicitly create it (for example, a custom view developer could offer a contextual menu action
+ * in a text-field view to let users manually request autofill).
+ *
+ * <p>After the context is created, the Android System creates a {@link android.view.ViewStructure}
+ * that represents the view hierarchy by calling
+ * {@link View#dispatchProvideAutofillStructure(android.view.ViewStructure, int)} in the root views
+ * of all application windows. By default, {@code dispatchProvideAutofillStructure()} results in
+ * subsequent calls to {@link View#onProvideAutofillStructure(android.view.ViewStructure, int)} and
+ * {@link View#onProvideAutofillVirtualStructure(android.view.ViewStructure, int)} for each view in
+ * the hierarchy.
+ *
+ * <p>The resulting {@link android.view.ViewStructure} is then passed to the autofill service, which
+ * parses it looking for views that can be autofilled. If the service finds such views, it returns
+ * a data structure to the Android System containing the following optional info:
+ *
+ * <ul>
+ *   <li>Datasets used to autofill subsets of views in the activity.
+ *   <li>Id of views that the service can save their values for future autofilling.
+ * </ul>
+ *
+ * <p>When the service returns datasets, the Android System displays an autofill dataset picker
+ * UI affordance associated with the view, when the view is focused on and is part of a dataset.
+ * The application can be notified when the affordance is shown by registering an
+ * {@link AutofillCallback} through {@link #registerCallback(AutofillCallback)}. When the user
+ * selects a dataset from the affordance, all views present in the dataset are autofilled, through
+ * calls to {@link View#autofill(AutofillValue)} or {@link View#autofill(SparseArray)}.
+ *
+ * <p>When the service returns ids of savable views, the Android System keeps track of changes
+ * made to these views, so they can be used to determine if the autofill save UI is shown later.
+ *
+ * <p>The context is then finished when one of the following occurs:
+ *
+ * <ul>
+ *   <li>{@link #commit()} is called or all savable views are gone.
+ *   <li>{@link #cancel()} is called.
+ * </ul>
+ *
+ * <p>Finally, after the autofill context is commited (i.e., not cancelled), the Android System
+ * shows a save UI affordance if the value of savable views have changed. If the user selects the
+ * option to Save, the current value of the views is then sent to the autofill service.
+ *
+ * <p>It is safe to call into its methods from any thread.
  */
 @SystemService(Context.AUTOFILL_MANAGER_SERVICE)
 public final class AutofillManager {
@@ -1472,10 +1527,10 @@
     }
 
     /**
-     * Callback for auto-fill related events.
+     * Callback for autofill related events.
      *
      * <p>Typically used for applications that display their own "auto-complete" views, so they can
-     * enable / disable such views when the auto-fill UI affordance is shown / hidden.
+     * enable / disable such views when the autofill UI affordance is shown / hidden.
      */
     public abstract static class AutofillCallback {
 
@@ -1485,7 +1540,7 @@
         public @interface AutofillEventType {}
 
         /**
-         * The auto-fill input UI affordance associated with the view was shown.
+         * The autofill input UI affordance associated with the view was shown.
          *
          * <p>If the view provides its own auto-complete UI affordance and its currently shown, it
          * should be hidden upon receiving this event.
@@ -1493,7 +1548,7 @@
         public static final int EVENT_INPUT_SHOWN = 1;
 
         /**
-         * The auto-fill input UI affordance associated with the view was hidden.
+         * The autofill input UI affordance associated with the view was hidden.
          *
          * <p>If the view provides its own auto-complete UI affordance that was hidden upon a
          * {@link #EVENT_INPUT_SHOWN} event, it could be shown again now.
@@ -1501,7 +1556,7 @@
         public static final int EVENT_INPUT_HIDDEN = 2;
 
         /**
-         * The auto-fill input UI affordance associated with the view won't be shown because
+         * The autofill input UI affordance associated with the view isn't shown because
          * autofill is not available.
          *
          * <p>If the view provides its own auto-complete UI affordance but was not displaying it
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialog.java b/core/java/com/android/internal/app/MediaRouteChooserDialog.java
index 47d2a9c..7108d14 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialog.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialog.java
@@ -24,6 +24,7 @@
 import android.media.MediaRouter.RouteInfo;
 import android.os.Bundle;
 import android.text.TextUtils;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -130,7 +131,8 @@
 
         // Must be called after setContentView.
         getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
-                R.drawable.ic_media_route_off_holo_dark);
+                isLightTheme(getContext()) ? R.drawable.ic_media_route_off_holo_light
+                    : R.drawable.ic_media_route_off_holo_dark);
 
         mAdapter = new RouteAdapter(getContext());
         mListView = (ListView)findViewById(R.id.media_route_list);
@@ -176,6 +178,12 @@
         }
     }
 
+    static boolean isLightTheme(Context context) {
+        TypedValue value = new TypedValue();
+        return context.getTheme().resolveAttribute(R.attr.isLightTheme, value, true)
+                && value.data != 0;
+    }
+
     private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo>
             implements ListView.OnItemClickListener {
         private final LayoutInflater mInflater;
diff --git a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
index 237feed..3cbc9ea 100644
--- a/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
+++ b/core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java
@@ -43,8 +43,12 @@
      * </p>
      */
     public MediaRouteChooserDialogFragment() {
+        int theme = MediaRouteChooserDialog.isLightTheme(getContext())
+                ? android.R.style.Theme_DeviceDefault_Light_Dialog
+                : android.R.style.Theme_DeviceDefault_Dialog;
+
         setCancelable(true);
-        setStyle(STYLE_NORMAL, android.R.style.Theme_DeviceDefault_Dialog);
+        setStyle(STYLE_NORMAL, theme);
     }
 
     public int getRouteTypes() {
diff --git a/core/java/com/android/internal/app/MediaRouteDialogPresenter.java b/core/java/com/android/internal/app/MediaRouteDialogPresenter.java
index fad7fd4..bb2d7fa 100644
--- a/core/java/com/android/internal/app/MediaRouteDialogPresenter.java
+++ b/core/java/com/android/internal/app/MediaRouteDialogPresenter.java
@@ -71,16 +71,18 @@
         final MediaRouter router = (MediaRouter)context.getSystemService(
                 Context.MEDIA_ROUTER_SERVICE);
 
+        int theme = MediaRouteChooserDialog.isLightTheme(context)
+                ? android.R.style.Theme_DeviceDefault_Light_Dialog
+                : android.R.style.Theme_DeviceDefault_Dialog;
+
         MediaRouter.RouteInfo route = router.getSelectedRoute();
         if (route.isDefault() || !route.matchesTypes(routeTypes)) {
-            final MediaRouteChooserDialog d = new MediaRouteChooserDialog(
-                    context, android.R.style.Theme_DeviceDefault_Dialog);
+            final MediaRouteChooserDialog d = new MediaRouteChooserDialog(context, theme);
             d.setRouteTypes(routeTypes);
             d.setExtendedSettingsClickListener(extendedSettingsClickListener);
             return d;
         } else {
-            MediaRouteControllerDialog d = new MediaRouteControllerDialog(
-                    context, android.R.style.Theme_DeviceDefault_Dialog);
+            MediaRouteControllerDialog d = new MediaRouteControllerDialog(context, theme);
             return d;
         }
     }
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 1168eec..1811800c 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -111,7 +111,7 @@
         return mContext.getResources().getString(R.string.config_dozeComponent);
     }
 
-    private boolean accessibilityInversionEnabled(int user) {
+    public boolean accessibilityInversionEnabled(int user) {
         return boolSettingDefaultOff(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, user);
     }
 
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 40ecc8c..6f54b0c 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -115,4 +115,6 @@
     void remQsTile(in ComponentName tile);
     void clickQsTile(in ComponentName tile);
     void handleSystemKey(in int key);
+
+    void showShutdownUi(boolean isReboot, String reason);
 }
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index be8b9de..b03c346 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -752,7 +752,8 @@
 
 static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
         SkBitmap::Allocator* alloc) {
-    LOG_ALWAYS_FATAL_IF(kIndex_8_SkColorType == dstCT, "Error, cannot copyTo kIndex8.");
+    LOG_ALWAYS_FATAL_IF(kIndex_8_SkColorType == dstCT &&
+            kIndex_8_SkColorType != src.colorType(), "Error, cannot copyTo kIndex8.");
 
     SkPixmap srcPM;
     if (!src.peekPixels(&srcPM)) {
@@ -787,7 +788,7 @@
     if (!dst->setInfo(dstInfo)) {
         return false;
     }
-    if (!dst->tryAllocPixels(alloc, nullptr)) {
+    if (!dst->tryAllocPixels(alloc, srcPM.ctable())) {
         return false;
     }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ae115d3..2a761c6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -304,7 +304,7 @@
     <protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
-    <protected-broadcast android:name="com.android.server.action.WIPE_EUICC_DATA" />
+    <protected-broadcast android:name="com.android.internal.action.EUICC_FACTORY_RESET" />
     <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
     <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
     <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_alpha.png
deleted file mode 100644
index e0a2ba1..0000000
--- a/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_dark.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_dark.png
new file mode 100644
index 0000000..8ad305d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_light.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_light.png
new file mode 100644
index 0000000..887fde4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_alpha.png
deleted file mode 100644
index d37e8ee..0000000
--- a/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_dark.png b/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_dark.png
new file mode 100644
index 0000000..5739df7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_light.png b/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_light.png
new file mode 100644
index 0000000..58c344a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_alpha.png
deleted file mode 100644
index 0c604d9..0000000
--- a/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_dark.png
new file mode 100644
index 0000000..ac699cf
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_light.png
new file mode 100644
index 0000000..84c5a11
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_alpha.png
deleted file mode 100644
index 2c3f4ff..0000000
--- a/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_dark.png
new file mode 100644
index 0000000..372ab35
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_light.png
new file mode 100644
index 0000000..7fc993d6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_alpha.png
deleted file mode 100644
index 991c50e..0000000
--- a/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_dark.png
new file mode 100644
index 0000000..3261626
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_light.png
new file mode 100644
index 0000000..36adcd0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_alpha.png
deleted file mode 100644
index 05fb919..0000000
--- a/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_dark.png b/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_dark.png
new file mode 100644
index 0000000..9fbc9b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_light.png b/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_light.png
new file mode 100644
index 0000000..086aefe
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_dark.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_dark.png
new file mode 100644
index 0000000..4446ea4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_light.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_light.png
new file mode 100644
index 0000000..4d790c6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_mtrl_dark.png b/core/res/res/drawable-mdpi/ic_media_route_off_mtrl_dark.png
new file mode 100644
index 0000000..c401dc0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_mtrl_light.png b/core/res/res/drawable-mdpi/ic_media_route_off_mtrl_light.png
new file mode 100644
index 0000000..e24d58650
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_mtrl_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_mtrl_dark.png
new file mode 100644
index 0000000..5a9fea0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_mtrl_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_mtrl_light.png
new file mode 100644
index 0000000..3029695
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_mtrl_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_mtrl_dark.png
new file mode 100644
index 0000000..d8d0b7b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_mtrl_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_mtrl_light.png
new file mode 100644
index 0000000..868c7f4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_mtrl_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_mtrl_dark.png
new file mode 100644
index 0000000..83a1b69
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_mtrl_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_mtrl_light.png
new file mode 100644
index 0000000..269ee8e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_mtrl_dark.png b/core/res/res/drawable-mdpi/ic_media_route_on_mtrl_dark.png
new file mode 100644
index 0000000..9f3d12e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_mtrl_light.png b/core/res/res/drawable-mdpi/ic_media_route_on_mtrl_light.png
new file mode 100644
index 0000000..ca865f2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_dark.png
new file mode 100644
index 0000000..c4dc132
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_light.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_light.png
new file mode 100644
index 0000000..b14617c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_mtrl_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_off_mtrl_dark.png
new file mode 100644
index 0000000..bb30773
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_mtrl_light.png b/core/res/res/drawable-xhdpi/ic_media_route_off_mtrl_light.png
new file mode 100644
index 0000000..a05d7d7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_mtrl_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_mtrl_dark.png
new file mode 100644
index 0000000..8690cf4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_mtrl_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_mtrl_light.png
new file mode 100644
index 0000000..2cf94ce
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_mtrl_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_mtrl_dark.png
new file mode 100644
index 0000000..e3fd200
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_mtrl_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_mtrl_light.png
new file mode 100644
index 0000000..0af22be
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_mtrl_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_mtrl_dark.png
new file mode 100644
index 0000000..6cb970c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_mtrl_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_mtrl_light.png
new file mode 100644
index 0000000..9577e7b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_mtrl_dark.png b/core/res/res/drawable-xhdpi/ic_media_route_on_mtrl_dark.png
new file mode 100644
index 0000000..8290b98
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_mtrl_light.png b/core/res/res/drawable-xhdpi/ic_media_route_on_mtrl_light.png
new file mode 100644
index 0000000..abdecfb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_dark.png
new file mode 100644
index 0000000..fdb2121
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_light.png
new file mode 100644
index 0000000..9ce7e3a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_mtrl_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_mtrl_dark.png
new file mode 100644
index 0000000..e8601ce
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_mtrl_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_mtrl_light.png
new file mode 100644
index 0000000..34928d7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_mtrl_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_mtrl_dark.png
new file mode 100644
index 0000000..23d8ba8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_mtrl_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_mtrl_light.png
new file mode 100644
index 0000000..ef5039c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_mtrl_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_mtrl_dark.png
new file mode 100644
index 0000000..4c0f0e0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_mtrl_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_mtrl_light.png
new file mode 100644
index 0000000..8cd82da
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_mtrl_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_mtrl_dark.png
new file mode 100644
index 0000000..ecfe346
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_mtrl_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_mtrl_light.png
new file mode 100644
index 0000000..d25288d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_mtrl_dark.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_mtrl_dark.png
new file mode 100644
index 0000000..8e47095
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_mtrl_dark.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_mtrl_light.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_mtrl_light.png
new file mode 100644
index 0000000..4b64a48
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_mtrl_light.png
Binary files differ
diff --git a/core/res/res/drawable/ic_media_route_connecting_material.xml b/core/res/res/drawable/ic_media_route_connecting_material_dark.xml
similarity index 100%
rename from core/res/res/drawable/ic_media_route_connecting_material.xml
rename to core/res/res/drawable/ic_media_route_connecting_material_dark.xml
diff --git a/core/res/res/drawable/ic_media_route_connecting_material.xml b/core/res/res/drawable/ic_media_route_connecting_material_light.xml
similarity index 100%
copy from core/res/res/drawable/ic_media_route_connecting_material.xml
copy to core/res/res/drawable/ic_media_route_connecting_material_light.xml
diff --git a/core/res/res/drawable/ic_media_route_material.xml b/core/res/res/drawable/ic_media_route_material_dark.xml
similarity index 97%
rename from core/res/res/drawable/ic_media_route_material.xml
rename to core/res/res/drawable/ic_media_route_material_dark.xml
index 3e3f388..eb26ac8 100644
--- a/core/res/res/drawable/ic_media_route_material.xml
+++ b/core/res/res/drawable/ic_media_route_material_dark.xml
@@ -17,7 +17,7 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_checked="true" android:state_enabled="true"
-        android:drawable="@android:drawable/ic_media_route_connecting_material" />
+        android:drawable="@android:drawable/ic_media_route_connecting_material_dark" />
     <item android:state_activated="true" android:state_enabled="true">
         <bitmap android:src="@android:drawable/ic_media_route_on_mtrl_alpha"
             android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_media_route_material.xml b/core/res/res/drawable/ic_media_route_material_light.xml
similarity index 97%
copy from core/res/res/drawable/ic_media_route_material.xml
copy to core/res/res/drawable/ic_media_route_material_light.xml
index 3e3f388..37bbf14 100644
--- a/core/res/res/drawable/ic_media_route_material.xml
+++ b/core/res/res/drawable/ic_media_route_material_light.xml
@@ -17,7 +17,7 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_checked="true" android:state_enabled="true"
-        android:drawable="@android:drawable/ic_media_route_connecting_material" />
+        android:drawable="@android:drawable/ic_media_route_connecting_material_light" />
     <item android:state_activated="true" android:state_enabled="true">
         <bitmap android:src="@android:drawable/ic_media_route_on_mtrl_alpha"
             android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index d62b93e..cf67abf 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -39,4 +39,7 @@
 
     <!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
     <bool name="config_useDefaultFocusHighlight">false</bool>
+
+    <!-- Allow SystemUI to show the shutdown dialog -->
+    <bool name="config_showSysuiShutdown">false</bool>
 </resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index e190bd1..5baf985 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -66,8 +66,10 @@
         <item>@drawable/ic_find_previous_material</item>
         <item>@drawable/ic_go</item>
         <item>@drawable/ic_go_search_api_material</item>
-        <item>@drawable/ic_media_route_connecting_material</item>
-        <item>@drawable/ic_media_route_material</item>
+        <item>@drawable/ic_media_route_connecting_material_dark</item>
+        <item>@drawable/ic_media_route_connecting_material_light</item>
+        <item>@drawable/ic_media_route_material_dark</item>
+        <item>@drawable/ic_media_route_material_light</item>
         <item>@drawable/ic_menu_close_clear_cancel</item>
         <item>@drawable/ic_menu_copy_material</item>
         <item>@drawable/ic_menu_cut_material</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7144127..831a3a8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3000,4 +3000,7 @@
 
     <!-- Enable the RingtonePickerActivity in 'com.android.providers.media'. -->
     <bool name="config_defaultRingtonePickerEnabled">true</bool>
+
+    <!-- Allow SystemUI to show the shutdown dialog -->
+    <bool name="config_showSysuiShutdown">true</bool>
 </resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index c783ea8..f39904d 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -1054,7 +1054,7 @@
     </style>
 
     <style name="Widget.Material.MediaRouteButton" parent ="Widget.Material.ActionButton">
-        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_material</item>
+        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_material_dark</item>
         <item name="contentDescription">@string/media_route_button_content_description</item>
     </style>
 
@@ -1203,7 +1203,10 @@
     <style name="Widget.Material.Light.ActionBar" parent="Widget.Material.ActionBar" />
     <style name="Widget.Material.Light.ActionBar.Solid" parent="Widget.Material.ActionBar.Solid" />
     <style name="Widget.Material.Light.FastScroll" parent="Widget.Material.FastScroll"/>
-    <style name="Widget.Material.Light.MediaRouteButton" parent="Widget.Material.MediaRouteButton" />
+
+    <style name="Widget.Material.Light.MediaRouteButton" parent ="Widget.Material.MediaRouteButton">
+        <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_material_light</item>
+    </style>
 
     <!-- Animation Styles -->
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4726dcf..29f4394 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1318,10 +1318,8 @@
   <java-symbol type="drawable" name="unlock_wave" />
   <java-symbol type="drawable" name="notification_template_icon_bg" />
   <java-symbol type="drawable" name="notification_template_icon_low_bg" />
-  <java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
   <java-symbol type="drawable" name="ic_media_route_off_holo_dark" />
-  <java-symbol type="drawable" name="ic_media_route_connecting_holo_dark" />
-  <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
+  <java-symbol type="drawable" name="ic_media_route_off_holo_light" />
   <java-symbol type="drawable" name="cling_button" />
   <java-symbol type="drawable" name="cling_arrow_up" />
   <java-symbol type="drawable" name="cling_bg" />
@@ -3067,4 +3065,5 @@
   <java-symbol type="bool" name="config_showAreaUpdateInfoSettings" />
   <java-symbol type="layout" name="shutdown_dialog" />
   <java-symbol type="dimen" name="chooser_service_spacing" />
+  <java-symbol type="bool" name="config_showSysuiShutdown" />
 </resources>
diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml
index 7fafef7..3a81c13 100644
--- a/data/etc/framework-sysconfig.xml
+++ b/data/etc/framework-sysconfig.xml
@@ -28,4 +28,6 @@
     <backup-transport-whitelisted-service
         service="android/com.android.internal.backup.LocalTransportService" />
 
+    <!-- Whitelist of bundled applications which all handle URLs to their websites by default -->
+    <app-link package="com.android.carrierdefaultapp" />
 </config>
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 20deeb16..05be088 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1501,7 +1501,9 @@
         if (AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADSET,"")
                 == AudioSystem.DEVICE_STATE_UNAVAILABLE &&
             AudioSystem.getDeviceConnectionState(DEVICE_OUT_WIRED_HEADPHONE,"")
-                == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
+                == AudioSystem.DEVICE_STATE_UNAVAILABLE &&
+            AudioSystem.getDeviceConnectionState(DEVICE_OUT_USB_HEADSET, "")
+              == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
             return false;
         } else {
             return true;
@@ -3324,6 +3326,9 @@
      * The audio output device code for a wired headphone without attached microphone */
     public static final int DEVICE_OUT_WIRED_HEADPHONE = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
     /** @hide
+     * The audio output device code for a USB headphone with attached microphone */
+    public static final int DEVICE_OUT_USB_HEADSET = AudioSystem.DEVICE_OUT_USB_HEADSET;
+    /** @hide
      * The audio output device code for generic Bluetooth SCO, for voice */
     public static final int DEVICE_OUT_BLUETOOTH_SCO = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
     /** @hide
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index c309133..1cd7b61 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -34,6 +34,7 @@
             <intent-filter>
                 <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
                 <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
+                <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
                 <action android:name="android.intent.action.LOCALE_CHANGED" />
             </intent-filter>
         </receiver>
@@ -43,10 +44,24 @@
             android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
             android:label="@string/action_bar_label"
             android:theme="@style/AppTheme"
-            android:configChanges="keyboardHidden|orientation|screenSize" >
+            android:configChanges="keyboardHidden|orientation|screenSize">
             <intent-filter>
                 <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
+
+        <activity-alias
+            android:name="com.android.carrierdefaultapp.URLHandlerActivity"
+            android:targetActivity="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
+            android:enabled="false" >
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" />
+                <data android:scheme="https" />
+                <data android:host="*" />
+            </intent-filter>
+        </activity-alias>
     </application>
 </manifest>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index 6194b87..b0052cc 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -20,6 +20,9 @@
 import android.app.LoadedApk;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.net.ConnectivityManager;
 import android.net.ConnectivityManager.NetworkCallback;
@@ -34,6 +37,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.TypedValue;
@@ -68,7 +72,7 @@
     private static final boolean DBG = true;
 
     private static final int SOCKET_TIMEOUT_MS = 10 * 1000;
-    public static final int NETWORK_REQUEST_TIMEOUT_MS = 5 * 1000;
+    private static final int NETWORK_REQUEST_TIMEOUT_MS = 5 * 1000;
 
     private URL mUrl;
     private Network mNetwork;
@@ -188,16 +192,19 @@
             CarrierActionUtils.applyCarrierAction(
                     CarrierActionUtils.CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS, getIntent(),
                     getApplicationContext());
-
+            CarrierActionUtils.applyCarrierAction(
+                    CarrierActionUtils.CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER, getIntent(),
+                    getApplicationContext());
+            CarrierActionUtils.applyCarrierAction(
+                    CarrierActionUtils.CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL, getIntent(),
+                    getApplicationContext());
         }
         finishAndRemoveTask();
     }
 
     private URL getUrlForCaptivePortal() {
         String url = getIntent().getStringExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY);
-        if (url.isEmpty()) {
-            url = mCm.getCaptivePortalServerUrl();
-        }
+        if (TextUtils.isEmpty(url)) url = mCm.getCaptivePortalServerUrl();
         final CarrierConfigManager configManager = getApplicationContext()
                 .getSystemService(CarrierConfigManager.class);
         final int subId = getIntent().getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
@@ -437,6 +444,27 @@
         }
     }
 
+    /**
+     * This alias presents the target activity, CaptivePortalLoginActivity, as a independent
+     * entity with its own intent filter to handle URL links. This alias will be enabled/disabled
+     * dynamically to handle url links based on the network conditions.
+     */
+    public static String getAlias(Context context) {
+        try {
+            PackageInfo p = context.getPackageManager().getPackageInfo(context.getPackageName(),
+                    PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS);
+            for (ActivityInfo activityInfo : p.activities) {
+                String targetActivity = activityInfo.targetActivity;
+                if (CaptivePortalLoginActivity.class.getName().equals(targetActivity)) {
+                    return activityInfo.name;
+                }
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
     private static void logd(String s) {
         Rlog.d(TAG, s);
     }
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 0213306..a2bf964 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -19,8 +19,10 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.telephony.SubscriptionManager;
@@ -49,6 +51,10 @@
     public static final int CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION          = 4;
     public static final int CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION = 5;
     public static final int CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS          = 6;
+    public static final int CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER        = 7;
+    public static final int CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER       = 8;
+    public static final int CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL    = 9;
+    public static final int CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL  = 10;
 
     public static void applyCarrierAction(int actionIdx, Intent intent, Context context) {
         switch (actionIdx) {
@@ -73,6 +79,18 @@
             case CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS:
                 onCancelAllNotifications(context);
                 break;
+            case CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER:
+                onEnableDefaultURLHandler(context);
+                break;
+            case CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER:
+                onDisableDefaultURLHandler(context);
+                break;
+            case CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL:
+                onRegisterDefaultNetworkAvail(intent, context);
+                break;
+            case CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL:
+                onDeregisterDefaultNetworkAvail(intent, context);
+                break;
             default:
                 loge("unsupported carrier action index: " + actionIdx);
         }
@@ -94,6 +112,38 @@
         telephonyMgr.carrierActionSetMeteredApnsEnabled(subId, ENABLE);
     }
 
+    private static void onEnableDefaultURLHandler(Context context) {
+        logd("onEnableDefaultURLHandler");
+        final PackageManager pm = context.getPackageManager();
+        pm.setComponentEnabledSetting(
+                new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)),
+                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+    }
+
+    private static void onDisableDefaultURLHandler(Context context) {
+        logd("onDisableDefaultURLHandler");
+        final PackageManager pm = context.getPackageManager();
+        pm.setComponentEnabledSetting(
+                new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)),
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+    }
+
+    private static void onRegisterDefaultNetworkAvail(Intent intent, Context context) {
+        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+                SubscriptionManager.getDefaultVoiceSubscriptionId());
+        logd("onRegisterDefaultNetworkAvail subId: " + subId);
+        final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+        telephonyMgr.carrierActionReportDefaultNetworkStatus(subId, true);
+    }
+
+    private static void onDeregisterDefaultNetworkAvail(Intent intent, Context context) {
+        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+                SubscriptionManager.getDefaultVoiceSubscriptionId());
+        logd("onDeregisterDefaultNetworkAvail subId: " + subId);
+        final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+        telephonyMgr.carrierActionReportDefaultNetworkStatus(subId, false);
+    }
+
     private static void onDisableRadio(Intent intent, Context context) {
         int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
                 SubscriptionManager.getDefaultVoiceSubscriptionId());
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
index d5d0b79..02c61d7 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
@@ -22,7 +22,6 @@
 import android.telephony.Rlog;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Pair;
 
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.util.ArrayUtils;
@@ -95,6 +94,12 @@
                     configs = b.getStringArray(CarrierConfigManager
                             .KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET);
                     break;
+                case TelephonyIntents.ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE:
+                    configs = b.getStringArray(CarrierConfigManager
+                            .KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE);
+                    arg1 = String.valueOf(intent.getBooleanExtra(TelephonyIntents
+                            .EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY, false));
+                    break;
                 default:
                     Rlog.e(TAG, "load carrier config failure with un-configured key: " +
                             intent.getAction());
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 8f62100..306f9ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -223,6 +223,8 @@
             mProviderFriendlyName = savedState.getString(KEY_PROVIDER_FRIENDLY_NAME);
         }
         update(mConfig, mInfo, mNetworkInfo);
+
+        // Do not evict old scan results on initial creation
         updateRssi();
         updateSeen();
         mId = sLastId.incrementAndGet();
@@ -442,10 +444,6 @@
     }
 
     private void evictOldScanResults() {
-        if (WifiTracker.sStaleScanResults) {
-            // Do not evict old scan results unless we are scanning and have fresh results.
-            return;
-        }
         long nowMs = SystemClock.elapsedRealtime();
         for (Iterator<ScanResult> iter = mScanResultCache.values().iterator(); iter.hasNext(); ) {
             ScanResult result = iter.next();
@@ -509,12 +507,8 @@
      * results, returning the best RSSI for all matching AccessPoints averaged with the previous
      * value. If the access point is not connected and there are no scan results, the rssi will be
      * set to {@link #UNREACHABLE_RSSI}.
-     *
-     * <p>Old scan results will be evicted from the cache when this method is invoked.
      */
     private void updateRssi() {
-        evictOldScanResults();
-
         if (this.isActive()) {
             return;
         }
@@ -533,14 +527,8 @@
         }
     }
 
-    /**
-     * Updates {@link #mSeen} based on the scan result cache.
-     *
-     * <p>Old scan results will be evicted from the cache when this method is invoked.
-     */
+    /** Updates {@link #mSeen} based on the scan result cache. */
     private void updateSeen() {
-        evictOldScanResults();
-
         // TODO(sghuman): Set to now if connected
 
         long seen = 0;
@@ -1030,12 +1018,22 @@
         mAccessPointListener = listener;
     }
 
-    boolean update(ScanResult result) {
+    /**
+     * Update the AP with the given scan result.
+     *
+     * @param result the ScanResult to add to the AccessPoint scan cache
+     * @param evictOldScanResults whether stale scan results should be removed
+     *         from the cache during this update process
+     * @return true if the scan result update caused a change in state which would impact ranking
+     *     or AccessPoint rendering (e.g. wifi level, security)
+     */
+    boolean update(ScanResult result, boolean evictOldScanResults) {
         if (matches(result)) {
             int oldLevel = getLevel();
 
             /* Add or update the scan result for the BSSID */
             mScanResultCache.put(result.BSSID, result);
+            if (evictOldScanResults) evictOldScanResults();
             updateSeen();
             updateRssi();
             int newLevel = getLevel();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index b299961..f8e2f8b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -145,7 +145,7 @@
     Scanner mScanner;
 
     @GuardedBy("mLock")
-    static boolean sStaleScanResults = true;
+    private boolean mStaleScanResults = true;
 
     public WifiTracker(Context context, WifiListener wifiListener,
             boolean includeSaved, boolean includeScans) {
@@ -354,7 +354,7 @@
      * <p>This should always be called when done with a WifiTracker (if startTracking was called) to
      * ensure proper cleanup and prevent any further callbacks from occurring.
      *
-     * <p>Calling this method will set the {@link #sStaleScanResults} bit, which prevents
+     * <p>Calling this method will set the {@link #mStaleScanResults} bit, which prevents
      * {@link WifiListener#onAccessPointsChanged()} callbacks from being invoked (until the bit
      * is unset on the next SCAN_RESULTS_AVAILABLE_ACTION).
      */
@@ -372,7 +372,7 @@
 
             mWorkHandler.removePendingMessages();
             mMainHandler.removePendingMessages();
-            sStaleScanResults = true;
+            mStaleScanResults = true;
         }
     }
 
@@ -478,14 +478,14 @@
     /**
      * Safely modify {@link #mInternalAccessPoints} by acquiring {@link #mLock} first.
      *
-     * <p>Will not perform the update if {@link #sStaleScanResults} is true
+     * <p>Will not perform the update if {@link #mStaleScanResults} is true
      */
     private void updateAccessPoints() {
         List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
         final List<ScanResult> newScanResults = mWifiManager.getScanResults();
 
         synchronized (mLock) {
-            if(!sStaleScanResults) {
+            if(!mStaleScanResults) {
                 updateAccessPointsLocked(newScanResults, configs);
             }
         }
@@ -495,7 +495,7 @@
      * Update the internal list of access points.
      *
      * <p>Do not called directly (except for forceUpdate), use {@link #updateAccessPoints()} which
-     * respects {@link #sStaleScanResults}.
+     * respects {@link #mStaleScanResults}.
      */
     @GuardedBy("mLock")
     private void updateAccessPointsLocked(final List<ScanResult> newScanResults,
@@ -569,7 +569,8 @@
 
                 boolean found = false;
                 for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
-                    if (accessPoint.update(result)) {
+                    // We want to evict old scan results if are current results are not stale
+                    if (accessPoint.update(result, !mStaleScanResults)) {
                         found = true;
                         break;
                     }
@@ -642,7 +643,8 @@
         for (int i = 0; i < N; i++) {
             if (cache.get(i).matches(result)) {
                 AccessPoint ret = cache.remove(i);
-                ret.update(result);
+                // evict old scan results only if we have fresh results
+                ret.update(result, !mStaleScanResults);
                 return ret;
             }
         }
@@ -842,7 +844,7 @@
                     // Only notify listeners of changes if we have fresh scan results, otherwise the
                     // UI will be updated with stale results. We want to copy the APs regardless,
                     // for instances where forceUpdate was invoked by the caller.
-                    if (sStaleScanResults) {
+                    if (mStaleScanResults) {
                         copyAndNotifyListeners(false /*notifyListeners*/);
                     } else {
                         copyAndNotifyListeners(true /*notifyListeners*/);
@@ -897,7 +899,7 @@
             switch (msg.what) {
                 case MSG_UPDATE_ACCESS_POINTS:
                     if (msg.arg1 == CLEAR_STALE_SCAN_RESULTS) {
-                        sStaleScanResults = false;
+                        mStaleScanResults = false;
                     }
                     updateAccessPoints();
                     break;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 2f02b9b..88d3a32 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -247,7 +247,7 @@
         scanResult.BSSID = "bssid";
         scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
         scanResult.capabilities = "";
-        assertThat(ap.update(scanResult)).isTrue();
+        assertThat(ap.update(scanResult, true /* evict old scan results */)).isTrue();
 
         assertThat(ap.getRssi()).isEqualTo(expectedRssi);
     }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 76d9823..df6587e 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -137,7 +137,6 @@
     private Looper mMainLooper;
 
     private int mOriginalScoringUiSettingValue;
-    private boolean mOriginalStaleScanResultsValue;
 
     @Before
     public void setUp() {
@@ -213,7 +212,6 @@
                 Settings.Global.NETWORK_SCORING_UI_ENABLED,
                 1 /* enabled */);
 
-        mOriginalStaleScanResultsValue = WifiTracker.sStaleScanResults;
     }
 
     @After
@@ -222,8 +220,6 @@
                 InstrumentationRegistry.getTargetContext().getContentResolver(),
                 Settings.Global.NETWORK_SCORING_UI_ENABLED,
                 mOriginalScoringUiSettingValue);
-
-        WifiTracker.sStaleScanResults = mOriginalStaleScanResultsValue;
     }
 
     private static ScanResult buildScanResult1() {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
index bb21fb3..1f633da 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
@@ -26,6 +26,8 @@
     int VERSION = 1;
 
     void showGlobalActions(GlobalActionsManager manager);
+    default void showShutdownUi(boolean isReboot, String reason) {
+    }
 
     @ProvidesInterface(version = GlobalActionsManager.VERSION)
     public interface GlobalActionsManager {
diff --git a/packages/SystemUI/res/drawable/ic_close_white_rounded.xml b/packages/SystemUI/res/drawable/ic_close_white_rounded.xml
new file mode 100644
index 0000000..ca37698
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_close_white_rounded.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M18.3,5.71a0.996,0.996 0,0 0,-1.41 0L12,10.59 7.11,5.7A0.996,0.996 0,1 0,5.7 7.11L10.59,12 5.7,16.89a0.996,0.996 0,1 0,1.41 1.41L12,13.41l4.89,4.89a0.996,0.996 0,1 0,1.41 -1.41L13.41,12l4.89,-4.89c0.38,-0.38 0.38,-1.02 0,-1.4z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_minus.xml b/packages/SystemUI/res/drawable/ic_qs_minus.xml
index 6a3410a..ead6b03 100644
--- a/packages/SystemUI/res/drawable/ic_qs_minus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_minus.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,12 +15,10 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24.0dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
     android:width="24.0dp" >
-
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M38.0,26.0L10.0,26.0l0.0,-4.0l28.0,0.0l0.0,4.0z" />
-
-</vector>
\ No newline at end of file
+        android:pathData="M18,13H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h12c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_plus.xml b/packages/SystemUI/res/drawable/ic_qs_plus.xml
index 393f51c..f1b19e1e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_plus.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,12 +15,10 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24.0dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
     android:width="24.0dp" >
-
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M38.0,26.0L26.0,26.0l0.0,12.0l-4.0,0.0L22.0,26.0L10.0,26.0l0.0,-4.0l12.0,0.0L22.0,10.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z" />
-
-</vector>
\ No newline at end of file
+        android:pathData="M18,13h-5v5c0,0.55 -0.45,1 -1,1h0c-0.55,0 -1,-0.45 -1,-1v-5H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h5V6c0,-0.55 0.45,-1 1,-1h0c0.55,0 1,0.45 1,1v5h5c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
index 370f89c..d73e2a4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
@@ -22,19 +22,19 @@
     The asset contains a briefcase symbol of 15.26dp x 13.6dp in the center.
 -->
     <path
-        android:fillColor="@android:color/white"
+        android:fillColor="#ff000000"
         android:pathData="M15.0815,4.5903 L15.0815,3.43636 L13.9276,2.2 L9.14696,2.2 L7.99302,3.43636
 L7.99302,4.5903 L9.14696,4.5903 L9.14696,3.43636 L13.9276,3.43636
 L13.9276,4.5903 Z" />
     <path
-        android:fillColor="@android:color/white"
+        android:fillColor="#ff000000"
         android:pathData="M18.0488,4.5903 L5.02575,4.5903 C4.36635,4.5903,3.87181,5.08485,3.87181,5.74424
 L3.87181,9.28848 C3.87181,9.94788,4.36635,10.4424,5.02575,10.4424
 L9.72393,10.4424 L9.72393,9.28848 L13.2682,9.28848 L13.2682,10.4424
 L17.9664,10.4424 C18.6257,10.4424,19.1203,9.94788,19.1203,9.28848
 L19.1203,5.74424 C19.2027,5.08485,18.6257,4.5903,18.0488,4.5903 Z" />
     <path
-        android:fillColor="@android:color/white"
+        android:fillColor="#ff000000"
         android:pathData="M9.80635,12.8327 L9.80635,11.6788 L4.44878,11.6788 L4.44878,14.6461
 C4.44878,15.3055,4.94332,15.8,5.60272,15.8 L17.3894,15.8
 C18.0488,15.8,18.5433,15.3055,18.5433,14.6461 L18.5433,11.6788 L13.2682,11.6788
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index 38627b6..7ffcb1e 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -51,7 +51,7 @@
             android:clickable="true"
             android:contentDescription="@string/accessibility_desc_close"
             android:scaleType="center"
-            android:src="@drawable/ic_close_white" />
+            android:src="@drawable/ic_close_white_rounded" />
 
         <TextView
             android:id="@+id/zen_introduction_message"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 5516983..3826bdd 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -59,7 +59,7 @@
                 android:clickable="true"
                 android:contentDescription="@string/accessibility_desc_close"
                 android:scaleType="center"
-                android:src="@drawable/ic_close_white" />
+                android:src="@drawable/ic_close_white_rounded" />
 
             <TextView
                 android:id="@+id/zen_introduction_message"
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0b59e1d..11f3fc0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -726,8 +726,8 @@
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Tanca"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrossega cap avall per ignorar-ho"</string>
-    <string name="pip_menu_title" msgid="3328510504196964712">"Menú per a Imatge en imatge"</string>
-    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> està en imatge en imatge"</string>
+    <string name="pip_menu_title" msgid="3328510504196964712">"Menú per a Pantalla en pantalla"</string>
+    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string>
     <string name="pip_notification_message" msgid="4171698133469539591">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
     <string name="pip_play" msgid="1417176722760265888">"Reprodueix"</string>
     <string name="pip_pause" msgid="8881063404466476571">"Posa en pausa"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 1271a27..60510d3 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -67,12 +67,12 @@
     <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"Սարքի վրա այս պահին մուտք գործած օգտատերը չի կարող միացնել USB վրիպազերծումը: Այս գործառույթից օգտվելու համար մուտք գործեք ադմինիստրատորի հաշվով:"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Խոշորացնել` էկրանը լցնելու համար"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ձգել` էկրանը լցնելու համար"</string>
-    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Պահում է էկրանի հանույթը…"</string>
-    <string name="screenshot_saving_title" msgid="8242282144535555697">"Պահում է էկրանի հանույթը..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Էկրանի հանույթը պահվում է:"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի հանույթը լուսանկարվել է:"</string>
+    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Պահում է էկրանի պատկերը…"</string>
+    <string name="screenshot_saving_title" msgid="8242282144535555697">"Պահում է էկրանի պատկերը..."</string>
+    <string name="screenshot_saving_text" msgid="2419718443411738818">"Էկրանի պատկերը պահվում է:"</string>
+    <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի պատկերը լուսանկարվել է:"</string>
     <string name="screenshot_saved_text" msgid="2685605830386712477">"Հպեք՝ էկրանի պատկերը տեսնելու համար:"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի հանույթը:"</string>
+    <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի պատկերը:"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Էկրանի պատկերը պահելիս խնդիր առաջացավ:"</string>
     <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Չհաջողվեց պահել էկրանի պատկերը սահմանափակ հիշողության պատճառով:"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում էկրանի պատկերի ստացումը"</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 99111f8..aacb4aa 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -307,6 +307,9 @@
         <item name="android:colorControlHighlight">@*android:color/primary_text_material_dark</item>
         <item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
         <item name="passwordStyle">@style/PasswordTheme</item>
+
+        <!-- Needed for MediaRoute chooser dialog -->
+        <item name="*android:isLightTheme">false</item>
     </style>
 
     <style name="Theme.SystemUI.Light" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
index 2bec2c7..f7936b6 100644
--- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
+++ b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
@@ -18,20 +18,26 @@
 import static com.android.systemui.tuner.TunablePadding.FLAG_END;
 
 import android.app.Fragment;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
 import android.graphics.PixelFormat;
+import android.provider.Settings.Secure;
 import android.support.annotation.VisibleForTesting;
 import android.util.DisplayMetrics;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnLayoutChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
+import android.widget.ImageView;
 
 import com.android.systemui.R.id;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
 import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.SecureSetting;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.NavigationBarFragment;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -69,12 +75,14 @@
         mOverlay = LayoutInflater.from(mContext)
                 .inflate(R.layout.rounded_corners, null);
         mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+        mOverlay.setAlpha(0);
         mOverlay.findViewById(R.id.right).setRotation(90);
 
         mContext.getSystemService(WindowManager.class)
                 .addView(mOverlay, getWindowLayoutParams());
         mBottomOverlay = LayoutInflater.from(mContext)
                 .inflate(R.layout.rounded_corners, null);
+        mBottomOverlay.setAlpha(0);
         mBottomOverlay.findViewById(R.id.right).setRotation(180);
         mBottomOverlay.findViewById(R.id.left).setRotation(270);
         WindowManager.LayoutParams layoutParams = getWindowLayoutParams();
@@ -88,6 +96,39 @@
         mDensity = metrics.density;
 
         Dependency.get(TunerService.class).addTunable(this, SIZE);
+
+        // Watch color inversion and invert the overlay as needed.
+        SecureSetting setting = new SecureSetting(mContext, Dependency.get(Dependency.MAIN_HANDLER),
+                Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) {
+            @Override
+            protected void handleValueChanged(int value, boolean observedChange) {
+                int tint = value != 0 ? Color.WHITE : Color.BLACK;
+                ColorStateList tintList = ColorStateList.valueOf(tint);
+                ((ImageView) mOverlay.findViewById(id.left)).setImageTintList(tintList);
+                ((ImageView) mOverlay.findViewById(id.right)).setImageTintList(tintList);
+                ((ImageView) mBottomOverlay.findViewById(id.left)).setImageTintList(tintList);
+                ((ImageView) mBottomOverlay.findViewById(id.right)).setImageTintList(tintList);
+            }
+        };
+        setting.setListening(true);
+        setting.onChange(false);
+
+        mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft,
+                    int oldTop, int oldRight, int oldBottom) {
+                mOverlay.removeOnLayoutChangeListener(this);
+                mOverlay.animate()
+                        .alpha(1)
+                        .setDuration(1000)
+                        .start();
+                mBottomOverlay.animate()
+                        .alpha(1)
+                        .setDuration(1000)
+                        .start();
+            }
+        });
     }
 
     private void setupPadding(int padding) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
index f07027e..09a08f0 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
@@ -46,6 +46,11 @@
     }
 
     @Override
+    public void handleShowShutdownUi(boolean isReboot, String reason) {
+        mExtension.get().showShutdownUi(isReboot, reason);
+    }
+
+    @Override
     public void handleShowGlobalActionsMenu() {
         mExtension.get().showGlobalActions(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 7799c01..33d5617 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -116,8 +116,6 @@
     private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
     private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
 
-    private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
-
     private final Context mContext;
     private final GlobalActionsManager mWindowManagerFuncs;
     private final AudioManager mAudioManager;
@@ -682,10 +680,7 @@
     /** {@inheritDoc} */
     public void onClick(DialogInterface dialog, int which) {
         Action item = mAdapter.getItem(which);
-        if ((item instanceof PowerAction)
-                || (item instanceof RestartAction)) {
-            if (mDialog != null) mDialog.fadeOut();
-        } else if (!(item instanceof SilentModeTriStateAction)) {
+        if (!(item instanceof SilentModeTriStateAction)) {
             dialog.dismiss();
         }
         item.onPress();
@@ -1325,23 +1320,6 @@
                     .start();
         }
 
-        public void fadeOut() {
-            mHardwareLayout.setTranslationX(0);
-            mHardwareLayout.setAlpha(1);
-            mListView.animate()
-                    .alpha(0)
-                    .translationX(getAnimTranslation())
-                    .setDuration(300)
-                    .setInterpolator(new LogAccelerateInterpolator())
-                    .setUpdateListener(animation -> {
-                        float frac = animation.getAnimatedFraction();
-                        float alpha = NotificationUtils.interpolate(
-                                ScrimController.GRADIENT_SCRIM_ALPHA, SHUTDOWN_SCRIM_ALPHA, frac);
-                        mGradientDrawable.setAlpha((int) (alpha * 255));
-                    })
-                    .start();
-        }
-
         private float getAnimTranslation() {
             return getContext().getResources().getDimension(
                     com.android.systemui.R.dimen.global_actions_panel_width) / 2;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 08b7b71..2cf230c 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -14,17 +14,33 @@
 
 package com.android.systemui.globalactions;
 
+import android.app.Dialog;
+import android.app.KeyguardManager;
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.internal.R;
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
+import com.android.internal.colorextraction.drawable.GradientDrawable;
+import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
-import com.android.systemui.R;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
-import android.content.Context;
-import android.support.v7.view.ContextThemeWrapper;
-
 public class GlobalActionsImpl implements GlobalActions {
 
+    private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
+
     private final Context mContext;
     private final KeyguardMonitor mKeyguardMonitor;
     private final DeviceProvisionedController mDeviceProvisionedController;
@@ -44,4 +60,51 @@
         mGlobalActions.showDialog(mKeyguardMonitor.isShowing(),
                 mDeviceProvisionedController.isDeviceProvisioned());
     }
+
+    @Override
+    public void showShutdownUi(boolean isReboot, String reason) {
+        GradientDrawable background = new GradientDrawable(mContext);
+        background.setAlpha((int) (SHUTDOWN_SCRIM_ALPHA * 255));
+
+        Dialog d = new Dialog(mContext,
+                com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
+        // Window initialization
+        Window window = d.getWindow();
+        window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
+        window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
+        window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+        window.requestFeature(Window.FEATURE_NO_TITLE);
+        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
+                | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
+        window.addFlags(
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+        window.setBackgroundDrawable(background);
+        window.setWindowAnimations(R.style.Animation_Toast);
+
+        d.setContentView(R.layout.shutdown_dialog);
+        d.setCancelable(false);
+
+        int color = Utils.getColorAttr(mContext, com.android.systemui.R.attr.wallpaperTextColor);
+        boolean onKeyguard = mContext.getSystemService(
+                KeyguardManager.class).isKeyguardLocked();
+
+        ProgressBar bar = d.findViewById(R.id.progress);
+        bar.getIndeterminateDrawable().setTint(color);
+        TextView message = d.findViewById(R.id.text1);
+        message.setTextColor(color);
+        if (isReboot) message.setText(R.string.reboot_to_reset_message);
+
+        Point displaySize = new Point();
+        mContext.getDisplay().getRealSize(displaySize);
+        GradientColors colors = Dependency.get(SysuiColorExtractor.class).getColors(
+                onKeyguard ? WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM);
+        background.setColors(colors, false);
+        background.setScreenSize(displaySize.x, displaySize.y);
+
+        d.show();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e23875f..d132e76 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -659,7 +659,7 @@
     }
 
     boolean mustNotUnlockCurrentUser() {
-        return (UserManager.isSplitSystemUser() || UserManager.isDeviceInDemoMode(mContext))
+        return UserManager.isSplitSystemUser()
                 && KeyguardUpdateMonitor.getCurrentUser() == UserHandle.USER_SYSTEM;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 6c6054c..b3f992d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -71,10 +71,6 @@
     TaskStackListener mTaskStackListener = new TaskStackListener() {
         @Override
         public void onActivityPinned(String packageName, int taskId) {
-            if (!checkCurrentUserId(mContext, false /* debug */)) {
-                return;
-            }
-
             mTouchHandler.onActivityPinned();
             mMediaController.onActivityPinned();
             mMenuController.onActivityPinned();
@@ -86,10 +82,6 @@
 
         @Override
         public void onActivityUnpinned() {
-            if (!checkCurrentUserId(mContext, false /* debug */)) {
-                return;
-            }
-
             ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext,
                     mActivityManager);
             mMenuController.onActivityUnpinned(topPipActivity);
@@ -116,10 +108,6 @@
 
         @Override
         public void onPinnedActivityRestartAttempt(boolean clearedTask) {
-            if (!checkCurrentUserId(mContext, false /* debug */)) {
-                return;
-            }
-
             mTouchHandler.getMotionHelper().expandPip(clearedTask /* skipAnimation */);
         }
     };
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
index 62ec09b..b3a0794 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -26,14 +26,18 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
 import android.media.session.MediaSessionManager;
+import android.media.session.MediaSessionManager.OnActiveSessionsChangedListener;
 import android.media.session.PlaybackState;
 import android.os.UserHandle;
 
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.UserInfoController;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -88,13 +92,21 @@
         }
     };
 
-    private MediaController.Callback mPlaybackChangedListener = new MediaController.Callback() {
+    private final MediaController.Callback mPlaybackChangedListener = new MediaController.Callback() {
         @Override
         public void onPlaybackStateChanged(PlaybackState state) {
             notifyActionsChanged();
         }
     };
 
+    private final MediaSessionManager.OnActiveSessionsChangedListener mSessionsChangedListener =
+            new OnActiveSessionsChangedListener() {
+        @Override
+        public void onActiveSessionsChanged(List<MediaController> controllers) {
+            resolveActiveMediaController(controllers);
+        }
+    };
+
     private ArrayList<ActionListener> mListeners = new ArrayList<>();
 
     public PipMediaController(Context context, IActivityManager activityManager) {
@@ -110,9 +122,11 @@
         createMediaActions();
         mMediaSessionManager =
                 (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
-        mMediaSessionManager.addOnActiveSessionsChangedListener(controllers -> {
-            resolveActiveMediaController(controllers);
-        }, null);
+
+        // The media session listener needs to be re-registered when switching users
+        UserInfoController userInfoController = Dependency.get(UserInfoController.class);
+        userInfoController.addCallback((String name, Drawable picture, String userAccount) ->
+                registerSessionListenerForCurrentUser());
     }
 
     /**
@@ -120,7 +134,8 @@
      */
     public void onActivityPinned() {
         // Once we enter PiP, try to find the active media controller for the top most activity
-        resolveActiveMediaController(mMediaSessionManager.getActiveSessions(null));
+        resolveActiveMediaController(mMediaSessionManager.getActiveSessionsForUser(null,
+                UserHandle.USER_CURRENT));
     }
 
     /**
@@ -201,6 +216,15 @@
     }
 
     /**
+     * Re-registers the session listener for the current user.
+     */
+    private void registerSessionListenerForCurrentUser() {
+        mMediaSessionManager.removeOnActiveSessionsChangedListener(mSessionsChangedListener);
+        mMediaSessionManager.addOnActiveSessionsChangedListener(mSessionsChangedListener, null,
+                UserHandle.USER_CURRENT, null);
+    }
+
+    /**
      * Tries to find and set the active media controller for the top PiP activity.
      */
     private void resolveActiveMediaController(List<MediaController> controllers) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index d3be19d..9b48320 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -42,6 +42,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityWindowInfo;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -387,7 +388,10 @@
                 if (!mSendingHoverAccessibilityEvents) {
                     AccessibilityEvent event = AccessibilityEvent.obtain(
                             AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
+                    event.setImportantForAccessibility(true);
                     event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
+                    event.setWindowId(
+                            AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
                     mAccessibilityManager.sendAccessibilityEvent(event);
                     mSendingHoverAccessibilityEvents = true;
                 }
@@ -397,7 +401,10 @@
                 if (mSendingHoverAccessibilityEvents) {
                     AccessibilityEvent event = AccessibilityEvent.obtain(
                             AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
+                    event.setImportantForAccessibility(true);
                     event.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID);
+                    event.setWindowId(
+                            AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
                     mAccessibilityManager.sendAccessibilityEvent(event);
                     mSendingHoverAccessibilityEvents = false;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index c4d88ae..8f41084 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -46,6 +46,7 @@
 import com.android.systemui.settings.BrightnessController;
 import com.android.systemui.settings.ToggleSliderView;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController.BrightnessMirrorListener;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 
@@ -53,7 +54,7 @@
 import java.util.Collection;
 
 /** View that represents the quick settings tile panel. **/
-public class QSPanel extends LinearLayout implements Tunable, Callback {
+public class QSPanel extends LinearLayout implements Tunable, Callback, BrightnessMirrorListener {
 
     public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
 
@@ -152,6 +153,9 @@
         if (mHost != null) {
             setTiles(mHost.getTiles());
         }
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.addCallback(this);
+        }
     }
 
     @Override
@@ -163,6 +167,9 @@
         for (TileRecord record : mRecords) {
             record.tile.removeCallbacks();
         }
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.removeCallback(this);
+        }
         super.onDetachedFromWindow();
     }
 
@@ -194,12 +201,19 @@
     }
 
     public void setBrightnessMirror(BrightnessMirrorController c) {
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.removeCallback(this);
+        }
         mBrightnessMirrorController = c;
-        ToggleSliderView brightnessSlider = findViewById(R.id.brightness_slider);
-        ToggleSliderView mirror = c.getMirror().findViewById(
-                R.id.brightness_slider);
-        brightnessSlider.setMirror(mirror);
-        brightnessSlider.setMirrorController(c);
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.addCallback(this);
+        }
+        updateBrightnessMirror();
+    }
+
+    @Override
+    public void onBrightnessMirrorReinflated(View brightnessMirror) {
+        updateBrightnessMirror();
     }
 
     View getBrightnessView() {
@@ -246,9 +260,16 @@
         super.onConfigurationChanged(newConfig);
         mFooter.onConfigurationChanged();
 
+        updateBrightnessMirror();
+    }
+
+    public void updateBrightnessMirror() {
         if (mBrightnessMirrorController != null) {
-            // Reload the mirror in case it got reinflated but we didn't.
-            setBrightnessMirror(mBrightnessMirrorController);
+            ToggleSliderView brightnessSlider = findViewById(R.id.brightness_slider);
+            ToggleSliderView mirrorSlider = mBrightnessMirrorController.getMirror()
+                    .findViewById(R.id.brightness_slider);
+            brightnessSlider.setMirror(mirrorSlider);
+            brightnessSlider.setMirrorController(mBrightnessMirrorController);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f9407dd..2f4cd0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -79,6 +79,7 @@
     private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS    = 32 << MSG_SHIFT;
     private static final int MSG_HANDLE_SYSTEM_KEY             = 33 << MSG_SHIFT;
     private static final int MSG_SHOW_GLOBAL_ACTIONS           = 34 << MSG_SHIFT;
+    private static final int MSG_SHOW_SHUTDOWN_UI              = 35 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -136,6 +137,7 @@
 
         default void handleSystemKey(int arg1) { }
         default void handleShowGlobalActionsMenu() { }
+        default void handleShowShutdownUi(boolean isReboot, String reason) { }
     }
 
     @VisibleForTesting
@@ -429,6 +431,15 @@
         }
     }
 
+    @Override
+    public void showShutdownUi(boolean isReboot, String reason) {
+        synchronized (mLock) {
+            mHandler.removeMessages(MSG_SHOW_SHUTDOWN_UI);
+            mHandler.obtainMessage(MSG_SHOW_SHUTDOWN_UI, isReboot ? 1 : 0, 0, reason)
+                    .sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         private H(Looper l) {
             super(l);
@@ -610,6 +621,11 @@
                         mCallbacks.get(i).handleShowGlobalActionsMenu();
                     }
                     break;
+                case MSG_SHOW_SHUTDOWN_UI:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj);
+                    }
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index e5b1afe..ef4f419 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -89,6 +89,7 @@
         private int mCachedContrastColor = COLOR_INVALID;
         private int mCachedContrastColorIsFor = COLOR_INVALID;
         private InflationTask mRunningTask = null;
+        private Throwable mDebugThrowable;
 
         public Entry(StatusBarNotification n) {
             this.key = n.getKey();
@@ -249,6 +250,19 @@
         public InflationTask getRunningTask() {
             return mRunningTask;
         }
+
+        /**
+         * Set a throwable that is used for debugging
+         *
+         * @param debugThrowable the throwable to save
+         */
+        public void setDebugThrowable(Throwable debugThrowable) {
+            mDebugThrowable = debugThrowable;
+        }
+
+        public Throwable getDebugThrowable() {
+            return mDebugThrowable;
+        }
     }
 
     private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 3794ac6..c45c05e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -23,14 +23,11 @@
 import android.content.Context;
 import android.os.Handler;
 import android.util.Log;
-import android.view.View;
 import android.view.animation.Interpolator;
 
-import com.android.keyguard.KeyguardStatusView;
 import com.android.systemui.Interpolators;
 import com.android.systemui.doze.DozeHost;
 import com.android.systemui.doze.DozeLog;
-import com.android.systemui.doze.DozeTriggers;
 
 /**
  * Controller which handles all the doze animations of the scrims.
@@ -341,18 +338,31 @@
             if (!mDozing) return;
             startScrimAnimation(true /* inFront */, 1,
                     mDozeParameters.getPulseOutDuration(),
-                    Interpolators.ALPHA_IN, mPulseOutFinished);
+                    Interpolators.ALPHA_IN, mPulseOutFinishing);
+        }
+    };
+
+    private final Runnable mPulseOutFinishing = new Runnable() {
+        @Override
+        public void run() {
+            if (DEBUG) Log.d(TAG, "Pulse out finished");
+            DozeLog.tracePulseFinish();
+            if (mDozeParameters.getAlwaysOn() && mDozing) {
+                // Setting power states can block rendering. For AOD, delay finishing the pulse and
+                // setting the power state until the fully black scrim had time to hit the
+                // framebuffer.
+                mHandler.postDelayed(mPulseOutFinished, 30);
+            } else {
+                mPulseOutFinished.run();
+            }
         }
     };
 
     private final Runnable mPulseOutFinished = new Runnable() {
         @Override
         public void run() {
-            if (DEBUG) Log.d(TAG, "Pulse out finished");
-            DozeLog.tracePulseFinish();
-
             // Signal that the pulse is all finished so we can turn the screen off now.
-            pulseFinished();
+            DozeScrimController.this.pulseFinished();
             if (mDozeParameters.getAlwaysOn()) {
                 mScrimController.setDozeInFrontAlpha(mAodFrontScrimOpacity);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index cdba24c..6cfa838 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -332,6 +332,7 @@
         lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
         lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
         mLockIcon.setLayoutParams(lp);
+        mLockIcon.setContentDescription(getContext().getText(R.string.accessibility_unlock_button));
         mLockIcon.update(true /* force */);
 
         lp = mLeftAffordanceView.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 881de67..a6691b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -50,6 +50,7 @@
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 /**
@@ -346,6 +347,9 @@
         applyDarkness(R.id.signal_cluster, tintArea, intensity, iconColor);
         applyDarkness(R.id.battery, tintArea, intensity, iconColor);
         applyDarkness(R.id.clock, tintArea, intensity, iconColor);
+        // Reload user avatar
+        ((UserInfoControllerImpl) Dependency.get(UserInfoController.class))
+                .onDensityOrFontScaleChanged();
     }
 
     private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index dd84dea..b75c7e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -18,6 +18,7 @@
 
 import android.service.notification.StatusBarNotification;
 import android.support.annotation.Nullable;
+import android.util.Log;
 
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.NotificationData;
@@ -29,7 +30,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 
@@ -38,6 +38,7 @@
  */
 public class NotificationGroupManager implements OnHeadsUpChangedListener {
 
+    private static final String TAG = "NotificationGroupManager";
     private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
     private OnGroupChangeListener mListener;
     private int mBarState = -1;
@@ -96,7 +97,7 @@
             return;
         }
         if (isGroupChild(sbn)) {
-            group.children.remove(removed);
+            group.children.remove(removed.key);
         } else {
             group.summary = null;
         }
@@ -109,6 +110,9 @@
     }
 
     public void onEntryAdded(final NotificationData.Entry added) {
+        if (added.row.isRemoved()) {
+            added.setDebugThrowable(new Throwable());
+        }
         final StatusBarNotification sbn = added.notification;
         boolean isGroupChild = isGroupChild(sbn);
         String groupKey = getGroupKey(sbn);
@@ -118,15 +122,25 @@
             mGroupMap.put(groupKey, group);
         }
         if (isGroupChild) {
-            group.children.add(added);
+            NotificationData.Entry existing = group.children.get(added.key);
+            if (existing != null && existing != added) {
+                Throwable existingThrowable = existing.getDebugThrowable();
+                Log.wtf(TAG, "Inconsistent entries found with the same key " + added.key
+                        + "existing removed: " + existing.row.isRemoved()
+                        + (existingThrowable != null
+                                ? Log.getStackTraceString(existingThrowable) + "\n": "")
+                        + " added removed" + added.row.isRemoved()
+                        , new Throwable());
+            }
+            group.children.put(added.key, added);
             updateSuppression(group);
         } else {
             group.summary = added;
             group.expanded = added.row.areChildrenExpanded();
             updateSuppression(group);
             if (!group.children.isEmpty()) {
-                HashSet<NotificationData.Entry> childrenCopy =
-                        (HashSet<NotificationData.Entry>) group.children.clone();
+                ArrayList<NotificationData.Entry> childrenCopy
+                        = new ArrayList<>(group.children.values());
                 for (NotificationData.Entry child : childrenCopy) {
                     onEntryBecomingChild(child);
                 }
@@ -410,7 +424,8 @@
         // The parent of a suppressed group got huned, lets hun the child!
         NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
         if (notificationGroup != null) {
-            Iterator<NotificationData.Entry> iterator = notificationGroup.children.iterator();
+            Iterator<NotificationData.Entry> iterator
+                    = notificationGroup.children.values().iterator();
             NotificationData.Entry child = iterator.hasNext() ? iterator.next() : null;
             if (child == null) {
                 child = getIsolatedChild(sbn.getGroupKey());
@@ -463,7 +478,7 @@
     }
 
     public static class NotificationGroup {
-        public final HashSet<NotificationData.Entry> children = new HashSet<>();
+        public final HashMap<String, NotificationData.Entry> children = new HashMap<>();
         public NotificationData.Entry summary;
         public boolean expanded;
         /**
@@ -474,10 +489,16 @@
         @Override
         public String toString() {
             String result = "    summary:\n      "
-                    + (summary != null ? summary.notification : "null");
+                    + (summary != null ? summary.notification : "null")
+                    + (summary != null && summary.getDebugThrowable() != null
+                            ? Log.getStackTraceString(summary.getDebugThrowable())
+                            : "");
             result += "\n    children size: " + children.size();
-            for (NotificationData.Entry child : children) {
-                result += "\n      " + child.notification;
+            for (NotificationData.Entry child : children.values()) {
+                result += "\n      " + child.notification
+                + (child.getDebugThrowable() != null
+                        ? Log.getStackTraceString(child.getDebugThrowable())
+                        : "");
             }
             return result;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 479b945..1d64480 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -543,7 +543,7 @@
                     mKeyguardFadingOutInProgress = false;
                     mAnimatingDozeUnlock = false;
                 }
-                if (mWakingUpFromAodAnimationRunning) {
+                if (mWakingUpFromAodAnimationRunning && !mDeferFinishedListener) {
                     mWakingUpFromAodAnimationRunning = false;
                     mWakingUpFromAodInProgress = false;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6f710da..b4b859c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -103,7 +103,7 @@
     private boolean mDeferScrimFadeOut;
 
     // Dismiss action to be launched when we stop dozing or the keyguard is gone.
-    private PendingDismissActionRequest mPendingDismissAction;
+    private DismissWithActionRequest mPendingWakeupAction;
 
     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
@@ -113,7 +113,7 @@
             // Since we won't get a setOccluded call we have to reset the view manually such that
             // the bouncer goes away.
             if (mOccluded) {
-                reset(false /* hideBouncerWhenShowing */);
+                reset(true /* hideBouncerWhenShowing */);
             }
         }
     };
@@ -174,7 +174,7 @@
 
     private void hideBouncer(boolean destroyView) {
         mBouncer.hide(destroyView);
-        cancelPendingDismissAction();
+        cancelPendingWakeupAction();
     }
 
     private void showBouncer() {
@@ -187,11 +187,11 @@
     public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
             boolean afterKeyguardGone) {
         if (mShowing) {
-            cancelPendingDismissAction();
+            cancelPendingWakeupAction();
             // If we're dozing, this needs to be delayed until after we wake up - unless we're
             // wake-and-unlocking, because there dozing will last until the end of the transition.
             if (mDozing && !isWakeAndUnlocking()) {
-                mPendingDismissAction = new PendingDismissActionRequest(
+                mPendingWakeupAction = new DismissWithActionRequest(
                         r, cancelAction, afterKeyguardGone);
                 return;
             }
@@ -280,7 +280,7 @@
             updateStates();
 
             if (!dozing) {
-                launchPendingDismissAction();
+                launchPendingWakeupAction();
             }
         }
     }
@@ -316,6 +316,7 @@
                 return;
             }
         }
+        boolean isOccluding = !mOccluded && occluded;
         mOccluded = occluded;
         if (mShowing) {
             mStatusBar.updateMediaMetaData(false, animate && !occluded);
@@ -326,7 +327,7 @@
         if (!mDozing) {
             // If Keyguard is reshown, don't hide the bouncer as it might just have been requested
             // by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
-            reset(false /* hideBouncerWhenShowing*/);
+            reset(isOccluding /* hideBouncerWhenShowing*/);
         }
         if (animate && !occluded && mShowing) {
             mStatusBar.animateKeyguardUnoccluding();
@@ -357,7 +358,7 @@
      */
     public void hide(long startTime, long fadeoutDuration) {
         mShowing = false;
-        launchPendingDismissAction();
+        launchPendingWakeupAction();
 
         if (KeyguardUpdateMonitor.getInstance(mContext).needsSlowUnlockTransition()) {
             fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
@@ -685,9 +686,9 @@
         return mStatusBar.getStatusBarView().getViewRootImpl();
     }
 
-    public void launchPendingDismissAction() {
-        PendingDismissActionRequest request = mPendingDismissAction;
-        mPendingDismissAction = null;
+    public void launchPendingWakeupAction() {
+        DismissWithActionRequest request = mPendingWakeupAction;
+        mPendingWakeupAction = null;
         if (request != null) {
             if (mShowing) {
                 dismissWithAction(request.dismissAction, request.cancelAction,
@@ -698,20 +699,20 @@
         }
     }
 
-    public void cancelPendingDismissAction() {
-        PendingDismissActionRequest request = mPendingDismissAction;
-        mPendingDismissAction = null;
+    public void cancelPendingWakeupAction() {
+        DismissWithActionRequest request = mPendingWakeupAction;
+        mPendingWakeupAction = null;
         if (request != null && request.cancelAction != null) {
             request.cancelAction.run();
         }
     }
 
-    private static class PendingDismissActionRequest {
+    private static class DismissWithActionRequest {
         final OnDismissAction dismissAction;
         final Runnable cancelAction;
         final boolean afterKeyguardGone;
 
-        PendingDismissActionRequest(OnDismissAction dismissAction, Runnable cancelAction,
+        DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction,
                 boolean afterKeyguardGone) {
             this.dismissAction = dismissAction;
             this.cancelAction = cancelAction;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 718c348..42ce4c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -16,14 +16,15 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.util.ArraySet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewPropertyAnimator;
 import android.widget.FrameLayout;
 
+import com.android.internal.util.Preconditions;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBarWindowView;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -31,7 +32,8 @@
 /**
  * Controls showing and hiding of the brightness mirror.
  */
-public class BrightnessMirrorController {
+public class BrightnessMirrorController
+        implements CallbackController<BrightnessMirrorController.BrightnessMirrorListener> {
 
     private final NotificationStackScrollLayout mStackScroller;
     public long TRANSITION_DURATION_OUT = 150;
@@ -40,6 +42,7 @@
     private final StatusBarWindowView mStatusBarWindow;
     private final ScrimController mScrimController;
     private final View mNotificationPanel;
+    private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
     private final int[] mInt2Cache = new int[2];
     private View mBrightnessMirror;
 
@@ -130,5 +133,24 @@
         mBrightnessMirror = LayoutInflater.from(mBrightnessMirror.getContext()).inflate(
                 R.layout.brightness_mirror, mStatusBarWindow, false);
         mStatusBarWindow.addView(mBrightnessMirror, index);
+
+        for (int i = 0; i < mBrightnessMirrorListeners.size(); i++) {
+            mBrightnessMirrorListeners.valueAt(i).onBrightnessMirrorReinflated(mBrightnessMirror);
+        }
+    }
+
+    @Override
+    public void addCallback(BrightnessMirrorListener listener) {
+        Preconditions.checkNotNull(listener);
+        mBrightnessMirrorListeners.add(listener);
+    }
+
+    @Override
+    public void removeCallback(BrightnessMirrorListener listener) {
+        mBrightnessMirrorListeners.remove(listener);
+    }
+
+    public interface BrightnessMirrorListener {
+        void onBrightnessMirrorReinflated(View brightnessMirror);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
index b1e4b03..527addf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -131,6 +131,7 @@
         final int userId = userInfo.id;
         final boolean isGuest = userInfo.isGuest();
         final String userName = userInfo.name;
+        final boolean lightIcon = mContext.getThemeResId() != R.style.Theme_SystemUI_Light;
 
         final Resources res = mContext.getResources();
         final int avatarSize = Math.max(
@@ -154,7 +155,7 @@
                             .setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
                 } else {
                     avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
-                            /* light= */ true);
+                            lightIcon);
                 }
 
                 // If it's a single-user device, get the profile name, since the nickname is not
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 28e3427..c4dc506 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -276,6 +276,42 @@
 
   // Count of saved Passpoint providers device has ever connected to.
   optional int32 num_passpoint_providers_successfully_connected = 63;
+
+  // Histogram counting instances of scans with N many ScanResults with unique ssids
+  repeated NumConnectableNetworksBucket total_ssids_in_scan_histogram = 64;
+
+  // Histogram counting instances of scans with N many ScanResults/bssids
+  repeated NumConnectableNetworksBucket total_bssids_in_scan_histogram = 65;
+
+  // Histogram counting instances of scans with N many unique open ssids
+  repeated NumConnectableNetworksBucket available_open_ssids_in_scan_histogram = 66;
+
+  // Histogram counting instances of scans with N many bssids for open networks
+  repeated NumConnectableNetworksBucket available_open_bssids_in_scan_histogram = 67;
+
+  // Histogram counting instances of scans with N many unique ssids for saved networks
+  repeated NumConnectableNetworksBucket available_saved_ssids_in_scan_histogram = 68;
+
+  // Histogram counting instances of scans with N many bssids for saved networks
+  repeated NumConnectableNetworksBucket available_saved_bssids_in_scan_histogram = 69;
+
+  // Histogram counting instances of scans with N many unique SSIDs for open or saved networks
+  repeated NumConnectableNetworksBucket available_open_or_saved_ssids_in_scan_histogram = 70;
+
+  // Histogram counting instances of scans with N many BSSIDs for open or saved networks
+  repeated NumConnectableNetworksBucket available_open_or_saved_bssids_in_scan_histogram = 71;
+
+  // Histogram counting instances of scans with N many ScanResults matching unique saved passpoint providers
+  repeated NumConnectableNetworksBucket available_saved_passpoint_provider_profiles_in_scan_histogram = 72;
+
+  // Histogram counting instances of scans with N many ScanResults BSSIDs matching a saved passpoint provider
+  repeated NumConnectableNetworksBucket available_saved_passpoint_provider_bssids_in_scan_histogram = 73;
+
+  // Counts the number of AllSingleScanLister.onResult calls with a full band scan result
+  optional int32 full_band_all_single_scan_listener_results = 74;
+
+  // Counts the number of AllSingleScanLister.onResult calls with a partial (channels) scan result
+  optional int32 partial_all_single_scan_listener_results = 75;
 }
 
 // Information that gets logged for every WiFi connection.
@@ -883,3 +919,11 @@
   }
 }
 
+// Data point used to build 'Number of Connectable Network' histograms
+message NumConnectableNetworksBucket {
+  // Number of connectable networks seen in a scan result
+  optional int32 num_connectable_networks = 1 [default = 0];
+
+  // Number of scan results with num_connectable_networks
+  optional int32 count = 2 [default = 0];
+}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d75e6a9..3620ddb 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3424,6 +3424,15 @@
             return mStackSupervisor.moveHomeStackTaskToTop(reason);
         }
 
+        if (stack.isAssistantStack() && top != null
+                && top.getTask().getTaskToReturnTo() == HOME_ACTIVITY_TYPE) {
+            // It is possible for the home stack to not be directly underneath the assistant stack.
+            // For example, the assistant may start an activity in the fullscreen stack. Upon
+            // returning to the assistant stack, we must ensure that the home stack is underneath
+            // when appropriate.
+            mStackSupervisor.moveHomeStackTaskToTop("adjustAssistantReturnToHome");
+        }
+
         stack.moveToFront(myReason);
         return true;
     }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index dda8c1c..d85460f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5413,6 +5413,9 @@
         } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE ||
                    device == AudioSystem.DEVICE_OUT_LINE) {
             intent.setAction(Intent.ACTION_HEADSET_PLUG);
+            intent.putExtra("microphone", (device & AudioSystem.DEVICE_BIT_IN) != 0 ? 1 : 0);
+        } else if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
+            intent.setAction(Intent.ACTION_HEADSET_PLUG);
             intent.putExtra("microphone", 0);
         } else if (device == AudioSystem.DEVICE_OUT_HDMI ||
                 device == AudioSystem.DEVICE_OUT_HDMI_ARC) {
@@ -5452,9 +5455,7 @@
             if ((state == 0) && ((device & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
                 setBluetoothA2dpOnInt(true);
             }
-            boolean isUsb = ((device & ~AudioSystem.DEVICE_OUT_ALL_USB) == 0) ||
-                            (((device & AudioSystem.DEVICE_BIT_IN) != 0) &&
-                             ((device & ~AudioSystem.DEVICE_IN_ALL_USB) == 0));
+
             if (!handleDeviceConnection(state == 1, device, address, deviceName)) {
                 // change of connection state failed, bailout
                 return;
@@ -5494,7 +5495,7 @@
                     }
                 }
             }
-            if (!isUsb && device != AudioSystem.DEVICE_IN_WIRED_HEADSET) {
+            if (device != AudioSystem.DEVICE_IN_WIRED_HEADSET) {
                 sendDeviceConnectionIntent(device, state, address, deviceName);
             }
             updateAudioRoutes(device, state);
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index b0be8f7..2b4f4e6 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -832,20 +832,33 @@
             //       functions are ready to use.
             //
             // For more explanation, see b/62552150 .
-            if (usbConnected && !usbConfigured) {
-                // Nothing for us to do here.
-                // TODO: consider ignoring DISCONNECTED broadcasts as well.
-                return;
-            }
-
             synchronized (Tethering.this.mPublicSync) {
+                // Always record the state of RNDIS.
+                // TODO: consider:
+                //     final boolean disconnected = !usbConnected;
+                //     if (disconnected) {
+                //         mRndisEnabled = false;
+                //         mUsbTetherRequested = false;
+                //         return;
+                //     }
+                //     final boolean configured = usbConnected && usbConfigured;
+                //     mRndisEnabled = configured ? rndisEnabled : false;
+                //     if (!configured) return;
                 mRndisEnabled = rndisEnabled;
+
+                if (usbConnected && !usbConfigured) {
+                    // Nothing to do here (only CONNECTED, not yet CONFIGURED).
+                    return;
+                }
+
                 // start tethering if we have a request pending
                 if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
                     tetherMatchingInterfaces(
                             IControlsTethering.STATE_TETHERED,
                             ConnectivityManager.TETHERING_USB);
                 }
+
+                // TODO: Figure out how to remove the need for this variable.
                 mUsbTetherRequested = false;
             }
         }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c1e820c..f8f8ffb 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1235,6 +1235,7 @@
                                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                 .setUserAuthenticationRequired(true)
                                 .setUserAuthenticationValidityDurationSeconds(30)
+                                .setCriticalToDeviceEncryption(true)
                                 .build());
                 // Key imported, obtain a reference to it.
                 SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index 4981d5c..12b29cf 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -58,6 +58,10 @@
             }
         }
 
+        if (!record.isRecentlyIntrusive()) {
+            return null;
+        }
+
         return new RankingReconsideration(record.getKey(), HANG_TIME_MS) {
             @Override
             public void work() {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index d1aecb1..b217677 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageParser;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
+import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Environment;
@@ -701,6 +702,16 @@
                         LOCATION_PERMISSIONS, true, userId);
             }
 
+            // Ringtone Picker
+            Intent ringtonePickerIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
+            PackageParser.Package ringtonePickerPackage =
+                    getDefaultSystemHandlerActivityPackageLPr(ringtonePickerIntent, userId);
+            if (ringtonePickerPackage != null
+                    && doesPackageSupportRuntimePermissions(ringtonePickerPackage)) {
+                grantRuntimePermissionsLPw(ringtonePickerPackage,
+                        STORAGE_PERMISSIONS, true, userId);
+            }
+
             mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1eabac1..a2fea49 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8938,9 +8938,12 @@
             }
         }
 
-        boolean updatedPkgBetter = false;
+        final boolean isUpdatedPkg = updatedPkg != null;
+        final boolean isUpdatedSystemPkg = isUpdatedPkg
+                && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0;
+        boolean isUpdatedPkgBetter = false;
         // First check if this is a system package that may involve an update
-        if (updatedPkg != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
+        if (isUpdatedSystemPkg) {
             // If new package is not located in "/system/priv-app" (e.g. due to an OTA),
             // it needs to drop FLAG_PRIVILEGED.
             if (locationIsPrivileged(scanFile)) {
@@ -8984,10 +8987,6 @@
                             updatedChildPkg.versionCode = pkg.mVersionCode;
                         }
                     }
-
-                    throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
-                            + scanFile + " ignored: updated version " + ps.versionCode
-                            + " better than this " + pkg.mVersionCode);
                 } else {
                     // The current app on the system partition is better than
                     // what we have updated to on the data partition; switch
@@ -9014,12 +9013,44 @@
                     synchronized (mPackages) {
                         mSettings.enableSystemPackageLPw(ps.name);
                     }
-                    updatedPkgBetter = true;
+                    isUpdatedPkgBetter = true;
                 }
             }
         }
 
-        if (updatedPkg != null) {
+        String resourcePath = null;
+        String baseResourcePath = null;
+        if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !isUpdatedPkgBetter) {
+            if (ps != null && ps.resourcePathString != null) {
+                resourcePath = ps.resourcePathString;
+                baseResourcePath = ps.resourcePathString;
+            } else {
+                // Should not happen at all. Just log an error.
+                Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
+            }
+        } else {
+            resourcePath = pkg.codePath;
+            baseResourcePath = pkg.baseCodePath;
+        }
+
+        // Set application objects path explicitly.
+        pkg.setApplicationVolumeUuid(pkg.volumeUuid);
+        pkg.setApplicationInfoCodePath(pkg.codePath);
+        pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
+        pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
+        pkg.setApplicationInfoResourcePath(resourcePath);
+        pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
+        pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
+
+        // throw an exception if we have an update to a system application, but, it's not more
+        // recent than the package we've already scanned
+        if (isUpdatedSystemPkg && !isUpdatedPkgBetter) {
+            throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
+                    + scanFile + " ignored: updated version " + ps.versionCode
+                    + " better than this " + pkg.mVersionCode);
+        }
+
+        if (isUpdatedPkg) {
             // An updated system app will not have the PARSE_IS_SYSTEM flag set
             // initially
             policyFlags |= PackageParser.PARSE_IS_SYSTEM;
@@ -9039,7 +9070,7 @@
          * same name installed earlier.
          */
         boolean shouldHideSystemApp = false;
-        if (updatedPkg == null && ps != null
+        if (!isUpdatedPkg && ps != null
                 && (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
             /*
              * Check to make sure the signatures match first. If they don't,
@@ -9094,31 +9125,6 @@
             }
         }
 
-        // TODO: extend to support forward-locked splits
-        String resourcePath = null;
-        String baseResourcePath = null;
-        if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
-            if (ps != null && ps.resourcePathString != null) {
-                resourcePath = ps.resourcePathString;
-                baseResourcePath = ps.resourcePathString;
-            } else {
-                // Should not happen at all. Just log an error.
-                Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
-            }
-        } else {
-            resourcePath = pkg.codePath;
-            baseResourcePath = pkg.baseCodePath;
-        }
-
-        // Set application objects path explicitly.
-        pkg.setApplicationVolumeUuid(pkg.volumeUuid);
-        pkg.setApplicationInfoCodePath(pkg.codePath);
-        pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
-        pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
-        pkg.setApplicationInfoResourcePath(resourcePath);
-        pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
-        pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
-
         final int userId = ((user == null) ? 0 : user.getIdentifier());
         if (ps != null && ps.getInstantApp(userId)) {
             scanFlags |= SCAN_AS_INSTANT_APP;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a64ab43..132b845 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3652,7 +3652,7 @@
         public UserInfo createUserEvenWhenDisallowed(String name, int flags) {
             UserInfo user = createUserInternalUnchecked(name, flags, UserHandle.USER_NULL, null);
             // Keep this in sync with UserManager.createUser
-            if (user != null && !user.isAdmin()) {
+            if (user != null && !user.isAdmin() && !user.isDemo()) {
                 setUserRestriction(UserManager.DISALLOW_SMS, true, user.id);
                 setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, true, user.id);
             }
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index e894275..0f61171 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -57,7 +57,9 @@
 import android.widget.TextView;
 
 import com.android.internal.telephony.ITelephony;
+import com.android.server.LocalServices;
 import com.android.server.pm.PackageManagerService;
+import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.io.File;
 import java.io.IOException;
@@ -288,6 +290,9 @@
                 pd.setMessage(context.getText(
                             com.android.internal.R.string.reboot_to_update_prepare));
             } else {
+                if (showSysuiReboot()) {
+                    return null;
+                }
                 pd.setIndeterminate(true);
                 pd.setMessage(context.getText(
                             com.android.internal.R.string.reboot_to_update_reboot));
@@ -296,39 +301,12 @@
             // Factory reset path. Set the dialog message accordingly.
             pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
             pd.setMessage(context.getText(
-                        com.android.internal.R.string.reboot_to_reset_message));
+                    com.android.internal.R.string.reboot_to_reset_message));
             pd.setIndeterminate(true);
-        } else if (mReason != null && mReason.equals(PowerManager.SHUTDOWN_USER_REQUESTED)) {
-            Dialog d = new Dialog(context);
-            d.setContentView(com.android.internal.R.layout.shutdown_dialog);
-            d.setCancelable(false);
-
-            int color;
-            try {
-                boolean onKeyguard = context.getSystemService(
-                        KeyguardManager.class).isKeyguardLocked();
-                WallpaperColors currentColors = context.getSystemService(WallpaperManager.class)
-                        .getWallpaperColors(onKeyguard ?
-                                WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM);
-                color = currentColors != null &&
-                        (currentColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT)
-                                != 0 ?
-                        Color.BLACK : Color.WHITE;
-            } catch (Exception e) {
-                color = Color.WHITE;
-            }
-
-            ProgressBar bar = d.findViewById(com.android.internal.R.id.progress);
-            bar.getIndeterminateDrawable().setTint(color);
-            ((TextView) d.findViewById(com.android.internal.R.id.text1)).setTextColor(color);
-            d.getWindow().getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
-            d.getWindow().getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
-            d.getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
-            d.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
-            d.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
-            d.show();
-            return null;
         } else {
+            if (showSysuiReboot()) {
+                return null;
+            }
             pd.setTitle(context.getText(com.android.internal.R.string.power_off));
             pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
             pd.setIndeterminate(true);
@@ -340,6 +318,23 @@
         return pd;
     }
 
+    private static boolean showSysuiReboot() {
+        Log.d(TAG, "Attempting to use SysUI shutdown UI");
+        try {
+            StatusBarManagerInternal service = LocalServices.getService(
+                    StatusBarManagerInternal.class);
+            if (service.showShutdownUi(mReboot, mReason)) {
+                // Sysui will handle shutdown UI.
+                Log.d(TAG, "SysUI handling shutdown UI");
+                return true;
+            }
+        } catch (Exception e) {
+            // If anything went wrong, ignore it and use fallback ui
+        }
+        Log.d(TAG, "SysUI is unavailable");
+        return false;
+    }
+
     private static void beginShutdownSequence(Context context) {
         synchronized (sIsStartedGuard) {
             if (sIsStarted) {
@@ -561,7 +556,7 @@
         Thread t = new Thread() {
             public void run() {
                 boolean nfcOff;
-                boolean bluetoothOff;
+                boolean bluetoothReadyForShutdown;
                 boolean radioOff;
 
                 final INfcAdapter nfc =
@@ -585,15 +580,15 @@
                 }
 
                 try {
-                    bluetoothOff = bluetooth == null ||
+                    bluetoothReadyForShutdown = bluetooth == null ||
                             bluetooth.getState() == BluetoothAdapter.STATE_OFF;
-                    if (!bluetoothOff) {
+                    if (!bluetoothReadyForShutdown) {
                         Log.w(TAG, "Disabling Bluetooth...");
                         bluetooth.disable(mContext.getPackageName(), false);  // disable but don't persist new state
                     }
                 } catch (RemoteException ex) {
                     Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
-                    bluetoothOff = true;
+                    bluetoothReadyForShutdown = true;
                 }
 
                 try {
@@ -618,14 +613,19 @@
                         sInstance.setRebootProgress(status, null);
                     }
 
-                    if (!bluetoothOff) {
+                    if (!bluetoothReadyForShutdown) {
                         try {
-                            bluetoothOff = bluetooth.getState() == BluetoothAdapter.STATE_OFF;
+                          // BLE only mode can happen when BT is turned off
+                          // We will continue shutting down in such case
+                          bluetoothReadyForShutdown =
+                                  bluetooth.getState() == BluetoothAdapter.STATE_OFF ||
+                                  bluetooth.getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF ||
+                                  bluetooth.getState() == BluetoothAdapter.STATE_BLE_ON;
                         } catch (RemoteException ex) {
                             Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
-                            bluetoothOff = true;
+                            bluetoothReadyForShutdown = true;
                         }
-                        if (bluetoothOff) {
+                        if (bluetoothReadyForShutdown) {
                             Log.i(TAG, "Bluetooth turned off.");
                         }
                     }
@@ -652,7 +652,7 @@
                         }
                     }
 
-                    if (radioOff && bluetoothOff && nfcOff) {
+                    if (radioOff && bluetoothReadyForShutdown && nfcOff) {
                         Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete.");
                         done[0] = true;
                         break;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 5e322da..866fdad 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -80,6 +80,8 @@
     void setGlobalActionsListener(GlobalActionsListener listener);
     void showGlobalActions();
 
+    boolean showShutdownUi(boolean isReboot, String requestString);
+
     public interface GlobalActionsListener {
         /**
          * Called when sysui starts and connects its status bar, or when the status bar binder
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 2df0f10..5b252e8 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -36,6 +36,7 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 
+import com.android.internal.R;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
@@ -329,6 +330,20 @@
                 } catch (RemoteException ex) {}
             }
         }
+
+        @Override
+        public boolean showShutdownUi(boolean isReboot, String reason) {
+            if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) {
+                return false;
+            }
+            if (mBar != null) {
+                try {
+                    mBar.showShutdownUi(isReboot, reason);
+                    return true;
+                } catch (RemoteException ex) {}
+            }
+            return false;
+        }
     };
 
     // ================================================================================
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index af90eea..e0ad8f5 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -115,6 +115,7 @@
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -376,40 +377,39 @@
     private void notifyColorListeners(@NonNull WallpaperColors wallpaperColors, int which,
             int userId) {
         final IWallpaperManagerCallback keyguardListener;
-        final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners;
-        final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners;
+        final ArrayList<IWallpaperManagerCallback> colorListeners = new ArrayList<>();
         synchronized (mLock) {
-            currentUserColorListeners = mColorsChangedListeners.get(userId);
-            userAllColorListeners = mColorsChangedListeners.get(UserHandle.USER_ALL);
+            final RemoteCallbackList<IWallpaperManagerCallback> currentUserColorListeners =
+                    mColorsChangedListeners.get(userId);
+            final RemoteCallbackList<IWallpaperManagerCallback> userAllColorListeners =
+                    mColorsChangedListeners.get(UserHandle.USER_ALL);
             keyguardListener = mKeyguardListener;
+
+            if (currentUserColorListeners != null) {
+                final int count = currentUserColorListeners.beginBroadcast();
+                for (int i = 0; i < count; i++) {
+                    colorListeners.add(currentUserColorListeners.getBroadcastItem(i));
+                }
+                currentUserColorListeners.finishBroadcast();
+            }
+
+            if (userAllColorListeners != null) {
+                final int count = userAllColorListeners.beginBroadcast();
+                for (int i = 0; i < count; i++) {
+                    colorListeners.add(userAllColorListeners.getBroadcastItem(i));
+                }
+                userAllColorListeners.finishBroadcast();
+            }
         }
 
-        if (currentUserColorListeners != null) {
-            int count = currentUserColorListeners.beginBroadcast();
-            for (int i = 0; i < count; i++) {
-                try {
-                    currentUserColorListeners.getBroadcastItem(i)
-                            .onWallpaperColorsChanged(wallpaperColors, which, userId);
-                } catch (RemoteException e) {
-                    // Callback is gone, it's not necessary to unregister it since
-                    // RemoteCallbackList#getBroadcastItem will take care of it.
-                }
+        final int count = colorListeners.size();
+        for (int i = 0; i < count; i++) {
+            try {
+                colorListeners.get(i).onWallpaperColorsChanged(wallpaperColors, which, userId);
+            } catch (RemoteException e) {
+                // Callback is gone, it's not necessary to unregister it since
+                // RemoteCallbackList#getBroadcastItem will take care of it.
             }
-            currentUserColorListeners.finishBroadcast();
-        }
-
-        if (userAllColorListeners != null) {
-            int count = userAllColorListeners.beginBroadcast();
-            for (int i = 0; i < count; i++) {
-                try {
-                    userAllColorListeners.getBroadcastItem(i)
-                            .onWallpaperColorsChanged(wallpaperColors, which, userId);
-                } catch (RemoteException e) {
-                    // Callback is gone, it's not necessary to unregister it since
-                    // RemoteCallbackList#getBroadcastItem will take care of it.
-                }
-            }
-            userAllColorListeners.finishBroadcast();
         }
 
         if (keyguardListener != null) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4d77d40..5bc4a6b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2681,7 +2681,7 @@
             if (!w.getOrientationChanging()) {
                 return;
             }
-            w.setOrientationChanging(false);
+            w.orientationChangeTimedOut();
             w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
                     - mService.mDisplayFreezeTime);
             Slog.w(TAG_WM, "Force clearing orientation change: " + w);
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 40528d0..7bcad9f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -52,6 +52,7 @@
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
@@ -760,16 +761,21 @@
 
         if (mUpdateRotation) {
             if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
-
-            for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-                final DisplayContent displayContent = mChildren.get(displayNdx);
-                final int displayId = displayContent.getDisplayId();
-                if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
-                    mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
-                } else if (displayId == DEFAULT_DISPLAY) {
-                    // TODO(multi-display): Track rotation updates for different displays separately
-                    mUpdateRotation = false;
-                }
+            // TODO(multi-display): Update rotation for different displays separately.
+            final int displayId = defaultDisplay.getDisplayId();
+            if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
+            } else {
+                mUpdateRotation = false;
+            }
+            // Update rotation of VR virtual display separately. Currently this is the only kind of
+            // secondary display that can be rotated because of the single-display limitations in
+            // PhoneWindowManager.
+            final DisplayContent vrDisplay = mService.mVr2dDisplayId != INVALID_DISPLAY
+                    ? getDisplayContent(mService.mVr2dDisplayId) : null;
+            if (vrDisplay != null && vrDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+                mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mService.mVr2dDisplayId)
+                        .sendToTarget();
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
index f5ef2e6..85ea3c0 100644
--- a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
+++ b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
@@ -180,6 +180,11 @@
         // Compute new scaled width and height for background that will depend on current animation
         // progress. Those consist of current crop rect for the main surface + scaled areas outside
         // of letterboxed area.
+        // TODO: Because the progress is computed with low precision we're getting smaller values
+        // for background width/height then screen size at the end of the animation. Will round when
+        // the value is smaller then some empiric epsilon. However, this should be fixed by
+        // computing correct frames for letterboxed windows in WindowState.
+        d = d < 0.02f ? 0 : d;
         mWindowSurfaceController.getContainerRect(mTmpContainerRect);
         final int backgroundWidth =
                 (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5);
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index fe5b7f2..079ae40 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -33,7 +33,6 @@
 import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 
-import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
 import com.android.server.AnimationThread;
 
 import java.io.PrintWriter;
@@ -134,26 +133,38 @@
      * sure other threads can make progress if this happens.
      */
     private void animate(long frameTimeNs) {
-        boolean transactionOpen = false;
-        try {
-            synchronized (mService.mWindowMap) {
-                if (!mInitialized) {
-                    return;
-                }
 
-                mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
-                mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
-                mAnimating = false;
-                mAppWindowAnimating = false;
-                if (DEBUG_WINDOW_TRACE) {
-                    Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
-                }
+        synchronized (mService.mWindowMap) {
+            if (!mInitialized) {
+                return;
+            }
 
-                if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION animate");
-                mService.openSurfaceTransaction();
-                transactionOpen = true;
-                SurfaceControl.setAnimationTransaction();
+            // Schedule next frame already such that back-pressure happens continuously
+            scheduleAnimation();
+        }
 
+        // Simulate back-pressure by opening and closing an empty animation transaction. This makes
+        // sure that an animation frame is at least presented once on the screen. We do this outside
+        // of the regular transaction such that we can avoid holding the window manager lock in case
+        // we receive back-pressure from SurfaceFlinger. Since closing an animation transaction
+        // without the window manager locks leads to ordering issues (as the transaction will be
+        // processed only at the beginning of the next frame which may result in another transaction
+        // that was executed later in WM side gets executed first on SF side), we don't update any
+        // Surface properties here such that reordering doesn't cause issues.
+        mService.executeEmptyAnimationTransaction();
+
+        synchronized (mService.mWindowMap) {
+            mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
+            mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
+            mAnimating = false;
+            mAppWindowAnimating = false;
+            if (DEBUG_WINDOW_TRACE) {
+                Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
+            }
+
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION animate");
+            mService.openSurfaceTransaction();
+            try {
                 final AccessibilityController accessibilityController =
                         mService.mAccessibilityController;
                 final int numDisplays = mDisplayContentsAnimators.size();
@@ -216,27 +227,20 @@
                     mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
                 }
 
-                if (mAnimating) {
-                    mService.scheduleAnimationLocked();
+                if (!mAnimating) {
+                    cancelAnimation();
                 }
 
                 if (mService.mWatermark != null) {
                     mService.mWatermark.drawIfNeeded();
                 }
-            }
-        } catch (RuntimeException e) {
-            Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
-        } finally {
-            if (transactionOpen) {
-
-                // Do not hold window manager lock while closing the transaction, as this might be
-                // blocking until the next frame, which can lead to total lock starvation.
-                mService.closeSurfaceTransaction(false /* withLockHeld */);
+            } catch (RuntimeException e) {
+                Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
+            } finally {
+                mService.closeSurfaceTransaction();
                 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION animate");
             }
-        }
 
-        synchronized (mService.mWindowMap) {
             boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
             boolean doRequest = false;
             if (mBulkUpdateParams != 0) {
@@ -404,6 +408,13 @@
         }
     }
 
+    private void cancelAnimation() {
+        if (mAnimationFrameCallbackScheduled) {
+            mAnimationFrameCallbackScheduled = false;
+            mChoreographer.removeFrameCallback(mAnimationFrameCallback);
+        }
+    }
+
     private class DisplayContentsAnimator {
         ScreenRotationAnimation mScreenRotationAnimation = null;
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b0775dd..8ba36d5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -908,29 +908,16 @@
         }
     }
 
-    void closeSurfaceTransaction() {
-        closeSurfaceTransaction(true /* withLockHeld */);
-    }
-
     /**
      * Closes a surface transaction.
-     *
-     * @param withLockHeld Whether to acquire the window manager while doing so. In some cases
-     *                     holding the lock my lead to starvation in WM in case closeTransaction
-     *                     blocks and we call it repeatedly, like we do for animations.
      */
-    void closeSurfaceTransaction(boolean withLockHeld) {
+    void closeSurfaceTransaction() {
         try {
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
             synchronized (mWindowMap) {
                 if (mRoot.mSurfaceTraceEnabled) {
                     mRoot.mRemoteEventTrace.closeSurfaceTransaction();
                 }
-                if (withLockHeld) {
-                    SurfaceControl.closeTransaction();
-                }
-            }
-            if (!withLockHeld) {
                 SurfaceControl.closeTransaction();
             }
         } finally {
@@ -938,6 +925,34 @@
         }
     }
 
+    /**
+     * Executes an empty animation transaction without holding the WM lock to simulate
+     * back-pressure. See {@link WindowAnimator#animate} why this is needed.
+     */
+    void executeEmptyAnimationTransaction() {
+        try {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
+            synchronized (mWindowMap) {
+                if (mRoot.mSurfaceTraceEnabled) {
+                    mRoot.mRemoteEventTrace.openSurfaceTransaction();
+                }
+                SurfaceControl.openTransaction();
+                SurfaceControl.setAnimationTransaction();
+                if (mRoot.mSurfaceTraceEnabled) {
+                    mRoot.mRemoteEventTrace.closeSurfaceTransaction();
+                }
+            }
+        } finally {
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+        }
+        try {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
+            SurfaceControl.closeTransaction();
+        } finally {
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+        }
+    }
+
     /** Listener to notify activity manager about app transitions. */
     final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
             = new WindowManagerInternal.AppTransitionListener() {
@@ -3471,21 +3486,11 @@
             }
 
             if (!mBootAnimationStopped) {
-                // Do this one time.
                 Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
-                try {
-                    IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
-                    if (surfaceFlinger != null) {
-                        Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
-                        Parcel data = Parcel.obtain();
-                        data.writeInterfaceToken("android.ui.ISurfaceComposer");
-                        surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
-                                data, null, 0);
-                        data.recycle();
-                    }
-                } catch (RemoteException ex) {
-                    Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
-                }
+                // stop boot animation
+                // formerly we would just kill the process, but we now ask it to exit so it
+                // can choose where to stop the animation.
+                SystemProperties.set("service.bootanim.exit", "1");
                 mBootAnimationStopped = true;
             }
 
@@ -3494,6 +3499,20 @@
                 return;
             }
 
+            try {
+                IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
+                if (surfaceFlinger != null) {
+                    Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
+                    Parcel data = Parcel.obtain();
+                    data.writeInterfaceToken("android.ui.ISurfaceComposer");
+                    surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
+                            data, null, 0);
+                    data.recycle();
+                }
+            } catch (RemoteException ex) {
+                Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
+            }
+
             EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
             Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
             mDisplayEnabled = true;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 02242f3..96582fc 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -444,6 +444,17 @@
     private boolean mOrientationChanging;
 
     /**
+     * Sometimes in addition to the mOrientationChanging
+     * flag we report that the orientation is changing
+     * due to a mismatch in current and reported configuration.
+     *
+     * In the case of timeout we still need to make sure we
+     * leave the orientation changing state though, so we
+     * use this as a special time out escape hatch.
+     */
+    private boolean mOrientationChangeTimedOut;
+
+    /**
      * The orientation during the last visible call to relayout. If our
      * current orientation is different, the window can't be ready
      * to be shown.
@@ -754,7 +765,7 @@
         // If the task has temp inset bounds set, we have to make sure all its windows uses
         // the temp inset frame. Otherwise different display frames get applied to the main
         // window and the child window, making them misaligned.
-        if (inFullscreenContainer) {
+        if (inFullscreenContainer || isLetterboxedAppWindow()) {
             mInsetFrame.setEmpty();
         } else if (task != null && isInMultiWindowMode()) {
             task.getTempInsetBounds(mInsetFrame);
@@ -1221,11 +1232,17 @@
         //                   better indicator consistent with the client.
         return (mOrientationChanging || (isVisible()
                 && getConfiguration().orientation != mLastReportedConfiguration.orientation))
-                && !mSeamlesslyRotated;
+                && !mSeamlesslyRotated
+                && !mOrientationChangeTimedOut;
     }
 
     void setOrientationChanging(boolean changing) {
         mOrientationChanging = changing;
+        mOrientationChangeTimedOut = false;
+    }
+
+    void orientationChangeTimedOut() {
+        mOrientationChangeTimedOut = true;
     }
 
     DisplayContent getDisplayContent() {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 73bb13a..d249b0a9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2384,6 +2384,9 @@
             BroadcastReceiver result) {
         Intent intent = new Intent(action);
         intent.setComponent(admin.info.getComponent());
+        if (UserManager.isDeviceInDemoMode(mContext)) {
+            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+        }
         if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) {
             intent.putExtra("expiration", admin.passwordExpirationDate);
         }
@@ -8183,23 +8186,6 @@
                 return null;
             }
 
-            final UserInfo userInfo = getUserInfo(userHandle);
-            if (userInfo != null && userInfo.isDemo()) {
-                try {
-                    final ApplicationInfo ai = mIPackageManager.getApplicationInfo(adminPkg,
-                            PackageManager.MATCH_DISABLED_COMPONENTS, userHandle);
-                    final boolean isSystemApp =
-                            ai != null && (ai.flags & (ApplicationInfo.FLAG_SYSTEM
-                                    | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
-                    if (isSystemApp) {
-                        mIPackageManager.setApplicationEnabledSetting(adminPkg,
-                                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
-                                PackageManager.DONT_KILL_APP, userHandle, "DevicePolicyManager");
-                    }
-                } catch (RemoteException e) {
-                }
-            }
-
             setActiveAdmin(profileOwner, true, userHandle);
             // User is not started yet, the broadcast by setActiveAdmin will not be received.
             // So we store adminExtras for broadcasting when the user starts for first time.
@@ -8493,6 +8479,8 @@
             enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
                     DELEGATION_ENABLE_SYSTEM_APP);
 
+            final boolean isDemo = isCurrentUserDemo();
+
             int userId = UserHandle.getCallingUserId();
             long id = mInjector.binderClearCallingIdentity();
 
@@ -8503,14 +8491,19 @@
                 }
 
                 int parentUserId = getProfileParentId(userId);
-                if (!isSystemApp(mIPackageManager, packageName, parentUserId)) {
+                if (!isDemo && !isSystemApp(mIPackageManager, packageName, parentUserId)) {
                     throw new IllegalArgumentException("Only system apps can be enabled this way.");
                 }
 
                 // Install the app.
                 mIPackageManager.installExistingPackageAsUser(packageName, userId,
                         0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY);
-
+                if (isDemo) {
+                    // Ensure the app is also ENABLED for demo users.
+                    mIPackageManager.setApplicationEnabledSetting(packageName,
+                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+                            PackageManager.DONT_KILL_APP, userId, "DevicePolicyManager");
+                }
             } catch (RemoteException re) {
                 // shouldn't happen
                 Slog.wtf(LOG_TAG, "Failed to install " + packageName, re);
@@ -8955,7 +8948,8 @@
                 return;
             }
 
-            if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)) {
+            if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)
+                    && !UserManager.isDeviceInDemoMode(mContext)) {
                 throw new SecurityException(String.format(
                         "Permission denial: device owners cannot update %1$s", setting));
             }
@@ -8987,11 +8981,12 @@
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
             if (isDeviceOwner(who, callingUserId)) {
-                if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) {
+                if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)
+                        && !isCurrentUserDemo()) {
                     throw new SecurityException(String.format(
                             "Permission denial: Device owners cannot update %1$s", setting));
                 }
-            } else if (!SECURE_SETTINGS_WHITELIST.contains(setting)) {
+            } else if (!SECURE_SETTINGS_WHITELIST.contains(setting) && !isCurrentUserDemo()) {
                 throw new SecurityException(String.format(
                         "Permission denial: Profile owners cannot update %1$s", setting));
             }
@@ -9442,12 +9437,6 @@
 
     @Override
     public SystemUpdatePolicy getSystemUpdatePolicy() {
-        if (UserManager.isDeviceInDemoMode(mContext)) {
-            // Pretending to have an automatic update policy when the device is in retail demo
-            // mode. This will allow the device to download and install an ota without
-            // any user interaction.
-            return SystemUpdatePolicy.createAutomaticInstallPolicy();
-        }
         synchronized (this) {
             SystemUpdatePolicy policy =  mOwners.getSystemUpdatePolicy();
             if (policy != null && !policy.isValid()) {
@@ -10454,6 +10443,19 @@
         }
     }
 
+    private boolean isCurrentUserDemo() {
+        if (UserManager.isDeviceInDemoMode(mContext)) {
+            final int userId = mInjector.userHandleGetCallingUserId();
+            final long callingIdentity = mInjector.binderClearCallingIdentity();
+            try {
+                return mUserManager.getUserInfo(userId).isDemo();
+            } finally {
+                mInjector.binderRestoreCallingIdentity(callingIdentity);
+            }
+        }
+        return false;
+    }
+
     private void removePackageIfRequired(final String packageName, final int userId) {
         if (!packageHasActiveAdmins(packageName, userId)) {
             // Will not do anything if uninstall was not requested or was already started.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index bad9b5b..23330f1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -382,74 +382,6 @@
         mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
     }
 
-    public void testCreateAndManageUser_demoUserSystemApp() throws Exception {
-        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
-
-        setDeviceOwner();
-
-        final int id = UserHandle.getUserId(DpmMockContext.CALLER_UID);
-
-        final UserInfo demoUserInfo = mock(UserInfo.class);
-        demoUserInfo.id = id;
-        doReturn(UserHandle.of(id)).when(demoUserInfo).getUserHandle();
-        doReturn(true).when(demoUserInfo).isDemo();
-        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        doReturn(demoUserInfo).when(um).getUserInfo(id);
-        doReturn(demoUserInfo).when(mContext.getUserManagerInternal())
-                .createUserEvenWhenDisallowed(anyString(), anyInt());
-
-        final ApplicationInfo applicationInfo = getServices().ipackageManager.getApplicationInfo(
-                admin2.getPackageName(), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, id);
-        applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
-        doReturn(applicationInfo).when(getServices().ipackageManager).getApplicationInfo(
-                anyString(), anyInt(), anyInt());
-
-        final UserHandle userHandle = dpm.createAndManageUser(admin1, "", admin2, null, 0);
-
-        verify(getServices().ipackageManager, times(1)).setApplicationEnabledSetting(
-                eq(admin2.getPackageName()),
-                eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
-                eq(PackageManager.DONT_KILL_APP),
-                eq(id),
-                anyString());
-
-        assertNotNull(userHandle);
-    }
-
-    public void testCreateAndManageUser_demoUserSystemUpdatedApp() throws Exception {
-        mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
-
-        setDeviceOwner();
-
-        final int id = UserHandle.getUserId(DpmMockContext.CALLER_UID);
-
-        final UserInfo demoUserInfo = mock(UserInfo.class);
-        demoUserInfo.id = id;
-        doReturn(UserHandle.of(id)).when(demoUserInfo).getUserHandle();
-        doReturn(true).when(demoUserInfo).isDemo();
-        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        doReturn(demoUserInfo).when(um).getUserInfo(id);
-        doReturn(demoUserInfo).when(mContext.getUserManagerInternal())
-                .createUserEvenWhenDisallowed(anyString(), anyInt());
-
-        final ApplicationInfo applicationInfo = getServices().ipackageManager.getApplicationInfo(
-                admin2.getPackageName(), PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS, id);
-        applicationInfo.flags = ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
-        doReturn(applicationInfo).when(getServices().ipackageManager).getApplicationInfo(
-                anyString(), anyInt(), anyInt());
-
-        final UserHandle userHandle = dpm.createAndManageUser(admin1, "", admin2, null, 0);
-
-        verify(getServices().ipackageManager, times(1)).setApplicationEnabledSetting(
-                eq(admin2.getPackageName()),
-                eq(PackageManager.COMPONENT_ENABLED_STATE_ENABLED),
-                eq(PackageManager.DONT_KILL_APP),
-                eq(id),
-                anyString());
-
-        assertNotNull(userHandle);
-    }
-
     public void testSetActiveAdmin_multiUsers() throws Exception {
 
         final int ANOTHER_USER_ID = 100;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 8121bcf..99f54ba 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -46,6 +46,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.provider.Settings;
 import android.security.KeyChain;
 import android.telephony.TelephonyManager;
 import android.test.mock.MockContentResolver;
@@ -53,6 +54,7 @@
 import android.util.Pair;
 import android.view.IWindowManager;
 
+import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.widget.LockPatternUtils;
 
 import java.io.File;
@@ -130,6 +132,7 @@
         packageManager = spy(realContext.getPackageManager());
 
         contentResolver = new MockContentResolver();
+        contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
 
         // Add the system user with a fake profile group already set up (this can happen in the real
         // world if a managed profile is added and then removed).
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 8fe4116..6e253e7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -363,6 +363,50 @@
                 Math.min(pf.height(), displayInfo.logicalHeight));
     }
 
+    @Test
+    public void testLayoutLetterboxedWindow() {
+        // First verify task behavior in multi-window mode.
+        final DisplayInfo displayInfo = sWm.getDefaultDisplayContentLocked().getDisplayInfo();
+        final int logicalWidth = displayInfo.logicalWidth;
+        final int logicalHeight = displayInfo.logicalHeight;
+
+        final int taskLeft = logicalWidth / 5;
+        final int taskTop = logicalHeight / 5;
+        final int taskRight = logicalWidth / 4 * 3;
+        final int taskBottom = logicalHeight / 4 * 3;
+        final Rect taskBounds = new Rect(taskLeft, taskTop, taskRight, taskBottom);
+        TaskWithBounds task = new TaskWithBounds(taskBounds);
+        task.mInsetBounds.set(taskLeft, taskTop, taskRight, taskBottom);
+        task.mFullscreenForTest = false;
+        WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
+        w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
+
+        final Rect pf = new Rect(0, 0, logicalWidth, logicalHeight);
+        w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
+                pf /* contentFrame */, pf /* visibleFrame */, pf /* decorFrame */,
+                pf /* stableFrame */, null /* outsetFrame */);
+        // For non fullscreen tasks the containing frame is based off the
+        // task bounds not the parent frame.
+        assertRect(w.mFrame, taskLeft, taskTop, taskRight, taskBottom);
+        assertRect(w.getContentFrameLw(), taskLeft, taskTop, taskRight, taskBottom);
+        assertRect(w.mContentInsets, 0, 0, 0, 0);
+
+        // Now simulate switch to fullscreen for letterboxed app.
+        final int xInset = logicalWidth / 10;
+        final int yInset = logicalWidth / 10;
+        final Rect cf = new Rect(xInset, yInset, logicalWidth - xInset, logicalHeight - yInset);
+        w.mAppToken.onOverrideConfigurationChanged(w.mAppToken.getOverrideConfiguration(), cf);
+        pf.set(0, 0, logicalWidth, logicalHeight);
+        task.mFullscreenForTest = true;
+
+        w.computeFrameLw(pf /* parentFrame */, pf /* displayFrame */, pf /* overscanFrame */,
+                cf /* contentFrame */, cf /* visibleFrame */, pf /* decorFrame */,
+                cf /* stableFrame */, null /* outsetFrame */);
+        assertEquals(cf, w.mFrame);
+        assertEquals(cf, w.getContentFrameLw());
+        assertRect(w.mContentInsets, 0, 0, 0, 0);
+    }
+
     private WindowStateWithTask createWindow(Task task, int width, int height) {
         final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
         attrs.width = width;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3821b9c..bbda1c6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1022,6 +1022,26 @@
      */
     public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET =
             "carrier_default_actions_on_reset_string_array";
+
+    /**
+     * Defines carrier-specific actions which act upon
+     * com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE,
+     * used for customization of the default carrier app
+     * Format:
+     * {
+     *     "true : CARRIER_ACTION_IDX_1",
+     *     "false: CARRIER_ACTION_IDX_2"
+     * }
+     * Where {@code true} is a boolean indicates default network available/unavailable
+     * Where {@code CARRIER_ACTION_IDX} is an integer defined in
+     * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+     * Example:
+     * {@link com.android.carrierdefaultapp.CarrierActionUtils
+     * #CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER enable the app as the default URL handler}
+     * @hide
+     */
+    public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE =
+            "carrier_default_actions_on_default_network_available_string_array";
     /**
      * Defines a list of acceptable redirection url for default carrier app
      * @hides
@@ -1684,9 +1704,10 @@
         sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, "");
         sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
                 new String[]{
-                        "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" +
-                                "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED," +
-                                "com.android.internal.telephony.CARRIER_SIGNAL_RESET"
+                        "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:"
+                                + "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED,"
+                                + "com.android.internal.telephony.CARRIER_SIGNAL_RESET,"
+                                + "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE"
                 });
         sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
 
@@ -1694,12 +1715,22 @@
         // Default carrier app configurations
         sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY,
                 new String[]{
-                        "4, 1"
+                        "9, 4, 1"
+                        //9: CARRIER_ACTION_REGISTER_NETWORK_AVAIL
                         //4: CARRIER_ACTION_DISABLE_METERED_APNS
                         //1: CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
                 });
         sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET, new String[]{
-                "6" //6: CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
+                "6, 8"
+                //6: CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
+                //8: CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER
+                });
+        sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE,
+                new String[] {
+                        String.valueOf(false) + ": 7",
+                        //7: CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER
+                        String.valueOf(true) + ": 8"
+                        //8: CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER
                 });
         sDefaults.putStringArray(KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY, null);
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 190361b..e334c63 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -6661,6 +6661,25 @@
     }
 
     /**
+     * Action set from carrier signalling broadcast receivers to start/stop reporting default
+     * network available events
+     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+     * @param subId the subscription ID that this action applies to.
+     * @param report control start/stop reporting network status.
+     * @hide
+     */
+    public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                service.carrierActionReportDefaultNetworkStatus(subId, report);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling ITelephony#carrierActionReportDefaultNetworkStatus", e);
+        }
+    }
+
+    /**
      * Get aggregated video call data usage since boot.
      * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
      *
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 654adb2..9262ec5 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1303,6 +1303,16 @@
     void carrierActionSetRadioEnabled(int subId, boolean enabled);
 
     /**
+     * Action set from carrier signalling broadcast receivers to start/stop reporting default
+     * network conditions.
+     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+     * @param subId the subscription ID that this action applies to.
+     * @param report control start/stop reporting default network events.
+     * @hide
+     */
+    void carrierActionReportDefaultNetworkStatus(int subId, boolean report);
+
+    /**
      * Get aggregated video call data usage since boot.
      * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
      *
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 0343890..f29d993c 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -447,6 +447,20 @@
             "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE";
 
     /**
+     * <p>Broadcast Action: when system default network available/unavailable with
+     * carrier-disabled mobile data. Intended for carrier apps to set/reset carrier actions when
+     * other network becomes system default network, Wi-Fi for example.
+     * The intent will have the following extra values:</p>
+     * <ul>
+     *   <li>defaultNetworkAvailable</li><dd>A boolean indicates default network available.</dd>
+     *   <li>subId</li><dd>Sub Id which associated the default data.</dd>
+     * </ul>
+     * <p class="note">This is a protected intent that can only be sent by the system. </p>
+     */
+    public static final String ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE =
+            "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE";
+
+    /**
      * <p>Broadcast Action: when framework reset all carrier actions on sim load or absent.
      * intended for carrier apps clean up (clear UI e.g.) and only sent to the specified carrier app
      * The intent will have the following extra values:</p>
@@ -465,7 +479,7 @@
     public static final String EXTRA_APN_PROTO_KEY = "apnProto";
     public static final String EXTRA_PCO_ID_KEY = "pcoId";
     public static final String EXTRA_PCO_VALUE_KEY = "pcoValue";
-
+    public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY = "defaultNetworkAvailable";
 
    /**
      * Broadcast action to trigger CI OMA-DM Session.
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7173775..4684c77 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1755,9 +1755,18 @@
 
     /**
      * Enable or disable Wi-Fi.
+     *
+     * Note: This method will return false if wifi cannot be enabled (e.g., an incompatible mode
+     * where the user has enabled tethering or Airplane Mode).
+     *
+     * Applications need to have the {@link android.Manifest.permission#CHANGE_WIFI_STATE}
+     * permission to toggle wifi. Callers without the permissions will trigger a
+     * {@link java.lang.SecurityException}.
+     *
      * @param enabled {@code true} to enable, {@code false} to disable.
      * @return {@code true} if the operation succeeds (or if the existing state
-     *         is the same as the requested state).
+     *         is the same as the requested state). False if wifi cannot be toggled on/off when the
+     *         request is made.
      */
     public boolean setWifiEnabled(boolean enabled) {
         try {