Merge "Remove non-safe mode boot vibration." into oc-dr1-dev
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index d59e993..531afa4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4551,11 +4551,16 @@
                     savedBundle.getBoolean(EXTRA_SHOW_CHRONOMETER));
             publicExtras.putBoolean(EXTRA_CHRONOMETER_COUNT_DOWN,
                     savedBundle.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN));
-            publicExtras.putCharSequence(EXTRA_TITLE,
-                    mContext.getString(com.android.internal.R.string.notification_hidden_text));
             mN.extras = publicExtras;
-            final RemoteViews view = ambient ? makeAmbientNotification()
-                    : applyStandardTemplate(getBaseLayoutResource());
+            RemoteViews view;
+            if (ambient) {
+                publicExtras.putCharSequence(EXTRA_TITLE,
+                        mContext.getString(com.android.internal.R.string.notification_hidden_text));
+                view = makeAmbientNotification();
+            } else{
+                view = makeNotificationHeader(false /* ambient */);
+                view.setBoolean(R.id.notification_header, "setExpandOnlyOnButton", true);
+            }
             mN.extras = savedBundle;
             mN.mLargeIcon = largeIcon;
             mN.largeIcon = largeIconLegacy;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ef61703..7d2f8d1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -126,8 +126,8 @@
      * File creation mode: allow all other applications to have read access to
      * the created file.
      * <p>
-     * As of {@link android.os.Build.VERSION_CODES#N} attempting to use this
-     * mode will throw a {@link SecurityException}.
+     * Starting from {@link android.os.Build.VERSION_CODES#N}, attempting to use this
+     * mode throws a {@link SecurityException}.
      *
      * @deprecated Creating world-readable files is very dangerous, and likely
      *             to cause security holes in applications. It is strongly
@@ -146,7 +146,7 @@
      * File creation mode: allow all other applications to have write access to
      * the created file.
      * <p>
-     * As of {@link android.os.Build.VERSION_CODES#N} attempting to use this
+     * Starting from {@link android.os.Build.VERSION_CODES#N}, attempting to use this
      * mode will throw a {@link SecurityException}.
      *
      * @deprecated Creating world-writable files is very dangerous, and likely
@@ -1129,13 +1129,47 @@
      * </ul>
      * <p>
      * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
-     * are required to read or write to the returned path; it's always
-     * accessible to the calling app. This only applies to paths generated for
-     * package name of the calling application. To access paths belonging to
-     * other packages,
-     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or
-     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
+     * are required to read or write to the path that this method returns.
+     * However, starting from {@link android.os.Build.VERSION_CODES#M},
+     * to read the OBB expansion files, you must declare the
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission in the app manifest and ask for
+     * permission at runtime as follows:
+     * </p>
      * <p>
+     * {@code <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+     * android:maxSdkVersion="23" />}
+     * </p>
+     * <p>
+     * Starting from {@link android.os.Build.VERSION_CODES#N},
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
+     * permission is not required, so don’t ask for this
+     * permission at runtime. To handle both cases, your app must first try to read the OBB file,
+     * and if it fails, you must request
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission at runtime.
+     * </p>
+     *
+     * <p>
+     * The following code snippet shows how to do this:
+     * </p>
+     *
+     * <pre>
+     * File obb = new File(obb_filename);
+     * boolean open_failed = false;
+     *
+     * try {
+     *     BufferedReader br = new BufferedReader(new FileReader(obb));
+     *     open_failed = false;
+     *     ReadObbFile(br);
+     * } catch (IOException e) {
+     *     open_failed = true;
+     * }
+     *
+     * if (open_failed) {
+     *     // request READ_EXTERNAL_STORAGE permission before reading OBB file
+     *     ReadObbFileWithPermission();
+     * }
+     * </pre>
+     *
      * On devices with multiple users (as described by {@link UserManager}),
      * multiple users may share the same OBB storage location. Applications
      * should ensure that multiple instances running under different users don't
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index 663e6e4..abf9cc9 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -26,7 +26,7 @@
 public class SyncStatusInfo implements Parcelable {
     private static final String TAG = "Sync";
 
-    static final int VERSION = 3;
+    static final int VERSION = 4;
 
     private static final int MAX_EVENT_COUNT = 10;
 
@@ -102,6 +102,7 @@
             parcel.writeLong(mLastEventTimes.get(i));
             parcel.writeString(mLastEvents.get(i));
         }
+        parcel.writeInt(numSourcePeriodic);
     }
 
     public SyncStatusInfo(Parcel parcel) {
@@ -146,6 +147,16 @@
                 }
             }
         }
+        if (version < 4) {
+            // Before version 4, numSourcePeriodic wasn't persisted.
+            numSourcePeriodic = numSyncs - numSourceLocal - numSourcePoll - numSourceServer
+                    - numSourceUser;
+            if (numSourcePeriodic < 0) { // Sanity check.
+                numSourcePeriodic = 0;
+            }
+        } else {
+            numSourcePeriodic = parcel.readInt();
+        }
     }
 
     public SyncStatusInfo(SyncStatusInfo other) {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 19fb15c..4160ed7 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -201,7 +201,7 @@
      * New in version 22:
      *   - BLE scan result background count, BLE unoptimized scan time
      */
-    static final String CHECKIN_VERSION = "23";
+    static final String CHECKIN_VERSION = "24";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d822f96..2d8ed7a 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -10080,22 +10080,6 @@
         public static final String DEVICE_DEMO_MODE = "device_demo_mode";
 
         /**
-         * Retail mode specific settings. This is encoded as a key=value list, separated by commas.
-         * Ex: "user_inactivity_timeout_ms=30000,warning_dialog_timeout_ms=10000". The following
-         * keys are supported:
-         *
-         * <pre>
-         * user_inactivity_timeout_ms  (long)
-         * warning_dialog_timeout_ms   (long)
-         * </pre>
-         * <p>
-         * Type: string
-         *
-         * @hide
-         */
-        public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants";
-
-        /**
          * Indicates the maximum time that an app is blocked for the network rules to get updated.
          *
          * Type: long
diff --git a/core/java/android/service/vr/IVrListener.aidl b/core/java/android/service/vr/IVrListener.aidl
index afb13d3..acca3fa 100644
--- a/core/java/android/service/vr/IVrListener.aidl
+++ b/core/java/android/service/vr/IVrListener.aidl
@@ -20,5 +20,5 @@
 
 /** @hide */
 oneway interface IVrListener {
-    void focusedActivityChanged(in ComponentName component);
+    void focusedActivityChanged(in ComponentName component, boolean running2dInVr, int pid);
 }
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
index 5da4560..fa3d065 100644
--- a/core/java/android/service/vr/VrListenerService.java
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -70,8 +70,10 @@
 
     private final IVrListener.Stub mBinder = new IVrListener.Stub() {
         @Override
-        public void focusedActivityChanged(ComponentName component) {
-            mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, component).sendToTarget();
+        public void focusedActivityChanged(
+                ComponentName component, boolean running2dInVr, int pid) {
+            mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, running2dInVr ? 1 : 0,
+                    pid, component).sendToTarget();
         }
     };
 
@@ -84,7 +86,8 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_ON_CURRENT_VR_ACTIVITY_CHANGED: {
-                    VrListenerService.this.onCurrentVrActivityChanged((ComponentName) msg.obj);
+                    VrListenerService.this.onCurrentVrActivityChanged(
+                            (ComponentName) msg.obj, msg.arg1 == 1, msg.arg2);
                 } break;
             }
         }
@@ -120,6 +123,29 @@
     }
 
     /**
+     * An extended version of onCurrentVrActivityChanged
+     *
+     * <p>This will be called when this service is initially bound, but is not
+     * guaranteed to be called before onUnbind.  In general, this is intended to be used to
+     * determine when user focus has transitioned between two VR activities, or between a
+     * VR activity and a 2D activity. This should be overridden instead of the above
+     * onCurrentVrActivityChanged as that version is deprecated.</p>
+     *
+     * @param component the {@link ComponentName} of the VR activity or the 2D intent.
+     * @param running2dInVr true if the component is a 2D component.
+     * @param pid the process the component is running in.
+     *
+     * @see android.app.Activity#setVrModeEnabled
+     * @see android.R.attr#enableVrMode
+     * @hide
+     */
+    public void onCurrentVrActivityChanged(
+            ComponentName component, boolean running2dInVr, int pid) {
+        // Override to implement. Default to old behaviour of sending null for 2D.
+        onCurrentVrActivityChanged(running2dInVr ? null : component);
+    }
+
+    /**
      * Checks if the given component is enabled in user settings.
      *
      * <p>If this component is not enabled in the user's settings, it will not be started when
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 568c40a..5804560 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -59,6 +59,7 @@
     private Drawable mBackground;
     private int mHeaderBackgroundHeight;
     private boolean mEntireHeaderClickable;
+    private boolean mExpandOnlyOnButton;
     private boolean mAcceptAllTouches;
 
     ViewOutlineProvider mProvider = new ViewOutlineProvider() {
@@ -315,6 +316,7 @@
     public class HeaderTouchListener implements View.OnTouchListener {
 
         private final ArrayList<Rect> mTouchRects = new ArrayList<>();
+        private Rect mExpandButtonRect;
         private int mTouchSlop;
         private boolean mTrackGesture;
         private float mDownX;
@@ -326,7 +328,7 @@
         public void bindTouchRects() {
             mTouchRects.clear();
             addRectAroundView(mIcon);
-            addRectAroundView(mExpandButton);
+            mExpandButtonRect = addRectAroundView(mExpandButton);
             addWidthRect();
             mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
         }
@@ -340,9 +342,10 @@
             mTouchRects.add(r);
         }
 
-        private void addRectAroundView(View view) {
+        private Rect addRectAroundView(View view) {
             final Rect r = getRectAroundView(view);
             mTouchRects.add(r);
+            return r;
         }
 
         private Rect getRectAroundView(View view) {
@@ -395,6 +398,9 @@
             if (mAcceptAllTouches) {
                 return true;
             }
+            if (mExpandOnlyOnButton) {
+                return mExpandButtonRect.contains((int) x, (int) y);
+            }
             for (int i = 0; i < mTouchRects.size(); i++) {
                 Rect r = mTouchRects.get(i);
                 if (r.contains((int) x, (int) y)) {
@@ -440,4 +446,12 @@
     public void setAcceptAllTouches(boolean acceptAllTouches) {
         mAcceptAllTouches = mEntireHeaderClickable || acceptAllTouches;
     }
+
+    /**
+     * Sets whether only the expand icon itself should serve as the expand target.
+     */
+    @RemotableViewMethod
+    public void setExpandOnlyOnButton(boolean expandOnlyOnButton) {
+        mExpandOnlyOnButton = expandOnlyOnButton;
+    }
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9b881fd..faf3e125 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2591,5 +2591,16 @@
             encoder.addProperty("type", type);
             encoder.addProperty("flags", flags);
         }
