Merge "Fix rounded corners fangs in RTL" into oc-dr1-dev
diff --git a/core/res/res/layout/shutdown_dialog.xml b/core/res/res/layout/shutdown_dialog.xml
new file mode 100644
index 0000000..398bfb1
--- /dev/null
+++ b/core/res/res/layout/shutdown_dialog.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2014 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:gravity="center_horizontal" >
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="6" />
+
+    <TextView
+        android:id="@id/text1"
+        android:layout_width="wrap_content"
+        android:layout_height="32dp"
+        android:text="@string/shutdown_progress"
+        android:textDirection="locale"
+        android:textSize="24sp"
+        android:textAppearance="?attr/textAppearanceLarge"
+        android:gravity="center"
+        android:layout_marginBottom="24dp"
+        android:fontFamily="@string/config_headlineFontFamily"/>
+
+    <ProgressBar
+        android:id="@id/progress"
+        android:layout_width="30dp"
+        android:layout_height="30dp"
+        style="?attr/progressBarStyleLarge" />
+
+    <Space
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="10" />
+
+</LinearLayout>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 99807f9..50550a4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3058,4 +3058,5 @@
   <java-symbol type="array" name="config_batteryPackageTypeSystem" />
   <java-symbol type="array" name="config_batteryPackageTypeService" />
   <java-symbol type="bool" name="config_showAreaUpdateInfoSettings" />
+  <java-symbol type="layout" name="shutdown_dialog" />
 </resources>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index 0c69d89..b3a0484 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="?android:attr/colorPrimary" />
+    <solid android:color="@color/qs_background_dark" />
 </shape>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 2ff626a..f8b7b8a 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -33,13 +33,13 @@
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="32dp"
+        android:layout_height="40dp"
         android:layout_alignParentEnd="true"
         android:clipChildren="false"
         android:clipToPadding="false"
         android:gravity="center"
-        android:paddingStart="16dp"
-        android:paddingEnd="16dp"
+        android:paddingStart="8dp"
+        android:paddingEnd="8dp"
         android:orientation="horizontal">
 
 
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 53d9cc5..8048c68 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -23,7 +23,8 @@
     android:drawableTop="@drawable/recents_empty"
     android:drawablePadding="25dp"
     android:textSize="16sp"
-    android:textColor="#ffffffff"
+    android:drawableTint="?attr/bgProtectTextColor"
+    android:textColor="?attr/bgProtectTextColor"
     android:text="@string/recents_empty_message"
     android:fontFamily="sans-serif"
     android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml
index 34b4e17..10b4316 100644
--- a/packages/SystemUI/res/layout/recents_stack_action_button.xml
+++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml
@@ -24,7 +24,7 @@
     android:paddingBottom="12dp"
     android:text="@string/recents_stack_action_button_label"
     android:textSize="14sp"
-    android:textColor="#FFFFFF"
+    android:textColor="?attr/bgProtectTextColor"
     android:textAllCaps="true"
     android:shadowColor="#99000000"
     android:shadowDx="0"
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 5274b64..93a0742 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="RecentsTheme" parent="@android:style/Theme.Material">
+    <style name="RecentsTheme" parent="RecentsBase">
         <!-- NoTitle -->
         <item name="android:windowNoTitle">true</item>
         <!-- Misc -->
@@ -27,6 +27,12 @@
         <item name="android:ambientShadowAlpha">0.35</item>
     </style>
 
+    <!-- OverlayManager might replace this style entirely, use RecentsTheme to set a property
+    that should exist in both light and dark versions of Recents -->
+    <style name="RecentsBase" parent="@android:style/Theme.Material">
+        <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_dark</item>
+        <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_dark</item>
+    </style>
 
     <!-- Recents theme -->
     <style name="RecentsTheme.Wallpaper">
@@ -35,6 +41,8 @@
         <item name="android:windowShowWallpaper">true</item>
         <item name="android:windowDisablePreview">true</item>
         <item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
+        <item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="bgProtectSecondaryTextColor">?android:attr/textColorSecondaryInverse</item>
     </style>
 
     <style name="ClearAllButtonDefaultMargins">
@@ -47,6 +55,8 @@
     <!-- Performance optimized Recents theme (no wallpaper) -->
     <style name="RecentsTheme.NoWallpaper">
         <item name="android:windowBackground">@android:color/black</item>