+
+        /**
+         * @hide
+         * @return True if the layout parameters will cause the window to cover the full screen;
+         *         false otherwise.
+         */
+        public boolean isFullscreen() {
+            return x == 0 && y == 0
+                    && width == WindowManager.LayoutParams.MATCH_PARENT
+                    && height == WindowManager.LayoutParams.MATCH_PARENT;
+        }
     }
 }
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index 68cf5cd..477285e63 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -29,7 +29,9 @@
 import com.android.internal.colorextraction.types.ExtractionType;
 import com.android.internal.colorextraction.types.Tonal;
 
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Iterator;
 
 /**
  * Class to process wallpaper colors and generate a tonal palette based on them.
@@ -44,7 +46,7 @@
     private static final String TAG = "ColorExtractor";
 
     private final SparseArray<GradientColors[]> mGradientColors;
-    private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners;
+    private final ArrayList<WeakReference<OnColorsChangedListener>> mOnColorsChangedListeners;
     private final Context mContext;
     private final ExtractionType mExtractionType;
     private WallpaperColors mSystemColors;
@@ -167,8 +169,17 @@
     }
 
     protected void triggerColorsChanged(int which) {
-        for (OnColorsChangedListener listener: mOnColorsChangedListeners) {
-            listener.onColorsChanged(this, which);
+        ArrayList<WeakReference<OnColorsChangedListener>> references =
+                new ArrayList<>(mOnColorsChangedListeners);
+        final int size = references.size();
+        for (int i = 0; i < size; i++) {
+            final WeakReference<OnColorsChangedListener> weakReference = references.get(i);
+            final OnColorsChangedListener listener = weakReference.get();
+            if (listener == null) {
+                mOnColorsChangedListeners.remove(weakReference);
+            } else {
+                listener.onColorsChanged(this, which);
+            }
         }
     }
 
@@ -187,11 +198,20 @@
     }
 
     public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
-        mOnColorsChangedListeners.add(listener);
+        mOnColorsChangedListeners.add(new WeakReference<>(listener));
     }
 
     public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener listener) {
-        mOnColorsChangedListeners.remove(listener);
+        ArrayList<WeakReference<OnColorsChangedListener>> references =
+                new ArrayList<>(mOnColorsChangedListeners);
+        final int size = references.size();
+        for (int i = 0; i < size; i++) {
+            final WeakReference<OnColorsChangedListener> weakReference = references.get(i);
+            if (weakReference.get() == listener) {
+                mOnColorsChangedListeners.remove(weakReference);
+                break;
+            }
+        }
     }
 
     public static class GradientColors {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 2363f68..dd7d43d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6553,9 +6553,12 @@
          * inactive so can be dropped.
          */
         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-        public boolean reset() {
+        public boolean reset(long uptime, long realtime) {
             boolean active = false;
 
+            mOnBatteryBackgroundTimeBase.init(uptime, realtime);
+            mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
+
             if (mWifiRunningTimer != null) {
                 active |= !mWifiRunningTimer.reset(false);
                 active |= mWifiRunning;
@@ -6741,11 +6744,6 @@
             mLastStepUserTime = mLastStepSystemTime = 0;
             mCurStepUserTime = mCurStepSystemTime = 0;
 
-            mOnBatteryBackgroundTimeBase.reset(mBsi.mClocks.elapsedRealtime() * 1000,
-                    mBsi.mClocks.uptimeMillis() * 1000);
-            mOnBatteryScreenOffBackgroundTimeBase.reset(mBsi.mClocks.elapsedRealtime() * 1000,
-                    mBsi.mClocks.uptimeMillis() * 1000);
-
             if (!active) {
                 if (mWifiRunningTimer != null) {
                     mWifiRunningTimer.detach();
@@ -9337,7 +9335,7 @@
         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
 
         for (int i=0; i<mUidStats.size(); i++) {
-            if (mUidStats.valueAt(i).reset()) {
+            if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
                 mUidStats.remove(mUidStats.keyAt(i));
                 i--;
             }
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index e212c43..fa645f4 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -315,7 +315,6 @@
     SettingProto boot_count = 270;
     SettingProto safe_boot_disallowed = 271;
     SettingProto device_demo_mode = 272;
-    SettingProto retail_demo_mode_constants = 273;
     SettingProto database_downgrade_reason = 274;
     SettingProto contacts_database_wal_enabled = 275;
     SettingProto multi_sim_voice_call_subscription = 276;
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index fe12e7f..ba35592 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -471,7 +471,7 @@
     <string name="permlab_nfc" msgid="4423351274757876953">"controlar Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Permite á aplicación comunicarse con etiquetas, tarxetas e lectores Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"desactivar o bloqueo da pantalla"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite á aplicación desactivar o bloqueo do teclado e calquera seguridade dos contrasinais asociada. Por exemplo, o teléfono desactiva o bloqueo do teclado ao recibir unha chamada telefónica entrante e, a continuación, volve activar o bloqueo do teclado unha vez finalizada a chamada."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite á aplicación desactivar o bloqueo do teclado e calquera seguranza dos contrasinais asociada. Por exemplo, o teléfono desactiva o bloqueo do teclado ao recibir unha chamada telefónica entrante e, a continuación, volve activar o bloqueo do teclado unha vez finalizada a chamada."</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"xestionar hardware de impresión dixital"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicación invoque métodos para engadir e eliminar modelos de uso de impresión dixital."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de impresión dixital"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index a36903a..ddc9dd8 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -528,10 +528,10 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ऐप्स को नेटवर्क नीतियां प्रबंधित करने और ऐप्स-विशिष्‍ट नियमों को परिभाषित करने देता है."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब बदलें"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ऐप्स  को यह संशोधित करने देता है कि ऐप्स की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्‍य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string>
-    <string name="permlab_accessNotifications" msgid="7673416487873432268">"नोटिफिकेशन तक पहुंचें"</string>
-    <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को नोटिफिकेशन को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
-    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"नोटिफिकेशन श्रवणकर्ता सेवा से जुड़ें"</string>
-    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को नोटिफिकेशन श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"नोटिफ़िकेशन तक पहुंचें"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को नोटिफ़िकेशन को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
+    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"नोटिफ़िकेशन श्रवणकर्ता सेवा से जुड़ें"</string>
+    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को नोटिफ़िकेशन श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"किसी स्थिति प्रदाता सेवा से आबद्ध हों"</string>
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"धारक को किसी स्थिति प्रदाता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"भावी सेवा से आबद्ध करें"</string>
@@ -1084,13 +1084,13 @@
     <string name="volume_call" msgid="3941680041282788711">"कॉल के दौरान वॉल्‍यूम"</string>
     <string name="volume_bluetooth_call" msgid="2002891926351151534">"ब्लूटूथ कॉल के दौरान वॉल्‍यूम"</string>
     <string name="volume_alarm" msgid="1985191616042689100">"अलार्म वॉल्‍यूम"</string>
-    <string name="volume_notification" msgid="2422265656744276715">"नोटिफिकेशन वॉल्‍यूम"</string>
+    <string name="volume_notification" msgid="2422265656744276715">"नोटिफ़िकेशन वॉल्‍यूम"</string>
     <string name="volume_unknown" msgid="1400219669770445902">"आवाज़"</string>
     <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ब्लूटूथ वॉल्‍यूम"</string>
     <string name="volume_icon_description_ringer" msgid="3326003847006162496">"रिंगटोन वॉल्‍यूम"</string>
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"कॉल वॉल्‍यूम"</string>
     <string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया वॉल्‍यूम"</string>
-    <string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफिकेशन वॉल्‍यूम"</string>
+    <string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफ़िकेशन वॉल्‍यूम"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"डिफ़ॉल्‍ट रिंगटोन"</string>
     <string name="ringtone_default_with_actual" msgid="1767304850491060581">"डिफ़ॉल्ट (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string>
@@ -1289,7 +1289,7 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"सरल उपयोग"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string>
-    <string name="notification_listener_binding_label" msgid="2014162835481906429">"नोटिफिकेशन श्रवणकर्ता"</string>
+    <string name="notification_listener_binding_label" msgid="2014162835481906429">"नोटिफ़िकेशन श्रवणकर्ता"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string>
     <string name="notification_ranker_binding_label" msgid="774540592299064747">"नोटिफ़िकेशन रैंकर सेवा"</string>
@@ -1703,7 +1703,7 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="5929663562028088222">"अवर्गीकृत"</string>
-    <string name="importance_from_user" msgid="7318955817386549931">"आपने इन नोटिफिकेशन का महत्व सेट किया है."</string>
+    <string name="importance_from_user" msgid="7318955817386549931">"आपने इन नोटिफ़िकेशन का महत्व सेट किया है."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"यह मौजूद व्यक्तियों के कारण महत्वपूर्ण है."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें (इस खाते वाला एक उपयोगकर्ता पहले से मौजूद है) ?"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 5f6631e..ff75939 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -203,7 +203,7 @@
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"रिंगर कंपन"</string>
     <string name="silent_mode_ring" msgid="8592241816194074353">"रिंगर चालू"</string>
     <string name="reboot_to_update_title" msgid="6212636802536823850">"Android सिस्टीम अद्यतन"</string>
-    <string name="reboot_to_update_prepare" msgid="6305853831955310890">"अद्यतनित करण्यासाठी तयार करीत आहे…"</string>
+    <string name="reboot_to_update_prepare" msgid="6305853831955310890">"अपडेट करण्याची तयारी करत आहे…"</string>
     <string name="reboot_to_update_package" msgid="3871302324500927291">"अद्यतन पॅकेजची प्रक्रिया करीत आहे…"</string>
     <string name="reboot_to_update_reboot" msgid="6428441000951565185">"रीस्टार्ट करीत आहे..."</string>
     <string name="reboot_to_reset_title" msgid="4142355915340627490">"फॅक्‍टरी डेटा रीसेट"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index d8ecd1e..db9bc0b 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -63,7 +63,7 @@
     <string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
     <string name="enablePin" msgid="209412020907207950">"Ação sem êxito. Ative o bloqueio do SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
-      <item quantity="one">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item>
+      <item quantity="one">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado.</item>
       <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item>
     </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
@@ -176,7 +176,7 @@
     <string name="low_memory" product="tv" msgid="516619861191025923">"O armazenamento da TV está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569">
-      <item quantity="one">Autoridades de certificação instaladas</item>
+      <item quantity="one">Autoridade de certificação instalada</item>
       <item quantity="other">Autoridades de certificação instaladas</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por um terceiro desconhecido"</string>
@@ -232,7 +232,7 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Utilize esta opção para uma interferência mínima do sistema quando o dispositivo não responder ou estiver demasiado lento, ou quando precisar de todas as secções de relatório. Não permite introduzir mais detalhes ou tirar capturas de ecrã adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos…</item>
+      <item quantity="one">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundo…</item>
       <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
@@ -868,7 +868,7 @@
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"Há 1 mês"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Há mais de 1 mês"</string>
     <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
-      <item quantity="one">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+      <item quantity="one">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dia</item>
       <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <string name="last_month" msgid="3959346739979055432">"Último mês"</string>
@@ -922,35 +922,35 @@
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
-      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> minuto</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
-      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> hora</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="2203515825765397130">
-      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> dia</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="4820062134188885734">
-      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> ano</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="4655043589817680966">
-      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minuto</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8084579714205223891">
-      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> hora</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="333215369363433992">
-      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dia</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="8644862986413104011">
-      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> ano</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
     </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
@@ -1099,11 +1099,11 @@
     <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notificação"</string>
     <string name="ringtone_unknown" msgid="3914515995813061520">"Desconhecido"</string>
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
-      <item quantity="one">Redes Wi-Fi disponíveis</item>
+      <item quantity="one">Rede Wi-Fi disponível</item>
       <item quantity="other">Redes Wi-Fi disponíveis</item>
     </plurals>
     <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
-      <item quantity="one">Redes Wi-Fi abertas disponíveis</item>
+      <item quantity="one">Rede Wi-Fi aberta disponível</item>
       <item quantity="other">Redes Wi-Fi abertas disponíveis</item>
     </plurals>
     <string name="wifi_available_title" msgid="3817100557900599505">"Ligar à rede Wi-Fi aberta"</string>
@@ -1602,7 +1602,7 @@
     <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Os PINs não correspondem. Tente novamente."</string>
     <string name="restr_pin_error_too_short" msgid="8173982756265777792">"O PIN é demasiado pequeno. Deve ter, no mínimo, 4 dígitos."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
-      <item quantity="one">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item>
+      <item quantity="one">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundo</item>
       <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Tente novamente mais tarde"</string>
@@ -1635,7 +1635,7 @@
     <string name="data_saver_enable_title" msgid="4674073932722787417">"Ativar a Poupança de dados?"</string>
     <string name="data_saver_enable_button" msgid="7147735965247211818">"Ativar"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
-      <item quantity="one">Durante %1$d minutos (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="one">Durante %1$d minuto (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Durante %1$d minutos (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="6830154222366042597">
@@ -1643,7 +1643,7 @@
       <item quantity="other">Durante %1$d min (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
-      <item quantity="one">Durante %1$d horas (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="one">Durante %1$d hora (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Durante %1$d horas (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="4787552595253082371">
@@ -1651,7 +1651,7 @@
       <item quantity="other">Durante %1$d h (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
-      <item quantity="one">Durante %d minutos</item>
+      <item quantity="one">Durante %d minuto</item>
       <item quantity="other">Durante %d minutos</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2199350154433426128">
@@ -1659,7 +1659,7 @@
       <item quantity="other">Durante %d min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
-      <item quantity="one">Durante %d horas</item>
+      <item quantity="one">Durante %d hora</item>
       <item quantity="other">Durante %d horas</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="6748277774662434217">
@@ -1699,7 +1699,7 @@
     <string name="close_button_text" msgid="3937902162644062866">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
     <plurals name="selected_count" formatted="false" msgid="7187339492915744615">
-      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionado</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="5929663562028088222">"Sem categoria"</string>
@@ -1763,7 +1763,7 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher automaticamente o conteúdo"</string>
     <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"Sem sugestões do preenchimento automático"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="5506565809835815274">
-      <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item>
+      <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> sugestão do preenchimento automático</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item>
     </plurals>
     <string name="autofill_save_title" msgid="3345527308992082601">"Pretende guardar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 7d1871f..7b54518 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -21,10 +21,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="byteShort" msgid="8340973892742019101">"б"</string>
-    <string name="kilobyteShort" msgid="7542884022844556968">"Кб"</string>
-    <string name="megabyteShort" msgid="6355851576770428922">"Мб"</string>
-    <string name="gigabyteShort" msgid="3259882455212193214">"Гб"</string>
-    <string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
+    <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+    <string name="megabyteShort" msgid="6355851576770428922">"МБ"</string>
+    <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+    <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
     <string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дн."</string>
@@ -1027,7 +1027,7 @@
     <string name="browse" msgid="6993590095938149861">"Веб-переглядач"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Закінчується пам’ять"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Деякі системні функції можуть не працювати"</string>
-    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Недостатньо місця для системи. Переконайтесь, що на пристрої є 250 Мб вільного місця, і повторіть спробу."</string>
+    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Недостатньо місця для системи. Переконайтесь, що на пристрої є 250 МБ вільного місця, і повторіть спробу."</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> працює"</string>
     <string name="app_running_notification_text" msgid="1197581823314971177">"Торкніться, щоб дізнатися більше або зупинити додаток."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bd8e14ea..ab26ae1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -591,10 +591,7 @@
     <string name="notification_header_divider_symbol_with_spaces" translatable="false">" • "</string>
 
     <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen -->
-    <string name="notification_hidden_text">Contents hidden</string>
-
-    <!-- Text shown in place of notification contents when the notification is hidden by policy on a secure lockscreen -->
-    <string name="notification_hidden_by_policy_text">Contents hidden by policy</string>
+    <string name="notification_hidden_text">New notification</string>
 
     <!-- Text shown when viewing channel settings for notifications related to the virtual keyboard -->
     <string name="notification_channel_virtual_keyboard">Virtual keyboard</string>
@@ -4590,22 +4587,10 @@
     <!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
     <string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
 
-    <!-- Title of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
-    <string name="reset_retail_demo_mode_title">Reset device?</string>
-    <!-- Text of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
-    <string name="reset_retail_demo_mode_text">Tap to reset device</string>
     <!-- Text of dialog shown when starting a demo user for the first time [CHAR LIMIT=40] -->
     <string name="demo_starting_message">Starting demo\u2026</string>
     <!-- Text of dialog shown when starting a new demo user in retail demo mode [CHAR LIMIT=40] -->
     <string name="demo_restarting_message">Resetting device\u2026</string>
-    <!-- Title of the dialog shown when user inactivity times out in retail demo mode [CHAR LIMIT=40] -->
-    <string name="demo_user_inactivity_timeout_title">Reset device?</string>
-    <!-- Warning message shown when user inactivity times out in retail demo mode [CHAR LIMIT=none] -->
-    <string name="demo_user_inactivity_timeout_countdown">You\u2019ll lose any changes and the demo will start again in <xliff:g id="timeout" example="9">%1$s</xliff:g> seconds\u2026</string>
-    <!-- Text of button to allow user to abort countdown and continue current session in retail demo mode [CHAR LIMIT=40] -->
-    <string name="demo_user_inactivity_timeout_left_button">Cancel</string>
-    <!-- Text of button to allow user to abort countdown and immediately start another session in retail demo mode [CHAR LIMIT=40] -->
-    <string name="demo_user_inactivity_timeout_right_button">Reset now</string>
 
     <!-- Accessibilty string added to a widget that has been suspended [CHAR LIMIT=20] -->
     <string name="suspended_widget_accessibility">Disabled <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index baa7386..a3b7ee8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2560,7 +2560,6 @@
   <java-symbol type="id" name="notification_material_reply_text_3" />
 
   <java-symbol type="string" name="notification_hidden_text" />
-  <java-symbol type="string" name="notification_hidden_by_policy_text" />
   <java-symbol type="id" name="app_name_text" />
   <java-symbol type="id" name="header_text" />
   <java-symbol type="id" name="expand_button" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ca53885..a979ac8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -298,7 +298,6 @@
                     Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
                     Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
                     Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
-                    Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
                     Settings.Global.SAFE_BOOT_DISALLOWED,
                     Settings.Global.SAMPLING_PROFILER_MS,
                     Settings.Global.SELINUX_STATUS,
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
index af4a6d9..8fd4e31 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
@@ -400,7 +400,7 @@
         assertNotNull(sensor.getSensorBackgroundTime());
 
         // Reset the stats. Since the sensor is still running, we should still see the timer
-        bi.getUidStatsLocked(UID).reset();
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
 
         sensor = uid.getSensorStats().get(SENSOR_ID);
         assertNotNull(sensor);
@@ -410,9 +410,111 @@
         bi.noteStopSensorLocked(UID, SENSOR_ID);
 
         // Now the sensor timer has stopped so this reset should also take out the sensor.
-        bi.getUidStatsLocked(UID).reset();
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
 
         sensor = uid.getSensorStats().get(SENSOR_ID);
         assertNull(sensor);
     }
+
+    @SmallTest
+    public void testSensorResetTimes() throws Exception {
+        final MockClocks clocks = new MockClocks();
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+        final int which = BatteryStats.STATS_SINCE_CHARGED;
+        bi.mForceOnBattery = true;
+        clocks.realtime = 100; // in ms
+        clocks.uptime = 100; // in ms
+
+        // TimeBases are on for some time.
+        BatteryStatsImpl.TimeBase timeBase = bi.getOnBatteryTimeBase();
+        BatteryStatsImpl.TimeBase bgTimeBase = bi.getOnBatteryBackgroundTimeBase(UID);
+        timeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        bgTimeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // TimeBases are turned off
+        timeBase.setRunning(false, clocks.uptime * 1000, clocks.realtime * 1000);
+        bgTimeBase.setRunning(false, clocks.uptime * 1000, clocks.realtime * 1000);
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Timer is turned on
+        bi.noteStartSensorLocked(UID, SENSOR_ID);
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Timebase was off so times are all 0.
+        BatteryStats.Uid.Sensor sensor = bi.getUidStats().get(UID).getSensorStats().get(SENSOR_ID);
+        BatteryStats.Timer timer = sensor.getSensorTime();
+        BatteryStats.Timer bgTimer = sensor.getSensorBackgroundTime();
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Reset the stats. Since the sensor is still running, we should still see the timer
+        // but still with 0 times.
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Now stop the timer. The times should still be 0.
+        bi.noteStopSensorLocked(UID, SENSOR_ID);
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        // Now repeat with the TimeBases turned on the entire time.
+        timeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        bgTimeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Timer is turned on
+        bi.noteStartSensorLocked(UID, SENSOR_ID);
+
+        clocks.realtime += 111;
+        clocks.uptime += 1111;
+
+        // Timebase and timer was on so times have increased.
+        assertEquals(111_000, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(111, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(111_000, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(111, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Reset the stats. Since the sensor is still running, we should still see the timer
+        // but with 0 times.
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 112;
+        clocks.uptime += 112;
+
+        // Now stop the timer. The times should have increased since the timebase was on.
+        bi.noteStopSensorLocked(UID, SENSOR_ID);
+        assertEquals(112_000, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(112, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(112_000, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(112, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+    }
 }
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SettingsLib/res/drawable/ic_qs_night_display_on.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
rename to packages/SettingsLib/res/drawable/ic_qs_night_display_on.xml
diff --git a/packages/SystemUI/res/drawable/ic_signal_location.xml b/packages/SettingsLib/res/drawable/ic_signal_location.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_signal_location.xml
rename to packages/SettingsLib/res/drawable/ic_signal_location.xml
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 1a6fd39..fe91f40 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -296,7 +296,7 @@
     <string name="enable_freeform_support" msgid="1461893351278940416">"Activar ventás de forma libre"</string>
     <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais."</string>
     <string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string>
-    <string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguridade de ordenador completas non están protexidas"</string>
+    <string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguranza de ordenador completas non están protexidas"</string>
     <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar ou eliminar o contrasinal para as copias de seguranza completas do escritorio"</string>
     <string name="local_backup_password_toast_success" msgid="582016086228434290">"Novo contrasinal da copia de seguranza definido"</string>
     <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"O contrasinal novo e a confirmación non coinciden"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index f0da2f7..12564b5 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -220,7 +220,7 @@
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"वाई-फ़ाई के सक्रिय रहने पर भी, हमेशा मोबाइल डेटा सक्रिय रखें (तेज़ी से नेटवर्क स्विच करने के लिए)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"हार्डवेयर त्‍वरण को टेदर करना उपलब्ध होने पर उसका उपयोग करें"</string>
     <string name="adb_warning_title" msgid="6234463310896563253">"USB डीबग करने की अनुमति दें?"</string>
-    <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करने का उद्देश्‍य केवल विकास है. इसका इस्तेमाल आपके कंप्‍यूटर और आपके डिवाइस के बीच डेटा को कॉपी करने, बिना नोटिफिकेशन के आपके डिवाइस पर ऐप इंस्‍टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करने का उद्देश्‍य केवल विकास है. इसका इस्तेमाल आपके कंप्‍यूटर और आपके डिवाइस के बीच डेटा को कॉपी करने, बिना नोटिफ़िकेशन के आपके डिवाइस पर ऐप इंस्‍टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string>
     <string name="adb_keys_warning_message" msgid="5659849457135841625">"आपके द्वारा पूर्व में प्राधिकृत सभी कंप्यूटर से USB डीबगिंग की पहुंच निरस्त करें?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"विकास सेटिंग की अनुमति दें?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"ये सेटिंग केवल विकास संबंधी उपयोग के प्रयोजन से हैं. वे आपके डिवाइस और उस पर स्‍थित ऐप्स  को खराब कर सकती हैं या उनके दुर्व्यवहार का कारण हो सकती हैं."</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
index 167ffe6..7f82a1ca 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
@@ -91,7 +91,8 @@
 
     // Shared prefs keys for storing dismissed state.
     // Index into current dismissed state.
-    private static final String DISMISS_INDEX = "_dismiss_index";
+    @VisibleForTesting
+    static final String DISMISS_INDEX = "_dismiss_index";
     private static final String SETUP_TIME = "_setup_time";
     private static final String IS_DISMISSED = "_is_dismissed";
 
@@ -355,7 +356,8 @@
         return elapsedTime > category.exclusiveExpireDaysInMillis;
     }
 
-    private boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
+    @VisibleForTesting
+    boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
         String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
         if (dismissControl == null) {
             return false;
@@ -372,7 +374,11 @@
             return false;
         }
         int index = mSharedPrefs.getInt(keyBase + DISMISS_INDEX, 0);
-        int currentDismiss = parseDismissString(dismissControl)[index];
+        int[] dismissRules = parseDismissString(dismissControl);
+        if (dismissRules.length <= index) {
+            return true;
+        }
+        int currentDismiss = dismissRules[index];
         long time = getEndTime(mSharedPrefs.getLong(keyBase + SETUP_TIME, 0), currentDismiss);
         if (System.currentTimeMillis() >= time) {
             // Dismiss timeout has passed, undismiss it.
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
index 60933cf..8391136 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.suggestions;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -42,8 +44,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import static com.google.common.truth.Truth.assertThat;
-
 @RunWith(SettingLibRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SuggestionParserTest {
@@ -190,6 +190,24 @@
         assertThat(sl.getSuggestionForCategory("category2")).hasSize(1);
     }
 
+    @Test
+    public void isSuggestionDismissed_mismatchRule_shouldDismiss() {
+        final Tile suggestion = new Tile();
+        suggestion.metaData = new Bundle();
+        suggestion.metaData.putString(SuggestionParser.META_DATA_DISMISS_CONTROL, "1,2,3");
+        suggestion.intent = new Intent().setComponent(new ComponentName("pkg", "cls"));
+
+        // Dismiss suggestion when smart suggestion is not enabled.
+        mSuggestionParser.dismissSuggestion(suggestion, false /* isSmartSuggestionEnabled */);
+        final String suggestionKey = suggestion.intent.getComponent().flattenToShortString();
+        // And point to last rule in dismiss control
+        mPrefs.edit().putInt(suggestionKey + SuggestionParser.DISMISS_INDEX, 2).apply();
+
+        // Turn on smart suggestion, and check if suggestion is enabled.
+        assertThat(mSuggestionParser.isDismissed(suggestion, true /* isSmartSuggestionEnabled */))
+                .isTrue();
+    }
+
     private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) {
         mSuggestionsBeforeDismiss = new ArrayList<>();
         mSuggestionsAfterDismiss = new ArrayList<>();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index b328933..819ee3e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -915,9 +915,6 @@
                 Settings.Global.DEVICE_DEMO_MODE,
                 GlobalSettingsProto.DEVICE_DEMO_MODE);
         dumpSetting(s, p,
-                Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
-                GlobalSettingsProto.RETAIL_DEMO_MODE_CONSTANTS);
-        dumpSetting(s, p,
                 Settings.Global.DATABASE_DOWNGRADE_REASON,
                 GlobalSettingsProto.DATABASE_DOWNGRADE_REASON);
         dumpSetting(s, p,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e322acc..47ffa5c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -208,7 +208,7 @@
         android:icon="@drawable/icon"
         android:process="com.android.systemui"
         android:supportsRtl="true"
-        android:theme="@style/systemui_theme"
+        android:theme="@style/Theme.SystemUI"
         android:defaultToDeviceProtectedStorage="true"
         android:directBootAware="true">
         <!-- Keep theme in sync with SystemUIApplication.onCreate().
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index b821e7e..9fdb00e 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -43,7 +43,7 @@
          android:layout_height="wrap_content"
          android:layout_width="280dp"
          android:layout_gravity="center_horizontal"
-         android:theme="@style/PasswordTheme"
+         android:theme="?attr/passwordStyle"
          >
 
          <EditText android:id="@+id/passwordEntry"
diff --git a/packages/SystemUI/res-keyguard/values/attrs.xml b/packages/SystemUI/res-keyguard/values/attrs.xml
index 802bd30..e2ce210 100644
--- a/packages/SystemUI/res-keyguard/values/attrs.xml
+++ b/packages/SystemUI/res-keyguard/values/attrs.xml
@@ -41,4 +41,6 @@
     <declare-styleable name="CarrierText">
         <attr name="allCaps" format="boolean" />
     </declare-styleable>
+
+    <attr name="passwordStyle" format="reference" />
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index ea867ee..c6f9423 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -60,7 +60,13 @@
         <item name="android:layout_gravity">center_horizontal|bottom</item>
     </style>
 
-    <style name="PasswordTheme" parent="systemui_theme">
+    <style name="PasswordTheme" parent="Theme.SystemUI">
+        <item name="android:textColor">?attr/wallpaperTextColor</item>
+        <item name="android:colorControlNormal">?attr/wallpaperTextColor</item>
+        <item name="android:colorControlActivated">?attr/wallpaperTextColor</item>
+    </style>
+
+    <style name="PasswordTheme.Light" parent="Theme.SystemUI.Light">
         <item name="android:textColor">?attr/wallpaperTextColor</item>
         <item name="android:colorControlNormal">?attr/wallpaperTextColor</item>
         <item name="android:colorControlActivated">?attr/wallpaperTextColor</item>
diff --git a/packages/SystemUI/res/drawable/ic_dnd.xml b/packages/SystemUI/res/drawable/ic_dnd.xml
index e658e68..9a1d502 100644
--- a/packages/SystemUI/res/drawable/ic_dnd.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd.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,13 +15,13 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
     android:width="24dp"
     android:tint="?android:attr/colorControlNormal">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z" />
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM16,13L8,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
index 0515b35..e7b9fa7 100644
--- a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence.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.
@@ -22,9 +22,6 @@
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0s10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,20.5c-4.7,0.0 -8.5,-3.8 -8.5,-8.5S7.3,3.5 12.0,3.5s8.5,3.8 8.5,8.5S16.7,20.5 12.0,20.5z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,3.3 2.7,6.0 6.0,6.0s6.0,-2.7 6.0,-6.0C18.0,8.7 15.4,6.0 12.0,6.0zM15.0,13.0L9.0,13.0l0.0,-2.0l6.0,0.0L15.0,13.0z"/>
+        android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10 10,-4.5 10,-10S17.5,2 12,2zM12,20.5c-4.7,0 -8.5,-3.8 -8.5,-8.5S7.3,3.5 12,3.5s8.5,3.8 8.5,8.5 -3.8,8.5 -8.5,8.5zM12,6c-3.3,0 -6,2.7 -6,6s2.7,6 6,6 6,-2.7 6,-6 -2.6,-6 -6,-6zM14,13h-4c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h4c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm.xml b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
index e64f445..996e488 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm.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,13 +15,13 @@
 -->
 <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"
     android:tint="?android:attr/colorControlNormal">
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z" />
+        android:pathData="M2.7,6.5c-0.4,-0.4 -0.3,-1 0.1,-1.4l3,-2.6c0.4,-0.4 1,-0.3 1.4,0.1C7.6,3 7.5,3.7 7.1,4l-3,2.6C3.6,7 3,6.9 2.7,6.5zM21.3,5.1l-3.1,-2.6c-0.4,-0.4 -0.99,-0.31 -1.4,0.1c-0.4,0.4 -0.3,1 0.1,1.4L20,6.6c0.41,0.37 1,0.3 1.4,-0.1C21.73,6.12 21.7,5.4 21.3,5.1zM21,13c0,5 -4,9 -9,9s-9,-4 -9,-9s4,-9 9,-9S21,8 21,13zM19.1,13c0,-3.9 -3.2,-7.1 -7.1,-7.1S4.9,9.1 4.9,13s3.2,7.1 7.1,7.1S19.1,16.9 19.1,13zM11.75,8C11.34,8 11,8.34 11,8.75V14l4.14,2.48c0.34,0.21 0.77,0.1 0.98,-0.24s0.09,-0.79 -0.25,-0.99l-3.37,-2v-4.5C12.5,8.34 12.16,8 11.75,8z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
index 37d7690..02fb1e7 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.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,13 +15,13 @@
 -->
 <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"
     android:tint="?android:attr/colorControlNormal" >
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z" />
+        android:pathData="M21.35,6.49c-0.35,0.42 -0.98,0.47 -1.4,0.12l-3.07,-2.57a1,1 0,1 1,1.29 -1.53l3.07,2.57c0.42,0.35 0.47,0.98 0.11,1.41zM20.72,20.09a0.9,0.9 0,0 1,0 1.27,0.9 0.9,0 0,1 -1.27,0l-1.57,-1.57A8.875,8.875 0,0 1,12 22c-4.98,0 -9,-4.03 -9,-9 0,-2.25 0.83,-4.31 2.2,-5.89l-0.8,-0.8 -0.41,0.35a1,1 0,0 1,-1.35 -0.06,1 1,0 0,1 0.07,-1.47l0.27,-0.23 -0.7,-0.7a0.9,0.9 0,0 1,0 -1.27c0.35,-0.35 0.93,-0.35 1.28,0l17.16,17.16zM16.54,18.45L6.55,8.46A7.041,7.041 0,0 0,4.9 13c0,3.91 3.19,7.1 7.1,7.1 1.73,0 3.31,-0.62 4.54,-1.65zM7.17,3.98A0.997,0.997 0,1 0,5.9 2.44l-0.16,0.13 1.42,1.42 0.01,-0.01zM12,4c-1.41,0 -2.73,0.33 -3.92,0.91l1.45,1.45c0.77,-0.29 1.6,-0.46 2.47,-0.46 3.91,0 7.1,3.18 7.1,7.1 0,0.87 -0.17,1.7 -0.45,2.47l1.44,1.44c0.58,-1.18 0.91,-2.5 0.91,-3.91a9,9 0,0 0,-9 -9z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
index 5c3c650..b0b9404 100644
--- a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_sco.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,13 +15,16 @@
 -->
 <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"
     android:tint="?android:attr/colorControlNormal" >
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M29.41,19.0L34.0,14.41L34.0,22.0l1.0,0.0l5.71,-5.71 -4.3,-4.29 4.29,-4.29L35.0,2.0l-1.0,0.0l0.0,7.59L29.41,5.0 28.0,6.41 33.59,12.0 28.0,17.59 29.41,19.0zM36.0,5.83l1.88,1.88L36.0,9.59L36.0,5.83zm0.0,8.58l1.88,1.88L36.0,18.17l0.0,-3.76zM40.0,31.0c-2.49,0.0 -4.89,-0.4 -7.14,-1.14 -0.69,-0.22 -1.48,-0.06 -2.0,0.49l-4.4,4.41c-5.67,-2.88 -10.29,-7.51 -13.18,-13.17l4.4,-4.41c0.55,-0.5 0.71,-1.3 0.49,-2.03C17.4,12.9 17.0,10.49 17.0,8.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0L8.0,6.0c-1.11,0.0 -2.0,0.89 -2.0,2.0 0.0,18.78 15.22,34.0 34.0,34.0 1.11,0.0 2.0,-0.89 2.0,-2.0l0.0,-7.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0z" />
+        android:pathData="M20,15.5c-1.25,0 -2.45,-0.2 -3.57,-0.57c-0.35,-0.11 -0.74,-0.03 -1.02,0.24l-2.2,2.2c-2.83,-1.44 -5.15,-3.75 -6.59,-6.59l2.2,-2.21c0.28,-0.26 0.36,-0.65 0.25,-1C8.7,6.45 8.5,5.25 8.5,4c0,-0.55 -0.45,-1 -1,-1H4C3.45,3 3,3.45 3,4c0,9.39 7.61,17 17,17c0.55,0 1,-0.45 1,-1v-3.5C21,15.95 20.55,15.5 20,15.5z"/>
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M17.97,6l1.88,-1.87c0.21,-0.21 0.21,-0.54 0,-0.74L17.6,1.16l-0.01,-0.01c-0.21,-0.2 -0.53,-0.2 -0.73,0.01c-0.09,0.1 -0.15,0.23 -0.15,0.36v3.23l-2.03,-2.03c-0.21,-0.21 -0.53,-0.21 -0.74,0c-0.21,0.21 -0.21,0.53 0,0.74L16.49,6l-2.55,2.55c-0.21,0.21 -0.21,0.53 0,0.74c0.21,0.21 0.53,0.21 0.74,0l2.03,-2.03v3.23c0,0.29 0.24,0.52 0.52,0.52c0.13,0 0.26,-0.05 0.35,-0.15l2.25,-2.25c0.21,-0.21 0.21,-0.54 0,-0.74L17.97,6zM17.75,2.78l0.99,0.99l-0.99,0.99V2.78zM17.75,9.23V7.27l0.99,0.99L17.75,9.23z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
index d689207..53c0740 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media.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.
@@ -22,6 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M12.0,3.0l0.0,9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12.0 6.0,14.01 6.0,16.5S8.01,21.0 10.5,21.0c2.31,0.0 4.2,-1.75 4.45,-4.0L15.0,17.0L15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0z" />
+        android:pathData="M18,3h-5c-0.55,0 -1,0.45 -1,1v8.3a3.88,3.88 0,0 0,-2.9 -0.04c-1.79,0.67 -3.11,2.35 -3.1,4.26A4.483,4.483 0,0 0,10.5 21c2.5,0 4.5,-2.3 4.5,-4.5V6h3c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
index 9b7b2da..60d0184 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt.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.
@@ -22,9 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M17.0,3.0l-7.0,0.0l0.0,9.3C9.5,12.1 9.0,12.0 8.5,12.0C6.0,12.0 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0s4.5,-2.3 4.5,-4.5C13.0,14.7 13.0,6.0 13.0,6.0l4.0,0.0L17.0,3.0z"/>
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
+        android:pathData="M16,3h-5c-0.55,0 -1,0.45 -1,1v8.3c-0.93,-0.39 -1.96,-0.4 -2.9,-0.04c-1.79,0.67 -3.11,2.35 -3.1,4.26C4,19 6.01,21 8.49,21c0,0 0.01,0 0.01,0c2.5,0 4.5,-2.3 4.5,-4.5V6h3c0.55,0 1,-0.45 1,-1V4C17,3.45 16.55,3 16,3zM20.97,12l1.88,-1.87c0.21,-0.21 0.21,-0.54 0,-0.74L20.6,7.16l-0.01,-0.01c-0.21,-0.2 -0.53,-0.2 -0.73,0.01c-0.09,0.1 -0.15,0.23 -0.15,0.36v3.23l-2.03,-2.03c-0.21,-0.21 -0.53,-0.21 -0.74,0c-0.21,0.21 -0.21,0.53 0,0.74L19.49,12l-2.55,2.55c-0.21,0.21 -0.21,0.53 0,0.74c0.21,0.21 0.53,0.21 0.74,0l2.03,-2.03v3.23c0,0.29 0.24,0.52 0.52,0.52c0.13,0 0.26,-0.05 0.35,-0.15l0.02,-0.02l2.23,-2.23c0.21,-0.21 0.21,-0.54 0,-0.74L20.97,12zM20.75,10.75V8.78l0.99,0.99L20.75,10.75zM20.75,15.23v-1.96l0.99,0.99C21.73,14.25 20.75,15.23 20.75,15.23z"/>
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
index 17ac01d..49fcfc4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.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.
@@ -22,12 +22,12 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M13.0,6.0l4.0,0.0L17.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C13.0,8.8 13.0,6.0 13.0,6.0z"/>
+        android:pathData="M13,6h3c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1h-5c-0.55,0 -1,0.45 -1,1v4.6l3,3V6z"/>
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M2.1,5.7L8.4,12.0C6.0,12.1 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3l0.0,-0.1l3.9,3.9l1.3,-1.3L3.4,4.5L2.1,5.7z"/>
+        android:pathData="M4,5.1C3.67,4.76 3.12,4.75 2.78,5.08C2.41,5.42 2.4,6 2.75,6.35L8.4,12C6,12.1 4,14 4,16.5c0,2.51 2.33,4.67 4.84,4.48C11.35,20.81 13,18.62 13,16.7v-0.1l3.27,3.27c0.35,0.35 0.91,0.35 1.25,0l0.05,-0.05c0.35,-0.35 0.35,-0.91 0,-1.25L4,5.1z"/>
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
+        android:pathData="M20.97,12l1.88,-1.87c0.21,-0.21 0.21,-0.54 0,-0.74L20.6,7.16l-0.01,-0.01c-0.21,-0.2 -0.53,-0.2 -0.73,0.01c-0.09,0.1 -0.15,0.23 -0.15,0.36v3.23l-2.03,-2.03c-0.21,-0.21 -0.53,-0.21 -0.74,0c-0.21,0.21 -0.21,0.53 0,0.74L19.49,12l-2.55,2.55c-0.21,0.21 -0.21,0.53 0,0.74c0.21,0.21 0.53,0.21 0.74,0l2.03,-2.03v3.23c0,0.29 0.24,0.52 0.52,0.52c0.13,0 0.26,-0.05 0.35,-0.15l2.25,-2.25c0.21,-0.21 0.21,-0.54 0,-0.74L20.97,12zM20.75,8.78l0.99,0.99l-0.99,0.98V8.78zM20.75,15.23v-1.96l0.99,0.99C21.73,14.25 20.75,15.23 20.75,15.23z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
index 267d09d..ebb86e8 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.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.
@@ -22,9 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C15.0,8.8 15.0,6.0 15.0,6.0z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M4.8,3.9L3.5,5.1l6.9,6.9C8.0,12.1 6.0,14.0 6.0,16.5C6.0,19.0 8.0,21.0 10.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3c0.0,0.0 0.0,-0.1 0.0,-0.1l4.0,4.0l1.3,-1.3L4.8,3.9z" />
+        android:pathData="M15,6h3c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1h-5c-0.55,0 -1,0.45 -1,1v4.6l3,3V6zM4.18,4.48c-0.37,0.34 -0.38,0.92 -0.03,1.27L10.4,12C8,12.1 6,14 6,16.5c0,2.51 2.33,4.67 4.84,4.48 2.51,-0.17 4.16,-2.36 4.16,-4.28v-0.1l3.37,3.37c0.35,0.35 0.91,0.35 1.25,0l0.05,-0.05c0.35,-0.35 0.35,-0.91 0,-1.25L5.4,4.5a0.866,0.866 0,0 0,-1.22 -0.02z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
index 18af711..f258856 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.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,13 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24dp"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0"
+    android:viewportHeight="23.4"
+    android:viewportWidth="23.4"
     android:width="24dp"
     android:tint="?android:attr/colorControlNormal" >
 
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z" />
+    <group
+        android:translateX="-0.78"
+        android:translateY="-0.5" >
+        <path
+            android:fillColor="#FFFFFF"
+            android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C7.63,5.36 6,7.92 6,11v5l-2.15,2.15c-0.19,0.2 -0.19,0.51 0.01,0.71C3.95,18.95 4.07,19 4.2,19h15.6c0.45,0 0.67,-0.54 0.35,-0.85L18,16z"/>
+    </group>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
index bc926c3..106d899 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.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,13 +15,23 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="23.4"
+    android:viewportWidth="23.3"
     android:width="24dp"
     android:tint="?android:attr/colorControlNormal" >
 
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z" />
+    <group
+        android:translateX="-0.85"
+        android:translateY="-0.5" >
+        <path
+            android:fillColor="#FF0"
+            android:pathData="M20.73,19.46l-0.6,-0.6c0,0 0,0 0,0L5.54,4.26c-0.35,-0.35 -0.92,-0.35 -1.27,0c-0.35,0.35 -0.35,0.92 0,1.27l2.4,2.4C6.25,8.85 6,9.88 6,11v5l-2.15,2.15c-0.19,0.2 -0.19,0.51 0.01,0.71C3.95,18.95 4.07,19 4.2,19h13.53l1.73,1.73c0.35,0.35 0.92,0.35 1.27,0C21.09,20.38 21.09,19.81 20.73,19.46z"/>
+        <path
+            android:fillColor="#FF0"
+            android:pathData="M18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C9.87,4.83 9.31,5.08 8.8,5.4l9.2,9.2V11z"/>
+        <path
+            android:fillColor="#FF0"
+            android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z"/>
+    </group>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
index ffbffad..9db8511 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.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.
@@ -22,6 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z" />
+        android:pathData="M1,15c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v4c0,0.55 0.45,1 1,1zM4,17c0.55,0 1,-0.45 1,-1L5,8c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v8c0,0.55 0.45,1 1,1zM22,10v4c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1zM20,17c0.55,0 1,-0.45 1,-1L21,8c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v8c0,0.55 0.45,1 1,1zM16.5,3h-9C6.67,3 6,3.67 6,4.5v15c0,0.83 0.67,1.5 1.5,1.5h9c0.83,0 1.5,-0.67 1.5,-1.5v-15c0,-0.83 -0.67,-1.5 -1.5,-1.5zM16,19L8,19L8,5h8v14z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 75ed110..4668b80 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -29,7 +29,7 @@
       <item quantity="one">अवलोकन में %d स्‍क्रीन</item>
       <item quantity="other">अवलोकन में %d स्‍क्रीन</item>
     </plurals>
-    <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"कोई नोटिफिकेशन नहीं"</string>
+    <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"कोई नोटिफ़िकेशन नहीं"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ऑनगोइंग"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"बैटरी कम है"</string>
@@ -166,7 +166,7 @@
     <string name="accessibility_settings_button" msgid="799583911231893380">"सिस्टम सेटिंग."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाएं."</string>
     <string name="accessibility_overflow_action" msgid="5681882033274783311">"सभी नोटिफ़िकेशन देखें"</string>
-    <string name="accessibility_remove_notification" msgid="3603099514902182350">"नोटिफिकेशन साफ़ करें"</string>
+    <string name="accessibility_remove_notification" msgid="3603099514902182350">"नोटिफ़िकेशन साफ़ करें"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त करना."</string>
     <string name="accessibility_tty_enabled" msgid="4613200365379426561">"टेलीटाइपराइटर सक्षम."</string>
@@ -181,8 +181,8 @@
     <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ऐप्लिकेशन जानकारी खोलें."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
-    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफिकेशन खारिज की गई."</string>
-    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"नोटिफिकेशन शेड."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफ़िकेशन खारिज की गई."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"नोटिफ़िकेशन शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"त्वरित सेटिंग."</string>
     <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"लॉक स्क्रीन."</string>
     <string name="accessibility_desc_settings" msgid="3417884241751434521">"सेटिंग"</string>
@@ -255,7 +255,7 @@
       <item quantity="one">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और नोटिफ़िकेशन हैं.</item>
       <item quantity="other">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और नोटिफ़िकेशन हैं.</item>
     </plurals>
-    <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"नोटिफिकेशन सेटिंग"</string>
+    <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"नोटिफ़िकेशन सेटिंग"</string>
     <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> सेटिंग"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्‍क्रीन स्‍वचालित रूप से घूमेगी."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्‍क्रीन लैंडस्केप अभिविन्यास में लॉक है."</string>
@@ -411,7 +411,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"फिर से न दिखाएं"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"सभी साफ करें"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"अब प्रारंभ करें"</string>
-    <string name="empty_shade_text" msgid="708135716272867002">"कोई नोटिफिकेशन नहीं"</string>
+    <string name="empty_shade_text" msgid="708135716272867002">"कोई नोटिफ़िकेशन नहीं"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"प्रोफ़ाइल को मॉनीटर किया जा सकता है"</string>
     <string name="vpn_footer" msgid="2388611096129106812">"नेटवर्क को मॉनीटर किया जा सकता है"</string>
     <string name="branded_vpn_footer" msgid="2168111859226496230">"नेटवर्क को मॉनिटर किया जा सकता है"</string>
@@ -542,8 +542,8 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ चालू करें?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करें"</string>
-    <string name="show_silently" msgid="6841966539811264192">"नोटिफिकेशन मौन रूप से दिखाएं"</string>
-    <string name="block" msgid="2734508760962682611">"सभी नोटिफिकेशन अवरुद्ध करें"</string>
+    <string name="show_silently" msgid="6841966539811264192">"नोटिफ़िकेशन मौन रूप से दिखाएं"</string>
+    <string name="block" msgid="2734508760962682611">"सभी नोटिफ़िकेशन अवरुद्ध करें"</string>
     <string name="do_not_silence" msgid="6878060322594892441">"मौन ना करें"</string>
     <string name="do_not_silence_block" msgid="4070647971382232311">"मौन या अवरुद्ध ना करें"</string>
     <string name="tuner_full_importance_settings" msgid="3207312268609236827">"पावर नोटिफ़िकेशन नियंत्रण"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c35c30c..7667c5e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -758,7 +758,7 @@
     <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string>
-    <string name="notification_channel_storage" msgid="3077205683020695313">"저장소"</string>
+    <string name="notification_channel_storage" msgid="3077205683020695313">"저장공간"</string>
     <string name="instant_apps" msgid="6647570248119804907">"인스턴트 앱"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"인스턴트 앱은 설치가 필요하지 않습니다."</string>
     <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 9f03e50..b40b6d4 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -26,7 +26,7 @@
     <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Os ecrãs recentes aparecem aqui"</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ignorar aplicações recentes"</string>
     <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
-      <item quantity="one">%d ecrãs na Vista geral</item>
+      <item quantity="one">%d ecrã na Vista geral</item>
       <item quantity="other">%d ecrãs na Vista geral</item>
     </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
@@ -252,7 +252,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
-      <item quantity="one">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
+      <item quantity="one">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificação no grupo.</item>
       <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
     </plurals>
     <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Definições de notificação"</string>
@@ -556,7 +556,7 @@
     <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicação não tem categorias de notificação"</string>
     <string name="notification_unblockable_desc" msgid="3561016061737896906">"Não é possível desativar as notificações desta aplicação"</string>
     <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorias de notificação desta aplicação</item>
+      <item quantity="one">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categoria de notificação desta aplicação</item>
       <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorias de notificação desta aplicação</item>
     </plurals>
     <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1705f79..58117bd 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -273,6 +273,9 @@
     <!-- Doze: the brightness value to use for the higher brightness AOD mode -->
     <integer name="config_doze_aod_brightness_high">27</integer>
 
+    <!-- Doze: the brightness value to use for the sunlight AOD mode -->
+    <integer name="config_doze_aod_brightness_sunlight">28</integer>
+
     <!-- Doze: whether the double tap sensor reports 2D touch coordinates -->
     <bool name="doze_double_tap_reports_touch_coordinates">false</bool>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index daed847..27e067a 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="RecentsBase">
+    <style name="RecentsTheme" parent="@android:style/Theme.Material">
         <!-- NoTitle -->
         <item name="android:windowNoTitle">true</item>
         <!-- Misc -->
@@ -27,13 +27,6 @@
         <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">
         <item name="android:windowBackground">@*android:color/transparent</item>
@@ -41,8 +34,13 @@
         <item name="android:windowShowWallpaper">true</item>
         <item name="android:windowDisablePreview">true</item>
         <item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
-        <item name="wallpaperTextColor">?android:attr/textColorPrimaryInverse</item>
-        <item name="wallpaperTextColorSecondary">?android:attr/textColorSecondaryInverse</item>
+        <item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
+        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_dark</item>
+    </style>
+
+    <style name="RecentsTheme.Wallpaper.Light">
+        <item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
+        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
     </style>
 
     <style name="ClearAllButtonDefaultMargins">
@@ -300,22 +298,27 @@
     <style name="Animation.StatusBar">
     </style>
 
-    <!-- Overlay manager may replace this theme -->
-    <style name="systemui_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
-
-    <style name="systemui_theme" parent="systemui_base">
+    <style name="Theme.SystemUI" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
         <item name="lightIconTheme">@style/DualToneLightTheme</item>
         <item name="darkIconTheme">@style/DualToneDarkTheme</item>
-        <item name="wallpaperTextColor">?android:attr/textColorPrimaryInverse</item>
-        <item name="wallpaperTextColorSecondary">?android:attr/textColorSecondaryInverse</item>
-        <item name="android:colorControlHighlight">?android:attr/textColorSecondaryInverse</item>
+        <item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
+        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_dark</item>
+        <item name="android:colorControlHighlight">@*android:color/primary_text_material_dark</item>
         <item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
+        <item name="passwordStyle">@style/PasswordTheme</item>
+    </style>
+
+    <style name="Theme.SystemUI.Light" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+        <item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
+        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
+        <item name="android:colorControlHighlight">@*android:color/primary_text_material_light</item>
+        <item name="passwordStyle">@style/PasswordTheme.Light</item>
     </style>
 
     <style name="LockPatternStyle">
-        <item name="*android:regularColor">?android:attr/textColorPrimaryInverse</item>
-        <item name="*android:successColor">?android:attr/textColorPrimaryInverse</item>
-        <item name="*android:errorColor">?android:attr/colorError</item>
+        <item name="*android:regularColor">?attr/wallpaperTextColor</item>
+        <item name="*android:successColor">?attr/wallpaperTextColor</item>
+        <item name="*android:errorColor">?attr/colorError</item>
     </style>
 
     <!-- Overlay manager may replace this theme -->
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index fe6eb4b..9f2dcd9 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -116,7 +116,7 @@
         // Set the application theme that is inherited by all services. Note that setting the
         // application theme in the manifest does only work for activities. Keep this in sync with
         // the theme set there.
-        setTheme(R.style.systemui_theme);
+        setTheme(R.style.Theme_SystemUI);
 
         SystemUIFactory.createFromConfig(this);
 
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 44cf003..fe8373f 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -98,7 +98,7 @@
      */
     @Override
     public GradientColors getColors(int which) {
-        return getColors(which, TYPE_NORMAL);
+        return getColors(which, TYPE_DARK);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 28a45aa..ed4b131 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -39,6 +39,7 @@
 
     private final int mHighBrightness;
     private final int mLowBrightness;
+    private final int mSunlightBrightness;
 
     public DozeScreenBrightness(Context context, DozeMachine.Service service,
             SensorManager sensorManager, Sensor lightSensor, Handler handler) {
@@ -52,6 +53,8 @@
                 R.integer.config_doze_aod_brightness_low);
         mHighBrightness = context.getResources().getInteger(
                 R.integer.config_doze_aod_brightness_high);
+        mSunlightBrightness = context.getResources().getInteger(
+                R.integer.config_doze_aod_brightness_sunlight);
     }
 
     @Override
@@ -83,9 +86,12 @@
     }
 
     private int computeBrightness(int sensorValue) {
-        // The sensor reports 0 for off, 1 for low brightness and 2 for high brightness.
-        // We currently use DozeScreenState for screen off, so we treat off as low brightness.
-        if (sensorValue >= 2) {
+        // The sensor reports 0 for off, 1 for low brightness, 2 for high brightness, and 3 for
+        // sunlight. We currently use DozeScreenState for screen off, so we treat off as low
+        // brightness.
+        if (sensorValue >= 3) {
+            return mSunlightBrightness;
+        } else if (sensorValue == 2) {
             return mHighBrightness;
         } else {
             return mLowBrightness;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 9b113d8..ad177a7 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -25,8 +25,10 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.HardwareUiLayout;
+import com.android.systemui.Interpolators;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.volume.VolumeDialogMotion.LogAccelerateInterpolator;
 import com.android.systemui.volume.VolumeDialogMotion.LogDecelerateInterpolator;
@@ -65,6 +67,7 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.MathUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -112,6 +115,8 @@
     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;
@@ -1291,7 +1296,7 @@
                     .alpha(1)
                     .translationX(0)
                     .setDuration(300)
-                    .setInterpolator(new LogDecelerateInterpolator())
+                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                     .setUpdateListener(animation -> {
                         int alpha = (int) ((Float) animation.getAnimatedValue()
                                 * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
@@ -1329,9 +1334,8 @@
                     .setInterpolator(new LogAccelerateInterpolator())
                     .setUpdateListener(animation -> {
                         float frac = animation.getAnimatedFraction();
-                        float alpha = frac *(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY
-                                        - ScrimController.GRADIENT_SCRIM_ALPHA)
-                                + ScrimController.GRADIENT_SCRIM_ALPHA;
+                        float alpha = NotificationUtils.interpolate(
+                                ScrimController.GRADIENT_SCRIM_ALPHA, SHUTDOWN_SCRIM_ALPHA, frac);
                         mGradientDrawable.setAlpha((int) (alpha * 255));
                     })
                     .start();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f2ea6a6..c0550b5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -20,11 +20,11 @@
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.TaskStackBuilder;
+import android.app.WallpaperManager;
 import android.content.BroadcastReceiver;
 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;
@@ -41,12 +41,15 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
+import com.android.internal.colorextraction.ColorExtractor;
 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.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
@@ -100,7 +103,8 @@
 /**
  * The main Recents activity that is started from RecentsComponent.
  */
-public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
+public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreDrawListener,
+        ColorExtractor.OnColorsChangedListener {
 
     private final static String TAG = "RecentsActivity";
     private final static boolean DEBUG = false;
@@ -129,6 +133,10 @@
     private DozeTrigger mIterateTrigger;
     private final UserInteractionEvent mUserInteractionEvent = new UserInteractionEvent();
 
+    // Theme and colors
+    private SysuiColorExtractor mColorExtractor;
+    private boolean mUsingDarkText;
+
     /**
      * A common Runnable to finish Recents by launching Home with an animation depending on the
      * last activity launch state. Generally we always launch home when we exit Recents rather than
@@ -329,6 +337,14 @@
         mPackageMonitor = new RecentsPackageMonitor();
         mPackageMonitor.register(this);
 
+        // Select theme based on wallpaper colors
+        mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+        mColorExtractor.addOnColorsChangedListener(this);
+        mUsingDarkText = mColorExtractor.getColors(ColorExtractor.TYPE_DARK,
+                WallpaperManager.FLAG_SYSTEM, true).supportsDarkText();
+        setTheme(mUsingDarkText ? R.style.RecentsTheme_Wallpaper_Light
+                : R.style.RecentsTheme_Wallpaper);
+
         // Set the Recents layout
         setContentView(R.layout.recents);
         takeKeyEvents(true);
@@ -375,13 +391,37 @@
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
         MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
 
-        // Make sure we have the right gradient and we're listening for update events
-        mRecentsView.onStart();
+        // Getting system scrim colors ignoring wallpaper visibility since it should never be grey.
+        ColorExtractor.GradientColors systemColors = mColorExtractor.getColors(
+                ColorExtractor.TYPE_DARK, WallpaperManager.FLAG_SYSTEM, true);
+        // We don't want to interpolate colors because we're defining the initial state.
+        // Gradient should be set/ready when you open "Recents".
+        mRecentsView.setScrimColors(systemColors, false);
+
         // Notify of the next draw
         mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);
     }
 
     @Override
+    public void onColorsChanged(ColorExtractor colorExtractor, int which) {
+        if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+            // Recents doesn't care about the wallpaper being visible or not, it always
+            // wants to scrim with wallpaper colors
+            ColorExtractor.GradientColors colors = mColorExtractor.getColors(
+                    WallpaperManager.FLAG_SYSTEM,
+                    ColorExtractor.TYPE_DARK, true /* ignoreVis */);
+            boolean darkText = colors.supportsDarkText();
+            if (darkText != mUsingDarkText) {
+                mUsingDarkText = darkText;
+                setTheme(mUsingDarkText ? R.style.RecentsTheme_Wallpaper_Light
+                        : R.style.RecentsTheme_Wallpaper);
+                mRecentsView.reevaluateStyles();
+            }
+            mRecentsView.setScrimColors(colors, true /* animated */);
+        }
+    }
+
+    @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
 
@@ -483,12 +523,7 @@
                 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();
-        }
+        mLastConfig.updateFrom(newDeviceConfiguration);
     }
 
     @Override
@@ -508,9 +543,6 @@
         MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
         Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
 
-        // We don't need to update the gradient when we're not visible
-        mRecentsView.onStop();
-
         if (!isChangingConfigurations()) {
             // Workaround for b/22542869, if the RecentsActivity is started again, but without going
             // through SystemUI, we need to reset the config launch flags to ensure that we do not
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 fd37b17..8e09481 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -21,13 +21,12 @@
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.app.ActivityOptions.OnAnimationStartedListener;
-import android.app.WallpaperColors;
-import android.app.WallpaperManager;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.PointF;
 import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.ArraySet;
 import android.util.AttributeSet;
@@ -43,12 +42,12 @@
 import android.widget.TextView;
 
 import com.android.internal.colorextraction.ColorExtractor;
+import com.android.internal.colorextraction.drawable.GradientDrawable;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
+import com.android.settingslib.Utils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
@@ -83,8 +82,6 @@
 import com.android.systemui.statusbar.FlingAnimationUtils;
 import com.android.systemui.statusbar.phone.ScrimController;
 
-import com.android.internal.colorextraction.drawable.GradientDrawable;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -93,7 +90,7 @@
  * This view is the the top level layout that contains TaskStacks (which are laid out according
  * to their SpaceNode bounds.
  */
-public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsChangedListener {
+public class RecentsView extends FrameLayout {
 
     private static final String TAG = "RecentsView";
 
@@ -107,6 +104,9 @@
     private TaskStackView mTaskStackView;
     private TextView mStackActionButton;
     private TextView mEmptyView;
+    private final float mStackButtonShadowRadius;
+    private final PointF mStackButtonShadowDistance;
+    private final int mStackButtonShadowColor;
 
     private boolean mAwaitingFirstLayout = true;
     private boolean mLastTaskLaunchedWasFreeform;
@@ -117,7 +117,6 @@
 
     private float mBusynessFactor;
     private GradientDrawable mBackgroundScrim;
-    private final SysuiColorExtractor mColorExtractor;
     private Animator mBackgroundScrimAnimator;
 
     private RecentsTransitionHelper mTransitionHelper;
@@ -148,29 +147,51 @@
         mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
         mBackgroundScrim = new GradientDrawable(context);
         mBackgroundScrim.setCallback(this);
-        mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+
+        boolean usingDarkText = Color.luminance(
+                Utils.getColorAttr(mContext, R.attr.wallpaperTextColor)) < 0.5f;
 
         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) {
+            if (mStackActionButton != null) {
+                removeView(mStackActionButton);
+            }
             mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button,
                     this, false);
-            mStackActionButton.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    EventBus.getDefault().send(new DismissAllTaskViewsEvent());
-                }
-            });
-            // Disable black shadow if text color is already dark.
+            mStackActionButton.setOnClickListener(
+                    v -> EventBus.getDefault().send(new DismissAllTaskViewsEvent()));
+
+            mStackButtonShadowRadius = mStackActionButton.getShadowRadius();
+            mStackButtonShadowDistance = new PointF(mStackActionButton.getShadowDx(),
+                    mStackActionButton.getShadowDy());
+            mStackButtonShadowColor = mStackActionButton.getShadowColor();
+            addView(mStackActionButton);
+        }
+
+        reevaluateStyles();
+    }
+
+    public void reevaluateStyles() {
+        int textColor = Utils.getColorAttr(mContext, R.attr.wallpaperTextColor);
+        boolean usingDarkText = Color.luminance(textColor) < 0.5f;
+
+        mEmptyView.setTextColor(textColor);
+        mEmptyView.setCompoundDrawableTintList(new ColorStateList(new int[][]{
+                {android.R.attr.state_enabled}}, new int[]{textColor}));
+
+        if (mStackActionButton != null) {
+            mStackActionButton.setTextColor(textColor);
+            // Enable/disable shadow if text color is already dark.
             if (usingDarkText) {
                 mStackActionButton.setShadowLayer(0, 0, 0, 0);
+            } else {
+                mStackActionButton.setShadowLayer(mStackButtonShadowRadius,
+                        mStackButtonShadowDistance.x, mStackButtonShadowDistance.y,
+                        mStackButtonShadowColor);
             }
-            addView(mStackActionButton);
         }
 
         // Let's also require dark status and nav bars if the text is dark
@@ -369,6 +390,16 @@
         }
     }
 
+    /**
+     * Set the color of the scrim.
+     *
+     * @param scrimColors Colors to use.
+     * @param animated Interpolate colors if true.
+     */
+    public void setScrimColors(ColorExtractor.GradientColors scrimColors, boolean animated) {
+        mBackgroundScrim.setColors(scrimColors, animated);
+    }
+
     @Override
     protected void onAttachedToWindow() {
         EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
@@ -888,29 +919,4 @@
             mTaskStackView.dump(innerPrefix, writer);
         }
     }
-
-    @Override
-    public void onColorsChanged(ColorExtractor colorExtractor, int which) {
-        if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
-            // Recents doesn't care about the wallpaper being visible or not, it always
-            // wants to scrim with wallpaper colors
-            mBackgroundScrim.setColors(
-                    mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM,
-                            ColorExtractor.TYPE_DARK, true));
-        }
-    }
-
-    public void onStart() {
-        mColorExtractor.addOnColorsChangedListener(this);
-        // Getting system scrim colors ignoring wallpaper visibility since it should never be grey.
-        ColorExtractor.GradientColors systemColors = mColorExtractor.getColors(
-                ColorExtractor.TYPE_DARK, WallpaperManager.FLAG_SYSTEM, true);
-        // We don't want to interpolate colors because we're defining the initial state.
-        // Gradient should be set/ready when you open "Recents".
-        mBackgroundScrim.setColors(systemColors, false);
-    }
-
-    public void onStop() {
-        mColorExtractor.removeOnColorsChangedListener(this);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
index 5436664..d7c6443 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.util.AttributeSet;
@@ -46,6 +47,10 @@
         mDismissButton = (DismissViewButton) findContentView();
     }
 
+    public void setTextColor(@ColorInt int color) {
+        mDismissButton.setTextColor(color);
+    }
+
     public void setOnButtonClickListener(OnClickListener listener) {
         mContent.setOnClickListener(listener);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
index 92b0890..58adde2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.util.AttributeSet;
@@ -45,6 +46,10 @@
         return findViewById(R.id.no_notifications);
     }
 
+    public void setTextColor(@ColorInt int color) {
+        mEmptyText.setTextColor(color);
+    }
+
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
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 9e1a2a2..bc37d83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -978,9 +978,6 @@
         Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
 
         Dependency.get(ConfigurationController.class).addCallback(this);
-
-        // Make sure that we're using the correct theme
-        onOverlayChanged();
     }
 
     protected void createIconController() {
@@ -993,6 +990,7 @@
         final Context context = mContext;
         updateDisplaySize(); // populates mDisplayMetrics
         updateResources();
+        updateTheme();
 
         inflateStatusBarWindow(context);
         mStatusBarWindow.setService(this);
@@ -1200,7 +1198,6 @@
             });
         }
 
-
         PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         if (!pm.isScreenOn()) {
             mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
@@ -1305,14 +1302,14 @@
         reevaluateStyles();
     }
 
-    public void onOverlayChanged() {
+    private void reinflateViews() {
         reevaluateStyles();
 
         // Clock and bottom icons
         mNotificationPanel.onOverlayChanged();
-
+        // The status bar on the keyguard is a special layout.
+        mKeyguardStatusBar.onOverlayChanged();
         // Recreate Indication controller because internal references changed
-        // TODO: unregister callbacks before recreating
         mKeyguardIndicationController =
                 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
                         mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
@@ -1930,9 +1927,6 @@
             boolean sensitive = userPublic && needsRedaction;
             boolean deviceSensitive = devicePublic
                     && !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
-            if (sensitive) {
-                updatePublicContentView(ent, ent.notification);
-            }
             ent.row.setSensitive(sensitive, deviceSensitive);
             ent.row.setNeedsRedaction(needsRedaction);
             if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) {
@@ -2860,17 +2854,6 @@
         updateTheme();
     }
 
-    public boolean isUsingDarkText() {
-        OverlayInfo themeInfo = null;
-        try {
-            themeInfo = mOverlayManager.getOverlayInfo("com.android.systemui.theme.lightwallpaper",
-                    mCurrentUserId);
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
-        return themeInfo != null && themeInfo.isEnabled();
-    }
-
     public boolean isUsingDarkTheme() {
         OverlayInfo themeInfo = null;
         try {
@@ -4569,24 +4552,13 @@
      * Switches theme from light to dark and vice-versa.
      */
     private void updateTheme() {
+        final boolean inflated = mStackScroller != null;
 
-        int which;
-        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
-            which = WallpaperManager.FLAG_LOCK;
-        } else {
-            which = WallpaperManager.FLAG_SYSTEM;
-        }
-
-        // Gradient defines if text color should be light or dark.
-        final boolean useDarkText = mColorExtractor.getColors(which, true /* ignoreVisibility */)
-                .supportsDarkText();
-        // And wallpaper defines if QS should be light or dark.
+        // The system wallpaper defines if QS should be light or dark.
         WallpaperColors systemColors = mColorExtractor
                 .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
         final boolean useDarkTheme = systemColors != null
                 && (systemColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_THEME) != 0;
-
-        // Enable/disable dark UI.
         if (isUsingDarkTheme() != useDarkTheme) {
             try {
                 mOverlayManager.setEnabled("com.android.systemui.theme.dark",
@@ -4595,18 +4567,33 @@
                 Log.w(TAG, "Can't change theme", e);
             }
         }
-        // Enable/disable dark text overlay.
-        if (isUsingDarkText() != useDarkText) {
-            try {
-                mOverlayManager.setEnabled("com.android.systemui.theme.lightwallpaper",
-                        useDarkText, mCurrentUserId);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Can't change theme", e);
+
+        // Lock wallpaper defines the color of the majority of the views, hence we'll use it
+        // to set our default theme.
+        final boolean lockDarkText = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, true
+                /* ignoreVisibility */).supportsDarkText();
+        final int themeResId = lockDarkText ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI;
+        if (mContext.getThemeResId() != themeResId) {
+            mContext.setTheme(themeResId);
+            if (inflated) {
+                reinflateViews();
             }
         }
 
-        // Make sure we have the correct navbar/statusbar colors.
-        mStatusBarWindowManager.setKeyguardDark(useDarkText);
+        if (inflated) {
+            int which;
+            if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+                which = WallpaperManager.FLAG_LOCK;
+            } else {
+                which = WallpaperManager.FLAG_SYSTEM;
+            }
+            final boolean useDarkText = mColorExtractor.getColors(which,
+                    true /* ignoreVisibility */).supportsDarkText();
+            mStackScroller.updateDecorViews(useDarkText);
+
+            // Make sure we have the correct navbar/statusbar colors.
+            mStatusBarWindowManager.setKeyguardDark(useDarkText);
+        }
     }
 
     private void updateDozingState() {
@@ -7216,24 +7203,6 @@
         setAreThereNotifications();
     }
 
-    protected void updatePublicContentView(Entry entry,
-            StatusBarNotification sbn) {
-        final RemoteViews publicContentView = entry.cachedPublicContentView;
-        View inflatedView = entry.getPublicContentView();
-        if (entry.autoRedacted && publicContentView != null && inflatedView != null) {
-            final boolean disabledByPolicy =
-                    !adminAllowsUnredactedNotifications(entry.notification.getUserId());
-            String notificationHiddenText = mContext.getString(disabledByPolicy
-                    ? com.android.internal.R.string.notification_hidden_by_policy_text
-                    : com.android.internal.R.string.notification_hidden_text);
-            TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
-            if (titleView != null
-                    && !titleView.getText().toString().equals(notificationHiddenText)) {
-                titleView.setText(notificationHiddenText);
-            }
-        }
-    }
-
     protected void notifyHeadsUpScreenOff() {
         maybeEscalateHeadsUp();
     }
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 42cebe2..4bbe895 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -23,6 +23,7 @@
 import android.animation.TimeAnimator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.ColorInt;
 import android.annotation.FloatRange;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -44,6 +45,7 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Property;
+import android.view.ContextThemeWrapper;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
@@ -61,6 +63,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.Utils;
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -363,6 +366,7 @@
                     return object.getBackgroundFadeAmount();
                 }
             };
+    private boolean mUsingLightTheme;
     private boolean mQsExpanded;
     private boolean mForwardScrollable;
     private boolean mBackwardScrollable;
@@ -3653,6 +3657,23 @@
         mTmpSortedChildren.clear();
     }
 
+    /**
+     * Update colors of "dismiss" and "empty shade" views.
+     *
+     * @param lightTheme True if light theme should be used.
+     */
+    public void updateDecorViews(boolean lightTheme) {
+        if (lightTheme == mUsingLightTheme) {
+            return;
+        }
+        mUsingLightTheme = lightTheme;
+        Context context = new ContextThemeWrapper(mContext,
+                lightTheme ? R.style.Theme_SystemUI_Light : R.style.Theme_SystemUI);
+        final int textColor = Utils.getColorAttr(context, R.attr.wallpaperTextColor);
+        mDismissView.setTextColor(textColor);
+        mEmptyShadeView.setTextColor(textColor);
+    }
+
     public void goToFullShade(long delay) {
         if (mDismissView != null) {
             mDismissView.setInvisible();
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/Android.mk b/packages/overlays/SysuiLightWallpaperThemeOverlay/Android.mk
deleted file mode 100644
index 4782a16..0000000
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_RRO_THEME := SysuiLightWallpaperTheme
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := SysuiLightWallpaperThemeOverlay
-
-include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
deleted file mode 100644
index 0a8749c..0000000
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.systemui.theme.lightwallpaper"
-    android:versionCode="1"
-    android:versionName="1.0">
-    <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/strings.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/strings.xml
deleted file mode 100644
index acc3d16..0000000
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <string name="sysui_overlay_light">Light</string>
-
-</resources>
-
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
deleted file mode 100644
index 53912b5..0000000
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?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/services/Android.mk b/services/Android.mk
index 5c863b0..c376470 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -34,7 +34,6 @@
     net \
     print \
     restrictions \
-    retaildemo \
     usage \
     usb \
     voiceinteraction
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index abfc31e..a27a77e 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -123,8 +123,8 @@
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.backup.PackageManagerBackupAgent.Metadata;
-
 import com.android.server.power.BatterySaverPolicy.ServiceType;
+
 import libcore.io.IoUtils;
 
 import java.io.BufferedInputStream;
@@ -691,6 +691,7 @@
     final SparseArray<Operation> mCurrentOperations = new SparseArray<Operation>();
     final Object mCurrentOpLock = new Object();
     final Random mTokenGenerator = new Random();
+    final AtomicInteger mNextToken = new AtomicInteger();
 
     final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<AdbParams>();
 
@@ -763,15 +764,13 @@
     @GuardedBy("mQueueLock")
     ArrayList<FullBackupEntry> mFullBackupQueue;
 
-    // Utility: build a new random integer token
+    // Utility: build a new random integer token.  The low bits are the ordinal of the
+    // operation for near-time uniqueness, and the upper bits are random for app-
+    // side unpredictability.
     @Override
     public int generateRandomIntegerToken() {
-        int token;
-        do {
-            synchronized (mTokenGenerator) {
-                token = mTokenGenerator.nextInt();
-            }
-        } while (token < 0);
+        int token = mTokenGenerator.nextInt() & ~0xFF;
+        token |= (mNextToken.incrementAndGet() & 0xFF);
         return token;
     }
 
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 7275461..a4e673d 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -243,8 +243,9 @@
 
     private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
 
-    private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
     private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
+
+    private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
     private IBatchedLocationCallback mGnssBatchingCallback;
     private LinkedCallback mGnssBatchingDeathCallback;
     private boolean mGnssBatchingInProgress = false;
diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java
index 048bef7..feddfe3 100644
--- a/services/core/java/com/android/server/am/VrController.java
+++ b/services/core/java/com/android/server/am/VrController.java
@@ -163,6 +163,7 @@
         ComponentName requestedPackage;
         ComponentName callingPackage;
         int userId;
+        int processId = -1;
         boolean changed = false;
         synchronized (mGlobalAmLock) {
             vrMode = record.requestedVrComponent != null;
@@ -172,11 +173,15 @@
 
             // Tell the VrController that a VR mode change is requested.
             changed = changeVrModeLocked(vrMode, record.app);
+
+            if (record.app != null) {
+                processId = record.app.pid;
+            }
         }
 
         // Tell VrManager that a VR mode changed is requested, VrManager will handle
         // notifying all non-AM dependencies if needed.
-        vrService.setVrMode(vrMode, requestedPackage, userId, callingPackage);
+        vrService.setVrMode(vrMode, requestedPackage, userId, processId, callingPackage);
         return changed;
     }
 
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 83bb17e..cdf25cf 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1754,20 +1754,32 @@
     }
 
     /**
-     * called from native code - Gps measurements callback
+     * called from native code - GNSS measurements callback
      */
     private void reportMeasurementData(GnssMeasurementsEvent event) {
         if (!mItarSpeedLimitExceeded) {
-            mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+            // send to handler to allow native to return quickly
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+                }
+            });
         }
     }
 
     /**
-     * called from native code - GPS navigation message callback
+     * called from native code - GNSS navigation message callback
      */
     private void reportNavigationMessage(GnssNavigationMessage event) {
         if (!mItarSpeedLimitExceeded) {
-            mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+            // send to handler to allow native to return quickly
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+                }
+            });
         }
     }
 
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index caf1d6c..924520b 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -54,9 +54,8 @@
     }
 
     public void onGpsEnabledChanged() {
-        if (tryUpdateRegistrationWithService()) {
-            updateResult();
-        }
+        tryUpdateRegistrationWithService();
+        updateResult();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 8d21928..df3c49b 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -55,9 +55,8 @@
     }
 
     public void onGpsEnabledChanged() {
-        if (tryUpdateRegistrationWithService()) {
-            updateResult();
-        }
+        tryUpdateRegistrationWithService();
+        updateResult();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index ec2828b..f51bc87 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -25,6 +25,7 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.lang.Runnable;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -45,7 +46,7 @@
 
     private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
 
-    private boolean mIsRegistered;
+    private boolean mIsRegistered;  // must access only on handler thread
     private boolean mHasIsSupported;
     private boolean mIsSupported;
 
@@ -83,12 +84,12 @@
             } else if (mHasIsSupported && !mIsSupported) {
                 result = RESULT_NOT_SUPPORTED;
             } else if (!isGpsEnabled()) {
-                result = RESULT_GPS_LOCATION_DISABLED;
-            } else if (!tryRegister()) {
                 // only attempt to register if GPS is enabled, otherwise we will register once GPS
                 // becomes available
-                result = RESULT_INTERNAL_ERROR;
+                result = RESULT_GPS_LOCATION_DISABLED;
             } else if (mHasIsSupported && mIsSupported) {
+                tryRegister();
+                // initially presume success, possible internal error could follow asynchornously
                 result = RESULT_SUCCESS;
             } else {
                 // at this point if the supported flag is not set, the notification will be sent
@@ -117,8 +118,8 @@
 
     protected abstract boolean isAvailableInPlatform();
     protected abstract boolean isGpsEnabled();
-    protected abstract boolean registerWithService();
-    protected abstract void unregisterFromService();
+    protected abstract boolean registerWithService(); // must access only on handler thread
+    protected abstract void unregisterFromService(); // must access only on handler thread
     protected abstract ListenerOperation<TListener> getHandlerOperation(int result);
 
     protected interface ListenerOperation<TListener extends IInterface> {
@@ -138,22 +139,16 @@
         }
     }
 
-    protected boolean tryUpdateRegistrationWithService() {
+    protected void tryUpdateRegistrationWithService() {
         synchronized (mListenerMap) {
             if (!isGpsEnabled()) {
                 tryUnregister();
-                return true;
+                return;
             }
             if (mListenerMap.isEmpty()) {
-                return true;
+                return;
             }
-            if (tryRegister()) {
-                // registration was successful, there is no need to update the state
-                return true;
-            }
-            ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR);
-            foreachUnsafe(operation);
-            return false;
+            tryRegister();
         }
     }
 
@@ -180,19 +175,40 @@
         }
     }
 
-    private boolean tryRegister() {
-        if (!mIsRegistered) {
-            mIsRegistered = registerWithService();
-        }
-        return mIsRegistered;
+    private void tryRegister() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (!mIsRegistered) {
+                    mIsRegistered = registerWithService();
+                }
+                if (!mIsRegistered) {
+                    // post back a failure
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            synchronized (mListenerMap) {
+                                ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR);
+                                foreachUnsafe(operation);
+                            }
+                        }
+                    });
+                }
+            }
+        });
     }
 
     private void tryUnregister() {
-        if (!mIsRegistered) {
-            return;
-        }
-        unregisterFromService();
-        mIsRegistered = false;
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (!mIsRegistered) {
+                    return;
+                }
+                unregisterFromService();
+                mIsRegistered = false;
+            }
+        });
     }
 
     private int calculateCurrentResultUnsafe() {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8a39df2..66f9c57 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5412,7 +5412,7 @@
             // represent should be hidden or if we should hide the lockscreen. For attached app
             // windows we defer the decision to the window it is attached to.
             if (appWindow && attached == null) {
-                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
+                if (attrs.isFullscreen() && StackId.normallyFullscreenWindows(stackId)) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
                     mTopFullscreenOpaqueWindowState = win;
                     if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5451,7 +5451,7 @@
         // separately, because both the "real fullscreen" opaque window and the one for the docked
         // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
         if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
-                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
+                && attrs.isFullscreen() && stackId == DOCKED_STACK_ID) {
             mTopDockedOpaqueWindowState = win;
             if (mTopDockedOpaqueOrDimmingWindowState == null) {
                 mTopDockedOpaqueOrDimmingWindowState = win;
@@ -5476,12 +5476,6 @@
         }
     }
 
-    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
-        return attrs.x == 0 && attrs.y == 0
-                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
-                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
-    }
-
     /** {@inheritDoc} */
     @Override
     public int finishPostLayoutPolicyLw() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a94484a..50f4f24 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -53,6 +53,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
@@ -197,6 +198,9 @@
     // System property indicating that the screen should remain off until an explicit user action
     private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
 
+    // System Property indicating that retail demo mode is currently enabled.
+    private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
+
     // Possible reasons for shutting down for use in data/misc/reboot/last_shutdown_reason
     private static final String REASON_SHUTDOWN = "shutdown";
     private static final String REASON_REBOOT = "reboot";
@@ -805,6 +809,9 @@
         resolver.registerContentObserver(Settings.Secure.getUriFor(
                 Settings.Secure.DOUBLE_TAP_TO_WAKE),
                 false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.DEVICE_DEMO_MODE),
+                false, mSettingsObserver, UserHandle.USER_SYSTEM);
         IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
         if (vrManager != null) {
             try {
@@ -912,6 +919,11 @@
             }
         }
 
+        final String retailDemoValue = UserManager.isDeviceInDemoMode(mContext) ? "1" : "0";
+        if (!retailDemoValue.equals(SystemProperties.get(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED))) {
+            SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, retailDemoValue);
+        }
+
         final int oldScreenBrightnessSetting = getCurrentBrightnessSettingLocked();
 
         mScreenBrightnessForVrSetting = Settings.System.getIntForUser(resolver,
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 1f75640..bdd9de0 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -52,10 +52,11 @@
      * @param enabled {@code true} to enable VR mode.
      * @param packageName The package name of the requested VrListenerService to bind.
      * @param userId the user requesting the VrListenerService component.
+     * @param processId the process the component is running in.
      * @param calling the component currently using VR mode, or null to leave unchanged.
      */
     public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
-            int userId, @NonNull ComponentName calling);
+            int userId, int processId, @NonNull ComponentName calling);
 
     /**
      * Set whether the system has acquired a sleep token.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index f13cc76..e737328 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -125,6 +125,8 @@
     private boolean mVrModeAllowed;
     private boolean mVrModeEnabled;
     private boolean mPersistentVrModeEnabled;
+    private boolean mRunning2dInVr;
+    private int mVrAppProcessId;
     private EnabledComponentsObserver mComponentObserver;
     private ManagedApplicationService mCurrentVrService;
     private ComponentName mDefaultVrService;
@@ -174,7 +176,7 @@
                 }
                 consumeAndApplyPendingStateLocked();
                 if (mBootsToVr && !mVrModeEnabled) {
-                  setVrMode(true, mDefaultVrService, 0, null);
+                  setVrMode(true, mDefaultVrService, 0, -1, null);
                 }
             } else {
                 // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
@@ -183,12 +185,12 @@
 
                 // Set pending state to current state.
                 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
-                    ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
-                        mCurrentVrService.getUserId(), mCurrentVrModeComponent)
+                    ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(),
+                        mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent)
                     : null;
 
                 // Unbind current VR service and do necessary callbacks.
-                updateCurrentVrServiceLocked(false, null, 0, null);
+                updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
             }
         }
     }
@@ -270,26 +272,33 @@
 
     private static class VrState {
         final boolean enabled;
+        final boolean running2dInVr;
         final int userId;
+        final int processId;
         final ComponentName targetPackageName;
         final ComponentName callingPackage;
         final long timestamp;
         final boolean defaultPermissionsGranted;
 
-        VrState(boolean enabled, ComponentName targetPackageName, int userId,
-                ComponentName callingPackage) {
+
+        VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+                int processId, ComponentName callingPackage) {
             this.enabled = enabled;
+            this.running2dInVr = running2dInVr;
             this.userId = userId;
+            this.processId = processId;
             this.targetPackageName = targetPackageName;
             this.callingPackage = callingPackage;
             this.defaultPermissionsGranted = false;
             this.timestamp = System.currentTimeMillis();
         }
 
-        VrState(boolean enabled, ComponentName targetPackageName, int userId,
-            ComponentName callingPackage, boolean defaultPermissionsGranted) {
+        VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+            int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) {
             this.enabled = enabled;
+            this.running2dInVr = running2dInVr;
             this.userId = userId;
+            this.processId = processId;
             this.targetPackageName = targetPackageName;
             this.callingPackage = callingPackage;
             this.defaultPermissionsGranted = defaultPermissionsGranted;
@@ -390,8 +399,9 @@
             }
 
             // There is an active service, update it if needed
-            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
-                    mCurrentVrService.getUserId(), mCurrentVrModeComponent);
+            updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr,
+                    mCurrentVrService.getComponent(), mCurrentVrService.getUserId(),
+                    mVrAppProcessId, mCurrentVrModeComponent);
         }
     }
 
@@ -527,9 +537,9 @@
      */
     private final class LocalService extends VrManagerInternal {
         @Override
-        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
+        public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId,
                 ComponentName callingPackage) {
-            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
+            VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage);
         }
 
         @Override