+        <item name="bgProtectTextColor">@android:color/white</item>
+        <item name="bgProtectSecondaryTextColor">@android:color/white</item>
     </style>
 
     <!-- Theme used for the activity that shows when the system forced an app to be resizable -->
@@ -290,7 +300,10 @@
     <style name="Animation.StatusBar">
     </style>
 
-    <style name="systemui_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+    <!-- Overlay manager may replace this theme -->
+    <style name="systemui_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
+
+    <style name="systemui_theme" parent="systemui_base">
         <item name="lightIconTheme">@style/DualToneLightTheme</item>
         <item name="darkIconTheme">@style/DualToneDarkTheme</item>
         <item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
@@ -303,7 +316,10 @@
         <item name="*android:successColor">?android:attr/textColorPrimaryInverse</item>
     </style>
 
-    <style name="qs_theme" parent="systemui_theme">
+    <!-- Overlay manager may replace this theme -->
+    <style name="qs_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
+
+    <style name="qs_theme" parent="qs_base">
         <item name="lightIconTheme">@style/QSIconTheme</item>
         <item name="darkIconTheme">@style/QSIconTheme</item>
     </style>
@@ -459,7 +475,7 @@
         <item name="android:paddingEnd">8dp</item>
     </style>
 
-    <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+    <style name="edit_theme" parent="qs_base">
         <item name="android:colorBackground">?android:attr/colorSecondary</item>
     </style>
 
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index bb0f2f9..22bb2a3 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -19,6 +19,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.view.Gravity;
@@ -28,9 +29,15 @@
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
-
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.leak.RotationUtils;
+
+import java.util.ArrayList;
+
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
 
 public class HardwareUiLayout extends FrameLayout implements Tunable {
 
@@ -49,7 +56,7 @@
     private int mEndPoint;
     private boolean mEdgeBleed;
     private boolean mRoundedDivider;
-    private boolean mLandscape;
+    private int mRotation = ROTATION_NONE;
     private boolean mRotatedBackground;
 
     public HardwareUiLayout(Context context, AttributeSet attrs) {
@@ -93,8 +100,10 @@
     private void updateEdgeMargin(int edge) {
         if (mChild != null) {
             MarginLayoutParams params = (MarginLayoutParams) mChild.getLayoutParams();
-            if (mLandscape) {
+            if (mRotation == ROTATION_LANDSCAPE) {
                 params.topMargin = edge;
+            } else if (mRotation == ROTATION_SEASCAPE) {
+                params.bottomMargin = edge;
             } else {
                 params.rightMargin = edge;
             }
@@ -118,6 +127,7 @@
                 mChild.addOnLayoutChangeListener(
                         (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
                                 updatePosition());
+                updateRotation();
             } else {
                 return;
             }
@@ -127,30 +137,69 @@
             animateChild(mOldHeight, newHeight);
         }
         post(() -> updatePosition());
-        boolean landscape = getMeasuredWidth() > getMeasuredHeight();
-        if (landscape != mLandscape) {
-            mLandscape = landscape;
-            if (mLandscape) {
-                toLandscape();
-                if (mChild instanceof LinearLayout) {
-                    mRotatedBackground = true;
-                    mBackground.setRotatedBackground(true);
-                    ((LinearLayout) mChild).setOrientation(LinearLayout.HORIZONTAL);
-                    swapDimens(mChild);
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateRotation();
+    }
+
+    private void updateRotation() {
+        int rotation = RotationUtils.getRotation(getContext());
+        if (rotation != mRotation) {
+            rotate(mRotation, rotation);
+            mRotation = rotation;
+        }
+    }
+
+    private void rotate(int from, int to) {
+        if (from != ROTATION_NONE && to != ROTATION_NONE) {
+            // Rather than handling this confusing case, just do 2 rotations.
+            rotate(from, ROTATION_NONE);
+            rotate(ROTATION_NONE, to);
+            return;
+        }
+        if (from == ROTATION_LANDSCAPE || to == ROTATION_SEASCAPE) {
+            rotateRight();
+        } else {
+            rotateLeft();
+        }
+        if (to != ROTATION_NONE) {
+            if (mChild instanceof LinearLayout) {
+                mRotatedBackground = true;
+                mBackground.setRotatedBackground(true);
+                LinearLayout linearLayout = (LinearLayout) mChild;
+                if (to == ROTATION_SEASCAPE) {
+                    swapOrder(linearLayout);
                 }
-            } else {
-                fromLandscape();
-                if (mChild instanceof LinearLayout) {
-                    mRotatedBackground = false;
-                    mBackground.setRotatedBackground(false);
-                    ((LinearLayout) mChild).setOrientation(LinearLayout.VERTICAL);
-                    swapDimens(mChild);
+                linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+                swapDimens(this.mChild);
+            }
+        } else {
+            if (mChild instanceof LinearLayout) {
+                mRotatedBackground = false;
+                mBackground.setRotatedBackground(false);
+                LinearLayout linearLayout = (LinearLayout) mChild;
+                if (from == ROTATION_SEASCAPE) {
+                    swapOrder(linearLayout);
                 }
+                linearLayout.setOrientation(LinearLayout.VERTICAL);
+                swapDimens(mChild);
             }
         }
     }
 
-    private void fromLandscape() {
+    private void swapOrder(LinearLayout linearLayout) {
+        ArrayList<View> children = new ArrayList<>();
+        for (int i = 0; i < linearLayout.getChildCount(); i++) {
+            children.add(0, linearLayout.getChildAt(i));
+            linearLayout.removeViewAt(i);
+        }
+        children.forEach(v -> linearLayout.addView(v));
+    }
+
+    private void rotateRight() {
         rotateRight(this);
         rotateRight(mChild);
         swapDimens(this);
@@ -202,7 +251,7 @@
         return retGravity;
     }
 
-    private void toLandscape() {
+    private void rotateLeft() {
         rotateLeft(this);
         rotateLeft(mChild);
         swapDimens(this);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 1a8a474..31d41ac 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -682,10 +682,14 @@
 
     /** {@inheritDoc} */
     public void onClick(DialogInterface dialog, int which) {
-        if (!(mAdapter.getItem(which) instanceof SilentModeTriStateAction)) {
+        Action item = mAdapter.getItem(which);
+        if ((item instanceof PowerAction)
+                || (item instanceof RestartAction)) {
+            if (mDialog != null) mDialog.fadeOut();
+        } else if (!(item instanceof SilentModeTriStateAction)) {
             dialog.dismiss();
         }
-        mAdapter.getItem(which).onPress();
+        item.onPress();
     }
 
     /**
@@ -1321,6 +1325,17 @@
                     .start();
         }
 
+        public void fadeOut() {
+            mHardwareLayout.setTranslationX(0);
+            mHardwareLayout.setAlpha(1);
+            mListView.animate()
+                    .alpha(0)
+                    .translationX(getAnimTranslation())
+                    .setDuration(300)
+                    .setInterpolator(new LogAccelerateInterpolator())
+                    .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/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 17a0d33..77c3bfa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -16,7 +16,9 @@
 
 import android.content.Context;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 
+import com.android.systemui.R;
 import com.android.systemui.plugins.qs.*;
 import com.android.systemui.plugins.qs.QSTileView;
 import com.android.systemui.qs.external.CustomTile;
@@ -78,7 +80,7 @@
 
     @Override
     public QSTileView createTileView(QSTile tile, boolean collapsedView) {
-        Context context = mHost.getContext();
+        Context context = new ContextThemeWrapper(mHost.getContext(), R.style.qs_theme);
         QSIconView icon = tile.createTileView(context);
         if (collapsedView) {
             return new QSTileBaseView(context, icon, collapsedView);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 4de1214..fa16f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Bundle;
@@ -42,9 +43,9 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.keyguard.LatencyTracker;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Interpolators;
-import com.android.keyguard.LatencyTracker;
 import com.android.systemui.R;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
@@ -110,11 +111,10 @@
     private RecentsPackageMonitor mPackageMonitor;
     private Handler mHandler = new Handler();
     private long mLastTabKeyEventTime;
-    private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
-    private int mLastDisplayDensity;
     private boolean mFinishedOnStartup;
     private boolean mIgnoreAltTabRelease;
     private boolean mIsVisible;
+    private Configuration mLastConfig;
 
     // Top level views
     private RecentsView mRecentsView;
@@ -333,16 +333,11 @@
         setContentView(R.layout.recents);
         takeKeyEvents(true);
         mRecentsView = findViewById(R.id.recents_view);
-        mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
-                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
-                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
         mScrimViews = new SystemBarScrimViews(this);
         getWindow().getAttributes().privateFlags |=
                 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
 
-        Configuration appConfiguration = Utilities.getAppConfiguration(this);
-        mLastDeviceOrientation = appConfiguration.orientation;
-        mLastDisplayDensity = appConfiguration.densityDpi;
+        mLastConfig = Utilities.getAppConfiguration(this);
         mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
         mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
             @Override
@@ -485,10 +480,15 @@
         Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
         int numStackTasks = mRecentsView.getStack().getStackTaskCount();
         EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
-                mLastDeviceOrientation != newDeviceConfiguration.orientation,
-                mLastDisplayDensity != newDeviceConfiguration.densityDpi, numStackTasks > 0));
-        mLastDeviceOrientation = newDeviceConfiguration.orientation;
-        mLastDisplayDensity = newDeviceConfiguration.densityDpi;
+                mLastConfig.orientation != newDeviceConfiguration.orientation,
+                mLastConfig.densityDpi != newDeviceConfiguration.densityDpi, numStackTasks > 0));
+
+        int configDiff = mLastConfig.updateFrom(newDeviceConfiguration);
+
+        // Recreate activity if an overlay was enabled/disabled
+        if ((configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
+            recreate();
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 521157d..d74970f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -43,14 +43,14 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
 
 import java.util.ArrayList;
 
-public class ScreenPinningRequest implements View.OnClickListener {
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
 
-    private static final int ROTATION_NONE = 0;
-    private static final int ROTATION_LANDSCAPE = 1;
-    private static final int ROTATION_SEASCAPE = 2;
+public class ScreenPinningRequest implements View.OnClickListener {
 
     private final Context mContext;
 
@@ -160,7 +160,7 @@
             DisplayMetrics metrics = new DisplayMetrics();
             mWindowManager.getDefaultDisplay().getMetrics(metrics);
             float density = metrics.density;
-            int rotation = getRotation(mContext);
+            int rotation = RotationUtils.getRotation(mContext);
 
             inflateView(rotation);
             int bgColor = mContext.getColor(
@@ -202,19 +202,6 @@
             mContext.registerReceiver(mReceiver, filter);
         }
 
-        private int getRotation(Context context) {
-            Configuration config = mContext.getResources().getConfiguration();
-            int rot = context.getDisplay().getRotation();
-            if (config.smallestScreenWidthDp < 600) {
-                if (rot == Surface.ROTATION_90) {
-                    return ROTATION_LANDSCAPE;
-                } else if (rot == Surface.ROTATION_270) {
-                    return ROTATION_SEASCAPE;
-                }
-            }
-            return ROTATION_NONE;
-        }
-
         private void inflateView(int rotation) {
             // We only want this landscape orientation on <600dp, so rather than handle
             // resource overlay for -land and -sw600dp-land, just inflate this
@@ -287,14 +274,14 @@
 
         protected void onConfigurationChanged() {
             removeAllViews();
-            inflateView(getRotation(mContext));
+            inflateView(RotationUtils.getRotation(mContext));
         }
 
         private final Runnable mUpdateLayoutRunnable = new Runnable() {
             @Override
             public void run() {
                 if (mLayout != null && mLayout.getParent() != null) {
-                    mLayout.setLayoutParams(getRequestLayoutParams(getRotation(mContext)));
+                    mLayout.setLayoutParams(getRequestLayoutParams(RotationUtils.getRotation(mContext)));
                 }
             }
         };
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 9ca756c..c1c41be0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -151,6 +151,12 @@
         mColorExtractor = Dependency.get(SysuiColorExtractor.class);
 
         LayoutInflater inflater = LayoutInflater.from(context);
+
+        mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
+        addView(mEmptyView);
+
+        boolean usingDarkText =
+                Color.luminance(mEmptyView.getTextColors().getDefaultColor()) < 0.5f;
         if (RecentsDebugFlags.Static.EnableStackActionButton) {
             mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button,
                     this, false);
@@ -160,10 +166,21 @@
                     EventBus.getDefault().send(new DismissAllTaskViewsEvent());
                 }
             });
+            // Disable black shadow if text color is already dark.
+            if (usingDarkText) {
+                mStackActionButton.setShadowLayer(0, 0, 0, 0);
+            }
             addView(mStackActionButton);
         }
-        mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
-        addView(mEmptyView);
+
+        // Let's also require dark status and nav bars if the text is dark
+        int systemBarsStyle = usingDarkText ? View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
+                View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0;
+
+        setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+                View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+                systemBarsStyle);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index bcba789..f6fab44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1150,7 +1150,6 @@
             ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
                     Dependency.get(ExtensionController.class).newExtension(QS.class)
                             .withPlugin(QS.class)
-                            .withUiMode(UI_MODE_TYPE_CAR, () -> new QSFragment())
                             .withDefault(() -> new QSFragment())
                             .build());
             final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
@@ -1318,6 +1317,9 @@
                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
         mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD);
         mKeyguardIndicationController.setDozing(mDozing);
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.onOverlayChanged();
+        }
     }
 
     protected void reevaluateStyles() {
@@ -4207,7 +4209,7 @@
         }
         if (shouldBeKeyguard) {
             showKeyguardImpl();
-        } else if (!shouldBeKeyguard && mIsKeyguard) {
+        } else {
             return hideKeyguardImpl();
         }
         return false;
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 ad406c7..ab55b23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -84,7 +84,6 @@
                 .setInterpolator(Interpolators.ALPHA_IN);
     }
 
-
     public void setLocation(View original) {
         original.getLocationInWindow(mInt2Cache);
 
@@ -115,7 +114,15 @@
         mBrightnessMirror.setLayoutParams(lp);
     }
 
+    public void onOverlayChanged() {
+        reinflate();
+    }
+
     public void onDensityOrFontScaleChanged() {
+        reinflate();
+    }
+
+    private void reinflate() {
         int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
         mStatusBarWindow.removeView(mBrightnessMirror);
         mBrightnessMirror = LayoutInflater.from(mBrightnessMirror.getContext()).inflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 2981b39..9d197d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2589,9 +2589,6 @@
         }
         updateAnimationState(false, child);
 
-        // Make sure the clipRect we might have set is removed
-        expandableView.setClipTopAmount(0);
-
         focusNextViewIfFocused(child);
     }
 
@@ -3038,10 +3035,6 @@
     private void generateChildRemovalEvents() {
         for (View child : mChildrenToRemoveAnimated) {
             boolean childWasSwipedOut = mSwipedOutViews.contains(child);
-            int animationType = childWasSwipedOut
-                    ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
-                    : AnimationEvent.ANIMATION_TYPE_REMOVE;
-            AnimationEvent event = new AnimationEvent(child, animationType);
 
             // we need to know the view after this one
             float removedTranslation = child.getTranslationY();
@@ -3052,7 +3045,16 @@
                     removedTranslation = row.getTranslationWhenRemoved();
                     ignoreChildren = false;
                 }
+                childWasSwipedOut |= Math.abs(row.getTranslation()) == row.getWidth();
             }
+            if (!childWasSwipedOut) {
+                Rect clipBounds = child.getClipBounds();
+                childWasSwipedOut = clipBounds.height() == 0;
+            }
+            int animationType = childWasSwipedOut
+                    ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
+                    : AnimationEvent.ANIMATION_TYPE_REMOVE;
+            AnimationEvent event = new AnimationEvent(child, animationType);
             event.viewAfterChangingView = getFirstChildBelowTranlsationY(removedTranslation,
                     ignoreChildren);
             mAnimationEvents.add(event);
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
new file mode 100644
index 0000000..ad20900
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.util.leak;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.view.Surface;
+
+public class RotationUtils {
+
+    public static final int ROTATION_NONE = 0;
+    public static final int ROTATION_LANDSCAPE = 1;
+    public static final int ROTATION_SEASCAPE = 2;
+
+    public static int getRotation(Context context) {
+        Configuration config = context.getResources().getConfiguration();
+        int rot = context.getDisplay().getRotation();
+        if (config.smallestScreenWidthDp < 600) {
+            if (rot == Surface.ROTATION_90) {
+                return ROTATION_LANDSCAPE;
+            } else if (rot == Surface.ROTATION_270) {
+                return ROTATION_SEASCAPE;
+            }
+        }
+        return ROTATION_NONE;
+    }
+}
diff --git a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
index ba1c91c..8b6ee2b 100644
--- a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
@@ -2,7 +2,7 @@
     package="com.android.systemui.theme.dark"
     android:versionCode="1"
     android:versionName="1.0">
-    <overlay android:targetPackage="android" android:priority="1"/>
+    <overlay android:targetPackage="com.android.systemui" android:priority="1"/>
 
     <application android:label="@string/sysui_overlay_dark" android:hasCode="false"/>
 </manifest>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
new file mode 100644
index 0000000..0c1b0ef
--- /dev/null
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="qs_base" parent="android:Theme.DeviceDefault">
+        <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
+        <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
+        <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
+        <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
+        <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
+        <item name="android:colorBackgroundFloating">#000</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
deleted file mode 100644
index 7e2b955..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault">
-        <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
-        <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
-        <!-- textColorPrimaryInverse is used on the lock screen and this means that we can't just
-        invert text colors otherwise we won't have contrast on the keyguard -->
-        <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_dark</item>
-        <!-- same for textColorSecondaryInverse -->
-        <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_dark</item>
-        <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
-        <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
-        <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
-        <item name="android:colorBackgroundFloating">#000</item>
-    </style>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
index 1745b4c..0a8749c 100644
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
@@ -2,7 +2,7 @@
     package="com.android.systemui.theme.lightwallpaper"
     android:versionCode="1"
     android:versionName="1.0">
-    <overlay android:targetPackage="android" android:priority="2"/>
+    <overlay android:targetPackage="com.android.systemui" android:priority="2"/>
 
     <application android:label="@string/sysui_overlay_light" android:hasCode="false"/>
 </manifest>
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
new file mode 100644
index 0000000..53912b5
--- /dev/null
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <style name="systemui_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+        <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+        <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+    </style>
+
+    <style name="RecentsBase" parent="@android:style/Theme.Material">
+        <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+        <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
deleted file mode 100644
index 877ebf8..0000000
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault.Light">
-        <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
-        <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
-    </style>
-</resources>
\ No newline at end of file
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index e2956dd..b657335 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -16,6 +16,7 @@
 
 package com.android.server.connectivity;
 
+import static android.hardware.usb.UsbManager.USB_CONFIGURED;
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
 import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -703,7 +704,7 @@
 
     private void showTetheredNotification(int id) {
         NotificationManager notificationManager =
-                (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+                (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
         if (notificationManager == null) {
             return;
         }
@@ -764,7 +765,7 @@
 
     private void clearTetheredNotification() {
         NotificationManager notificationManager =
-            (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+            (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
         if (notificationManager != null && mLastNotificationId != 0) {
             notificationManager.cancelAsUser(null, mLastNotificationId,
                     UserHandle.ALL);
@@ -803,11 +804,37 @@
 
         private void handleUsbAction(Intent intent) {
             final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
+            final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
             final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
+
+            mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
+                    usbConnected, usbConfigured, rndisEnabled));
+
+            // There are three types of ACTION_USB_STATE:
+            //
+            //     - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0)
+            //       Meaning: USB connection has ended either because of
+            //       software reset or hard unplug.
+            //
+            //     - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0)
+            //       Meaning: the first stage of USB protocol handshake has
+            //       occurred but it is not complete.
+            //
+            //     - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1)
+            //       Meaning: the USB handshake is completely done and all the
+            //       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) {
                 mRndisEnabled = rndisEnabled;
                 // start tethering if we have a request pending
-                if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
+                if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
                     tetherMatchingInterfaces(
                             IControlsTethering.STATE_TETHERED,
                             ConnectivityManager.TETHERING_USB);
@@ -983,7 +1010,7 @@
 
     public int setUsbTethering(boolean enable) {
         if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
-        UsbManager usbManager = mContext.getSystemService(UsbManager.class);
+        UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
 
         synchronized (mPublicSync) {
             if (enable) {
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 1fc1684..09fd96b 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -76,6 +76,10 @@
             }
         }
 
+        final String logmsg = String.format("initOffloadControl(%s)",
+                (controlCb == null) ? "null"
+                        : "0x" + Integer.toHexString(System.identityHashCode(controlCb)));
+
         mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, mControlCallback);
         final CbResults results = new CbResults();
         try {
@@ -86,11 +90,11 @@
                         results.errMsg = errMsg;
                     });
         } catch (RemoteException e) {
-            mLog.e("failed to initOffload: " + e);
+            record(logmsg, e);
             return false;
         }
 
-        if (!results.success) mLog.e("initOffload failed: " + results.errMsg);
+        record(logmsg, results);
         return results.success;
     }
 
@@ -108,14 +112,18 @@
         mOffloadControl = null;
         mTetheringOffloadCallback = null;
         mControlCallback = null;
+        mLog.log("stopOffloadControl()");
     }
 
     public boolean setUpstreamParameters(
             String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
-        iface = iface != null ? iface : NO_INTERFACE_NAME;
-        v4addr = v4addr != null ? v4addr : NO_IPV4_ADDRESS;
-        v4gateway = v4gateway != null ? v4gateway : NO_IPV4_GATEWAY;
-        v6gws = v6gws != null ? v6gws : new ArrayList<>();
+        iface = (iface != null) ? iface : NO_INTERFACE_NAME;
+        v4addr = (v4addr != null) ? v4addr : NO_IPV4_ADDRESS;
+        v4gateway = (v4gateway != null) ? v4gateway : NO_IPV4_GATEWAY;
+        v6gws = (v6gws != null) ? v6gws : new ArrayList<>();
+
+        final String logmsg = String.format("setUpstreamParameters(%s, %s, %s, [%s])",
+                iface, v4addr, v4gateway, String.join(",", v6gws));
 
         final CbResults results = new CbResults();
         try {
@@ -126,14 +134,27 @@
                         results.errMsg = errMsg;
                     });
         } catch (RemoteException e) {
-            mLog.e("failed to setUpstreamParameters: " + e);
+            record(logmsg, e);
             return false;
         }
 
-        if (!results.success) mLog.e("setUpstreamParameters failed: " + results.errMsg);
+        record(logmsg, results);
         return results.success;
     }
 
+    private void record(String msg, Throwable t) {
+        mLog.e(msg + " -> exception: " + t);
+    }
+
+    private void record(String msg, CbResults results) {
+        final String logmsg = msg + " -> " + results;
+        if (!results.success) {
+            mLog.e(logmsg);
+        } else {
+            mLog.log(logmsg);
+        }
+    }
+
     private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
         public final Handler handler;
         public final ControlCallback controlCb;
@@ -162,5 +183,13 @@
     private static class CbResults {
         boolean success;
         String errMsg;
+
+        public String toString() {
+            if (success) {
+                return "ok";
+            } else {
+                return "fail: " + errMsg;
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index ebb9450..c6ec287 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -19,6 +19,7 @@
 import android.animation.ArgbEvaluator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
+import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -79,7 +80,7 @@
     boolean mVrModeEnabled = false;
 
     public ImmersiveModeConfirmation(Context context) {
-        mContext = context;
+        mContext = ActivityThread.currentActivityThread().getSystemUiContext();
         mHandler = new H();
         mShowDelayMs = getNavBarExitDuration() * 3;
         mPanicThresholdMs = context.getResources()
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 02f2afc..56612ad 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -23,14 +23,17 @@
 import android.app.ProgressDialog;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.IBluetoothManager;
-import android.media.AudioAttributes;
-import android.nfc.NfcAdapter;
-import android.nfc.INfcAdapter;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.om.IOverlayManager;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.media.AudioAttributes;
+import android.nfc.INfcAdapter;
+import android.nfc.NfcAdapter;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -39,24 +42,21 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.SystemVibrator;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
-import android.os.SystemVibrator;
-import android.os.storage.IStorageShutdownObserver;
 import android.os.storage.IStorageManager;
-import android.system.ErrnoException;
-import android.system.Os;
-
+import android.os.storage.IStorageShutdownObserver;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ProgressBar;
+import android.widget.TextView;
 import com.android.internal.telephony.ITelephony;
 import com.android.server.pm.PackageManagerService;
 
-import android.util.Log;
-import android.view.WindowManager;
-
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileReader;
 import java.io.IOException;
 
 public final class ShutdownThread extends Thread {
@@ -243,15 +243,7 @@
         shutdownInner(context, confirm);
     }
 
-    private static void beginShutdownSequence(Context context) {
-        synchronized (sIsStartedGuard) {
-            if (sIsStarted) {
-                Log.d(TAG, "Shutdown sequence already running, returning.");
-                return;
-            }
-            sIsStarted = true;
-        }
-
+    private static ProgressDialog showShutdownDialog(Context context) {
         // Throw up a system dialog to indicate the device is rebooting / shutting down.
         ProgressDialog pd = new ProgressDialog(context);
 
@@ -303,6 +295,32 @@
             pd.setMessage(context.getText(
                         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 = Color.WHITE;
+            try {
+                IOverlayManager service = IOverlayManager.Stub.asInterface(
+                        ServiceManager.getService(Context.OVERLAY_SERVICE));
+                if (service.getOverlayInfo("com.android.systemui.theme.lightwallpaper", 0).isEnabled()) {
+                    color = Color.BLACK;
+                }
+            } catch (Exception e) {
+                // Shutdown UI really shouldn't crash or have strict dependencies on other services.
+                Log.w(TAG, "Problem getting overlay state", e);
+            }
+            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 {
             pd.setTitle(context.getText(com.android.internal.R.string.power_off));
             pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
@@ -312,8 +330,19 @@
         pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
 
         pd.show();
+        return pd;
+    }
 
-        sInstance.mProgressDialog = pd;
+    private static void beginShutdownSequence(Context context) {
+        synchronized (sIsStartedGuard) {
+            if (sIsStarted) {
+                Log.d(TAG, "Shutdown sequence already running, returning.");
+                return;
+            }
+            sIsStarted = true;
+        }
+
+        sInstance.mProgressDialog = showShutdownDialog(context);
         sInstance.mContext = context;
         sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
 
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index ab874ce..acf9e8f7 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -16,6 +16,11 @@
 
 package com.android.server.connectivity;
 
+import static android.hardware.usb.UsbManager.USB_CONFIGURED;
+import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_USB;
 import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
 import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
@@ -133,6 +138,7 @@
         public Object getSystemService(String name) {
             if (Context.CONNECTIVITY_SERVICE.equals(name)) return mConnectivityManager;
             if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
+            if (Context.USB_SERVICE.equals(name)) return mUsbManager;
             return super.getSystemService(name);
         }
     }
@@ -145,7 +151,7 @@
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
                 .thenReturn(new String[0]);
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
-                .thenReturn(new String[]{ "test_wlan\\d" });
+                .thenReturn(new String[]{ "test_wlan\\d", "test_rndis\\d" });
         when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
                 .thenReturn(new String[0]);
         when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
@@ -245,6 +251,14 @@
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
+    private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
+        final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
+        intent.putExtra(USB_CONNECTED, connected);
+        intent.putExtra(USB_CONFIGURED, configured);
+        intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
+        mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
     private void verifyInterfaceServingModeStarted() throws Exception {
         verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
         verify(mNMService, times(1))
@@ -287,6 +301,32 @@
     }
 
     @Test
+    public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
+        when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
+
+        // Emulate pressing the USB tethering button in Settings UI.
+        mTethering.startTethering(TETHERING_USB, null, false);
+        mLooper.dispatchAll();
+        verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
+
+        // Pretend we receive a USB connected broadcast. Here we also pretend
+        // that the RNDIS function is somehow enabled, so that we see if we
+        // might trip ourselves up.
+        sendUsbBroadcast(true, false, true);
+        mLooper.dispatchAll();
+        // This should produce no activity of any kind.
+        verifyNoMoreInteractions(mConnectivityManager);
+        verifyNoMoreInteractions(mNMService);
+
+        // Pretend we then receive USB configured broadcast.
+        sendUsbBroadcast(true, true, true);
+        mLooper.dispatchAll();
+        // Now we should see the start of tethering mechanics (in this case:
+        // tetherMatchingInterfaces() which starts by fetching all interfaces).
+        verify(mNMService, times(1)).listInterfaces();
+    }
+
+    @Test
     public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
         failingLocalOnlyHotspotLegacyApBroadcast(true);
     }
@@ -366,7 +406,7 @@
         when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+        mTethering.startTethering(TETHERING_WIFI, null, false);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startSoftAp(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -394,7 +434,7 @@
         when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+        mTethering.startTethering(TETHERING_WIFI, null, false);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startSoftAp(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -440,7 +480,7 @@
         /////
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.stopTethering(ConnectivityManager.TETHERING_WIFI);
+        mTethering.stopTethering(TETHERING_WIFI);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).stopSoftAp();
         verifyNoMoreInteractions(mWifiManager);
@@ -476,7 +516,7 @@
         doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+        mTethering.startTethering(TETHERING_WIFI, null, false);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startSoftAp(null);
         verifyNoMoreInteractions(mWifiManager);