@@ -704,14 +714,16 @@
      * Note: Must be called while holding {@code mLock}.
      *
      * @param enabled new state for VR mode.
+     * @param running2dInVr true if we have a top-level 2D intent.
      * @param component new component to be bound as a VR listener.
      * @param userId user owning the component to be bound.
-     * @param calling the component currently using VR mode.
+     * @param processId the process hosting the activity specified by calling.
+     * @param calling the component currently using VR mode or a 2D intent.
      *
      * @return {@code true} if the component/user combination specified is valid.
      */
-    private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
-            int userId, ComponentName calling) {
+    private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr,
+            @NonNull ComponentName component, int userId, int processId, ComponentName calling) {
 
         boolean sendUpdatedCaller = false;
         final long identity = Binder.clearCallingIdentity();
@@ -771,6 +783,8 @@
                 sendUpdatedCaller = true;
             }
             mCurrentVrModeComponent = calling;
+            mRunning2dInVr = running2dInVr;
+            mVrAppProcessId = processId;
 
             if (mCurrentVrModeUser != userId) {
                 mCurrentVrModeUser = userId;
@@ -788,11 +802,13 @@
 
             if (mCurrentVrService != null && sendUpdatedCaller) {
                 final ComponentName c = mCurrentVrModeComponent;
+                final boolean b = running2dInVr;
+                final int pid = processId;
                 mCurrentVrService.sendEvent(new PendingEvent() {
                     @Override
                     public void runEvent(IInterface service) throws RemoteException {
                         IVrListener l = (IVrListener) service;
-                        l.focusedActivityChanged(c);
+                        l.focusedActivityChanged(c, b, pid);
                     }
                 });
             }
@@ -1017,20 +1033,20 @@
      */
     private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
         if (mPendingState != null) {
-            updateCurrentVrServiceLocked(mPendingState.enabled,
-                    mPendingState.targetPackageName, mPendingState.userId,
+            updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr,
+                    mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId,
                     mPendingState.callingPackage);
             mPendingState = null;
         } else if (disconnectIfNoPendingState) {
-            updateCurrentVrServiceLocked(false, null, 0, null);
+            updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
         }
     }
 
     private void logStateLocked() {
         ComponentName currentBoundService = (mCurrentVrService == null) ? null :
             mCurrentVrService.getComponent();
-        VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
-            mCurrentVrModeComponent, mWasDefaultGranted);
+        VrState current = new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService,
+            mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted);
         if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
             mLoggingDeque.removeFirst();
         }
@@ -1074,27 +1090,24 @@
      * Implementation of VrManagerInternal calls.  These are callable from system services.
      */
     private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
-            int userId, @NonNull ComponentName callingPackage) {
+            int userId, int processId, @NonNull ComponentName callingPackage) {
 
         synchronized (mLock) {
             VrState pending;
             ComponentName targetListener;
-            ComponentName foregroundVrComponent;
 
             // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
             // and the system default VR listener is used.
             boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
-            if (!enabled && mPersistentVrModeEnabled) {
+            boolean running2dInVr = !enabled && mPersistentVrModeEnabled;
+            if (running2dInVr) {
                 targetListener = mDefaultVrService;
-
-                // Current foreground component isn't a VR one (in 2D app case)
-                foregroundVrComponent = null;
             } else {
                 targetListener = targetPackageName;
-                foregroundVrComponent = callingPackage;
             }
-            pending = new VrState(
-                    targetEnabledState, targetListener, userId, foregroundVrComponent);
+
+            pending = new VrState(targetEnabledState, running2dInVr, targetListener,
+                    userId, processId, callingPackage);
 
             if (!mVrModeAllowed) {
                 // We're not allowed to be in VR mode.  Make this state pending.  This will be
@@ -1119,8 +1132,8 @@
                 mPendingState = null;
             }
 
-            updateCurrentVrServiceLocked(
-                    targetEnabledState, targetListener, userId, foregroundVrComponent);
+            updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener,
+                    userId, processId, callingPackage);
         }
     }
 
@@ -1129,7 +1142,7 @@
             setPersistentModeAndNotifyListenersLocked(enabled);
             // Disabling persistent mode when not showing a VR should disable the overall vr mode.
             if (!enabled && mCurrentVrModeComponent == null) {
-                setVrMode(false, null, 0, null);
+                setVrMode(false, null, 0, -1, null);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 05f4626..a37b2e5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2992,14 +2992,14 @@
                 // Don't include wallpaper in bounds calculation
                 if (!w.mIsWallpaper && !mutableIncludeFullDisplay.value) {
                     if (includeDecor) {
-                        final TaskStack stack = w.getStack();
-                        if (stack != null) {
-                            stack.getBounds(frame);
-                        }
+                        final Task task = w.getTask();
+                        if (task != null) {
+                            task.getBounds(frame);
+                        } else {
 
-                        // We want to screenshot with the exact bounds of the surface of the app. Thus,
-                        // intersect it with the frame.
-                        frame.intersect(w.mFrame);
+                            // No task bounds? Too bad! Ain't no screenshot then.
+                            return true;
+                        }
                     } else {
                         final Rect wf = w.mFrame;
                         final Rect cr = w.mContentInsets;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc3b146..e5055e9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -624,6 +624,17 @@
         return token != null ? token.findMainWindow() : null;
     }
 
+    AppWindowToken getTopFullscreenAppToken() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final AppWindowToken token = mChildren.get(i);
+            final WindowState win = token.findMainWindow();
+            if (win != null && win.mAttrs.isFullscreen()) {
+                return token;
+            }
+        }
+        return null;
+    }
+
     AppWindowToken getTopVisibleAppToken() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final AppWindowToken token = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 469dab4..d7f0496 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -151,14 +151,27 @@
         final int currentOrientation;
         synchronized (service.mWindowMap) {
             final WindowState mainWindow = token.findMainWindow();
-            if (mainWindow == null) {
+            final Task task = token.getTask();
+            if (task == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for token="
+                        + token);
+                return null;
+            }
+            final AppWindowToken topFullscreenToken = token.getTask().getTopFullscreenAppToken();
+            if (topFullscreenToken == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
+                        + task);
+                return null;
+            }
+            final WindowState topFullscreenWindow = topFullscreenToken.findMainWindow();
+            if (mainWindow == null || topFullscreenWindow == null) {
                 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
                         + token);
                 return null;
             }
-            sysUiVis = mainWindow.getSystemUiVisibility();
-            windowFlags = mainWindow.getAttrs().flags;
-            windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+            sysUiVis = topFullscreenWindow.getSystemUiVisibility();
+            windowFlags = topFullscreenWindow.getAttrs().flags;
+            windowPrivateFlags = topFullscreenWindow.getAttrs().privateFlags;
 
             layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
             layoutParams.type = TYPE_APPLICATION_STARTING;
@@ -172,22 +185,17 @@
             layoutParams.width = LayoutParams.MATCH_PARENT;
             layoutParams.height = LayoutParams.MATCH_PARENT;
             layoutParams.systemUiVisibility = sysUiVis;
-            final Task task = token.getTask();
-            if (task != null) {
-                layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
+            layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
 
-                final TaskDescription taskDescription = task.getTaskDescription();
-                if (taskDescription != null) {
-                    backgroundColor = taskDescription.getBackgroundColor();
-                    statusBarColor = taskDescription.getStatusBarColor();
-                    navigationBarColor = taskDescription.getNavigationBarColor();
-                }
-                taskBounds = new Rect();
-                task.getBounds(taskBounds);
-            } else {
-                taskBounds = null;
+            final TaskDescription taskDescription = task.getTaskDescription();
+            if (taskDescription != null) {
+                backgroundColor = taskDescription.getBackgroundColor();
+                statusBarColor = taskDescription.getStatusBarColor();
+                navigationBarColor = taskDescription.getNavigationBarColor();
             }
-            currentOrientation = mainWindow.getConfiguration().orientation;
+            taskBounds = new Rect();
+            task.getBounds(taskBounds);
+            currentOrientation = topFullscreenWindow.getConfiguration().orientation;
         }
         try {
             final int res = session.addToDisplay(window, window.mSeq, layoutParams,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c9be3a2..a902a19 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -100,7 +100,6 @@
 import com.android.server.power.ShutdownThread;
 import com.android.server.radio.RadioService;
 import com.android.server.restrictions.RestrictionsManagerService;
-import com.android.server.retaildemo.RetailDemoModeService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
 import com.android.server.security.KeyChainSystemService;
 import com.android.server.soundtrigger.SoundTriggerService;
@@ -1551,10 +1550,6 @@
         mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
         traceEnd();
 
-        traceBeginAndSlog("StartRetailDemoModeService");
-        mSystemServiceManager.startService(RetailDemoModeService.class);
-        traceEnd();
-
         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOFILL)) {
             traceBeginAndSlog("StartAutoFillService");
             mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
diff --git a/services/profile-classes b/services/profile-classes
index b0d2da7..289b113 100644
--- a/services/profile-classes
+++ b/services/profile-classes
@@ -5085,11 +5085,6 @@
 Lcom/android/server/RescueParty$Threshold;
 Lcom/android/server/restrictions/RestrictionsManagerService;
 Lcom/android/server/restrictions/RestrictionsManagerService$RestrictionsManagerImpl;
-Lcom/android/server/retaildemo/RetailDemoModeService;
-Lcom/android/server/retaildemo/RetailDemoModeService$1;
-Lcom/android/server/retaildemo/RetailDemoModeService$Injector;
-Lcom/android/server/retaildemo/RetailDemoModeService$MainHandler;
-Lcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;
 Lcom/android/server/SamplingProfilerService;
 Lcom/android/server/SamplingProfilerService$1;
 Lcom/android/server/SamplingProfilerService$SamplingProfilerSettingsObserver;
diff --git a/services/retaildemo/Android.mk b/services/retaildemo/Android.mk
deleted file mode 100644
index 670c6bf..0000000
--- a/services/retaildemo/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.retaildemo
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
deleted file mode 100644
index 90c58d0..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.retaildemo;
-
-import android.app.AppGlobals;
-import android.app.PackageInstallObserver;
-import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * Helper class for installing preloaded APKs
- */
-class PreloadAppsInstaller {
-    private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
-    private static String TAG = PreloadAppsInstaller.class.getSimpleName();
-    private static final String PRELOAD_APK_EXT = ".apk.preload";
-    private static boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private final IPackageManager mPackageManager;
-    private final File preloadsAppsDirectory;
-    private final Context mContext;
-
-    private final Map<String, String> mApkToPackageMap;
-
-    PreloadAppsInstaller(Context context) {
-        this(context, AppGlobals.getPackageManager(), Environment.getDataPreloadsAppsDirectory());
-    }
-
-    @VisibleForTesting
-    PreloadAppsInstaller(Context context, IPackageManager packageManager, File preloadsAppsDirectory) {
-        mContext = context;
-        mPackageManager = packageManager;
-        mApkToPackageMap = Collections.synchronizedMap(new ArrayMap<>());
-        this.preloadsAppsDirectory = preloadsAppsDirectory;
-    }
-
-    void installApps(int userId) {
-        File[] files = preloadsAppsDirectory.listFiles();
-        AppInstallCounter counter = new AppInstallCounter(mContext, userId);
-        if (ArrayUtils.isEmpty(files)) {
-            counter.setExpectedAppsCount(0);
-            return;
-        }
-        int expectedCount = 0;
-        for (File file : files) {
-            String apkName = file.getName();
-            if (apkName.endsWith(PRELOAD_APK_EXT) && file.isFile()) {
-                String packageName = mApkToPackageMap.get(apkName);
-                if (packageName != null) {
-                    try {
-                        expectedCount++;
-                        installExistingPackage(packageName, userId, counter);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "Failed to install existing package " + packageName, e);
-                    }
-                } else {
-                    try {
-                        installPackage(file, userId, counter);
-                        expectedCount++;
-                    } catch (Exception e) {
-                        Slog.e(TAG, "Failed to install package from " + file, e);
-                    }
-                }
-            }
-        }
-        counter.setExpectedAppsCount(expectedCount);
-    }
-
-    private void installExistingPackage(String packageName, int userId,
-            AppInstallCounter counter) {
-        if (DEBUG) {
-            Log.d(TAG, "installExistingPackage " + packageName + " u" + userId);
-        }
-        try {
-            mPackageManager.installExistingPackageAsUser(packageName, userId,
-                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } finally {
-            counter.appInstallFinished();
-        }
-    }
-
-    private void installPackage(File file, final int userId, AppInstallCounter counter)
-            throws IOException, RemoteException {
-        final String apkName = file.getName();
-        if (DEBUG) {
-            Log.d(TAG, "installPackage " + apkName + " u" + userId);
-        }
-        mPackageManager.installPackageAsUser(file.getPath(), new PackageInstallObserver() {
-            @Override
-            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
-                    Bundle extras) {
-                if (DEBUG) {
-                    Log.d(TAG, "Package " + basePackageName + " installed u" + userId
-                            + " returnCode: " + returnCode + " msg: " + msg);
-                }
-                // Don't notify the counter for now, we'll do it in installExistingPackage
-                if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                    mApkToPackageMap.put(apkName, basePackageName);
-                    // Install on user 0 so that the package is cached when demo user is re-created
-                    installExistingPackage(basePackageName, UserHandle.USER_SYSTEM, counter);
-                } else if (returnCode == PackageManager.INSTALL_FAILED_ALREADY_EXISTS) {
-                    // This can only happen in first session after a reboot
-                    if (!mApkToPackageMap.containsKey(apkName)) {
-                        mApkToPackageMap.put(apkName, basePackageName);
-                    }
-                    installExistingPackage(basePackageName, userId, counter);
-                } else {
-                    Log.e(TAG, "Package " + basePackageName + " cannot be installed from "
-                            + apkName + ": " + msg + " (returnCode " + returnCode + ")");
-                    counter.appInstallFinished();
-                }
-            }
-        }.getBinder(), 0, SYSTEM_SERVER_PACKAGE_NAME, userId);
-    }
-
-    private static class AppInstallCounter {
-        private int expectedCount = -1; // -1 means expectedCount not set
-        private int finishedCount;
-        private final Context mContext;
-        private final int userId;
-
-        AppInstallCounter(Context context, int userId) {
-            mContext = context;
-            this.userId = userId;
-        }
-
-        synchronized void appInstallFinished() {
-            this.finishedCount++;
-            checkIfAllFinished();
-        }
-
-        synchronized void setExpectedAppsCount(int expectedCount) {
-            this.expectedCount = expectedCount;
-            checkIfAllFinished();
-        }
-
-        private void checkIfAllFinished() {
-            if (expectedCount == finishedCount) {
-                Log.i(TAG, "All preloads finished installing for user " + userId);
-                Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, "1", userId);
-            }
-        }
-    }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
deleted file mode 100644
index 711d4d9d..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.retaildemo;
-
-import android.Manifest;
-import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
-import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.RetailDemoModeServiceInternal;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.database.ContentObserver;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.media.AudioManager;
-import android.media.AudioSystem;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.KeyValueListParser;
-import android.util.Slog;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.LocalServices;
-import com.android.server.PreloadsFileCacheExpirationJobService;
-import com.android.server.ServiceThread;
-import com.android.server.SystemService;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.retaildemo.UserInactivityCountdownDialog.OnCountDownExpiredListener;
-
-import java.io.File;
-import java.util.ArrayList;
-
-public class RetailDemoModeService extends SystemService {
-    private static final boolean DEBUG = false;
-
-    private static final String TAG = RetailDemoModeService.class.getSimpleName();
-    private static final String DEMO_USER_NAME = "Demo";
-    private static final String ACTION_RESET_DEMO =
-            "com.android.server.retaildemo.ACTION_RESET_DEMO";
-    @VisibleForTesting
-    static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
-
-    private static final int MSG_TURN_SCREEN_ON = 0;
-    private static final int MSG_INACTIVITY_TIME_OUT = 1;
-    private static final int MSG_START_NEW_SESSION = 2;
-
-    private static final long SCREEN_WAKEUP_DELAY = 2500;
-    private static final long USER_INACTIVITY_TIMEOUT_MIN = 10000;
-    private static final long USER_INACTIVITY_TIMEOUT_DEFAULT = 90000;
-    private static final long WARNING_DIALOG_TIMEOUT_DEFAULT = 0;
-    private static final long MILLIS_PER_SECOND = 1000;
-
-    @VisibleForTesting
-    static final int[] VOLUME_STREAMS_TO_MUTE = {
-            AudioSystem.STREAM_RING,
-            AudioSystem.STREAM_MUSIC
-    };
-
-    // Tron Vars
-    private static final String DEMO_SESSION_COUNT = "retail_demo_session_count";
-    private static final String DEMO_SESSION_DURATION = "retail_demo_session_duration";
-
-    boolean mDeviceInDemoMode;
-    boolean mIsCarrierDemoMode;
-    int mCurrentUserId = UserHandle.USER_SYSTEM;
-    long mUserInactivityTimeout;
-    long mWarningDialogTimeout;
-    private Injector mInjector;
-    Handler mHandler;
-    private ServiceThread mHandlerThread;
-    private String[] mCameraIdsWithFlash;
-    private PreloadAppsInstaller mPreloadAppsInstaller;
-
-    final Object mActivityLock = new Object();
-    // Whether the newly created demo user has interacted with the screen yet
-    @GuardedBy("mActivityLock")
-    boolean mUserUntouched;
-    @GuardedBy("mActivityLock")
-    long mFirstUserActivityTime;
-    @GuardedBy("mActivityLock")
-    long mLastUserActivityTime;
-
-    private boolean mSafeBootRestrictionInitialState;
-    private int mPackageVerifierEnableInitialState;
-
-    private IntentReceiver mBroadcastReceiver = null;
-
-    private final class IntentReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (!mDeviceInDemoMode) {
-                return;
-            }
-            final String action = intent.getAction();
-            switch (action) {
-                case Intent.ACTION_SCREEN_OFF:
-                    mHandler.removeMessages(MSG_TURN_SCREEN_ON);
-                    mHandler.sendEmptyMessageDelayed(MSG_TURN_SCREEN_ON, SCREEN_WAKEUP_DELAY);
-                    break;
-                case ACTION_RESET_DEMO:
-                    mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-                    break;
-            }
-        }
-    };
-
-    final class MainHandler extends Handler {
-
-        MainHandler(Looper looper) {
-            super(looper, null, true);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            if (!mDeviceInDemoMode) {
-                return;
-            }
-            switch (msg.what) {
-                case MSG_TURN_SCREEN_ON:
-                    if (mInjector.isWakeLockHeld()) {
-                        mInjector.releaseWakeLock();
-                    }
-                    mInjector.acquireWakeLock();
-                    break;
-                case MSG_INACTIVITY_TIME_OUT:
-                    if (!mIsCarrierDemoMode && isDemoLauncherDisabled()) {
-                        Slog.i(TAG, "User inactivity timeout reached");
-                        showInactivityCountdownDialog();
-                    }
-                    break;
-                case MSG_START_NEW_SESSION:
-                    if (DEBUG) {
-                        Slog.d(TAG, "Switching to a new demo user");
-                    }
-                    removeMessages(MSG_START_NEW_SESSION);
-                    removeMessages(MSG_INACTIVITY_TIME_OUT);
-                    if (!mIsCarrierDemoMode && mCurrentUserId != UserHandle.USER_SYSTEM) {
-                        logSessionDuration();
-                    }
-
-                    final UserManager um = mInjector.getUserManager();
-                    UserInfo demoUser = null;
-                    if (mIsCarrierDemoMode) {
-                        // Re-use the existing demo user in carrier demo mode.
-                        for (UserInfo user : um.getUsers()) {
-                            if (user.isDemo()) {
-                                demoUser = user;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (demoUser == null) {
-                        // User in carrier demo mode should survive reboots.
-                        final int flags = UserInfo.FLAG_DEMO
-                                | (mIsCarrierDemoMode ? 0 : UserInfo.FLAG_EPHEMERAL);
-                        demoUser = um.createUser(DEMO_USER_NAME, flags);
-                    }
-
-                    if (demoUser != null && mCurrentUserId != demoUser.id) {
-                        setupDemoUser(demoUser);
-                        mInjector.switchUser(demoUser.id);
-                    }
-                    break;
-            }
-        }
-    }
-
-    @VisibleForTesting
-    class SettingsObserver extends ContentObserver {
-
-        private final static String KEY_USER_INACTIVITY_TIMEOUT = "user_inactivity_timeout_ms";
-        private final static String KEY_WARNING_DIALOG_TIMEOUT = "warning_dialog_timeout_ms";
-
-        private final Uri mDeviceDemoModeUri = Settings.Global
-                .getUriFor(Settings.Global.DEVICE_DEMO_MODE);
-        private final Uri mDeviceProvisionedUri = Settings.Global
-                .getUriFor(Settings.Global.DEVICE_PROVISIONED);
-        private final Uri mRetailDemoConstantsUri = Settings.Global
-                .getUriFor(Settings.Global.RETAIL_DEMO_MODE_CONSTANTS);
-
-        private final KeyValueListParser mParser = new KeyValueListParser(',');
-
-        public SettingsObserver(Handler handler) {
-            super(handler);
-        }
-
-        public void register() {
-            final ContentResolver cr = mInjector.getContentResolver();
-            cr.registerContentObserver(mDeviceDemoModeUri, false, this, UserHandle.USER_SYSTEM);
-            cr.registerContentObserver(mDeviceProvisionedUri, false, this, UserHandle.USER_SYSTEM);
-            cr.registerContentObserver(mRetailDemoConstantsUri, false, this,
-                    UserHandle.USER_SYSTEM);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            if (mRetailDemoConstantsUri.equals(uri)) {
-                refreshTimeoutConstants();
-                return;
-            }
-
-            // If device is provisioned and left demo mode - run the cleanup in demo folder
-            if (isDeviceProvisioned()) {
-                if (UserManager.isDeviceInDemoMode(getContext())) {
-                    startDemoMode();
-                } else {
-                    mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0");
-
-                    // Run on the bg thread to not block the fg thread
-                    BackgroundThread.getHandler().post(() -> {
-                        if (!deletePreloadsFolderContents()) {
-                            Slog.w(TAG, "Failed to delete preloads folder contents");
-                        }
-                        PreloadsFileCacheExpirationJobService.schedule(mInjector.getContext());
-                    });
-
-                    stopDemoMode();
-
-                    if (mInjector.isWakeLockHeld()) {
-                        mInjector.releaseWakeLock();
-                    }
-                }
-            }
-        }
-
-        private void refreshTimeoutConstants() {
-            try {
-                mParser.setString(Settings.Global.getString(mInjector.getContentResolver(),
-                        Settings.Global.RETAIL_DEMO_MODE_CONSTANTS));
-            } catch (IllegalArgumentException exc) {
-                Slog.e(TAG, "Invalid string passed to KeyValueListParser");
-                // Consuming the exception to fall back to default values.
-            }
-            mWarningDialogTimeout = mParser.getLong(KEY_WARNING_DIALOG_TIMEOUT,
-                    WARNING_DIALOG_TIMEOUT_DEFAULT);
-            mUserInactivityTimeout = mParser.getLong(KEY_USER_INACTIVITY_TIMEOUT,
-                    USER_INACTIVITY_TIMEOUT_DEFAULT);
-            mUserInactivityTimeout = Math.max(mUserInactivityTimeout, USER_INACTIVITY_TIMEOUT_MIN);
-        }
-    }
-
-    private void showInactivityCountdownDialog() {
-        UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
-                mWarningDialogTimeout, MILLIS_PER_SECOND);
-        dialog.setNegativeButtonClickListener(null);
-        dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-            }
-        });
-        dialog.setOnCountDownExpiredListener(new OnCountDownExpiredListener() {
-            @Override
-            public void onCountDownExpired() {
-                mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-            }
-        });
-        dialog.show();
-    }
-
-    public RetailDemoModeService(Context context) {
-        this(new Injector(context));
-    }
-
-    @VisibleForTesting
-    RetailDemoModeService(Injector injector) {
-        super(injector.getContext());
-
-        mInjector = injector;
-        synchronized (mActivityLock) {
-            mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis();
-        }
-    }
-
-    boolean isDemoLauncherDisabled() {
-        int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-        try {
-            final IPackageManager iPm = mInjector.getIPackageManager();
-            final String demoLauncherComponent =
-                    getContext().getString(R.string.config_demoModeLauncherComponent);
-            enabledState = iPm.getComponentEnabledSetting(
-                    ComponentName.unflattenFromString(demoLauncherComponent), mCurrentUserId);
-        } catch (RemoteException re) {
-            Slog.e(TAG, "Error retrieving demo launcher enabled setting", re);
-        }
-        return enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
-    }
-
-    private void setupDemoUser(UserInfo userInfo) {
-        final UserManager um = mInjector.getUserManager();
-        final UserHandle user = UserHandle.of(userInfo.id);
-        um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
-        // Set this to false because the default is true on user creation
-        um.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
-        // Disallow rebooting in safe mode - controlled by user 0
-        um.setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
-        if (mIsCarrierDemoMode) {
-            // Enable SMS in carrier demo mode.
-            um.setUserRestriction(UserManager.DISALLOW_SMS, false, user);
-        }
-
-        Settings.Secure.putIntForUser(mInjector.getContentResolver(),
-                Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
-        Settings.Global.putInt(mInjector.getContentResolver(),
-                Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
-
-        grantRuntimePermissionToCamera(user);
-        clearPrimaryCallLog();
-
-        if (!mIsCarrierDemoMode) {
-            // Enable demo launcher.
-            final String demoLauncher = getContext().getString(
-                    R.string.config_demoModeLauncherComponent);
-            if (!TextUtils.isEmpty(demoLauncher)) {
-                final ComponentName componentToEnable =
-                        ComponentName.unflattenFromString(demoLauncher);
-                final String packageName = componentToEnable.getPackageName();
-                try {
-                    final IPackageManager iPm = AppGlobals.getPackageManager();
-                    iPm.setComponentEnabledSetting(componentToEnable,
-                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id);
-                    iPm.setApplicationEnabledSetting(packageName,
-                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
-                } catch (RemoteException re) {
-                    // Internal, shouldn't happen
-                }
-            }
-        } else {
-            // Set the carrier demo mode setting for the demo user.
-            final String carrierDemoModeSetting = getContext().getString(
-                    R.string.config_carrierDemoModeSetting);
-            Settings.Secure.putIntForUser(getContext().getContentResolver(),
-                    carrierDemoModeSetting, 1, userInfo.id);
-
-            // Enable packages for carrier demo mode.
-            final String packageList = getContext().getString(
-                    R.string.config_carrierDemoModePackages);
-            final String[] packageNames = packageList == null ? new String[0]
-                    : TextUtils.split(packageList, ",");
-            final IPackageManager iPm = AppGlobals.getPackageManager();
-            for (String packageName : packageNames) {
-                try {
-                    iPm.setApplicationEnabledSetting(packageName,
-                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
-                } catch (RemoteException re) {
-                    Slog.e(TAG, "Error enabling application: " + packageName, re);
-                }
-            }
-        }
-    }
-
-    private void grantRuntimePermissionToCamera(UserHandle user) {
-        final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-        final PackageManager pm = mInjector.getPackageManager();
-        final ResolveInfo handler = pm.resolveActivityAsUser(cameraIntent,
-                PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                user.getIdentifier());
-        if (handler == null || handler.activityInfo == null) {
-            return;
-        }
-        try {
-            pm.grantRuntimePermission(handler.activityInfo.packageName,
-                    Manifest.permission.ACCESS_FINE_LOCATION, user);
-        } catch (Exception e) {
-            // Ignore
-        }
-    }
-
-    private void clearPrimaryCallLog() {
-        final ContentResolver resolver = mInjector.getContentResolver();
-
-        // Deleting primary user call log so that it doesn't get copied to the new demo user
-        final Uri uri = CallLog.Calls.CONTENT_URI;
-        try {
-            resolver.delete(uri, null, null);
-        } catch (Exception e) {
-            Slog.w(TAG, "Deleting call log failed: " + e);
-        }
-    }
-
-    void logSessionDuration() {
-        final int sessionDuration;
-        synchronized (mActivityLock) {
-            sessionDuration = (int) ((mLastUserActivityTime - mFirstUserActivityTime) / 1000);
-        }
-        mInjector.logSessionDuration(sessionDuration);
-    }
-
-    private boolean isDeviceProvisioned() {
-        return Settings.Global.getInt(
-                mInjector.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
-    }
-
-    /**
-     * Deletes contents of {@link Environment#getDataPreloadsDirectory()},
-     * but leave {@link Environment#getDataPreloadsFileCacheDirectory()}
-     * @return true if contents was sucessfully deleted
-     */
-    private boolean deletePreloadsFolderContents() {
-        final File dir = mInjector.getDataPreloadsDirectory();
-        final File[] files = FileUtils.listFilesOrEmpty(dir);
-        final File fileCacheDirectory = mInjector.getDataPreloadsFileCacheDirectory();
-        Slog.i(TAG, "Deleting contents of " + dir);
-        boolean success = true;
-        for (File file : files) {
-            if (file.isFile()) {
-                if (!file.delete()) {
-                    success = false;
-                    Slog.w(TAG, "Cannot delete file " + file);
-                }
-            } else {
-                // Do not remove file_cache dir
-                if (!file.equals(fileCacheDirectory)) {
-                    if (!FileUtils.deleteContentsAndDir(file)) {
-                        success = false;
-                        Slog.w(TAG, "Cannot delete dir and its content " + file);
-                    }
-                } else {
-                    Slog.i(TAG, "Skipping directory with file cache " + file);
-                }
-            }
-        }
-        return success;
-    }
-
-    private void registerBroadcastReceiver() {
-        if (mBroadcastReceiver != null) {
-            return;
-        }
-
-        final IntentFilter filter = new IntentFilter();
-        if (!mIsCarrierDemoMode) {
-            filter.addAction(Intent.ACTION_SCREEN_OFF);
-        }
-        filter.addAction(ACTION_RESET_DEMO);
-        mBroadcastReceiver = new IntentReceiver();
-        getContext().registerReceiver(mBroadcastReceiver, filter);
-    }
-
-    private void unregisterBroadcastReceiver() {
-        if (mBroadcastReceiver != null) {
-            getContext().unregisterReceiver(mBroadcastReceiver);
-            mBroadcastReceiver = null;
-        }
-    }
-
-    private String[] getCameraIdsWithFlash() {
-        ArrayList<String> cameraIdsList = new ArrayList<String>();
-        final CameraManager cm = mInjector.getCameraManager();
-        if (cm != null) {
-            try {
-                for (String cameraId : cm.getCameraIdList()) {
-                    CameraCharacteristics c = cm.getCameraCharacteristics(cameraId);
-                    if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) {
-                        cameraIdsList.add(cameraId);
-                    }
-                }
-            } catch (CameraAccessException e) {
-                Slog.e(TAG, "Unable to access camera while getting camera id list", e);
-            }
-        }
-        return cameraIdsList.toArray(new String[cameraIdsList.size()]);
-    }
-
-    private void muteVolumeStreams() {
-        for (int stream : VOLUME_STREAMS_TO_MUTE) {
-            mInjector.getAudioManager().setStreamVolume(stream,
-                    mInjector.getAudioManager().getStreamMinVolume(stream), 0);
-        }
-    }
-
-    private void startDemoMode() {
-        mDeviceInDemoMode = true;
-
-        mPreloadAppsInstaller = mInjector.getPreloadAppsInstaller();
-        mInjector.initializeWakeLock();
-        if (mCameraIdsWithFlash == null) {
-            mCameraIdsWithFlash = getCameraIdsWithFlash();
-        }
-        registerBroadcastReceiver();
-
-        final String carrierDemoModeSetting =
-                getContext().getString(R.string.config_carrierDemoModeSetting);
-        mIsCarrierDemoMode = !TextUtils.isEmpty(carrierDemoModeSetting)
-                && (Settings.Secure.getInt(getContext().getContentResolver(),
-                        carrierDemoModeSetting, 0) == 1);
-
-        mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1");
-        mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-
-        mSafeBootRestrictionInitialState = mInjector.getUserManager().hasUserRestriction(
-                UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM);
-        mPackageVerifierEnableInitialState = Settings.Global.getInt(mInjector.getContentResolver(),
-                Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
-    }
-
-    private void stopDemoMode() {
-        mPreloadAppsInstaller = null;
-        mCameraIdsWithFlash = null;
-        mInjector.destroyWakeLock();
-        unregisterBroadcastReceiver();
-
-        if (mDeviceInDemoMode) {
-            mInjector.getUserManager().setUserRestriction(UserManager.DISALLOW_SAFE_BOOT,
-                    mSafeBootRestrictionInitialState, UserHandle.SYSTEM);
-            Settings.Global.putInt(mInjector.getContentResolver(),
-                        Settings.Global.PACKAGE_VERIFIER_ENABLE,
-                        mPackageVerifierEnableInitialState);
-        }
-
-        mDeviceInDemoMode = false;
-        mIsCarrierDemoMode = false;
-    }
-
-    @Override
-    public void onStart() {
-        if (DEBUG) {
-            Slog.d(TAG, "Service starting up");
-        }
-        mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND,
-                false);
-        mHandlerThread.start();
-        mHandler = new MainHandler(mHandlerThread.getLooper());
-        mInjector.publishLocalService(this, mLocalService);
-    }
-
-    @Override
-    public void onBootPhase(int bootPhase) {
-        switch (bootPhase) {
-            case PHASE_THIRD_PARTY_APPS_CAN_START:
-                final SettingsObserver settingsObserver = new SettingsObserver(mHandler);
-                settingsObserver.register();
-                settingsObserver.refreshTimeoutConstants();
-                break;
-            case PHASE_BOOT_COMPLETED:
-                if (UserManager.isDeviceInDemoMode(getContext())) {
-                    startDemoMode();
-                }
-                break;
-        }
-    }
-
-    @Override
-    public void onSwitchUser(int userId) {
-        if (!mDeviceInDemoMode) {
-            return;
-        }
-        if (DEBUG) {
-            Slog.d(TAG, "onSwitchUser: " + userId);
-        }
-        final UserInfo ui = mInjector.getUserManager().getUserInfo(userId);
-        if (!ui.isDemo()) {
-            Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
-            return;
-        }
-        if (!mIsCarrierDemoMode && !mInjector.isWakeLockHeld()) {
-            mInjector.acquireWakeLock();
-        }
-        mCurrentUserId = userId;
-        mInjector.getActivityManagerInternal().updatePersistentConfigurationForUser(
-                mInjector.getSystemUsersConfiguration(), userId);
-
-        mInjector.turnOffAllFlashLights(mCameraIdsWithFlash);
-        muteVolumeStreams();
-        if (!mInjector.getWifiManager().isWifiEnabled()) {
-            mInjector.getWifiManager().setWifiEnabled(true);
-        }
-
-        // Disable lock screen for demo users.
-        mInjector.getLockPatternUtils().setLockScreenDisabled(true, userId);
-
-        if (!mIsCarrierDemoMode) {
-            // Show reset notification (except in carrier demo mode).
-            mInjector.getNotificationManager().notifyAsUser(TAG, SystemMessage.NOTE_RETAIL_RESET,
-                    mInjector.createResetNotification(), UserHandle.of(userId));
-
-            synchronized (mActivityLock) {
-                mUserUntouched = true;
-            }
-            mInjector.logSessionCount(1);
-            mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mPreloadAppsInstaller.installApps(userId);
-                }
-            });
-        }
-    }
-
-    private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
-        private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000;
-
-        @Override
-        public void onUserActivity() {
-            if (!mDeviceInDemoMode || mIsCarrierDemoMode) {
-                return;
-            }
-            long timeOfActivity = SystemClock.uptimeMillis();
-            synchronized (mActivityLock) {
-                if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
-                    return;
-                }
-                mLastUserActivityTime = timeOfActivity;
-                if (mUserUntouched && isDemoLauncherDisabled()) {
-                    Slog.d(TAG, "retail_demo first touch");
-                    mUserUntouched = false;
-                    mFirstUserActivityTime = timeOfActivity;
-                }
-            }
-            mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
-            mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, mUserInactivityTimeout);
-        }
-    };
-
-    static class Injector {
-        private Context mContext;
-        private UserManager mUm;
-        private PackageManager mPm;
-        private NotificationManager mNm;
-        private ActivityManagerService mAms;
-        private ActivityManagerInternal mAmi;
-        private AudioManager mAudioManager;
-        private PowerManager mPowerManager;
-        private CameraManager mCameraManager;
-        private PowerManager.WakeLock mWakeLock;
-        private WifiManager mWifiManager;
-        private Configuration mSystemUserConfiguration;
-        private PendingIntent mResetDemoPendingIntent;
-        private PreloadAppsInstaller mPreloadAppsInstaller;
-
-        Injector(Context context) {
-            mContext = context;
-        }
-
-        Context getContext() {
-            return mContext;
-        }
-
-        WifiManager getWifiManager() {
-            if (mWifiManager == null) {
-                mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
-            }
-            return mWifiManager;
-        }
-
-        UserManager getUserManager() {
-            if (mUm == null) {
-                mUm = getContext().getSystemService(UserManager.class);
-            }
-            return mUm;
-        }
-
-        void switchUser(int userId) {
-            if (mAms == null) {
-                mAms = (ActivityManagerService) ActivityManager.getService();
-            }
-            mAms.switchUser(userId);
-        }
-
-        AudioManager getAudioManager() {
-            if (mAudioManager == null) {
-                mAudioManager = getContext().getSystemService(AudioManager.class);
-            }
-            return mAudioManager;
-        }
-
-        private PowerManager getPowerManager() {
-            if (mPowerManager == null) {
-                mPowerManager = (PowerManager) getContext().getSystemService(
-                        Context.POWER_SERVICE);
-            }
-            return mPowerManager;
-        }
-
-        NotificationManager getNotificationManager() {
-            if (mNm == null) {
-                mNm = NotificationManager.from(getContext());
-            }
-            return mNm;
-        }
-
-        ActivityManagerInternal getActivityManagerInternal() {
-            if (mAmi == null) {
-                mAmi = LocalServices.getService(ActivityManagerInternal.class);
-            }
-            return mAmi;
-        }
-
-        CameraManager getCameraManager() {
-            if (mCameraManager == null) {
-                mCameraManager = (CameraManager) getContext().getSystemService(
-                        Context.CAMERA_SERVICE);
-            }
-            return mCameraManager;
-        }
-
-        PackageManager getPackageManager() {
-            if (mPm == null) {
-                mPm = getContext().getPackageManager();
-            }
-            return mPm;
-        }
-
-        IPackageManager getIPackageManager() {
-            return AppGlobals.getPackageManager();
-        }
-
-        ContentResolver getContentResolver() {
-            return getContext().getContentResolver();
-        }
-
-        PreloadAppsInstaller getPreloadAppsInstaller() {
-            if (mPreloadAppsInstaller == null) {
-                mPreloadAppsInstaller = new PreloadAppsInstaller(getContext());
-            }
-            return mPreloadAppsInstaller;
-        }
-
-        void systemPropertiesSet(String key, String value) {
-            SystemProperties.set(key, value);
-        }
-
-        void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
-            for (String cameraId : cameraIdsWithFlash) {
-                try {
-                    getCameraManager().setTorchMode(cameraId, false);
-                } catch (CameraAccessException e) {
-                    Slog.e(TAG, "Unable to access camera " + cameraId
-                            + " while turning off flash", e);
-                }
-            }
-        }
-
-        void initializeWakeLock() {
-            if (mWakeLock == null) {
-                mWakeLock = getPowerManager().newWakeLock(
-                        PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
-            }
-        }
-
-        void destroyWakeLock() {
-            mWakeLock = null;
-        }
-
-        boolean isWakeLockHeld() {
-            return mWakeLock != null && mWakeLock.isHeld();
-        }
-
-        void acquireWakeLock() {
-            mWakeLock.acquire();
-        }
-
-        void releaseWakeLock() {
-            mWakeLock.release();
-        }
-
-        void logSessionDuration(int duration) {
-            MetricsLogger.histogram(getContext(), DEMO_SESSION_DURATION, duration);
-        }
-
-        void logSessionCount(int count) {
-            MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, count);
-        }
-
-        Configuration getSystemUsersConfiguration() {
-            if (mSystemUserConfiguration == null) {
-                Settings.System.getConfiguration(getContentResolver(),
-                        mSystemUserConfiguration = new Configuration());
-            }
-            return mSystemUserConfiguration;
-        }
-
-        LockPatternUtils getLockPatternUtils() {
-            return new LockPatternUtils(getContext());
-        }
-
-        Notification createResetNotification() {
-            return new Notification.Builder(getContext(), SystemNotificationChannels.RETAIL_MODE)
-                    .setContentTitle(getContext().getString(R.string.reset_retail_demo_mode_title))
-                    .setContentText(getContext().getString(R.string.reset_retail_demo_mode_text))
-                    .setOngoing(true)
-                    .setSmallIcon(R.drawable.platlogo)
-                    .setShowWhen(false)
-                    .setVisibility(Notification.VISIBILITY_PUBLIC)
-                    .setContentIntent(getResetDemoPendingIntent())
-                    .setColor(getContext().getColor(R.color.system_notification_accent_color))
-                    .build();
-        }
-
-        private PendingIntent getResetDemoPendingIntent() {
-            if (mResetDemoPendingIntent == null) {
-                Intent intent = new Intent(ACTION_RESET_DEMO);
-                mResetDemoPendingIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
-            }
-            return mResetDemoPendingIntent;
-        }
-
-        File getDataPreloadsDirectory() {
-            return Environment.getDataPreloadsDirectory();
-        }
-
-        File getDataPreloadsFileCacheDirectory() {
-            return Environment.getDataPreloadsFileCacheDirectory();
-        }
-
-        void publishLocalService(RetailDemoModeService service,
-                RetailDemoModeServiceInternal localService) {
-            service.publishLocalService(RetailDemoModeServiceInternal.class, localService);
-        }
-    }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
deleted file mode 100644
index 013eab8..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.retaildemo;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.os.CountDownTimer;
-import android.view.WindowManager;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-public class UserInactivityCountdownDialog extends AlertDialog {
-
-    private OnCountDownExpiredListener mOnCountDownExpiredListener;
-    private CountDownTimer mCountDownTimer;
-    private long mCountDownDuration;
-    private long mRefreshInterval;
-
-    UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) {
-        super(context);
-        mCountDownDuration = duration;
-        mRefreshInterval = refreshInterval;
-
-        getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
-        WindowManager.LayoutParams attrs = getWindow().getAttributes();
-        attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-        getWindow().setAttributes(attrs);
-
-        setTitle(R.string.demo_user_inactivity_timeout_title);
-        setMessage(getContext().getString(R.string.demo_user_inactivity_timeout_countdown,
-                duration));
-    }
-
-    public void setOnCountDownExpiredListener(
-            OnCountDownExpiredListener onCountDownExpiredListener) {
-        mOnCountDownExpiredListener = onCountDownExpiredListener;
-    }
-
-    public void setPositiveButtonClickListener(OnClickListener onClickListener) {
-        setButton(Dialog.BUTTON_POSITIVE,
-                getContext().getString(R.string.demo_user_inactivity_timeout_right_button),
-                onClickListener);
-    }
-
-    public void setNegativeButtonClickListener(OnClickListener onClickListener) {
-        setButton(Dialog.BUTTON_NEGATIVE,
-                getContext().getString(R.string.demo_user_inactivity_timeout_left_button),
-                onClickListener);
-    }
-
-    @Override
-    public void show() {
-        super.show();
-        final TextView messageView = findViewById(R.id.message);
-        messageView.post(new Runnable() {
-            @Override
-            public void run() {
-                mCountDownTimer = new CountDownTimer(mCountDownDuration, mRefreshInterval) {
-
-                    @Override
-                    public void onTick(long millisUntilFinished) {
-                        String msg = getContext().getString(
-                                R.string.demo_user_inactivity_timeout_countdown,
-                                millisUntilFinished / 1000);
-                        messageView.setText(msg);
-                    }
-
-                    @Override
-                    public void onFinish() {
-                        dismiss();
-                        if (mOnCountDownExpiredListener != null)
-                            mOnCountDownExpiredListener.onCountDownExpired();
-                    }
-                }.start();
-            }
-        });
-    }
-
-    @Override
-    public void onStop() {
-        if (mCountDownTimer != null) {
-            mCountDownTimer.cancel();
-        }
-    }
-
-    interface OnCountDownExpiredListener {
-        void onCountDownExpired();
-    }
-}
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index 940db79..79f96fd 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -18,7 +18,6 @@
     services.core \
     services.devicepolicy \
     services.net \
-    services.retaildemo \
     services.usage \
     guava \
     android-support-test \
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 2c3283c..e3a6dae 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -19,7 +19,6 @@
     services.core \
     services.devicepolicy \
     services.net \
-    services.retaildemo \
     services.usage \
     guava \
     android-support-test \
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
deleted file mode 100644
index cf27a50..0000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.retaildemo;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.IPackageInstallObserver2;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.FileUtils;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentResolver;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.io.File;
-import java.util.ArrayList;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class PreloadAppsInstallerTest {
-    private static final int TEST_DEMO_USER = 111;
-
-    private Context mContext;
-    private @Mock IPackageManager mIpm;
-    private MockContentResolver mContentResolver;
-    private File mPreloadsAppsDirectory;
-    private String[] mPreloadedApps =
-            new String[] {"test1.apk.preload", "test2.apk.preload", "test3.apk.preload"};
-    private ArrayList<String> mPreloadedAppPaths = new ArrayList<>();
-
-    private PreloadAppsInstaller mInstaller;
-
-    @BeforeClass
-    @AfterClass
-    public static void clearSettingsProvider() {
-        FakeSettingsProvider.clearSettingsProvider();
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
-        mContentResolver = new MockContentResolver(mContext);
-        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
-        when(mContext.getContentResolver()).thenReturn(mContentResolver);
-        initializePreloadedApps();
-        Settings.Secure.putStringForUser(mContentResolver,
-                Settings.Secure.DEMO_USER_SETUP_COMPLETE, "0", TEST_DEMO_USER);
-
-        mInstaller = new PreloadAppsInstaller(mContext, mIpm, mPreloadsAppsDirectory);
-    }
-
-    private void initializePreloadedApps() throws Exception {
-        mPreloadsAppsDirectory = new File(InstrumentationRegistry.getContext().getFilesDir(),
-                 "test_preload_apps_dir");
-        mPreloadsAppsDirectory.mkdir();
-        for (String name : mPreloadedApps) {
-            final File f = new File(mPreloadsAppsDirectory, name);
-            f.createNewFile();
-            mPreloadedAppPaths.add(f.getPath());
-        }
-    }
-
-    @After
-    public void tearDown() {
-        if (mPreloadsAppsDirectory != null) {
-            FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
-        }
-    }
-
-    @Test
-    public void testInstallApps() throws Exception {
-        mInstaller.installApps(TEST_DEMO_USER);
-        for (String path : mPreloadedAppPaths) {
-            ArgumentCaptor<IPackageInstallObserver2> observer =
-                    ArgumentCaptor.forClass(IPackageInstallObserver2.class);
-            verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
-                    anyString(), eq(TEST_DEMO_USER));
-            observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
-                    null, null);
-            // Verify that we try to install the package in system user.
-            verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
-                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
-        }
-        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
-                "1",
-                Settings.Secure.getStringForUser(mContentResolver,
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
-    }
-
-    @Test
-    public void testInstallApps_noPreloads() throws Exception {
-        // Delete all files in preloaded apps directory - no preloaded apps
-        FileUtils.deleteContents(mPreloadsAppsDirectory);
-        mInstaller.installApps(TEST_DEMO_USER);
-        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
-                "1",
-                Settings.Secure.getStringForUser(mContentResolver,
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
-    }
-
-    @Test
-    public void testInstallApps_installationFails() throws Exception {
-        mInstaller.installApps(TEST_DEMO_USER);
-        for (int i = 0; i < mPreloadedAppPaths.size(); ++i) {
-            ArgumentCaptor<IPackageInstallObserver2> observer =
-                    ArgumentCaptor.forClass(IPackageInstallObserver2.class);
-            final String path = mPreloadedAppPaths.get(i);
-            verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
-                    anyString(), eq(TEST_DEMO_USER));
-            if (i == 0) {
-                observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_FAILED_DEXOPT,
-                        null, null);
-                continue;
-            }
-            observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
-                    null, null);
-            // Verify that we try to install the package in system user.
-            verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
-                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
-        }
-        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
-                "1",
-                Settings.Secure.getStringForUser(mContentResolver,
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
deleted file mode 100644
index a93f6439..0000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.retaildemo;
-
-import static com.android.server.retaildemo.RetailDemoModeService.SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.app.ActivityManagerInternal;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.RetailDemoModeServiceInternal;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentProvider;
-import android.test.mock.MockContentResolver;
-import android.util.ArrayMap;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.SystemService;
-import com.android.server.retaildemo.RetailDemoModeService.Injector;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.compat.ArgumentMatcher;
-
-import java.io.File;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class RetailDemoModeServiceTest {
-    private static final int TEST_DEMO_USER = 111;
-    private static final long SETUP_COMPLETE_TIMEOUT_MS = 2000; // 2 sec
-    private static final String TEST_CAMERA_PKG = "test.cameraapp";
-    private static final String TEST_PRELOADS_DIR_NAME = "test_preloads";
-
-    private Context mContext;
-    private @Mock UserManager mUm;
-    private @Mock PackageManager mPm;
-    private @Mock IPackageManager mIpm;
-    private @Mock NotificationManager mNm;
-    private @Mock ActivityManagerInternal mAmi;
-    private @Mock AudioManager mAudioManager;
-    private @Mock WifiManager mWifiManager;
-    private @Mock LockPatternUtils mLockPatternUtils;
-    private @Mock JobScheduler mJobScheduler;
-    private MockPreloadAppsInstaller mPreloadAppsInstaller;
-    private MockContentResolver mContentResolver;
-    private MockContactsProvider mContactsProvider;
-    private Configuration mConfiguration;
-    private File mTestPreloadsDir;
-    private CountDownLatch mLatch;
-
-    private RetailDemoModeService mService;
-    private TestInjector mInjector;
-
-    @BeforeClass
-    @AfterClass
-    public static void clearSettingsProvider() {
-        FakeSettingsProvider.clearSettingsProvider();
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
-        when(mContext.getSystemServiceName(eq(JobScheduler.class))).thenReturn(
-                Context.JOB_SCHEDULER_SERVICE);
-        when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
-        mContentResolver = new MockContentResolver(mContext);
-        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
-        mContactsProvider = new MockContactsProvider(mContext);
-        mContentResolver.addProvider(CallLog.AUTHORITY, mContactsProvider);
-        when(mContext.getContentResolver()).thenReturn(mContentResolver);
-        mPreloadAppsInstaller = new MockPreloadAppsInstaller(mContext);
-        mConfiguration = new Configuration();
-        mTestPreloadsDir = new File(InstrumentationRegistry.getContext().getFilesDir(),
-                TEST_PRELOADS_DIR_NAME);
-
-        Settings.Global.putString(mContentResolver, Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
-        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1);
-        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 1);
-
-        // Initialize RetailDemoModeService
-        mInjector = new TestInjector();
-        mService = new RetailDemoModeService(mInjector);
-        mService.onStart();
-    }
-
-    @After
-    public void tearDown() {
-        if (mTestPreloadsDir != null) {
-            FileUtils.deleteContentsAndDir(mTestPreloadsDir);
-        }
-    }
-
-    @Test
-    public void testDemoUserSetup() throws Exception {
-        mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
-
-        mLatch = new CountDownLatch(1);
-        final UserInfo userInfo = new UserInfo();
-        userInfo.id = TEST_DEMO_USER;
-        when(mUm.createUser(anyString(), anyInt())).thenReturn(userInfo);
-
-        setCameraPackage(TEST_CAMERA_PKG);
-        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
-        assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
-                "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
-        final ArgumentCaptor<IntentFilter> intentFilter =
-                ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
-        assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
-                intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
-
-        // Wait for the setup to complete.
-        mLatch.await(SETUP_COMPLETE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-        ArgumentCaptor<Integer> flags = ArgumentCaptor.forClass(Integer.class);
-        verify(mUm).createUser(anyString(), flags.capture());
-        assertTrue("FLAG_DEMO not set during user creation",
-                (flags.getValue() & UserInfo.FLAG_DEMO) != 0);
-        assertTrue("FLAG_EPHEMERAL not set during user creation",
-                (flags.getValue() & UserInfo.FLAG_EPHEMERAL) != 0);
-        // Verify if necessary restrictions are being set.
-        final UserHandle user = UserHandle.of(TEST_DEMO_USER);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
-        // Verify if necessary settings are updated.
-        assertEquals("SKIP_FIRST_USE_HINTS setting is not set for demo user",
-                Settings.Secure.getIntForUser(mContentResolver,
-                        Settings.Secure.SKIP_FIRST_USE_HINTS, TEST_DEMO_USER),
-                1);
-        assertEquals("PACKAGE_VERIFIER_ENABLE settings should be set to 0 for demo user",
-                Settings.Global.getInt(mContentResolver,
-                        Settings.Global.PACKAGE_VERIFIER_ENABLE),
-                0);
-        // Verify if camera is granted location permission.
-        verify(mPm).grantRuntimePermission(TEST_CAMERA_PKG,
-                Manifest.permission.ACCESS_FINE_LOCATION, user);
-        // Verify call logs are cleared.
-        assertTrue("Call logs should be deleted", mContactsProvider.isCallLogDeleted());
-    }
-
-    @Test
-    public void testSettingsObserver_disableDemoMode() throws Exception {
-        final RetailDemoModeService.SettingsObserver observer =
-                mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
-        final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
-        when(mUm.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM))
-                .thenReturn(false);
-        Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
-        // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
-        observer.onChange(false, deviceDemoModeUri);
-        final ArgumentCaptor<BroadcastReceiver> receiver =
-                ArgumentCaptor.forClass(BroadcastReceiver.class);
-        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
-
-        Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
-        new File(mTestPreloadsDir, "dir1").mkdirs();
-        new File(mTestPreloadsDir, "file1").createNewFile();
-        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 0);
-        observer.onChange(false, deviceDemoModeUri);
-        verify(mContext).unregisterReceiver(receiver.getValue());
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, false, UserHandle.SYSTEM);
-        assertEquals("Package verifier enable value has not been reset", 1,
-                Settings.Global.getInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE));
-        Thread.sleep(20); // Wait for the deletion to complete.
-        // verify that the preloaded directory is emptied.
-        assertEquals("Preloads directory is not emptied",
-                0, mTestPreloadsDir.list().length);
-        // Verify that the expiration job was scheduled
-        verify(mJobScheduler).schedule(any(JobInfo.class));
-    }
-
-    @Test
-    public void testSettingsObserver_enableDemoMode() throws Exception {
-        final RetailDemoModeService.SettingsObserver observer =
-                mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
-        final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
-        // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
-        observer.onChange(false, deviceDemoModeUri);
-        assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
-                "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
-        final ArgumentCaptor<IntentFilter> intentFilter =
-                ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
-        assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
-                intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
-    }
-
-    @Test
-    public void testSwitchToDemoUser() {
-        // To make the RetailDemoModeService update it's internal state.
-        mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
-        final RetailDemoModeService.SettingsObserver observer =
-                mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
-        observer.onChange(false, Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE));
-
-        final UserInfo userInfo = new UserInfo(TEST_DEMO_USER, "demo_user",
-                UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
-        when(mUm.getUserInfo(TEST_DEMO_USER)).thenReturn(userInfo);
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
-        final int minVolume = -111;
-        for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
-            when(mAudioManager.getStreamMinVolume(stream)).thenReturn(minVolume);
-        }
-
-        mService.onSwitchUser(TEST_DEMO_USER);
-        verify(mAmi).updatePersistentConfigurationForUser(mConfiguration, TEST_DEMO_USER);
-        for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
-            verify(mAudioManager).setStreamVolume(stream, minVolume, 0);
-        }
-        verify(mLockPatternUtils).setLockScreenDisabled(true, TEST_DEMO_USER);
-        verify(mWifiManager).setWifiEnabled(true);
-    }
-
-    private void setCameraPackage(String pkgName) {
-        final ResolveInfo ri = new ResolveInfo();
-        final ActivityInfo ai = new ActivityInfo();
-        ai.packageName = pkgName;
-        ri.activityInfo = ai;
-        when(mPm.resolveActivityAsUser(
-                argThat(new IntentMatcher(MediaStore.ACTION_IMAGE_CAPTURE)),
-                anyInt(),
-                eq(TEST_DEMO_USER))).thenReturn(ri);
-    }
-
-    private class IntentMatcher extends ArgumentMatcher<Intent> {
-        private final Intent mIntent;
-
-        IntentMatcher(String action) {
-            mIntent = new Intent(action);
-        }
-
-        @Override
-        public boolean matchesObject(Object argument) {
-            if (argument instanceof Intent) {
-                return ((Intent) argument).filterEquals(mIntent);
-            }
-            return false;
-        }
-
-        @Override
-        public String toString() {
-            return "Expected: " + mIntent;
-        }
-    }
-
-    private class MockContactsProvider extends MockContentProvider {
-        private boolean mCallLogDeleted;
-
-        MockContactsProvider(Context context) {
-            super(context);
-        }
-
-        @Override
-        public int delete(Uri uri, String selection, String[] selectionArgs) {
-            if (CallLog.Calls.CONTENT_URI.equals(uri)) {
-                mCallLogDeleted = true;
-            }
-            return 0;
-        }
-
-        public boolean isCallLogDeleted() {
-            return mCallLogDeleted;
-        }
-    }
-
-    private class MockPreloadAppsInstaller extends PreloadAppsInstaller {
-        MockPreloadAppsInstaller(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void installApps(int userId) {
-        }
-    }
-
-    private class TestInjector extends Injector {
-        private ArrayMap<String, String> mSystemProperties = new ArrayMap<>();
-
-        TestInjector() {
-            super(mContext);
-        }
-
-        @Override
-        Context getContext() {
-            return mContext;
-        }
-
-        @Override
-        UserManager getUserManager() {
-            return mUm;
-        }
-
-        @Override
-        WifiManager getWifiManager() {
-            return mWifiManager;
-        }
-
-        @Override
-        void switchUser(int userId) {
-            if (mLatch != null) {
-                mLatch.countDown();
-            }
-        }
-
-        @Override
-        AudioManager getAudioManager() {
-            return mAudioManager;
-        }
-
-        @Override
-        NotificationManager getNotificationManager() {
-            return mNm;
-        }
-
-        @Override
-        ActivityManagerInternal getActivityManagerInternal() {
-            return mAmi;
-        }
-
-        @Override
-        PackageManager getPackageManager() {
-            return mPm;
-        }
-
-        @Override
-        IPackageManager getIPackageManager() {
-            return mIpm;
-        }
-
-        @Override
-        ContentResolver getContentResolver() {
-            return mContentResolver;
-        }
-
-        @Override
-        PreloadAppsInstaller getPreloadAppsInstaller() {
-            return mPreloadAppsInstaller;
-        }
-
-        @Override
-        void systemPropertiesSet(String key, String value) {
-            mSystemProperties.put(key, value);
-        }
-
-        @Override
-        void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
-        }
-
-        @Override
-        void initializeWakeLock() {
-        }
-
-        @Override
-        void destroyWakeLock() {
-        }
-
-        @Override
-        boolean isWakeLockHeld() {
-            return false;
-        }
-
-        @Override
-        void acquireWakeLock() {
-        }
-
-        @Override
-        void releaseWakeLock() {
-        }
-
-        @Override
-        void logSessionDuration(int duration) {
-        }
-
-        @Override
-        void logSessionCount(int count) {
-        }
-
-        @Override
-        Configuration getSystemUsersConfiguration() {
-            return mConfiguration;
-        }
-
-        @Override
-        LockPatternUtils getLockPatternUtils() {
-            return mLockPatternUtils;
-        }
-
-        @Override
-        Notification createResetNotification() {
-            return null;
-        }
-
-        @Override
-        File getDataPreloadsDirectory() {
-            return mTestPreloadsDir;
-        }
-
-        @Override
-        File getDataPreloadsFileCacheDirectory() {
-            return new File(mTestPreloadsDir, "file_cache");
-        }
-
-        @Override
-        void publishLocalService(RetailDemoModeService service,
-                RetailDemoModeServiceInternal localService) {
-        }
-
-        String systemPropertiesGet(String key) {
-            return mSystemProperties.get(key);
-        }
-    }
-}
diff --git a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
index 0060901..cb6a83d 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
@@ -16,12 +16,14 @@
 package com.android.internal.colorextraction;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.mockito.Mockito.any;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.graphics.Color;
@@ -29,7 +31,6 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
-import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.internal.colorextraction.types.ExtractionType;
 import com.android.internal.colorextraction.types.Tonal;
@@ -78,10 +79,10 @@
         ExtractionType type =
                 (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
                         outGradientColorsExtraDark) -> {
-            outGradientColorsNormal.set(colorsExpectedNormal);
-            outGradientColorsDark.set(colorsExpectedDark);
-            outGradientColorsExtraDark.set(colorsExpectedExtraDark);
-        };
+                    outGradientColorsNormal.set(colorsExpectedNormal);
+                    outGradientColorsDark.set(colorsExpectedDark);
+                    outGradientColorsExtraDark.set(colorsExpectedExtraDark);
+                };
         ColorExtractor extractor = new ColorExtractor(mContext, type);
 
         GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM,
@@ -92,4 +93,22 @@
         colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_EXTRA_DARK);
         assertEquals("Extracted colors not being used!", colors, colorsExpectedExtraDark);
     }
+
+    @Test
+    public void addOnColorsChangedListener_invokesListener() {
+        ColorExtractor.OnColorsChangedListener mockedListeners =
+                mock(ColorExtractor.OnColorsChangedListener.class);
+        ColorExtractor extractor = new ColorExtractor(mContext, new Tonal(mContext));
+        extractor.addOnColorsChangedListener(mockedListeners);
+
+        extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.RED), null, null),
+                WallpaperManager.FLAG_LOCK);
+        verify(mockedListeners, times(1)).onColorsChanged(any(),
+                eq(WallpaperManager.FLAG_LOCK));
+
+        extractor.removeOnColorsChangedListener(mockedListeners);
+        extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.RED), null, null),
+                WallpaperManager.FLAG_LOCK);
+        verifyNoMoreInteractions(mockedListeners);
+    }
 }