Merge "Add unofficial intent for BatterySaverSchedule screen"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c8f91a8..4166d6f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -340,7 +340,7 @@
                   android:clearTaskOnLaunch="true"
                   android:excludeFromRecents="true"
                   android:exported="true"
-                  android:permission="android.permission.CONNECTIVITY_INTERNAL"
+                  android:permission="android.permission.NETWORK_STACK"
                   android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
             <intent-filter>
                 <action android:name="android.net.conn.PROMPT_UNVALIDATED" />
@@ -901,8 +901,7 @@
 
         <activity android:name=".Settings$MyDeviceInfoActivity"
                   android:label="@string/about_settings"
-                  android:icon="@drawable/ic_homepage_about"
-                  android:parentActivityName="Settings">
+                  android:icon="@drawable/ic_homepage_about">
             <intent-filter android:priority="1">
                 <action android:name="android.settings.DEVICE_INFO_SETTINGS" />
                 <action android:name="android.settings.DEVICE_NAME" />
@@ -1633,8 +1632,9 @@
             android:icon="@drawable/ic_suggestion_security">
             <intent-filter android:priority="1">
                 <action android:name="android.intent.action.MAIN" />
-                <category android:name="com.android.settings.suggested.category.DEFAULT" />
+                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
             </intent-filter>
+            <meta-data android:name="com.android.settings.dismiss" android:value="14" />
             <meta-data android:name="com.android.settings.title"
                        android:resource="@string/suggested_lock_settings_title" />
             <meta-data android:name="com.android.settings.summary"
@@ -1648,7 +1648,7 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
             </intent-filter>
-            <meta-data android:name="com.android.settings.dismiss" android:value="2," />
+            <meta-data android:name="com.android.settings.dismiss" android:value="14" />
             <meta-data android:name="com.android.settings.require_feature"
                 android:value="android.hardware.fingerprint" />
             <meta-data android:name="com.android.settings.title"
@@ -2390,6 +2390,19 @@
         </activity>
 
         <activity
+            android:name="Settings$ZenAccessDetailSettingsActivity"
+            android:label="@string/manage_zen_access_title"
+            android:excludeFromRecents="true">
+            <intent-filter>
+                <action android:name="android.settings.NOTIFICATION_POLICY_ACCESS_DETAIL_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:scheme="package" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails" />
+        </activity>
+
+        <activity
             android:name="Settings$ZenAccessSettingsActivity"
             android:label="@string/manage_zen_access_title"
             android:parentActivityName="Settings">
@@ -2540,7 +2553,7 @@
 
         <receiver android:name=".sim.SimSelectNotification">
             <intent-filter>
-                <action android:name="android.intent.action.SIM_STATE_CHANGED"/>
+                <action android:name="android.intent.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED"/>
             </intent-filter>
         </receiver>
 
@@ -2609,6 +2622,8 @@
             android:name=".wifi.NetworkRequestDialogActivity"
             android:theme="@style/Transparent"
             android:excludeFromRecents="true"
+            android:launchMode="singleTop"
+            android:taskAffinity=".wifi.NetworkRequestDialogActivity"
             android:exported="true"
             android:permission="android.permission.NETWORK_SETTINGS">
             <intent-filter>
@@ -2958,6 +2973,17 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name=".development.qstile.DevelopmentTiles$SensorsOff"
+            android:label="@string/sensors_off_quick_settings_title"
+            android:icon="@drawable/tile_icon_sensors_off"
+            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
+            android:enabled="false">
+            <intent-filter>
+                <action android:name="android.service.quicksettings.action.QS_TILE" />
+            </intent-filter>
+        </service>
+
         <activity
             android:name=".HelpTrampoline"
             android:exported="true"
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 7074481..7ab18a4 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -965,7 +965,7 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;homepage_about_background&quot;>#9FA8DA&lt;/color>"
+        errorLine1="    &lt;color name=&quot;homepage_about_background&quot;>#6F86DA&lt;/color>"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/colors.xml"
@@ -1317,6 +1317,230 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_icon_1&quot;>#48a50e0e&lt;/color> &lt;!-- 72% Material Red 900 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="144"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_icon_2&quot;>#480d652d&lt;/color> &lt;!-- 72% Material Green 900 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="145"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_icon_3&quot;>#48e37400&lt;/color> &lt;!-- 72% Material Yellow 900 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="146"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_icon_4&quot;>#48b06000&lt;/color> &lt;!-- 72% Material Orange 900 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="147"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_icon_5&quot;>#489c166b&lt;/color> &lt;!-- 72% Material Pink 900 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="148"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_icon_6&quot;>#48681da8&lt;/color> &lt;!-- 72% Material Purple 900 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="149"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_icon_7&quot;>#48007b83&lt;/color> &lt;!-- 72% Material Cyan 900 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="150"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_bg_1&quot;>#fad2cf&lt;/color> &lt;!-- Material Red 100 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="152"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_bg_2&quot;>#ceead6&lt;/color> &lt;!-- Material Green 100 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="153"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_bg_3&quot;>#feefc3&lt;/color> &lt;!-- Material Yellow 100 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="154"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_bg_4&quot;>#fedfc8&lt;/color> &lt;!-- Material Orange 100 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="155"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_bg_5&quot;>#fdcfe8&lt;/color> &lt;!-- Material Pink 100 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="156"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_bg_6&quot;>#e9d2fd&lt;/color> &lt;!-- Material Purple 100 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="157"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="    &lt;color name=&quot;bt_color_bg_7&quot;>#cbf0f8&lt;/color> &lt;!-- Material Cyan 100 -->"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/values/colors.xml"
+            line="158"
+            column="5"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="                android:background=&quot;@color/lock_pattern_background&quot; />"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2537,7 +2761,7 @@
         errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
         <location
             file="res/values/strings.xml"
-            line="6026"
+            line="6020"
             column="36"/>
     </issue>
 
diff --git a/res/color/circle_outline_color.xml b/res/color/circle_outline_color.xml
new file mode 100644
index 0000000..eb4e83c
--- /dev/null
+++ b/res/color/circle_outline_color.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:alpha="0.14"
+          android:color="?android:attr/colorForeground"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/circle_outline.xml b/res/drawable/circle_outline.xml
new file mode 100644
index 0000000..1b2631d
--- /dev/null
+++ b/res/drawable/circle_outline.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="oval">
+    <stroke
+        android:width="1dp"
+        android:color="@color/circle_outline_color"/>
+</shape>
diff --git a/res/drawable/face_enroll_introduction.xml b/res/drawable/face_enroll_introduction.xml
index 4493d66..6065f23 100644
--- a/res/drawable/face_enroll_introduction.xml
+++ b/res/drawable/face_enroll_introduction.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
   ~ Copyright (C) 2018 The Android Open Source Project
   ~
@@ -15,9 +16,29 @@
   -->
 
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="24dp"
-    android:width="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-    <path android:fillColor="#000" android:pathData="M9,11.75A1.25,1.25 0 0,0 7.75,13A1.25,1.25 0 0,0 9,14.25A1.25,1.25 0 0,0 10.25,13A1.25,1.25 0 0,0 9,11.75M15,11.75A1.25,1.25 0 0,0 13.75,13A1.25,1.25 0 0,0 15,14.25A1.25,1.25 0 0,0 16.25,13A1.25,1.25 0 0,0 15,11.75M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20C7.59,20 4,16.41 4,12C4,11.71 4,11.42 4.05,11.14C6.41,10.09 8.28,8.16 9.26,5.77C11.07,8.33 14.05,10 17.42,10C18.2,10 18.95,9.91 19.67,9.74C19.88,10.45 20,11.21 20,12C20,16.41 16.41,20 12,20Z" />
+    android:width="240dp"
+    android:height="240dp"
+    android:viewportWidth="300"
+    android:viewportHeight="300">
+
+    <path
+        android:fillColor="#DADCE0"
+        android:fillType="evenOdd"
+        android:pathData="M150,0C67.16,0,0,67.16,0,150s67.16,150,150,150 s150-67.16,150-150S232.84,0,150,0 M150,4c39,0,75.66,15.19,103.24,42.76C280.81,74.34,296,111,296,150s-15.19,75.66-42.76,103.24 C225.66,280.81,189,296,150,296s-75.66-15.19-103.24-42.76C19.19,225.66,4,189,4,150S19.19,74.34,46.76,46.76 C74.34,19.19,111,4,150,4" />
+    <path
+        android:fillColor="?android:attr/colorAccent"
+        android:fillType="evenOdd"
+        android:pathData="M220,120c0,5.52-4.48,10-10,10s-10-4.48-10-10 s4.48-10,10-10S220,114.48,220,120" />
+    <path
+        android:fillColor="?android:attr/colorAccent"
+        android:fillType="evenOdd"
+        android:pathData="M90,130c-5.52,0-10-4.48-10-10s4.48-10,10-10 s10,4.48,10,10S95.52,130,90,130" />
+    <path
+        android:fillColor="?android:attr/colorAccent"
+        android:fillType="evenOdd"
+        android:pathData="M164.2,215.88c-3.83,3.25-8.79,5.22-14.2,5.22 c-12.13,0-22-9.87-22-22c0-0.03,0-0.06,0-0.09l-8-0.03c0,0.04,0,0.08,0,0.13c0,6.24,1.9,12.03,5.16,16.83 c5.4,7.95,14.51,13.17,24.84,13.17c1.04,0,2.06-0.05,3.08-0.15c6.18-0.63,11.81-3.14,16.3-6.95L164.2,215.88z" />
+    <path
+        android:fillColor="?android:attr/colorAccent"
+        android:fillType="evenOdd"
+        android:pathData="M 153 140 L 153 166 L 137 166 L 137 174 L 161 174 L 161 140 Z" />
 </vector>
\ No newline at end of file
diff --git a/res/drawable/ic_face_enroll_introduction_detail.xml b/res/drawable/ic_face_enroll_introduction_detail.xml
new file mode 100644
index 0000000..7159148
--- /dev/null
+++ b/res/drawable/ic_face_enroll_introduction_detail.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:tint="?android:attr/colorControlNormal"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M0 0h24v24H0V0z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M11 15h2v2h-2zm0-8h2v6h-2zm0.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_gray_scale_24dp.xml b/res/drawable/ic_gray_scale_24dp.xml
new file mode 100644
index 0000000..3fda134
--- /dev/null
+++ b/res/drawable/ic_gray_scale_24dp.xml
@@ -0,0 +1,25 @@
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM11,19.93C7.06,19.44 4,16.08 4,12s3.05,-7.44 7,-7.93V19.93zM13,4.07C14.03,4.2 15,4.52 15.87,5H13V4.07zM13,7h5.24c0.25,0.31 0.48,0.65 0.68,1H13V7zM13,10h6.74c0.08,0.33 0.15,0.66 0.19,1H13V10zM13,19.93V19h2.87C15,19.48 14.03,19.8 13,19.93zM18.24,17H13v-1h5.92C18.72,16.35 18.49,16.69 18.24,17zM19.74,14H13v-1h6.93C19.89,13.34 19.82,13.67 19.74,14z"/>
+</vector>
+
diff --git a/res/drawable/ic_qrcode_24dp.xml b/res/drawable/ic_qrcode_24dp.xml
index ff7806f..6928cb9 100644
--- a/res/drawable/ic_qrcode_24dp.xml
+++ b/res/drawable/ic_qrcode_24dp.xml
@@ -2,7 +2,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorAccent">
   <path
       android:fillColor="#FF000000"
       android:pathData="M7,4v3H4V4H7M9,2H2v7h7V2L9,2z"/>
diff --git a/res/drawable/ic_scan_24dp.xml b/res/drawable/ic_scan_24dp.xml
index bcef8e3..c7b82d1 100644
--- a/res/drawable/ic_scan_24dp.xml
+++ b/res/drawable/ic_scan_24dp.xml
@@ -2,7 +2,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorAccent">
   <path
       android:fillColor="#FF000000"
       android:pathData="M9,2l-7,0l0,2l7,0l0,-2z"/>
diff --git a/res/drawable/tile_icon_sensors_off.xml b/res/drawable/tile_icon_sensors_off.xml
new file mode 100644
index 0000000..890fa83
--- /dev/null
+++ b/res/drawable/tile_icon_sensors_off.xml
@@ -0,0 +1,39 @@
+<!--
+     Copyright (C) 2019 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M21.966,2 L2,22"
+        android:strokeLineCap="round"
+        android:strokeColor="#000000"
+        android:fillColor="#00000000"
+        android:strokeWidth="1.6521436"
+        android:strokeLineJoin="miter"
+        android:strokeAlpha="1"/>
+    <path
+        android:pathData="M0.752,12L4.496,12l2.496,-6.25 2.496,12.5 2.496,-15 2.496,12.5 2.496,-7.5 1.248,3.75h4.992"
+        android:strokeLineCap="round"
+        android:strokeColor="#000000"
+        android:fillColor="#00000000"
+        android:strokeWidth="1.25090861"
+        android:strokeLineJoin="round"
+        android:strokeAlpha="1"/>
+</vector>
+
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
index 3a0e659..c408a97 100644
--- a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -60,10 +60,10 @@
                 android:id="@+id/error_message"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
                 android:textAlignment="center"
-                android:layout_marginTop="8dp"
-                android:visibility="invisible"
-                android:textColor="?android:attr/colorError"/>
+                android:textColor="?android:attr/colorError"
+                android:visibility="invisible"/>
 
         </LinearLayout>
 
diff --git a/res/layout/advanced_bt_entity_sub.xml b/res/layout/advanced_bt_entity_sub.xml
index 07ea814..0f30583 100644
--- a/res/layout/advanced_bt_entity_sub.xml
+++ b/res/layout/advanced_bt_entity_sub.xml
@@ -26,9 +26,11 @@
         android:id="@+id/header_icon"
         android:layout_width="72dp"
         android:layout_height="72dp"
-        android:scaleType="fitCenter"
         android:layout_gravity="center_horizontal"
-        android:antialias="true"/>
+        android:antialias="true"
+        android:background="@drawable/circle_outline"
+        android:padding="8dp"
+        android:scaleType="fitCenter"/>
 
     <TextView
         android:id="@+id/header_title"
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index b5f13db..b55041a 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -27,7 +27,7 @@
     <LinearLayout
         style="@style/SudContentFrame"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
         android:clipChildren="false"
         android:clipToPadding="false"
         android:orientation="vertical">
@@ -45,50 +45,87 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
 
-        <com.google.android.setupdesign.view.FillContentLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_weight="1">
-
-            <com.google.android.setupdesign.view.IllustrationVideoView
-                xmlns:android="http://schemas.android.com/apk/res/android"
-                xmlns:app="http://schemas.android.com/apk/res-auto"
-                android:id="@+id/face_enroll_introduction_animation"
-                style="@style/SudContentIllustration"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                app:sudVideo="@raw/face_enroll_introduction_animation" />
-
-        </com.google.android.setupdesign.view.FillContentLayout>
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"/>
 
         <FrameLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center">
-            <Button
-                android:id="@+id/accessibility_button"
-                style="@style/SudGlifButton.Secondary"
-                android:layout_gravity="center"
+            android:layout_height="wrap_content">
+
+            <com.google.android.setupdesign.view.IllustrationVideoView
+                android:id="@+id/illustration_normal"
+                style="@style/SudContentIllustration"
+                android:layout_width="240dp"
+                android:layout_height="240dp"
+                app:sudVideo="@raw/face_enroll_introduction_animation" />
+
+            <ImageView
+                android:id="@+id/illustration_accessibility"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:text="@string/security_settings_face_enroll_introduction_accessibility" />
-
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
                 android:layout_gravity="center"
-                android:id="@+id/accessibility_layout"
-                android:orientation="vertical"
-                android:visibility="invisible">
+                android:visibility="invisible"
+                android:background="@drawable/face_enroll_introduction" />
+
+        </FrameLayout>
+
+        <Space
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="2"/>
+
+        <!-- Contains the buttons and extra information text at the bottom -->
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:layout_gravity="center_horizontal|bottom">
+
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <Button
+                    android:id="@+id/accessibility_button"
+                    style="@style/SudGlifButton.Secondary"
+                    android:layout_gravity="center"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/security_settings_face_enroll_introduction_accessibility" />
 
                 <com.android.settings.biometrics.face.FaceEnrollAccessibilityToggle
                     android:id="@+id/toggle_diversity"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
+                    android:visibility="invisible"
                     FaceEnrollAccessibilitySwitch:messageText="@string/security_settings_face_enroll_introduction_accessibility_diversity"/>
 
+            </FrameLayout>
+
+            <LinearLayout
+                android:id="@+id/footer_layout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp">
+
+                <ImageView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/ic_face_enroll_introduction_detail">
+                </ImageView>
+                <Space
+                    android:layout_width="8dp"
+                    android:layout_height="wrap_content" />
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:text="@string/security_settings_face_enroll_introduction_footer_message"/>
             </LinearLayout>
-        </FrameLayout>
+
+        </LinearLayout>
 
     </LinearLayout>
 
diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml
index e95129e..ca8791f 100644
--- a/res/layout/homepage_slice_tile.xml
+++ b/res/layout/homepage_slice_tile.xml
@@ -31,7 +31,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
-            android:animateLayoutChanges="true"
+            android:importantForAccessibility="no"
             style="@style/SliceViewStyle"/>
 
         <!--dismissal view-->
diff --git a/res/layout/manage_applications_apps.xml b/res/layout/manage_applications_apps.xml
index 87db820..9c90f02 100644
--- a/res/layout/manage_applications_apps.xml
+++ b/res/layout/manage_applications_apps.xml
@@ -26,41 +26,34 @@
         android:layout_height="match_parent"
         settings:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
 
-        <LinearLayout
+        <FrameLayout
             android:id="@+id/list_container"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:orientation="vertical"
             android:visibility="gone">
 
-            <FrameLayout
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/apps_list"
                 android:layout_width="match_parent"
-                android:layout_height="match_parent">
+                android:layout_height="match_parent"
+                android:clipToPadding="false"
+                settings:fastScrollEnabled="true"
+                settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
+                settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
+                settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
+                settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
 
-                <androidx.recyclerview.widget.RecyclerView
-                    android:id="@+id/apps_list"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:clipToPadding="false"
-                    settings:fastScrollEnabled="true"
-                    settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
-                    settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
-                    settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
-                    settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
+            <TextView
+                android:id="@android:id/empty"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:gravity="center"
+                android:layout_gravity="center"
+                android:text="@string/no_applications"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:visibility="invisible"/>
 
-                <TextView
-                    android:id="@android:id/empty"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:gravity="center"
-                    android:layout_gravity="center"
-                    android:text="@string/no_applications"
-                    android:textAppearance="?android:attr/textAppearanceLarge"
-                    android:visibility="invisible"/>
-
-            </FrameLayout>
-
-        </LinearLayout>
+        </FrameLayout>
 
         <include layout="@layout/loading_container"/>
 
diff --git a/res/layout/master_clear.xml b/res/layout/master_clear.xml
index 9c1dd80..6368588 100644
--- a/res/layout/master_clear.xml
+++ b/res/layout/master_clear.xml
@@ -127,12 +127,9 @@
                         android:text="@string/erase_external_storage_description"/>
                 </LinearLayout>
             </LinearLayout>
-            <include
-                layout="@layout/reset_esim_checkbox"
-                android:layout_marginTop="40dp"
-                android:id="@+id/erase_esim_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"/>
+
+            <include layout="@layout/reset_esim_checkbox"/>
+
         </LinearLayout>
     </ScrollView>
 </com.google.android.setupdesign.GlifLayout>
diff --git a/res/layout/network_request_dialog_title.xml b/res/layout/network_request_dialog_title.xml
index f643e0f..b61a7db 100644
--- a/res/layout/network_request_dialog_title.xml
+++ b/res/layout/network_request_dialog_title.xml
@@ -25,14 +25,12 @@
   <TextView
       android:id="@+id/network_request_title_text"
       android:layout_width="0dp"
-      android:layout_height="match_parent"
+      android:layout_height="wrap_content"
       android:paddingLeft="24dp"
       android:paddingTop="18dp"
       android:layout_weight="1"
       android:textSize="18sp"
       android:gravity="center_vertical"
-      android:maxLines="1"
-      android:ellipsize="end"
       style="@style/info_label"/>
 
   <ProgressBar
diff --git a/res/layout/reset_esim_checkbox.xml b/res/layout/reset_esim_checkbox.xml
index 2195435..77b90a1 100644
--- a/res/layout/reset_esim_checkbox.xml
+++ b/res/layout/reset_esim_checkbox.xml
@@ -15,7 +15,9 @@
 -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/erase_esim_container"
     style="@style/SudDescription"
+    android:layout_marginTop="40dp"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
@@ -41,10 +43,10 @@
         android:orientation="vertical">
 
         <TextView
-            android:id="@+id/erase_esim_title"
             style="@style/TextAppearance.SudGlifItemTitle"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content"/>
+            android:layout_height="wrap_content"
+            android:text="@string/reset_esim_title"/>
 
         <TextView
             style="@style/TextAppearance.SudGlifItemSummary"
diff --git a/res/layout/reset_network.xml b/res/layout/reset_network.xml
index 7eb5d2a..2c31d1a 100644
--- a/res/layout/reset_network.xml
+++ b/res/layout/reset_network.xml
@@ -40,10 +40,7 @@
                 android:textDirection="locale"
                 android:text="@string/reset_network_desc" />
 
-            <include layout="@layout/reset_esim_checkbox"
-                android:id="@+id/erase_esim_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
+            <include layout="@layout/reset_esim_checkbox"/>
 
         </LinearLayout>
 
diff --git a/res/layout/settings_homepage.xml b/res/layout/settings_homepage.xml
index e04b372..6e2b302 100644
--- a/res/layout/settings_homepage.xml
+++ b/res/layout/settings_homepage.xml
@@ -21,7 +21,7 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <androidx.recyclerview.widget.RecyclerView
+    <com.android.settings.homepage.contextualcards.FocusRecyclerView
         android:id="@+id/card_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/res/layout/settings_homepage_container.xml b/res/layout/settings_homepage_container.xml
index 78a0278..9332463 100644
--- a/res/layout/settings_homepage_container.xml
+++ b/res/layout/settings_homepage_container.xml
@@ -25,6 +25,7 @@
         android:id="@+id/main_content_scrollable_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+        android:importantForAccessibility="no"
         app:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
 
         <LinearLayout
diff --git a/res/layout/slice_preference_layout.xml b/res/layout/slice_preference_layout.xml
index ae58901..4cea9c0 100644
--- a/res/layout/slice_preference_layout.xml
+++ b/res/layout/slice_preference_layout.xml
@@ -25,5 +25,5 @@
     <androidx.slice.widget.SliceView
         android:id="@+id/slice_view"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/slice_preference_group_height"/>
+        android:layout_height="wrap_content"/>
 </FrameLayout>
diff --git a/res/layout/time_zone_search_header.xml b/res/layout/time_zone_search_header.xml
new file mode 100644
index 0000000..5c4e0ee
--- /dev/null
+++ b/res/layout/time_zone_search_header.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<!-- similar to preference_material.xml but textview for emoji country flag
+instead of an ImageView -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:id="@+android:id/title"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:layout_marginBottom="16dp"
+          android:layout_marginTop="16dp"
+          android:textAppearance="@style/TextAppearance.CategoryTitle"
+          android:textColor="?android:attr/colorAccent"
+          android:paddingStart="@dimen/preference_no_icon_padding_start"/>
diff --git a/res/layout/wifi_button_preference_widget.xml b/res/layout/wifi_button_preference_widget.xml
index 0999d20..4b004e3 100644
--- a/res/layout/wifi_button_preference_widget.xml
+++ b/res/layout/wifi_button_preference_widget.xml
@@ -22,5 +22,4 @@
            android:minWidth="@dimen/min_tap_target_size"
            android:minHeight="@dimen/min_tap_target_size"
            android:layout_gravity="center"
-           android:background="@null"
-           android:visibility="gone"/>
+           android:background="?android:attr/selectableItemBackground"/>
diff --git a/res/layout/wifi_dialog.xml b/res/layout/wifi_dialog.xml
index 333296c..d5dbb17 100644
--- a/res/layout/wifi_dialog.xml
+++ b/res/layout/wifi_dialog.xml
@@ -50,29 +50,31 @@
                         android:text="@string/wifi_ssid"
                         android:textDirection="locale" />
 
-                <RelativeLayout
+                <androidx.constraintlayout.widget.ConstraintLayout
+                        xmlns:app="http://schemas.android.com/apk/res-auto"
                         android:layout_width="match_parent"
-                        android:layout_height="wrap_content" >
+                        android:layout_height="wrap_content">
                     <EditText android:id="@+id/ssid"
-                            android:layout_width="match_parent"
+                            android:layout_width="0dp"
                             android:layout_height="wrap_content"
-                            android:layout_alignParentStart="true"
+                            app:layout_constraintStart_toStartOf="parent"
+                            app:layout_constraintEnd_toStartOf="@+id/ssid_scanner_button"
                             style="@style/wifi_item_edit_content"
                             android:hint="@string/wifi_ssid_hint"
                             android:singleLine="true"
-                            android:inputType="textNoSuggestions" />
+                            android:inputType="textNoSuggestions"/>
+
                     <ImageButton
                         android:id="@+id/ssid_scanner_button"
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:minWidth="@dimen/min_tap_target_size"
                         android:minHeight="@dimen/min_tap_target_size"
-                        android:layout_alignParentEnd="true"
-                        android:layout_centerVertical="true"
-                        android:background="@null"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        android:background="?android:attr/selectableItemBackground"
                         android:src="@drawable/ic_scan_24dp"
                         android:contentDescription="@string/wifi_dpp_scan_qr_code"/>
-                </RelativeLayout>
+                </androidx.constraintlayout.widget.ConstraintLayout>
 
                 <LinearLayout android:id="@+id/ssid_too_long_warning"
                               android:layout_width="match_parent"
@@ -286,16 +288,18 @@
                         style="@style/wifi_item_label"
                         android:text="@string/wifi_password" />
 
-                <RelativeLayout
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    xmlns:app="http://schemas.android.com/apk/res-auto"
                     android:layout_width="match_parent"
-                    android:layout_height="wrap_content" >
+                    android:layout_height="wrap_content">
                     <EditText android:id="@+id/password"
-                              android:layout_width="match_parent"
+                              android:layout_width="0dp"
                               android:layout_height="wrap_content"
-                              android:layout_alignParentStart="true"
+                              app:layout_constraintStart_toStartOf="parent"
+                              app:layout_constraintEnd_toStartOf="@+id/password_scanner_button"
                               style="@style/wifi_item_edit_content"
                               android:singleLine="true"
-                              android:password="true" />
+                              android:password="true"/>
 
                     <ImageButton
                         android:id="@+id/password_scanner_button"
@@ -303,12 +307,11 @@
                         android:layout_height="wrap_content"
                         android:minWidth="@dimen/min_tap_target_size"
                         android:minHeight="@dimen/min_tap_target_size"
-                        android:layout_alignParentEnd="true"
-                        android:layout_centerVertical="true"
-                        android:background="@null"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        android:background="?android:attr/selectableItemBackground"
                         android:src="@drawable/ic_scan_24dp"
                         android:contentDescription="@string/wifi_dpp_scan_qr_code"/>
-                </RelativeLayout>
+                </androidx.constraintlayout.widget.ConstraintLayout>
             </LinearLayout>
 
             <LinearLayout android:id="@+id/show_password_layout"
diff --git a/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
index ed288f0..3606ccd 100644
--- a/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
+++ b/res/layout/wifi_dpp_choose_saved_wifi_network_fragment.xml
@@ -22,28 +22,24 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <ScrollView
+    <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="0dp"
+        android:gravity="center_horizontal"
+        android:orientation="vertical"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@+id/footer">
 
-        <LinearLayout
+        <include layout="@layout/wifi_dpp_fragment_header"/>
+
+        <LinearLayout android:id="@+id/wifi_network_list_container"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="center_horizontal"
-            android:orientation="vertical">
+            android:layout_height="wrap_content"/>
 
-            <include layout="@layout/wifi_dpp_fragment_header"/>
-
-            <LinearLayout android:id="@+id/wifi_network_list_container"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                app:layout_constraintTop_toBottomOf="@+id/header"/>
-
-        </LinearLayout>
-
-    </ScrollView>
+    </LinearLayout>
 
     <include
+        android:id="@+id/footer"
         layout="@layout/wifi_dpp_fragment_footer"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
diff --git a/res/layout/wifi_dpp_qrcode_generator_fragment.xml b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
index 2617aea..31bf7cc 100644
--- a/res/layout/wifi_dpp_qrcode_generator_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
@@ -40,6 +40,14 @@
                 android:layout_height="@dimen/qrcode_size"
                 android:src="@android:color/transparent"/>
 
+            <TextView
+                android:id="@+id/password"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
+                android:textAlignment="center"
+                android:textAppearance="@android:style/TextAppearance.Material.Body1"
+                android:textColor="?android:attr/textColorSecondary"/>
         </LinearLayout>
 
     </ScrollView>
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 4fa8e8b..9bd742a 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -60,10 +60,10 @@
                 android:id="@+id/error_message"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
                 android:textAlignment="center"
-                android:layout_marginTop="8dp"
-                android:visibility="invisible"
-                android:textColor="?android:attr/colorError"/>
+                android:textColor="?android:attr/colorError"
+                android:visibility="invisible"/>
 
         </LinearLayout>
 
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 7e0ba10..521d709 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1378,4 +1378,25 @@
          <item>@string/wifi_calling_mode_cellular_preferred_summary</item>
     </string-array>
 
+    <!-- Bluetooth icon foreground colors -->
+    <integer-array name="bt_icon_fg_colors">
+        <item>@color/bt_color_icon_1</item>
+        <item>@color/bt_color_icon_2</item>
+        <item>@color/bt_color_icon_3</item>
+        <item>@color/bt_color_icon_4</item>
+        <item>@color/bt_color_icon_5</item>
+        <item>@color/bt_color_icon_6</item>
+        <item>@color/bt_color_icon_7</item>
+    </integer-array>
+
+    <!-- Bluetooth icon background colors -->
+    <integer-array name="bt_icon_bg_colors">
+        <item>@color/bt_color_bg_1</item>
+        <item>@color/bt_color_bg_2</item>
+        <item>@color/bt_color_bg_3</item>
+        <item>@color/bt_color_bg_4</item>
+        <item>@color/bt_color_bg_5</item>
+        <item>@color/bt_color_bg_6</item>
+        <item>@color/bt_color_bg_7</item>
+    </integer-array>
 </resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0afd288..59ed4c4 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -96,7 +96,7 @@
     <color name="homepage_support_background">#26459C</color>
     <color name="homepage_generic_icon_background">#1A73E8</color>
     <color name="homepage_location_background">#2EC7DC</color>
-    <color name="homepage_about_background">#9FA8DA</color>
+    <color name="homepage_about_background">#6F86DA</color>
     <color name="homepage_privacy_background">#5E97F6</color>
 
     <color name="homepage_card_stroke_color">#1f000000</color>
@@ -140,4 +140,20 @@
     <color name="qr_focused_corner_line_color">#ff1a73e8</color>
     <color name="qr_background_color">#b3ffffff</color> <!-- 70% white transparency -->
     <!-- End of QR code scanner colors -->
+
+    <color name="bt_color_icon_1">#48a50e0e</color> <!-- 72% Material Red 900 -->
+    <color name="bt_color_icon_2">#480d652d</color> <!-- 72% Material Green 900 -->
+    <color name="bt_color_icon_3">#48e37400</color> <!-- 72% Material Yellow 900 -->
+    <color name="bt_color_icon_4">#48b06000</color> <!-- 72% Material Orange 900 -->
+    <color name="bt_color_icon_5">#489c166b</color> <!-- 72% Material Pink 900 -->
+    <color name="bt_color_icon_6">#48681da8</color> <!-- 72% Material Purple 900 -->
+    <color name="bt_color_icon_7">#48007b83</color> <!-- 72% Material Cyan 900 -->
+
+    <color name="bt_color_bg_1">#fad2cf</color> <!-- Material Red 100 -->
+    <color name="bt_color_bg_2">#ceead6</color> <!-- Material Green 100 -->
+    <color name="bt_color_bg_3">#feefc3</color> <!-- Material Yellow 100 -->
+    <color name="bt_color_bg_4">#fedfc8</color> <!-- Material Orange 100 -->
+    <color name="bt_color_bg_5">#fdcfe8</color> <!-- Material Pink 100 -->
+    <color name="bt_color_bg_6">#e9d2fd</color> <!-- Material Purple 100 -->
+    <color name="bt_color_bg_7">#cbf0f8</color> <!-- Material Cyan 100 -->
 </resources>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index e6ada66..805469a 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -356,4 +356,7 @@
 
     <!-- Slice Uri to query nearby devices. -->
     <string name="config_nearby_devices_slice_uri" translatable="false">content://com.google.android.gms.nearby.fastpair/device_status_list_item</string>
+
+    <!-- Grayscale settings intent -->
+    <string name="config_grayscale_settings_intent" translate="false"></string>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f5b6e95..248fb81 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -392,7 +392,7 @@
     <dimen name="homepage_condition_header_indicator_padding_top">4dp</dimen>
     <dimen name="homepage_condition_header_indicator_padding_start">16dp</dimen>
     <dimen name="homepage_condition_header_indicator_padding_end">16dp</dimen>
-    <dimen name="homepage_condition_footer_height">44dp</dimen>
+    <dimen name="homepage_condition_footer_height">48dp</dimen>
     <dimen name="homepage_condition_footer_padding_top">10dp</dimen>
     <dimen name="homepage_condition_footer_padding_end">10dp</dimen>
     <dimen name="homepage_condition_header_icon_width_height">24dp</dimen>
@@ -404,7 +404,4 @@
 
     <!-- Wi-Fi DPP fragment icon size -->
     <dimen name="wifi_dpp_fragment_icon_width_height">48dp</dimen>
-
-    <!-- Height for slice preference, which contains 6 items at most -->
-    <dimen name="slice_preference_group_height">360dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index aa43f12..069da2a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -898,8 +898,10 @@
     <string name="security_settings_face_enroll_introduction_message">Use your face to unlock your phone, authorize purchases, or sign in to apps.</string>
     <!-- Introduction detail message shown in face enrollment dialog, when face unlock is disabled by device admin [CHAR LIMIT=NONE] -->
     <string name="security_settings_face_enroll_introduction_message_unlock_disabled">Use your face to unlock your phone or approve purchases.\n\nNote: You can\u2019t use your face to unlock this device. For more information, contact your organization\u2019s admin.</string>
-    <!-- Introduction detail message shwon in face enrollment screen in setup wizard. [CHAR LIMIT=NONE] -->
+    <!-- Introduction detail message shown in face enrollment screen in setup wizard. [CHAR LIMIT=NONE] -->
     <string name="security_settings_face_enroll_introduction_message_setup">Use your face to unlock your phone, authorize purchases, or sign in to apps</string>
+    <!-- Introduction detail message shown in face enrollment that provides extra detais. [CHAR LIMIT=NONE] -->
+    <string name="security_settings_face_enroll_introduction_footer_message"></string>
     <!-- Title shown in face enrollment dialog [CHAR LIMIT=40] -->
     <string name="security_settings_face_enroll_repeat_title">Center your face in the circle</string>
     <!-- Button text to skip enrollment of face [CHAR LIMIT=40] -->
@@ -941,6 +943,11 @@
     <!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
     <string name="security_settings_face_settings_footer">Your face can be used to unlock your device and access apps.
         <annotation id="url">Learn more</annotation></string>
+    <!-- Dialog title shown when the user removes an enrollment [CHAR LIMIT=35] -->
+    <string name="security_settings_face_settings_remove_dialog_title">Delete face data?</string>
+    <!-- Dialog contents shown when the user removes an enrollment [CHAR LIMIT=NONE] -->
+    <string name="security_settings_face_settings_remove_dialog_details">Data recorded by face unlock will be permanently and securely deleted. After removal, you will need your PIN, pattern, or password to unlock your phone, sign in to apps, and confirm payments.</string>
+
 
     <!-- Fingerprint enrollment and settings --><skip />
     <!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
@@ -1577,6 +1584,9 @@
     <!-- Label for ChoosePassword/PIN Clear button that clears all text entered by the user so far. -->
     <string name="lockpassword_clear_label">Clear</string>
 
+    <!-- Toast for a failed password change attempt when the old credential has been changed. [CHAR LIMIT=120]-->
+    <string name="lockpassword_credential_changed">Screen lock was already changed. Try again with the new screen lock.</string>
+
     <!-- Label for LockPatternTutorial Cancel button -->
     <string name="lockpattern_tutorial_cancel_label">Cancel</string>
 
@@ -2122,7 +2132,9 @@
     <!-- Title for the fragment to share Wi-Fi [CHAR LIMIT=50]  -->
     <string name="wifi_dpp_share_wifi">Share Wi\u2011Fi</string>
     <!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
-    <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code with another device to join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+    <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code to connect to \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d and share the password</string>
+    <!-- Hint for the user to use another device to scan QR code on screen to join a open Wi-Fi [CHAR LIMIT=NONE] -->
+    <string name="wifi_dpp_scan_open_network_qr_code_with_another_device">Scan this QR code to connect to \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
     <!-- Hint for QR code detection [CHAR LIMIT=NONE]  -->
     <string name="wifi_dpp_could_not_detect_valid_qr_code">Couldn\u2019t read QR code. Re-center code and try again</string>
     <!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE]  -->
@@ -2159,8 +2171,16 @@
     <string name="wifi_dpp_connecting">Connecting\u2026</string>
     <!-- Title for the fragment to show that the QR code is for sharing Wi-Fi hotspot network [CHAR LIMIT=50] -->
     <string name="wifi_dpp_share_hotspot">Share hotspot</string>
-    <!-- Hint for the user to share Wi-Fi hotspot network [CHAR LIMIT=NONE] -->
-    <string name="wifi_dpp_scan_qr_code_to_share_hotspot">Scan this QR code with another device to join hotspot \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+    <!-- Title for Wi-Fi DPP lockscreen title [CHAR LIMIT=50] -->
+    <string name="wifi_dpp_lockscreen_title">Verify it\u0027s you</string>
+    <!-- Hint for Wi-Fi password [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_wifi_password">Wi\u2011Fi password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
+    <!-- Hint for Wi-Fi hotspot password [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_hotspot_password">Hotspot password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
+    <!-- Label for "Connect to this network using a QR code" [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_add_device">Add device</string>
+    <!-- Hint for "Add device" [CHAR LIMIT=NONE]  -->
+    <string name="wifi_dpp_connect_network_using_qr_code">Connect to this network using a QR code</string>
      <!-- Label for the try again button [CHAR LIMIT=20]-->
     <string name="retry">Retry</string>
     <!-- Label for the check box to share a network with other users on the same device -->
@@ -2213,6 +2233,8 @@
 
     <!-- Dialog text to tell the user that the selected network does not have Internet access. -->
     <string name="no_internet_access_text">This network has no internet access. Stay connected?</string>
+    <!-- Dialog text to tell the user that the selected network has incomplete Internet access. [CHAR LIMIT=100] -->
+    <string name="partial_connectivity_text">Some apps and services may not work due to limited connectivity. Use anyway?</string>
     <string name="no_internet_access_remember">Don\u2019t ask again for this network</string>
 
     <!-- Dialog text to tell the user that the selected network has lost Internet access, and asking the user whether they want to avoid this network. -->
@@ -2235,6 +2257,8 @@
     <string name="wifi_disconnect">@string/bluetooth_device_context_disconnect</string>
     <!-- Failured notification for connect -->
     <string name="wifi_failed_connect_message">Failed to connect to network</string>
+    <!-- Not in range notification for connect [CHAR LIMIT=40] -->
+    <string name="wifi_not_in_range_message">Network not in range</string>
     <!-- Button label to delete a Wi-Fi network -->
     <string name="wifi_forget">Forget</string>
     <!-- Button label to modify a Wi-Fi network -->
@@ -2986,6 +3010,8 @@
     <string name="device_status_summary" product="default">Phone number, signal, etc.</string>
     <!-- Main settings screen item's title to go into the storage settings screen [CHAR LIMIT=25] -->
     <string name="storage_settings" >Storage</string>
+    <!-- Settings title that shows user how much storage and cache space an App is taking [CHAR LIMIT=50] -->
+    <string name="storage_settings_for_app" >Storage &amp; cache</string>
     <!-- Main settings screen item's title to go into the storage & USB settings screen [CHAR LIMIT=25] -->
     <string name="storage_usb_settings" >Storage</string>
     <!-- Storage settings screen title -->
@@ -3581,10 +3607,10 @@
     <string name="reset_network_title">Reset Wi-Fi, mobile &amp; Bluetooth</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Reset network settings [CHAR LIMIT=NONE] -->
     <string name="reset_network_desc">This will reset all network settings, including:\n\n<li>Wi\u2011Fi</li>\n<li>Mobile data</li>\n<li>Bluetooth</li>"</string>
-    <!-- SD card & phone storage settings screen, title for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
-    <string name="reset_esim_title">Also reset eSIM</string>
+    <!-- SD card & phone storage settings screen, title for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=30] -->
+    <string name="reset_esim_title">Erase eSIMs</string>
     <!-- SD card & phone storage settings screen, message for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
-    <string name="reset_esim_desc">Erase all eSIMs on the phone. You\u2019ll have to contact your carrier to redownload your eSIMs. This will not cancel your mobile service plan.</string>
+    <string name="reset_esim_desc">You\u2019ll have to contact your carrier to download replacement eSIMs. This won\u2019t cancel any mobile service plans.</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Reset network settings -->
     <string name="reset_network_button_text">Reset settings</string>
     <!-- SD card & phone storage settings screen, message on screen after user selects Reset settings button -->
@@ -3633,12 +3659,6 @@
     <string name="erase_external_storage_description" product="nosdcard">Erase all the data on the internal USB storage, such as music or photos</string>
     <!-- SD card & phone storage settings screen, description for check box to erase USB storage [CHAR LIMIT=NONE] -->
     <string name="erase_external_storage_description" product="default">Erase all the data on the SD card, such as music or photos</string>
-    <!-- SD card & phone storage settings screen, label for check box to erase all the carriers information on the embedded SIM card [CHAR LIMIT=30] -->
-    <string name="erase_esim_storage">Erase eSIM</string>
-    <!-- SD card & phone storage settings screen, description for check box to erase eSIMs for default devices [CHAR LIMIT=NONE] -->
-    <string name="erase_esim_storage_description" product="default">Erase all eSIMs on the phone. This will not cancel your mobile service plan.</string>
-    <!-- SD card & phone storage settings screen, description for check box to erase eSIMs for tablets [CHAR LIMIT=NONE] -->
-    <string name="erase_esim_storage_description" product="tablet">Erase all eSIMs on the tablet. This will not cancel your mobile service plan.</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
     <string name="master_clear_button_text" product="tablet">Erase all data</string>
     <!-- SD card & phone storage settings screen, button on screen after user selects Factory data reset -->
@@ -3938,8 +3958,6 @@
     <string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
     <!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
     <string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
-    <!-- Message on Wi-Fi Sharing screen [CHAR LIMIT=NONE] -->
-    <string name="wifi_sharing_message">Your Wi\u2011Fi name and password for \"<xliff:g id="SSID" example="GoogleGuest">%1$s</xliff:g>\" will be shared.</string>
 
     <!-- Message to be used to explain the user that he needs to enter his pattern to continue a
          particular operation. [CHAR LIMIT=70]-->
@@ -4189,6 +4207,8 @@
     <string name="uninstall_all_users_text">Uninstall for all users</string>
     <!-- [CHAR LIMIT=NONE] Manage applications, individual application info screen, button label under Storage heading. Button to install an application for the user. -->
     <string name="install_text">Install</string>
+    <!-- [CHAR LIMIT=25] Manage applications, individual application info screen, button label under Storage heading. Button to disable an existing application. -->
+    <string name="disable_text">Disable</string>
     <!-- [CHAR LIMIT=25] Manage applications, individual application info screen, button label under Storage heading. Button to re-enable an existing application. -->
     <string name="enable_text">Enable</string>
     <!-- Manage applications, individual application info screen, button label under Storage heading. Button to clear all data associated with tis app (for example, remove all cached emails for an Email app) -->
@@ -4327,9 +4347,9 @@
     <!-- Manage applications. application installation location summary -->
     <string name="app_install_location_summary">Change the preferred installation location for new apps</string>
     <!-- [CHAR LIMIT=30] Manage applications, label for option to disable app -->
-    <string name="app_disable_dlg_positive">Uninstall app</string>
-    <!-- [CHAR LIMIT=200] Manage applications, text for dialog when disabling apps -->
-    <string name="app_disable_dlg_text">If you uninstall this app, Android and other apps may no longer function as intended.</string>
+    <string name="app_disable_dlg_positive">Disable app</string>
+    <!-- [CHAR LIMIT=NONE] Manage applications, text for dialog when disabling apps -->
+    <string name="app_disable_dlg_text">If you disable this app, Android and other apps may no longer function as intended. Keep in mind, you can\u2019t delete this app since it came pre-installed on your device. By disabling, you turn this app off and hide it on your device.</string>
     <!-- [CHAR LIMIT=30] Manage applications, title for dialog when disabling notifications for an app -->
     <string name="app_disable_notifications_dlg_title">Turn off notifications?</string>
     <!-- Manage applications, individual application info screen, section heading for information about the app installer [CHAR_LIMIT=25] -->
@@ -4531,8 +4551,8 @@
     <string name="keyboard_shortcuts_helper">Keyboard shortcuts helper</string>
     <!-- Summary text for the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=100] -->
     <string name="keyboard_shortcuts_helper_summary">Display available shortcuts</string>
-    <!-- Title for the 'Work profile input & assistance' preference category inside Languages and inputs'. [CHAR LIMIT=50] -->
-    <string name="language_and_input_for_work_category_title">Work profile input &amp; assistance</string>
+    <!-- Title for the 'Work profile keyboards & tools' preference category inside Languages and inputs'. [CHAR LIMIT=50] -->
+    <string name="language_and_input_for_work_category_title">Work profile keyboards &amp; tools</string>
     <!-- Title for the 'Virtual keyboards for work' preference. [CHAR LIMIT=45] -->
     <string name="virtual_keyboards_for_work_title">Virtual keyboard for work</string>
 
@@ -5259,11 +5279,13 @@
     <!-- Summary for the battery high usage tip, which presents battery may run out earlier [CHAR LIMIT=NONE] -->
     <string name="battery_tip_high_usage_summary">Battery may run out earlier than usual</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dialog_message" product="default">Your phone has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+    <string name="battery_tip_dialog_message" product="default">Your phone has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dialog_message" product="tablet">Your tablet has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+    <string name="battery_tip_dialog_message" product="tablet">Your tablet has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dialog_message" product="device">Your device has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+    <string name="battery_tip_dialog_message" product="device">Your device has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
+    <!-- Footer message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
+    <string name="battery_tip_dialog_message_footer">Includes high-power background activity</string>
     <!-- Title for restricted app preference, showing how many app need to be restricted [CHAR LIMIT=NONE] -->
     <plurals name="battery_tip_restrict_title">
         <item quantity="one">Restrict %1$d app</item>
@@ -7056,7 +7078,7 @@
     handle actions such as open web page, making phone calls, default SMS apps [CHAR  LIMIT=40]-->
     <string name="app_default_dashboard_title">Default apps</string>
     <!-- Summary text for system preference tile, showing important setting items under system setting [CHAR LIMIT=NONE]-->
-    <string name="system_dashboard_summary">Languages, time, backup, updates</string>
+    <string name="system_dashboard_summary">Languages, gestures, time, backup</string>
 
     <!-- Search strings -->
     <!-- Text to describe the search results fragment title [CHAR LIMIT=16] -->
@@ -7158,7 +7180,7 @@
     <string name="keywords_screen_timeout">screen, lock time, timeout, lockscreen</string>
 
     <!-- List of synonyms for Storage settings (everything related to storage on the device), used to match in settings search [CHAR LIMIT=NONE] -->
-    <string name="keywords_storage_settings">memory, data, delete, clear, free, space</string>
+    <string name="keywords_storage_settings">memory, cache, data, delete, clear, free, space</string>
 
     <!-- List of synonyms for the Bluetooth setting, used to match in settings search [CHAR LIMIT=NONE] -->
     <string name="keywords_bluetooth_settings">connected, device, headphones, headset, speaker, wireless, pair, earbuds, music, media </string>
@@ -7675,6 +7697,18 @@
     <string name="profile_section_header">Work notifications</string>
 
     <!-- Configure Notifications: setting title [CHAR LIMIT=80] -->
+    <string name="asst_capability_prioritizer_title">Automatic Notification Prioritizer</string>
+
+    <!-- Configure Notifications: setting summary [CHAR LIMIT=200] -->
+    <string name="asst_capability_prioritizer_summary">Automatically silence and demote less important notifications</string>
+
+    <!-- Configure Notifications: setting title [CHAR LIMIT=80] -->
+    <string name="asst_capabilities_actions_replies_title">Smart actions and replies</string>
+
+    <!-- Configure Notifications: setting summary [CHAR LIMIT=200] -->
+    <string name="asst_capabilities_actions_replies_summary">Automatically add contextual notification actions and quick replies to notifications</string>
+
+    <!-- Configure Notifications: setting title [CHAR LIMIT=80] -->
     <string name="hide_silent_icons_title">Hide silent notification status icons</string>
 
     <!-- Configure Notifications: setting summary [CHAR LIMIT=NONE] -->
@@ -7684,7 +7718,23 @@
     <string name="notification_badging_title">Allow notification dots</string>
 
     <!-- Configure Notifications: Title for the notification bubbles option. [CHAR LIMIT=60] -->
-    <string name="notification_bubbles_title">Allow notification bubbles</string>
+    <string name="notification_bubbles_title">Allow bubbles</string>
+    <!-- Configure Notifications: Summary for the notification bubbles option. [CHAR LIMIT=NONE] -->
+    <string name="notification_bubbles_summary">Allow apps to show some notifications as bubbles</string>
+    <!-- Feature education for bubbles. [CHAR LIMIT=NONE] -->
+    <string name="bubbles_feature_education">Some notifications and other content can appear as bubbles on the screen. To open a bubble, tap it. To dismiss it, drag it down the screen.</string>
+    <!-- Title for the toggle shown on the app-level bubbles page  [CHAR LIMIT=60] -->
+    <string name="bubbles_app_toggle_title">Bubbles</string>
+    <!-- Description for the toggle shown on the app-level bubbles page  [CHAR LIMIT=NONE] -->
+    <string name="bubbles_app_toggle_summary">Allow <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> to show some notifications as bubbles</string>
+    <!-- Title of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=NONE] -->
+    <string name="bubbles_feature_disabled_dialog_title">Turn on bubbles</string>
+    <!-- Description of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=NONE] -->
+    <string name="bubbles_feature_disabled_dialog_text">Before you can turn on bubbles for this app, you need to turn on bubbles for your device</string>
+    <!-- Button of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=60]-->
+    <string name="bubbles_feature_disabled_button_go_to_bubbles">Go to Bubbles</string>
+    <!-- Button to cancel out of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=60] -->
+    <string name="bubbles_feature_disabled_button_cancel">Cancel</string>
 
     <!-- Configure notifications: title for swipe direction [CHAR LIMIT=60] -->
     <string name="swipe_direction_title">Swipe actions</string>
@@ -7945,6 +7995,9 @@
     <!-- Sound & notification > Advanced section: Title for managing Do Not Disturb access option. [CHAR LIMIT=40] -->
     <string name="manage_zen_access_title">Do Not Disturb access</string>
 
+    <!-- Button title that grants 'Do Not Disturb' permission to an app [CHAR_LIMIT=60]-->
+    <string name="zen_access_detail_switch">Allow Do Not Disturb</string>
+
     <!-- Sound & notification > Do Not Disturb access > Text to display when the list is empty. [CHAR LIMIT=NONE] -->
     <string name="zen_access_empty_text">No installed apps have requested Do Not Disturb access</string>
 
@@ -9331,6 +9384,12 @@
     <!-- Summary of condition that night display is on (renamed "Night Light" with title caps). [CHAR LIMIT=NONE] -->
     <string name="condition_night_display_summary">Screen tinted amber</string>
 
+    <!-- Title of condition that gray scale is on [CHAR LIMIT=NONE] -->
+    <string name="condition_grayscale_title">Greyscale</string>
+
+    <!-- Summary of condition that gray scale is on [CHAR LIMIT=NONE] -->
+    <string name="condition_grayscale_summary">Display only in grey color</string>
+
     <!-- Summary for the condition section on the dashboard, representing number of conditions. [CHAR LIMIT=10] -->
     <string name="condition_summary" translatable="false"><xliff:g name="count" example="3">%1$d</xliff:g></string>
 
@@ -9769,16 +9828,21 @@
     <!-- [CHAR LIMIT=25] Title of developer tile to toggle winscope trace -->
     <string name="winscope_trace_quick_settings_title">Winscope Trace</string>
 
+    <!-- [CHAR LIMIT=25] Title of developer tile to toggle sensors -->
+    <string name="sensors_off_quick_settings_title">Sensors Off</string>
+
     <!-- [CHAR LIMIT=60] Title of work profile setting page -->
     <string name="managed_profile_settings_title">Work profile settings</string>
     <!-- [CHAR LIMIT=60] The preference title for enabling cross-profile remote contact search -->
     <string name="managed_profile_contact_search_title">Contact search</string>
     <!-- [CHAR LIMIT=NONE] The preference summary for enabling cross-profile remote contact search -->
     <string name="managed_profile_contact_search_summary">Allow contact searches by your organization to identify callers and contacts</string>
-    <!-- [CHAR LIMIT=60] The preference title for enabling cross profile calendar sync -->
+    <!-- [CHAR LIMIT=NONE] Settings label. This setting lets the user show their work events on their personal calendar. The adjective 'Cross-profile' is referring to the work and personal profiles a user has on their phone. -->
     <string name="cross_profile_calendar_title">Cross-profile calendar</string>
-    <!-- [CHAR LIMIT=NONE] The preference summary for enabling cross profile calendar sync -->
-    <string name="cross_profile_calendar_summary">Show work events on personal calendar</string>
+    <!-- [CHAR LIMIT=NONE] Setting description. If the user turns on this setting, they can see their work events on their personal calendar. -->
+    <string name="cross_profile_calendar_summary">Show work events on your personal calendar</string>
+    <!-- [CHAR LIMIT=NONE] The preference summary when cross-profile calendar is restricted. -->
+    <string name="cross_profile_calendar_restricted_summary">Your organization doesn\u2019t allow personal apps to access your work calendar</string>
 
 
     <!-- Time in hours -->
@@ -9892,8 +9956,6 @@
 
     <!-- Preference and settings suggestion title text for display wake-up gesture [CHAR LIMIT=60]-->
     <string name="ambient_display_wake_screen_title">Wake up display</string>
-    <!-- Summary text for ambient display wake-up gesture [CHAR LIMIT=NONE]-->
-    <string name="ambient_display_wake_screen_summary"></string>
 
     <!-- Summary text for ambient display (phone) [CHAR LIMIT=NONE]-->
     <string name="ambient_display_pickup_summary" product="default">To check time, notifications, and other info, pick up your phone.</string>
@@ -10733,6 +10795,10 @@
     <string name="contextual_card_dismiss_keep">Keep</string>
     <!-- String for contextual card dismissal [CHAR LIMIT=NONE] -->
     <string name="contextual_card_dismiss_confirm_message">Remove this suggestion?</string>
+    <!-- String for snack bar message when users swipe to dismiss a contextual card [CHAR LIMIT=60]-->
+    <string name="contextual_card_removed_message">Suggestion removed</string>
+    <!-- Label for snack bar action allowing users to undo contextual card dismissal [CHAR LIMIT=30]-->
+    <string name="contextual_card_undo_dismissal_text">Undo</string>
 
     <!-- Summary for low storage slice. [CHAR LIMIT=NONE] -->
     <string name="low_storage_summary">Storage is low. <xliff:g id="percentage" example="54%">%1$s</xliff:g> used - <xliff:g id="free_space" example="32GB">%2$s</xliff:g> free</string>
@@ -10767,7 +10833,7 @@
     </plurals>
 
     <!-- Title for notification channel slice. [CHAR LIMIT=NONE] -->
-    <string name="manage_app_notification">Manage <xliff:g id="app_name" example="Settings">%1$s</xliff:g> Notifications</string>
+    <string name="manage_app_notification">Manage <xliff:g id="app_name" example="Settings">%1$s</xliff:g> notifications</string>
     <!-- Title for no suggested app in notification channel slice. [CHAR LIMIT=NONE] -->
     <string name="no_suggested_app">No suggested application</string>
     <!-- Summary for the channels count is equal or less than 3 in notification channel slice. [CHAR LIMIT=NONE] -->
@@ -10777,6 +10843,8 @@
     </plurals>
     <!-- Summary for the channels count is more than 3 in notification channel slice. [CHAR LIMIT=NONE] -->
     <string name="notification_many_channel_count_summary"><xliff:g id="notification_channel_count" example="4">%1$d</xliff:g> notification channels. Tap to manage all.</string>
+    <!-- Summary for recently installed app in contextual notification channel slice. [CHAR LIMIT=NONE] -->
+    <string name="recently_installed_app">You recently installed this app.</string>
 
     <!-- Title for the Switch output dialog (settings panel) with media related devices [CHAR LIMIT=50] -->
     <string name="media_output_panel_title">Switch output</string>
diff --git a/res/xml/app_info_settings.xml b/res/xml/app_info_settings.xml
index 506686a..435a7ef 100644
--- a/res/xml/app_info_settings.xml
+++ b/res/xml/app_info_settings.xml
@@ -55,7 +55,7 @@
 
     <Preference
         android:key="storage_settings"
-        android:title="@string/storage_settings"
+        android:title="@string/storage_settings_for_app"
         android:summary="@string/summary_placeholder"
         settings:controller="com.android.settings.applications.appinfo.AppStoragePreferenceController" />
 
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index 38fa060..e48ddc1 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -27,6 +27,18 @@
         settings:controller="com.android.settings.notification.NotificationAssistantPreferenceController"/>
 
     <SwitchPreference
+        android:key="asst_capability_prioritizer"
+        android:title="@string/asst_capability_prioritizer_title"
+        android:summary="@string/asst_capability_prioritizer_summary"
+        settings:controller="com.android.settings.notification.AssistantCapabilityPreferenceController" />
+
+    <SwitchPreference
+        android:key="asst_capabilities_actions_replies"
+        android:title="@string/asst_capabilities_actions_replies_title"
+        android:summary="@string/asst_capabilities_actions_replies_summary"
+        settings:controller="com.android.settings.notification.AssistantCapabilityPreferenceController" />
+
+    <SwitchPreference
         android:key="hide_silent_icons"
         android:title="@string/hide_silent_icons_title"
         android:summary="@string/hide_silent_icons_summary"
@@ -61,6 +73,7 @@
         <SwitchPreference
             android:key="notification_bubbles"
             android:title="@string/notification_bubbles_title"
+            android:summary="@string/notification_bubbles_summary"
             settings:controller="com.android.settings.notification.BubbleNotificationPreferenceController"/>
 
         <!-- Pulse notification light -->
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 032f622..a9af2d4 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -113,7 +113,8 @@
         <Preference
             android:key="quick_settings_tiles"
             android:title="@string/quick_settings_developer_tiles"
-            android:fragment="com.android.settings.development.qstile.DevelopmentTileConfigFragment" />
+            android:fragment="com.android.settings.development.qstile.DevelopmentTileConfigFragment"
+            settings:searchable="false" />
 
     <!-- Configure trust agent behavior -->
     <SwitchPreference
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index f705630..8515bd7 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -28,12 +28,6 @@
         settings:controller="com.android.settings.gestures.AssistGestureSettingsPreferenceController" />
 
     <Preference
-        android:key="gesture_wake_screen_input_summary"
-        android:title="@string/ambient_display_wake_screen_title"
-        android:fragment="com.android.settings.gestures.WakeScreenGestureSettings"
-        settings:controller="com.android.settings.gestures.WakeScreenGesturePreferenceController" />
-
-    <Preference
         android:key="gesture_swipe_down_fingerprint_input_summary"
         android:title="@string/fingerprint_swipe_for_notifications_title"
         android:fragment="com.android.settings.gestures.SwipeToNotificationSettings"
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index 6833922..611d33f 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -60,12 +60,6 @@
             settings:controller="com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController" />
 
         <Preference
-            android:key="ambient_display_wake_screen"
-            android:title="@string/ambient_display_wake_screen_title"
-            android:fragment="com.android.settings.gestures.WakeScreenGestureSettings"
-            settings:controller="com.android.settings.gestures.WakeScreenGesturePreferenceController" />
-
-        <Preference
             android:key="ambient_display_tap"
             android:title="@string/ambient_display_tap_screen_title"
             android:fragment="com.android.settings.gestures.TapScreenGestureSettings"
diff --git a/res/xml/wake_screen_gesture_settings.xml b/res/xml/wake_screen_gesture_settings.xml
deleted file mode 100644
index 7bcb2e9..0000000
--- a/res/xml/wake_screen_gesture_settings.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright (C) 2018 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.
-  -->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:key="gesture_wake_screen_screen"
-    android:title="@string/ambient_display_wake_screen_title">
-
-    <com.android.settings.widget.VideoPreference
-        android:key="gesture_wake_screen_video"
-        app:animation="@raw/gesture_ambient_wake_screen"
-        app:preview="@drawable/gesture_ambient_wake_screen" />
-
-    <SwitchPreference
-        android:key="gesture_wake_screen"
-        android:title="@string/ambient_display_wake_screen_title"
-        android:summary="@string/ambient_display_wake_screen_summary"
-        app:keywords="@string/keywords_gesture"
-        app:controller="com.android.settings.gestures.WakeScreenGesturePreferenceController"
-        app:allowDividerAbove="true" />
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/zen_access_permission_details.xml b/res/xml/zen_access_permission_details.xml
new file mode 100644
index 0000000..afa8d80
--- /dev/null
+++ b/res/xml/zen_access_permission_details.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2019 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:key="zen_access_permission_detail_settings"
+    android:title="@string/manage_zen_access_title">
+
+    <SwitchPreference
+        android:key="zen_access_switch"
+        android:title="@string/zen_access_detail_switch"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index 58bc58c..c78115d 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -326,8 +326,6 @@
 
         if (showWipeEuicc()) {
             if (showWipeEuiccCheckbox()) {
-                TextView title = mContentView.findViewById(R.id.erase_esim_title);
-                title.setText(R.string.erase_esim_storage);
                 mEsimStorageContainer.setVisibility(View.VISIBLE);
                 mEsimStorageContainer.setOnClickListener(new View.OnClickListener() {
                     @Override
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 495d35c..6f6e6c4 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -1571,7 +1571,8 @@
     }
 
     private static boolean isDsdsSupported() {
-        return TelephonyManager.getDefault().isMultisimSupported();
+        return (TelephonyManager.getDefault().isMultiSimSupported()
+            == TelephonyManager.MULTISIM_ALLOWED);
     }
 
     private static boolean isDsdsEnabled() {
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index bd45f9b..5d7dd99 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -213,8 +213,6 @@
         mInitiateButton.setOnClickListener(mInitiateListener);
         if (showEuiccSettings(getContext())) {
             mEsimContainer.setVisibility(View.VISIBLE);
-            TextView title = mContentView.findViewById(R.id.erase_esim_title);
-            title.setText(R.string.reset_esim_title);
             mEsimContainer.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View v) {
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 4d615da..7595657 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -97,6 +97,7 @@
     public static class PictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
     public static class AppPictureInPictureSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ZenAccessSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class ZenAccessDetailSettingsActivity extends SettingsActivity {}
     public static class ConditionProviderSettingsActivity extends SettingsActivity { /* empty */ }
     public static class UsbSettingsActivity extends SettingsActivity { /* empty */ }
     public static class UsbDetailsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/UserCredentialsSettings.java b/src/com/android/settings/UserCredentialsSettings.java
index c30e51d..d322819 100644
--- a/src/com/android/settings/UserCredentialsSettings.java
+++ b/src/com/android/settings/UserCredentialsSettings.java
@@ -154,11 +154,15 @@
                         dialog.dismiss();
                     }
                 };
-                if (item.isSystem()) {
-                    // TODO: a safe means of clearing wifi certificates. Configs refer to aliases
-                    //       directly so deleting certs will break dependent access points.
-                    builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener);
-                }
+                // TODO: b/127865361
+                //       a safe means of clearing wifi certificates. Configs refer to aliases
+                //       directly so deleting certs will break dependent access points.
+                //       However, Wi-Fi used to remove this certificate from storage if the network
+                //       was removed, regardless if it is used in more than one network.
+                //       It has been decided to allow removing certificates from this menu, as we
+                //       assume that the user who manually adds certificates must have a way to
+                //       manually remove them.
+                builder.setNegativeButton(R.string.trusted_credentials_remove_label, listener);
             }
             return builder.create();
         }
@@ -172,7 +176,8 @@
          * Deletes all certificates and keys under a given alias.
          *
          * If the {@link Credential} is for a system alias, all active grants to the alias will be
-         * removed using {@link KeyChain}.
+         * removed using {@link KeyChain}. If the {@link Credential} is for Wi-Fi alias, all
+         * credentials and keys will be removed using {@link KeyStore}.
          */
         private class RemoveCredentialsTask extends AsyncTask<Credential, Void, Credential[]> {
             private Context context;
@@ -188,14 +193,32 @@
                 for (final Credential credential : credentials) {
                     if (credential.isSystem()) {
                         removeGrantsAndDelete(credential);
-                        continue;
+                    } else {
+                        deleteWifiCredential(credential);
                     }
-                    throw new UnsupportedOperationException(
-                            "Not implemented for wifi certificates. This should not be reachable.");
                 }
                 return credentials;
             }
 
+            private void deleteWifiCredential(final Credential credential) {
+                final KeyStore keyStore = KeyStore.getInstance();
+                final EnumSet<Credential.Type> storedTypes = credential.getStoredTypes();
+
+                // Remove all Wi-Fi credentials
+                if (storedTypes.contains(Credential.Type.USER_KEY)) {
+                    keyStore.delete(Credentials.USER_PRIVATE_KEY + credential.getAlias(),
+                            Process.WIFI_UID);
+                }
+                if (storedTypes.contains(Credential.Type.USER_CERTIFICATE)) {
+                    keyStore.delete(Credentials.USER_CERTIFICATE + credential.getAlias(),
+                            Process.WIFI_UID);
+                }
+                if (storedTypes.contains(Credential.Type.CA_CERTIFICATE)) {
+                    keyStore.delete(Credentials.CA_CERTIFICATE + credential.getAlias(),
+                            Process.WIFI_UID);
+                }
+            }
+
             private void removeGrantsAndDelete(final Credential credential) {
                 final KeyChainConnection conn;
                 try {
@@ -488,5 +511,11 @@
         public boolean isSystem() {
             return UserHandle.getAppId(uid) == Process.SYSTEM_UID;
         }
+
+        public String getAlias() { return alias; }
+
+        public EnumSet<Type> getStoredTypes() {
+            return storedTypes;
+        }
     }
 }
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index a93fb76..36230d1 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -22,6 +22,8 @@
 import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
 
 import android.annotation.Nullable;
+import android.app.ActionBar;
+import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.IActivityManager;
@@ -92,6 +94,7 @@
 import androidx.annotation.StringRes;
 import androidx.core.graphics.drawable.IconCompat;
 import androidx.fragment.app.Fragment;
+import androidx.lifecycle.Lifecycle;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceGroup;
 
@@ -101,6 +104,7 @@
 import com.android.settings.core.FeatureFlags;
 import com.android.settings.development.featureflags.FeatureFlagPersistent;
 import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settingslib.widget.ActionBarShadowController;
 
 import java.net.InetAddress;
 import java.util.Iterator;
@@ -1023,4 +1027,28 @@
         ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         return !(am.isLowRamDevice() && (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q));
     }
+
+    /**
+     * Adds a shadow appear/disappear animation to action bar scroll.
+     *
+     * <p/>
+     * This method must be called after {@link Fragment#onCreate(Bundle)}.
+     */
+    public static void setActionBarShadowAnimation(Activity activity, Lifecycle lifecycle,
+            View scrollView) {
+        if (activity == null) {
+            Log.w(TAG, "No activity, cannot style actionbar.");
+            return;
+        }
+        final ActionBar actionBar = activity.getActionBar();
+        if (actionBar == null) {
+            Log.w(TAG, "No actionbar, cannot style actionbar.");
+            return;
+        }
+        actionBar.setElevation(0);
+
+        if (lifecycle != null && scrollView != null) {
+            ActionBarShadowController.attachToView(activity, lifecycle, scrollView);
+        }
+    }
 }
diff --git a/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
index 1881ca7..641d8ca 100644
--- a/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
+++ b/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
@@ -31,6 +31,9 @@
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.Lifecycle.Event;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
@@ -40,9 +43,6 @@
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
 
 import java.util.Iterator;
 import java.util.List;
@@ -53,7 +53,7 @@
  * Controller that shows and updates the bluetooth device name
  */
 public class AccessibilityHearingAidPreferenceController extends BasePreferenceController
-        implements LifecycleObserver, OnResume, OnPause {
+        implements LifecycleObserver {
     private static final String TAG = "AccessibilityHearingAidPreferenceController";
     private Preference mHearingAidPreference;
 
@@ -104,7 +104,7 @@
         return mHearingAidProfileSupported ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
-    @Override
+    @OnLifecycleEvent(Event.ON_RESUME)
     public void onResume() {
         if (mHearingAidProfileSupported) {
             IntentFilter filter = new IntentFilter();
@@ -114,7 +114,7 @@
         }
     }
 
-    @Override
+    @OnLifecycleEvent(Event.ON_PAUSE)
     public void onPause() {
         if (mHearingAidProfileSupported) {
             mContext.unregisterReceiver(mHearingAidChangedReceiver);
diff --git a/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java b/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
index 7aaf80d..c32a33d 100644
--- a/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
+++ b/src/com/android/settings/applications/AppAndNotificationDashboardFragment.java
@@ -21,6 +21,7 @@
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.R;
+import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.notification.EmergencyBroadcastPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
@@ -85,6 +86,10 @@
 
         super.onResume();
         mIsFirstLaunch = false;
+
+        if (mRecentAppsPreferenceController.isAvailable()) {
+            Utils.setActionBarShadowAnimation(getActivity(), getSettingsLifecycle(), getListView());
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index c661890..e118ed6 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -559,15 +559,15 @@
         if (mHomePackages.contains(mAppEntry.info.packageName)
                 || isSystemPackage(mActivity.getResources(), mPm, mPackageInfo)) {
             // Disable button for core system applications.
-            mButtonsPref.setButton2Text(R.string.uninstall_text)
+            mButtonsPref.setButton2Text(R.string.disable_text)
                     .setButton2Icon(R.drawable.ic_settings_delete);
         } else if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
-            mButtonsPref.setButton2Text(R.string.uninstall_text)
+            mButtonsPref.setButton2Text(R.string.disable_text)
                     .setButton2Icon(R.drawable.ic_settings_delete);
             disableable = !mApplicationFeatureProvider.getKeepEnabledPackages()
                     .contains(mAppEntry.info.packageName);
         } else {
-            mButtonsPref.setButton2Text(R.string.install_text)
+            mButtonsPref.setButton2Text(R.string.enable_text)
                     .setButton2Icon(R.drawable.ic_settings_install);
             disableable = true;
         }
diff --git a/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
index d0b26a5..0f90c69 100644
--- a/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
+++ b/src/com/android/settings/applications/appinfo/DrawOverlayDetails.java
@@ -15,22 +15,13 @@
  */
 package com.android.settings.applications.appinfo;
 
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-
-import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
@@ -55,16 +46,11 @@
     private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
     private static final String LOG_TAG = "DrawOverlayDetails";
 
-    private static final int[] APP_OPS_OP_CODE = {
-            AppOpsManager.OP_SYSTEM_ALERT_WINDOW
-    };
-
     // Use a bridge to get the overlay details but don't initialize it to connect with all state.
     // TODO: Break out this functionality into its own class.
     private AppStateOverlayBridge mOverlayBridge;
     private AppOpsManager mAppOpsManager;
     private SwitchPreference mSwitchPref;
-    private Intent mSettingsIntent;
     private OverlayState mOverlayState;
 
     @Override
@@ -82,18 +68,15 @@
 
         // find preferences
         addPreferencesFromResource(R.xml.draw_overlay_permissions_details);
-        mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
+        mSwitchPref = findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
 
         // install event listeners
         mSwitchPref.setOnPreferenceChangeListener(this);
-
-        mSettingsIntent = new Intent(Intent.ACTION_MAIN)
-                .setAction(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
     }
 
     // Override here so we don't have an empty screen
     @Override
-    public View onCreateView (LayoutInflater inflater,
+    public View onCreateView(LayoutInflater inflater,
             ViewGroup container,
             Bundle savedInstanceState) {
         // if we don't have a package info, show a page saying this is unsupported
@@ -104,21 +87,6 @@
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        Window window = getActivity().getWindow();
-        WindowManager.LayoutParams attrs = window.getAttributes();
-        attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-        window.setAttributes(attrs);
-    }
-
-    @Override
     public void onDestroy() {
         super.onDestroy();
         mOverlayBridge.release();
@@ -164,7 +132,9 @@
 
     @Override
     protected boolean refreshUi() {
-        if (mPackageInfo == null) return true;
+        if (mPackageInfo == null) {
+            return true;
+        }
 
         mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName,
                 mPackageInfo.applicationInfo.uid);
@@ -174,9 +144,6 @@
         // you cannot ask a user to grant you a permission you did not have!
         mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled);
 
-        ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
-                PackageManager.GET_META_DATA, mUserId);
-
         return true;
     }
 
diff --git a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
index e46f294..bd08236 100644
--- a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
+++ b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
@@ -19,7 +19,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -41,10 +40,6 @@
     private final TextView mAppName;
     private final ImageView mAppIcon;
 
-    private final boolean mKeepStableHeight;
-
-    @VisibleForTesting
-    View mSummaryContainer;
     @VisibleForTesting
     final TextView mSummary;
     @VisibleForTesting
@@ -54,20 +49,18 @@
     @VisibleForTesting
     final Switch mSwitch;
 
-    ApplicationViewHolder(View itemView, boolean keepStableHeight) {
+    ApplicationViewHolder(View itemView) {
         super(itemView);
         mAppName = itemView.findViewById(android.R.id.title);
         mAppIcon = itemView.findViewById(android.R.id.icon);
-        mSummaryContainer = itemView.findViewById(R.id.summary_container);
         mSummary = itemView.findViewById(android.R.id.summary);
         mDisabled = itemView.findViewById(R.id.appendix);
-        mKeepStableHeight = keepStableHeight;
         mSwitch = itemView.findViewById(R.id.switchWidget);
         mWidgetContainer = itemView.findViewById(android.R.id.widget_frame);
     }
 
     static View newView(ViewGroup parent) {
-        return newView(parent, false);
+        return newView(parent, false /* twoTarget */);
     }
 
     static View newView(ViewGroup parent, boolean twoTarget) {
@@ -76,13 +69,13 @@
         final ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame);
         if (twoTarget) {
             if (widgetFrame != null) {
-               LayoutInflater.from(parent.getContext())
-                       .inflate(R.layout.preference_widget_master_switch, widgetFrame, true);
+                LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.preference_widget_master_switch, widgetFrame, true);
 
-               View divider = LayoutInflater.from(parent.getContext()).inflate(
-                       R.layout.preference_two_target_divider, view, false);
-               // second to last, before widget frame
-               view.addView(divider, view.getChildCount() - 1);
+                View divider = LayoutInflater.from(parent.getContext()).inflate(
+                        R.layout.preference_two_target_divider, view, false);
+                // second to last, before widget frame
+                view.addView(divider, view.getChildCount() - 1);
             }
         } else if (widgetFrame != null) {
             widgetFrame.setVisibility(View.GONE);
@@ -92,12 +85,10 @@
 
     void setSummary(CharSequence summary) {
         mSummary.setText(summary);
-        updateSummaryContainer();
     }
 
     void setSummary(@StringRes int summary) {
         mSummary.setText(summary);
-        updateSummaryContainer();
     }
 
     void setEnabled(boolean isEnabled) {
@@ -133,17 +124,6 @@
         } else {
             mDisabled.setVisibility(View.GONE);
         }
-        updateSummaryContainer();
-    }
-
-    void updateSummaryContainer() {
-        if (mKeepStableHeight) {
-            mSummaryContainer.setVisibility(View.VISIBLE);
-            return;
-        }
-        final boolean hasContent =
-                !TextUtils.isEmpty(mDisabled.getText()) || !TextUtils.isEmpty(mSummary.getText());
-        mSummaryContainer.setVisibility(hasContent ? View.VISIBLE : View.GONE);
     }
 
     void updateSizeText(AppEntry entry, CharSequence invalidSizeStr, int whichSize) {
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 9586be0..9839934 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -33,7 +33,6 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.settings.SettingsEnums;
 import android.app.usage.IUsageStatsManager;
 import android.content.Context;
@@ -50,22 +49,18 @@
 import android.util.ArraySet;
 import android.util.IconDrawableFactory;
 import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.Filter;
 import android.widget.FrameLayout;
 import android.widget.SearchView;
 import android.widget.Spinner;
-import android.widget.TextView;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
@@ -1059,14 +1054,13 @@
 
         @Override
         public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-            View view;
+            final View view;
             if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                 view = ApplicationViewHolder.newView(parent, true /* twoTarget */);
             } else {
                 view = ApplicationViewHolder.newView(parent, false /* twoTarget */);
             }
-            return new ApplicationViewHolder(view,
-                    shouldUseStableItemHeight(mManageApplications.mListType));
+            return new ApplicationViewHolder(view);
         }
 
         @Override
@@ -1153,11 +1147,6 @@
             mSearchFilter.filter(query);
         }
 
-        @VisibleForTesting
-        static boolean shouldUseStableItemHeight(int listType) {
-            return true;
-        }
-
         private static boolean packageNameEquals(PackageItemInfo info1, PackageItemInfo info2) {
             if (info1 == null || info2 == null) {
                 return false;
diff --git a/src/com/android/settings/applications/managedomainurls/DomainAppPreference.java b/src/com/android/settings/applications/managedomainurls/DomainAppPreference.java
index 94d2818..bc7b855 100644
--- a/src/com/android/settings/applications/managedomainurls/DomainAppPreference.java
+++ b/src/com/android/settings/applications/managedomainurls/DomainAppPreference.java
@@ -47,12 +47,6 @@
         setState();
     }
 
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-        holder.itemView.findViewById(R.id.appendix).setVisibility(View.GONE);
-    }
-
     public void reuse() {
         setState();
         notifyChanged();
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/FriendlyWarningDialogFragment.java b/src/com/android/settings/applications/specialaccess/zenaccess/FriendlyWarningDialogFragment.java
new file mode 100644
index 0000000..fc85f7d
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/FriendlyWarningDialogFragment.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.zenaccess;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * Warning dialog when revoking zen access warning that zen rule instances will be deleted.
+ */
+public class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
+    static final String KEY_PKG = "p";
+    static final String KEY_LABEL = "l";
+
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_ZEN_ACCESS_REVOKE;
+    }
+
+    public FriendlyWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
+        Bundle args = new Bundle();
+        args.putString(KEY_PKG, pkg);
+        args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
+        setArguments(args);
+        return this;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Bundle args = getArguments();
+        final String pkg = args.getString(KEY_PKG);
+        final String label = args.getString(KEY_LABEL);
+
+        final String title = getResources().getString(
+                R.string.zen_access_revoke_warning_dialog_title, label);
+        final String summary = getResources()
+                .getString(R.string.zen_access_revoke_warning_dialog_summary);
+        return new AlertDialog.Builder(getContext())
+                .setMessage(summary)
+                .setTitle(title)
+                .setCancelable(true)
+                .setPositiveButton(R.string.okay,
+                        (dialog, id) -> {
+                            ZenAccessController.deleteRules(getContext(), pkg);
+                            ZenAccessController.setAccess(getContext(), pkg, false);
+                        })
+                .setNegativeButton(R.string.cancel,
+                        (dialog, id) -> {
+                            // pass
+                        })
+                .create();
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ScaryWarningDialogFragment.java b/src/com/android/settings/applications/specialaccess/zenaccess/ScaryWarningDialogFragment.java
new file mode 100644
index 0000000..69318f8
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ScaryWarningDialogFragment.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.zenaccess;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.notification.ZenAccessSettings;
+
+/**
+ * Warning dialog when allowing zen access warning about the privileges being granted.
+ */
+public class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
+    static final String KEY_PKG = "p";
+    static final String KEY_LABEL = "l";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_ZEN_ACCESS_GRANT;
+    }
+
+    public ScaryWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
+        Bundle args = new Bundle();
+        args.putString(KEY_PKG, pkg);
+        args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
+        setArguments(args);
+        return this;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        final Bundle args = getArguments();
+        final String pkg = args.getString(KEY_PKG);
+        final String label = args.getString(KEY_LABEL);
+
+        final String title = getResources().getString(R.string.zen_access_warning_dialog_title,
+                label);
+        final String summary = getResources()
+                .getString(R.string.zen_access_warning_dialog_summary);
+        return new AlertDialog.Builder(getContext())
+                .setMessage(summary)
+                .setTitle(title)
+                .setCancelable(true)
+                .setPositiveButton(R.string.allow,
+                        (dialog, id) -> ZenAccessController.setAccess(getContext(), pkg, true))
+                .setNegativeButton(R.string.deny,
+                        (dialog, id) -> {
+                            // pass
+                        })
+                .create();
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessController.java b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessController.java
index 88d444d..946599b 100644
--- a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessController.java
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessController.java
@@ -17,12 +17,29 @@
 package com.android.settings.applications.specialaccess.zenaccess;
 
 import android.app.ActivityManager;
+import android.app.AppGlobals;
+import android.app.NotificationManager;
+import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+import java.util.List;
+import java.util.Set;
 
 public class ZenAccessController extends BasePreferenceController {
 
+    private static final String TAG = "ZenAccessController";
+
     private final ActivityManager mActivityManager;
 
     public ZenAccessController(Context context, String preferenceKey) {
@@ -32,8 +49,68 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return !mActivityManager.isLowRamDevice()
+        return isSupported(mActivityManager)
                 ? AVAILABLE_UNSEARCHABLE
                 : UNSUPPORTED_ON_DEVICE;
     }
+
+    public static boolean isSupported(ActivityManager activityManager) {
+        return !activityManager.isLowRamDevice();
+    }
+
+    public static Set<String> getPackagesRequestingNotificationPolicyAccess() {
+        final ArraySet<String> requestingPackages = new ArraySet<>();
+        try {
+            final String[] PERM = {
+                    android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
+            };
+            final ParceledListSlice list = AppGlobals.getPackageManager()
+                    .getPackagesHoldingPermissions(PERM, 0 /*flags*/,
+                            ActivityManager.getCurrentUser());
+            final List<PackageInfo> pkgs = list.getList();
+            if (pkgs != null) {
+                for (PackageInfo info : pkgs) {
+                    requestingPackages.add(info.packageName);
+                }
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Cannot reach packagemanager", e);
+        }
+        return requestingPackages;
+    }
+
+    public static Set<String> getAutoApprovedPackages(Context context) {
+        final Set<String> autoApproved = new ArraySet<>();
+        autoApproved.addAll(context.getSystemService(NotificationManager.class)
+                .getEnabledNotificationListenerPackages());
+        return autoApproved;
+    }
+
+    public static boolean hasAccess(Context context, String pkg) {
+        return context.getSystemService(
+                NotificationManager.class).isNotificationPolicyAccessGrantedForPackage(pkg);
+    }
+
+    public static void setAccess(final Context context, final String pkg, final boolean access) {
+        logSpecialPermissionChange(access, pkg, context);
+        AsyncTask.execute(() -> {
+            final NotificationManager mgr = context.getSystemService(NotificationManager.class);
+            mgr.setNotificationPolicyAccessGranted(pkg, access);
+        });
+    }
+
+    public static void deleteRules(final Context context, final String pkg) {
+        AsyncTask.execute(() -> {
+            final NotificationManager mgr = context.getSystemService(NotificationManager.class);
+            mgr.removeAutomaticZenRules(pkg);
+        });
+    }
+
+    @VisibleForTesting
+    static void logSpecialPermissionChange(boolean enable, String packageName, Context context) {
+        int logCategory = enable ? SettingsEnums.APP_SPECIAL_PERMISSION_DND_ALLOW
+                : SettingsEnums.APP_SPECIAL_PERMISSION_DND_DENY;
+        FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
+                logCategory, packageName);
+    }
 }
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java
new file mode 100644
index 0000000..a18e7d6
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessDetails.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.zenaccess;
+
+import android.app.ActivityManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoWithHeader;
+
+import java.util.Set;
+
+public class ZenAccessDetails extends AppInfoWithHeader implements
+        ZenAccessSettingObserverMixin.Listener {
+
+    private static final String SWITCH_PREF_KEY = "zen_access_switch";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.ZEN_ACCESS_DETAIL;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.zen_access_permission_details);
+        getSettingsLifecycle().addObserver(
+                new ZenAccessSettingObserverMixin(getContext(), this /* listener */));
+    }
+
+    @Override
+    protected boolean refreshUi() {
+        final Context context = getContext();
+        if (!ZenAccessController.isSupported(context.getSystemService(ActivityManager.class))) {
+            return false;
+        }
+        // If this app didn't declare this permission in their manifest, don't bother showing UI.
+        final Set<String> needAccessApps =
+                ZenAccessController.getPackagesRequestingNotificationPolicyAccess();
+        if (!needAccessApps.contains(mPackageName)) {
+            return false;
+        }
+        updatePreference(context, findPreference(SWITCH_PREF_KEY));
+        return true;
+    }
+
+    @Override
+    protected AlertDialog createDialog(int id, int errorCode) {
+        return null;
+    }
+
+    public void updatePreference(Context context, SwitchPreference preference) {
+        final CharSequence label = mPackageInfo.applicationInfo.loadLabel(mPm);
+        final Set<String> autoApproved = ZenAccessController.getAutoApprovedPackages(context);
+        if (autoApproved.contains(mPackageName)) {
+            //Auto approved, user cannot do anything. Hard code summary and disable preference.
+            preference.setEnabled(false);
+            preference.setSummary(getString(R.string.zen_access_disabled_package_warning));
+            return;
+        }
+        preference.setChecked(ZenAccessController.hasAccess(context, mPackageName));
+        preference.setOnPreferenceChangeListener((p, newValue) -> {
+            final boolean access = (Boolean) newValue;
+            if (access) {
+                new ScaryWarningDialogFragment()
+                        .setPkgInfo(mPackageName, label)
+                        .show(getFragmentManager(), "dialog");
+            } else {
+                new FriendlyWarningDialogFragment()
+                        .setPkgInfo(mPackageName, label)
+                        .show(getFragmentManager(), "dialog");
+            }
+            return false;
+        });
+    }
+
+    @Override
+    public void onZenAccessPolicyChanged() {
+        refreshUi();
+    }
+}
diff --git a/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixin.java b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixin.java
new file mode 100644
index 0000000..30507ef
--- /dev/null
+++ b/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixin.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.zenaccess;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+public class ZenAccessSettingObserverMixin extends ContentObserver implements LifecycleObserver,
+        OnStart, OnStop {
+
+    public interface Listener {
+        void onZenAccessPolicyChanged();
+    }
+
+    private final Context mContext;
+    private final Listener mListener;
+
+    public ZenAccessSettingObserverMixin(Context context, Listener listener) {
+        super(new Handler(Looper.getMainLooper()));
+        mContext = context;
+        mListener = listener;
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        if (mListener != null) {
+            mListener.onZenAccessPolicyChanged();
+        }
+    }
+
+    @Override
+    public void onStart() {
+        if (!ZenAccessController.isSupported(mContext.getSystemService(ActivityManager.class))) {
+            return;
+        }
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(
+                        Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES),
+                false /* notifyForDescendants */,
+                this /* observer */);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS),
+                false /* notifyForDescendants */,
+                this /* observer */);
+    }
+
+    @Override
+    public void onStop() {
+        if (!ZenAccessController.isSupported(mContext.getSystemService(ActivityManager.class))) {
+            return;
+        }
+        mContext.getContentResolver().unregisterContentObserver(this /* observer */);
+    }
+}
diff --git a/src/com/android/settings/backup/BackupSettingsHelper.java b/src/com/android/settings/backup/BackupSettingsHelper.java
index b836e55..1d3455b 100644
--- a/src/com/android/settings/backup/BackupSettingsHelper.java
+++ b/src/com/android/settings/backup/BackupSettingsHelper.java
@@ -25,6 +25,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
@@ -91,9 +92,9 @@
      *
      * @return Label for the backup settings item.
      */
-    public String getLabelForBackupSettings() {
-        String label = getLabelFromBackupTransport();
-        if (label == null || label.isEmpty()) {
+    public CharSequence getLabelForBackupSettings() {
+        CharSequence label = getLabelFromBackupTransport();
+        if (TextUtils.isEmpty(label)) {
             label = mContext.getString(R.string.privacy_settings_title);
         }
         return label;
@@ -222,10 +223,11 @@
     }
 
     @VisibleForTesting
-    String getLabelFromBackupTransport() {
+    CharSequence getLabelFromBackupTransport() {
         try {
-            String label =
-                    mBackupManager.getDataManagementLabel(mBackupManager.getCurrentTransport());
+            CharSequence label =
+                    mBackupManager.getDataManagementLabelForUser(
+                            UserHandle.myUserId(), mBackupManager.getCurrentTransport());
             if (Log.isLoggable(TAG, Log.DEBUG)) {
                 Log.d(TAG, "Received the backup settings label from backup transport: " + label);
             }
diff --git a/src/com/android/settings/backup/BackupSettingsPreferenceController.java b/src/com/android/settings/backup/BackupSettingsPreferenceController.java
index 2a657ea..4e0e3b4 100644
--- a/src/com/android/settings/backup/BackupSettingsPreferenceController.java
+++ b/src/com/android/settings/backup/BackupSettingsPreferenceController.java
@@ -31,7 +31,7 @@
     private static final String BACKUP_SETTINGS = "backup_settings";
     private static final  String MANUFACTURER_SETTINGS = "manufacturer_backup";
     private Intent mBackupSettingsIntent;
-    private String mBackupSettingsTitle;
+    private CharSequence mBackupSettingsTitle;
     private String mBackupSettingsSummary;
     private Intent mManufacturerIntent;
     private String mManufacturerLabel;
diff --git a/src/com/android/settings/backup/DataManagementPreferenceController.java b/src/com/android/settings/backup/DataManagementPreferenceController.java
index d19b866..34d51ac 100644
--- a/src/com/android/settings/backup/DataManagementPreferenceController.java
+++ b/src/com/android/settings/backup/DataManagementPreferenceController.java
@@ -48,7 +48,7 @@
             return;
         }
         preference.setIntent(mPSCD.getManageIntent());
-        final String manageLabel = mPSCD.getManageLabel();
+        final CharSequence manageLabel = mPSCD.getManageLabel();
         if (manageLabel != null) {
             preference.setTitle(manageLabel);
         }
diff --git a/src/com/android/settings/backup/OWNERS b/src/com/android/settings/backup/OWNERS
index c026a35..a7b55fd 100644
--- a/src/com/android/settings/backup/OWNERS
+++ b/src/com/android/settings/backup/OWNERS
@@ -1,6 +1,13 @@
-# Default reviewers for this and subdirectories.
+# Use this reviewer by default.
+br-framework-team+reviews@google.com
+
+# People who can approve changes for submission.
+anniemeng@google.com
+nathch@google.com
+rthakohov@google.com
+
+# Others (in case above are not available).
 bryanmawhinney@google.com
-cprins@google.com
 jorlow@google.com
 philippov@google.com
 stefanot@google.com
\ No newline at end of file
diff --git a/src/com/android/settings/backup/PrivacySettingsConfigData.java b/src/com/android/settings/backup/PrivacySettingsConfigData.java
index ffe05b8..8bea11b 100644
--- a/src/com/android/settings/backup/PrivacySettingsConfigData.java
+++ b/src/com/android/settings/backup/PrivacySettingsConfigData.java
@@ -27,7 +27,7 @@
     private Intent mConfigIntent;
     private String mConfigSummary;
     private Intent mManageIntent;
-    private String mManageLabel;
+    private CharSequence mManageLabel;
 
     private PrivacySettingsConfigData() {
         mBackupEnabled = false;
@@ -85,11 +85,11 @@
         mManageIntent = manageIntent;
     }
 
-    public String getManageLabel() {
+    public CharSequence getManageLabel() {
         return mManageLabel;
     }
 
-    public void setManageLabel(final String manageLabel) {
+    public void setManageLabel(final CharSequence manageLabel) {
         mManageLabel = manageLabel;
     }
 }
diff --git a/src/com/android/settings/backup/PrivacySettingsUtils.java b/src/com/android/settings/backup/PrivacySettingsUtils.java
index f8f21dd..bb1108c 100644
--- a/src/com/android/settings/backup/PrivacySettingsUtils.java
+++ b/src/com/android/settings/backup/PrivacySettingsUtils.java
@@ -97,7 +97,8 @@
             data.setConfigSummary(backupManager.getDestinationString(transport));
             data.setManageIntent(validatedActivityIntent(context,
                     backupManager.getDataManagementIntent(transport), "management"));
-            data.setManageLabel(backupManager.getDataManagementLabel(transport));
+            data.setManageLabel(
+                    backupManager.getDataManagementLabelForUser(UserHandle.myUserId(), transport));
             data.setBackupGray(false);
         } catch (RemoteException e) {
             // leave it 'false' and disable the UI; there's no backup manager
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 097ffe2..81b70b5 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -140,7 +140,7 @@
         if (!mHasPassword) {
             // No password registered, launch into enrollment wizard.
             launchChooseLock();
-        } else {
+        } else if (!mLaunchedConfirmLock || mToken == null) {
             launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
         }
     }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
index 2db654b..dffc67d 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
@@ -20,6 +20,7 @@
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
+import android.widget.CompoundButton;
 import android.widget.LinearLayout;
 import android.widget.Switch;
 import android.widget.TextView;
@@ -68,4 +69,12 @@
     public void setChecked(boolean checked) {
         mSwitch.setChecked(checked);
     }
+
+    public void setListener(CompoundButton.OnCheckedChangeListener listener) {
+        mSwitch.setOnCheckedChangeListener(listener);
+    }
+
+    public Switch getSwitch() {
+        return mSwitch;
+    }
 }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index c7966f2..d923e55 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -25,7 +25,7 @@
 import android.text.TextUtils;
 import android.view.View;
 import android.widget.Button;
-import android.widget.LinearLayout;
+import android.widget.CompoundButton;
 import android.widget.TextView;
 
 import com.android.settings.R;
@@ -38,6 +38,7 @@
 import com.google.android.setupcompat.template.FooterButton;
 import com.google.android.setupcompat.util.WizardManagerHelper;
 import com.google.android.setupdesign.span.LinkSpan;
+import com.google.android.setupdesign.view.IllustrationVideoView;
 
 public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
 
@@ -46,19 +47,44 @@
     private FaceManager mFaceManager;
     private FaceEnrollAccessibilityToggle mSwitchDiversity;
 
+    private IllustrationVideoView mIllustrationNormal;
+    private View mIllustrationAccessibility;
+
+    private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
+            new CompoundButton.OnCheckedChangeListener() {
+        @Override
+        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+            if (isChecked) {
+                mIllustrationNormal.stop();
+                mIllustrationNormal.setVisibility(View.INVISIBLE);
+                mIllustrationAccessibility.setVisibility(View.VISIBLE);
+            } else {
+                mIllustrationNormal.setVisibility(View.VISIBLE);
+                mIllustrationNormal.start();
+                mIllustrationAccessibility.setVisibility(View.INVISIBLE);
+            }
+        }
+    };
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+
         mFaceManager = Utils.getFaceManagerOrNull(this);
-        final LinearLayout accessibilityLayout = findViewById(R.id.accessibility_layout);
         final Button accessibilityButton = findViewById(R.id.accessibility_button);
+        final View footerView = findViewById(R.id.footer_layout);
         accessibilityButton.setOnClickListener(view -> {
             mSwitchDiversity.setChecked(true);
-            accessibilityButton.setVisibility(View.INVISIBLE);
-            accessibilityLayout.setVisibility(View.VISIBLE);
+            accessibilityButton.setVisibility(View.GONE);
+            mSwitchDiversity.setVisibility(View.VISIBLE);
+            footerView.setVisibility(View.GONE);
         });
 
         mSwitchDiversity = findViewById(R.id.toggle_diversity);
+        mSwitchDiversity.setListener(mSwitchDiversityListener);
+
+        mIllustrationNormal = findViewById(R.id.illustration_normal);
+        mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
 
         mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
         if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
@@ -92,6 +118,13 @@
     }
 
     @Override
+    protected void onResume() {
+        super.onResume();
+        mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
+                mSwitchDiversity.isChecked());
+     }
+
+    @Override
     protected boolean isDisabledByAdmin() {
         return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                 this, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId) != null;
@@ -114,7 +147,7 @@
 
     @Override
     protected int getDescriptionResDisabledByAdmin() {
-        return R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled;
+        return R.string.security_settings_face_enroll_introduction_message_unlock_disabled;
     }
 
     @Override
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index ea5a303..9651eec 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -31,6 +31,7 @@
 import android.util.Log;
 
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.password.ChooseLockSettingsHelper;
@@ -56,6 +57,7 @@
     private int mUserId;
     private byte[] mToken;
     private FaceSettingsAttentionPreferenceController mAttentionController;
+    private FaceSettingsRemoveButtonPreferenceController mRemoveController;
 
     private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
         if (getActivity() != null) {
@@ -166,8 +168,9 @@
             if (controller instanceof FaceSettingsAttentionPreferenceController) {
                 mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
             } else if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
-                ((FaceSettingsRemoveButtonPreferenceController) controller)
-                        .setListener(mRemovalListener);
+                mRemoveController = (FaceSettingsRemoveButtonPreferenceController) controller;
+                mRemoveController.setListener(mRemovalListener);
+                mRemoveController.setActivity((SettingsActivity) getActivity());
             }
         }
 
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
index baab391..5174482 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
@@ -16,9 +16,14 @@
 
 package com.android.settings.biometrics.face;
 
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
+import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Log;
 import android.view.View;
@@ -28,7 +33,9 @@
 import androidx.preference.Preference;
 
 import com.android.settings.R;
+import com.android.settings.SettingsActivity;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settingslib.widget.LayoutPreference;
 
 import java.util.List;
@@ -43,6 +50,33 @@
     private static final String TAG = "FaceSettings/Remove";
     private static final String KEY = "security_settings_face_delete_faces_container";
 
+    public static class ConfirmRemoveDialog extends InstrumentedDialogFragment {
+
+        private DialogInterface.OnClickListener mOnClickListener;
+
+        @Override
+        public int getMetricsCategory() {
+            return SettingsEnums.DIALOG_FACE_REMOVE;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+
+            builder.setTitle(R.string.security_settings_face_settings_remove_dialog_title)
+                    .setMessage(R.string.security_settings_face_settings_remove_dialog_details)
+                    .setPositiveButton(R.string.okay, mOnClickListener)
+                    .setNegativeButton(R.string.cancel, mOnClickListener);
+            AlertDialog dialog = builder.create();
+            dialog.setCanceledOnTouchOutside(false);
+            return dialog;
+        }
+
+        public void setOnClickListener(DialogInterface.OnClickListener listener) {
+            mOnClickListener = listener;
+        }
+    }
+
     interface Listener {
         void onRemoved();
     }
@@ -50,6 +84,7 @@
     private Button mButton;
     private List<Face> mFaces;
     private Listener mListener;
+    private SettingsActivity mActivity;
 
     private final Context mContext;
     private final int mUserId;
@@ -77,6 +112,27 @@
         }
     };
 
+    private final DialogInterface.OnClickListener mOnClickListener
+            = new DialogInterface.OnClickListener() {
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            if (which == DialogInterface.BUTTON_POSITIVE) {
+                if (mFaces.isEmpty()) {
+                    Log.e(TAG, "No faces");
+                    return;
+                }
+                if (mFaces.size() > 1) {
+                    Log.e(TAG, "Multiple enrollments: " + mFaces.size());
+                }
+
+                // Remove the first/only face
+                mFaceManager.remove(mFaces.get(0), mUserId, mRemovalCallback);
+            } else {
+                mButton.setEnabled(true);
+            }
+        }
+    };
+
     public FaceSettingsRemoveButtonPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
         mContext = context;
@@ -115,20 +171,17 @@
     public void onClick(View v) {
         if (v == mButton) {
             mButton.setEnabled(false);
-            if (mFaces.isEmpty()) {
-                Log.e(TAG, "No faces");
-                return;
-            }
-            if (mFaces.size() > 1) {
-                Log.e(TAG, "Multiple enrollments: " + mFaces.size());
-            }
-
-            // Remove the first/only face
-            mFaceManager.remove(mFaces.get(0), mUserId, mRemovalCallback);
+            ConfirmRemoveDialog dialog = new ConfirmRemoveDialog();
+            dialog.setOnClickListener(mOnClickListener);
+            dialog.show(mActivity.getSupportFragmentManager(), ConfirmRemoveDialog.class.getName());
         }
     }
 
     public void setListener(Listener listener) {
         mListener = listener;
     }
+
+    public void setActivity(SettingsActivity activity) {
+        mActivity = activity;
+    }
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
index fd805b8..3860352 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
@@ -26,7 +26,6 @@
 
 import com.android.settings.R;
 import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -66,10 +65,8 @@
     }
 
     protected void setHeaderProperties() {
-        final Pair<Drawable, String> pair = BluetoothUtils
-                .getBtClassDrawableWithDescription(mContext, mCachedDevice,
-                        mContext.getResources().getFraction(R.fraction.bt_battery_scale_fraction, 1,
-                                1));
+        final Pair<Drawable, String> pair = Utils.getBtRainbowDrawableWithDescription(mContext,
+                mCachedDevice);
         String summaryText = mCachedDevice.getConnectionSummary();
         // If both the hearing aids are connected, two device status should be shown.
         // If Second Summary is unavailable, to set it to null.
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index d4c0ed0..8d727eb 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -38,7 +38,6 @@
 import com.android.settings.R;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.GearPreference;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
@@ -130,8 +129,8 @@
         // Null check is done at the framework
         setSummary(mCachedDevice.getConnectionSummary());
 
-        final Pair<Drawable, String> pair = BluetoothUtils
-                .getBtClassDrawableWithDescription(getContext(), mCachedDevice);
+        final Pair<Drawable, String> pair = Utils
+                .getBtRainbowDrawableWithDescription(getContext(), mCachedDevice);
         if (pair.first != null) {
             setIcon(pair.first);
             contentDescription = pair.second;
@@ -246,5 +245,4 @@
                     R.string.bluetooth_pairing_error_message);
         }
     }
-
 }
diff --git a/src/com/android/settings/bluetooth/Utils.java b/src/com/android/settings/bluetooth/Utils.java
index ff4a98f..e02ddc4 100755
--- a/src/com/android/settings/bluetooth/Utils.java
+++ b/src/com/android/settings/bluetooth/Utils.java
@@ -21,8 +21,12 @@
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
 import android.provider.Settings;
 import android.util.Log;
+import android.util.Pair;
 import android.widget.Toast;
 
 import androidx.annotation.VisibleForTesting;
@@ -30,8 +34,10 @@
 
 import com.android.settings.R;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.AdaptiveIcon;
 import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback;
 
@@ -179,4 +185,25 @@
             return META_INT_ERROR;
         }
     }
+
+    /**
+     * Get colorful bluetooth icon with description
+     */
+    public static Pair<Drawable, String> getBtRainbowDrawableWithDescription(Context context,
+            CachedBluetoothDevice cachedDevice) {
+        final Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
+                context, cachedDevice);
+        final Resources resources = context.getResources();
+        final int[] iconFgColors = resources.getIntArray(R.array.bt_icon_fg_colors);
+        final int[] iconBgColors = resources.getIntArray(R.array.bt_icon_bg_colors);
+
+        // get color index based on mac address
+        final int index =  Math.abs(cachedDevice.getAddress().hashCode()) % iconBgColors.length;
+        pair.first.setColorFilter(iconFgColors[index], PorterDuff.Mode.SRC_ATOP);
+        final Drawable adaptiveIcon = new AdaptiveIcon(context, pair.first);
+        ((AdaptiveIcon) adaptiveIcon).setBackgroundColor(iconBgColors[index]);
+
+        return new Pair<>(adaptiveIcon, pair.second);
+    }
+
 }
diff --git a/src/com/android/settings/core/HideNonSystemOverlayMixin.java b/src/com/android/settings/core/HideNonSystemOverlayMixin.java
new file mode 100644
index 0000000..59cef3b
--- /dev/null
+++ b/src/com/android/settings/core/HideNonSystemOverlayMixin.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.core;
+
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import android.app.Activity;
+import android.view.Window;
+import android.view.WindowManager;
+
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.OnLifecycleEvent;
+
+
+/**
+ * A mixin that adds window flag to prevent non-system overlays showing on top of Settings
+ * activities.
+ */
+public class HideNonSystemOverlayMixin implements LifecycleObserver {
+
+    private final Activity mActivity;
+
+    public HideNonSystemOverlayMixin(Activity activity) {
+        mActivity = activity;
+    }
+
+    @OnLifecycleEvent(ON_START)
+    public void onStart() {
+        if (mActivity == null) {
+            return;
+        }
+        mActivity.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        android.util.EventLog.writeEvent(0x534e4554, "120484087", -1, "");
+    }
+
+
+    @OnLifecycleEvent(ON_STOP)
+    public void onStop() {
+        if (mActivity == null) {
+            return;
+        }
+        final Window window = mActivity.getWindow();
+        final WindowManager.LayoutParams attrs = window.getAttributes();
+        attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        window.setAttributes(attrs);
+    }
+}
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index 294e754..cd13654 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -32,7 +32,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
-import android.view.WindowManager.LayoutParams;
 import android.widget.Toolbar;
 
 import androidx.fragment.app.FragmentActivity;
@@ -59,8 +58,8 @@
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
         final long startTime = System.currentTimeMillis();
+        getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
 
         final TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
         if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index fb9b75b..10eec4e 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -50,6 +50,7 @@
 import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureDetails;
 import com.android.settings.applications.specialaccess.pictureinpicture.PictureInPictureSettings;
 import com.android.settings.applications.specialaccess.vrlistener.VrListenerSettings;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails;
 import com.android.settings.backup.PrivacySettings;
 import com.android.settings.backup.ToggleBackupSettingFragment;
 import com.android.settings.backup.UserBackupSettingsActivity;
@@ -210,6 +211,7 @@
             UserSettings.class.getName(),
             NotificationAccessSettings.class.getName(),
             ZenAccessSettings.class.getName(),
+            ZenAccessDetails.class.getName(),
             ZenModeAutomationSettings.class.getName(),
             PrintSettingsFragment.class.getName(),
             PrintJobSettingsFragment.class.getName(),
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 6348b91..744cbd2 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -46,7 +46,7 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.dashboard.profileselector.ProfileSelectDialog;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.widget.AdaptiveHomepageIcon;
+import com.android.settings.widget.AdaptiveIcon;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.Tile;
@@ -197,8 +197,8 @@
             Drawable iconDrawable = tileIcon.loadDrawable(preference.getContext());
             if (forceRoundedIcon
                     && !TextUtils.equals(mContext.getPackageName(), tile.getPackageName())) {
-                iconDrawable = new AdaptiveHomepageIcon(mContext, iconDrawable);
-                ((AdaptiveHomepageIcon) iconDrawable).setBackgroundColor(mContext, tile);
+                iconDrawable = new AdaptiveIcon(mContext, iconDrawable);
+                ((AdaptiveIcon) iconDrawable).setBackgroundColor(mContext, tile);
             }
             preference.setIcon(iconDrawable);
         } else if (tile.getMetaData() != null
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
index ff980b2..66735c8 100644
--- a/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZoneAdapter.java
@@ -77,9 +77,10 @@
     @Override
     public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         LayoutInflater inflater = LayoutInflater.from(parent.getContext());
-        switch(viewType) {
+        switch (viewType) {
             case TYPE_HEADER: {
-                final View view = inflater.inflate(R.layout.preference_category_material,
+                final View view = inflater.inflate(
+                        R.layout.time_zone_search_header,
                         parent, false);
                 return new HeaderViewHolder(view);
             }
@@ -136,7 +137,8 @@
         return mShowHeader && position == 0;
     }
 
-    public @NonNull ArrayFilter getFilter() {
+    @NonNull
+    public ArrayFilter getFilter() {
         if (mFilter == null) {
             mFilter = new ArrayFilter();
         }
@@ -153,14 +155,18 @@
 
     public interface AdapterItem {
         CharSequence getTitle();
+
         CharSequence getSummary();
+
         String getIconText();
+
         String getCurrentTime();
 
         /**
          * @return unique non-negative number
          */
         long getItemId();
+
         String[] getSearchKeys();
     }
 
diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java
index 5edbc70..bb791ab 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTiles.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java
@@ -16,9 +16,12 @@
 
 package com.android.settings.development.qstile;
 
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.SensorPrivacyManager;
+import android.app.KeyguardManager;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.RemoteException;
@@ -38,6 +41,8 @@
 
 import com.android.internal.app.LocalePicker;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.development.SystemPropPoker;
 
@@ -273,4 +278,45 @@
             }
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * Tile to toggle sensors off to control camera, mic, and sensors managed by the SensorManager.
+     */
+    public static class SensorsOff extends DevelopmentTiles {
+        private Context mContext;
+        private SensorPrivacyManager mSensorPrivacyManager;
+        private KeyguardManager mKeyguardManager;
+        private MetricsFeatureProvider mMetricsFeatureProvider;
+        private boolean mIsEnabled;
+
+        @Override
+        public void onCreate() {
+            super.onCreate();
+            mContext = getApplicationContext();
+            mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService(
+                    Context.SENSOR_PRIVACY_SERVICE);
+            mIsEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
+            mMetricsFeatureProvider = FeatureFactory.getFactory(
+                    mContext).getMetricsFeatureProvider();
+            mKeyguardManager = (KeyguardManager) mContext.getSystemService(
+                    Context.KEYGUARD_SERVICE);
+        }
+
+        @Override
+        protected boolean isEnabled() {
+            return mIsEnabled;
+        }
+
+        @Override
+        public void setIsEnabled(boolean isEnabled) {
+            // Don't allow sensors to be reenabled from the lock screen.
+            if (mIsEnabled && mKeyguardManager.isKeyguardLocked()) {
+                return;
+            }
+            mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY,
+                    isEnabled);
+            mIsEnabled = isEnabled;
+            mSensorPrivacyManager.setSensorPrivacy(isEnabled);
+        }
+    }
+}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
index d95320f..a014c29 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -174,7 +174,8 @@
             return;
         }
 
-        mTelephonyManager.listen(mPhoneStateListener,
+        mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId())
+                .listen(mPhoneStateListener,
                 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                         | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
                         | PhoneStateListener.LISTEN_SERVICE_STATE);
@@ -197,8 +198,8 @@
             return;
         }
 
-        mTelephonyManager.listen(mPhoneStateListener,
-                PhoneStateListener.LISTEN_NONE);
+        mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId())
+                .listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
 
         if (mShowLatestAreaInfo) {
             mContext.unregisterReceiver(mAreaInfoReceiver);
@@ -432,8 +433,7 @@
 
     @VisibleForTesting
     PhoneStateListener getPhoneStateListener() {
-        return new PhoneStateListener(
-                mSubscriptionInfo.getSubscriptionId()) {
+        return new PhoneStateListener() {
             @Override
             public void onDataConnectionStateChanged(int state) {
                 updateDataState(state);
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
index b14fec9..7a1f7f5 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceController.java
@@ -19,7 +19,7 @@
 
     @Override
     public void updateState(Preference preference) {
-        int setting = Settings.System.getInt(mContext.getContentResolver(),
+        int setting = Settings.Global.getInt(mContext.getContentResolver(),
                 LOW_POWER_STICKY_AUTO_DISABLE_ENABLED, 1);
 
         ((SwitchPreference) preference).setChecked(setting == 0);
@@ -28,7 +28,7 @@
     @Override
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         boolean keepActive = (Boolean) newValue;
-        Settings.System.putInt(mContext.getContentResolver(),
+        Settings.Global.putInt(mContext.getContentResolver(),
                 LOW_POWER_STICKY_AUTO_DISABLE_ENABLED,
                 keepActive ? 0 : 1);
         return true;
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
index f75588c..bb69999 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
@@ -59,7 +59,7 @@
         mDatabaseHelper = AnomalyDatabaseHelper.getInstance(context);
     }
 
-    public static BatteryDatabaseManager getInstance(Context context) {
+    public static synchronized BatteryDatabaseManager getInstance(Context context) {
         if (sSingleton == null) {
             sSingleton = new BatteryDatabaseManager(context);
         }
@@ -84,15 +84,15 @@
     public synchronized boolean insertAnomaly(int uid, String packageName, int type,
             int anomalyState,
             long timestampMs) {
-        try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
-            ContentValues values = new ContentValues();
-            values.put(UID, uid);
-            values.put(PACKAGE_NAME, packageName);
-            values.put(ANOMALY_TYPE, type);
-            values.put(ANOMALY_STATE, anomalyState);
-            values.put(TIME_STAMP_MS, timestampMs);
-            return db.insertWithOnConflict(TABLE_ANOMALY, null, values, CONFLICT_IGNORE) != -1;
-        }
+        final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
+        ContentValues values = new ContentValues();
+        values.put(UID, uid);
+        values.put(PACKAGE_NAME, packageName);
+        values.put(ANOMALY_TYPE, type);
+        values.put(ANOMALY_STATE, anomalyState);
+        values.put(TIME_STAMP_MS, timestampMs);
+
+        return db.insertWithOnConflict(TABLE_ANOMALY, null, values, CONFLICT_IGNORE) != -1;
     }
 
     /**
@@ -100,43 +100,41 @@
      */
     public synchronized List<AppInfo> queryAllAnomalies(long timestampMsAfter, int state) {
         final List<AppInfo> appInfos = new ArrayList<>();
-        try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
-            final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE, UID};
-            final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC";
-            final Map<Integer, AppInfo.Builder> mAppInfoBuilders = new ArrayMap<>();
-            final String selection = TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ";
-            final String[] selectionArgs = new String[]{String.valueOf(timestampMsAfter),
-                    String.valueOf(state)};
+        final SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
+        final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE, UID};
+        final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC";
+        final Map<Integer, AppInfo.Builder> mAppInfoBuilders = new ArrayMap<>();
+        final String selection = TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ";
+        final String[] selectionArgs = new String[]{String.valueOf(timestampMsAfter),
+                String.valueOf(state)};
 
-            try (Cursor cursor = db.query(TABLE_ANOMALY, projection, selection, selectionArgs,
-                    null /* groupBy */, null /* having */, orderBy)) {
-                while (cursor.moveToNext()) {
-                    final int uid = cursor.getInt(cursor.getColumnIndex(UID));
-                    if (!mAppInfoBuilders.containsKey(uid)) {
-                        final AppInfo.Builder builder = new AppInfo.Builder()
-                                .setUid(uid)
-                                .setPackageName(
-                                        cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)));
-                        mAppInfoBuilders.put(uid, builder);
-                    }
-                    mAppInfoBuilders.get(uid).addAnomalyType(
-                            cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)));
+        try (Cursor cursor = db.query(TABLE_ANOMALY, projection, selection, selectionArgs,
+                null /* groupBy */, null /* having */, orderBy)) {
+            while (cursor.moveToNext()) {
+                final int uid = cursor.getInt(cursor.getColumnIndex(UID));
+                if (!mAppInfoBuilders.containsKey(uid)) {
+                    final AppInfo.Builder builder = new AppInfo.Builder()
+                            .setUid(uid)
+                            .setPackageName(
+                                    cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)));
+                    mAppInfoBuilders.put(uid, builder);
                 }
+                mAppInfoBuilders.get(uid).addAnomalyType(
+                        cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)));
             }
+        }
 
-            for (Integer uid : mAppInfoBuilders.keySet()) {
-                appInfos.add(mAppInfoBuilders.get(uid).build());
-            }
+        for (Integer uid : mAppInfoBuilders.keySet()) {
+            appInfos.add(mAppInfoBuilders.get(uid).build());
         }
 
         return appInfos;
     }
 
     public synchronized void deleteAllAnomaliesBeforeTimeStamp(long timestampMs) {
-        try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
-            db.delete(TABLE_ANOMALY, TIME_STAMP_MS + " < ?",
-                    new String[]{String.valueOf(timestampMs)});
-        }
+        final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
+        db.delete(TABLE_ANOMALY, TIME_STAMP_MS + " < ?",
+                new String[]{String.valueOf(timestampMs)});
     }
 
     /**
@@ -152,12 +150,12 @@
             for (int i = 0; i < size; i++) {
                 whereArgs[i] = appInfos.get(i).packageName;
             }
-            try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
-                final ContentValues values = new ContentValues();
-                values.put(ANOMALY_STATE, state);
-                db.update(TABLE_ANOMALY, values, PACKAGE_NAME + " IN (" + TextUtils.join(",",
-                        Collections.nCopies(appInfos.size(), "?")) + ")", whereArgs);
-            }
+
+            final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
+            final ContentValues values = new ContentValues();
+            values.put(ANOMALY_STATE, state);
+            db.update(TABLE_ANOMALY, values, PACKAGE_NAME + " IN (" + TextUtils.join(",",
+                    Collections.nCopies(appInfos.size(), "?")) + ")", whereArgs);
         }
     }
 
@@ -170,21 +168,20 @@
     public synchronized SparseLongArray queryActionTime(
             @AnomalyDatabaseHelper.ActionType int type) {
         final SparseLongArray timeStamps = new SparseLongArray();
-        try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
-            final String[] projection = {ActionColumns.UID, ActionColumns.TIME_STAMP_MS};
-            final String selection = ActionColumns.ACTION_TYPE + " = ? ";
-            final String[] selectionArgs = new String[]{String.valueOf(type)};
+        final SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
+        final String[] projection = {ActionColumns.UID, ActionColumns.TIME_STAMP_MS};
+        final String selection = ActionColumns.ACTION_TYPE + " = ? ";
+        final String[] selectionArgs = new String[]{String.valueOf(type)};
 
-            try (Cursor cursor = db.query(TABLE_ACTION, projection, selection, selectionArgs,
-                    null /* groupBy */, null /* having */, null /* orderBy */)) {
-                final int uidIndex = cursor.getColumnIndex(ActionColumns.UID);
-                final int timestampIndex = cursor.getColumnIndex(ActionColumns.TIME_STAMP_MS);
+        try (Cursor cursor = db.query(TABLE_ACTION, projection, selection, selectionArgs,
+                null /* groupBy */, null /* having */, null /* orderBy */)) {
+            final int uidIndex = cursor.getColumnIndex(ActionColumns.UID);
+            final int timestampIndex = cursor.getColumnIndex(ActionColumns.TIME_STAMP_MS);
 
-                while (cursor.moveToNext()) {
-                    final int uid = cursor.getInt(uidIndex);
-                    final long timeStamp = cursor.getLong(timestampIndex);
-                    timeStamps.append(uid, timeStamp);
-                }
+            while (cursor.moveToNext()) {
+                final int uid = cursor.getInt(uidIndex);
+                final long timeStamp = cursor.getLong(timestampIndex);
+                timeStamps.append(uid, timeStamp);
             }
         }
 
@@ -196,14 +193,14 @@
      */
     public synchronized boolean insertAction(@AnomalyDatabaseHelper.ActionType int type,
             int uid, String packageName, long timestampMs) {
-        try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
-            final ContentValues values = new ContentValues();
-            values.put(ActionColumns.UID, uid);
-            values.put(ActionColumns.PACKAGE_NAME, packageName);
-            values.put(ActionColumns.ACTION_TYPE, type);
-            values.put(ActionColumns.TIME_STAMP_MS, timestampMs);
-            return db.insertWithOnConflict(TABLE_ACTION, null, values, CONFLICT_REPLACE) != -1;
-        }
+        final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
+        final ContentValues values = new ContentValues();
+        values.put(ActionColumns.UID, uid);
+        values.put(ActionColumns.PACKAGE_NAME, packageName);
+        values.put(ActionColumns.ACTION_TYPE, type);
+        values.put(ActionColumns.TIME_STAMP_MS, timestampMs);
+
+        return db.insertWithOnConflict(TABLE_ACTION, null, values, CONFLICT_REPLACE) != -1;
     }
 
     /**
@@ -211,14 +208,13 @@
      */
     public synchronized boolean deleteAction(@AnomalyDatabaseHelper.ActionType int type,
             int uid, String packageName) {
-        try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
-            final String where =
-                    ActionColumns.ACTION_TYPE + " = ? AND " + ActionColumns.UID + " = ? AND "
-                            + ActionColumns.PACKAGE_NAME + " = ? ";
-            final String[] whereArgs = new String[]{String.valueOf(type), String.valueOf(uid),
-                    String.valueOf(packageName)};
+        SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
+        final String where =
+                ActionColumns.ACTION_TYPE + " = ? AND " + ActionColumns.UID + " = ? AND "
+                        + ActionColumns.PACKAGE_NAME + " = ? ";
+        final String[] whereArgs = new String[]{String.valueOf(type), String.valueOf(uid),
+                String.valueOf(packageName)};
 
-            return db.delete(TABLE_ACTION, where, whereArgs) != 0;
-        }
+        return db.delete(TABLE_ACTION, where, whereArgs) != 0;
     }
 }
diff --git a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
index a11754e..e1be9d4 100644
--- a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
@@ -51,13 +51,15 @@
     private static final String ENABLE_ASSISTANT_GESTURE = "ENABLE_ASSISTANT_GESTURE";
     private static final String PROTOTYPE_ENABLED = "prototype_enabled";
 
-    private static final int EDGE_SENSITIVITY_WIDTH = 32;
+    private static final int EDGE_SENSITIVITY_WIDTH = 48;
     private static final String EDGE_SENSITIVITY_KEY = "quickstepcontroller_edge_width_sensitivity";
 
     private static final String GESTURES_MATCH_MAP_OFF = "000000";
     private static final String GESTURES_MATCH_MAP_ON = "071133";
     private static final String GESTURES_MATCH_MAP_KEY = "quickstepcontroller_gesture_match_map";
 
+    private static final String OVERLAY_NAVBAR_KEY =
+            "com.android.internal.experiment.navbar.default";
     private static final String OVERLAY_NAVBAR_TYPE_INSET =
             "com.android.internal.experiment.navbar.type.inset";
     private static final String OVERLAY_NAVBAR_TYPE_FLOATING =
@@ -174,6 +176,7 @@
                 .asInterface(ServiceManager.getService(Context.OVERLAY_SERVICE));
         if (overlayManager != null) {
             try {
+                overlayManager.setEnabled(OVERLAY_NAVBAR_KEY, true, USER_SYSTEM);
                 overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_FLOATING, false, USER_SYSTEM);
                 overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_INSET, enable, USER_SYSTEM);
             } catch (RemoteException e) {
diff --git a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java b/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
deleted file mode 100644
index e9d03d7..0000000
--- a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2018 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.settings.gestures;
-
-import static android.provider.Settings.Secure.DOZE_WAKE_SCREEN_GESTURE;
-
-import android.annotation.UserIdInt;
-import android.content.Context;
-import android.hardware.display.AmbientDisplayConfiguration;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.aware.AwareFeatureProvider;
-import com.android.settings.overlay.FeatureFactory;
-
-public class WakeScreenGesturePreferenceController extends GesturePreferenceController {
-
-    private static final int ON = 1;
-    private static final int OFF = 0;
-
-    private static final String PREF_KEY_VIDEO = "gesture_wake_screen_video";
-
-    private final AwareFeatureProvider mFeatureProvider;
-    private AmbientDisplayConfiguration mAmbientConfig;
-    @UserIdInt
-    private final int mUserId;
-
-    public WakeScreenGesturePreferenceController(Context context, String key) {
-        super(context, key);
-        mUserId = UserHandle.myUserId();
-        mFeatureProvider = FeatureFactory.getFactory(context).getAwareFeatureProvider();
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        if (!getAmbientConfig().wakeScreenGestureAvailable()
-                || !mFeatureProvider.isSupported(mContext)) {
-            return UNSUPPORTED_ON_DEVICE;
-        }
-
-        if (!mFeatureProvider.isEnabled(mContext)) {
-            return CONDITIONALLY_UNAVAILABLE;
-        }
-
-        return getAmbientConfig().alwaysOnEnabled(mUserId)
-                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
-    }
-
-    @Override
-    protected boolean canHandleClicks() {
-        return getAmbientConfig().alwaysOnEnabled(mUserId);
-    }
-
-    @Override
-    public boolean isSliceable() {
-        return TextUtils.equals(getPreferenceKey(), "gesture_wake_screen");
-    }
-
-    @Override
-    protected String getVideoPrefKey() {
-        return PREF_KEY_VIDEO;
-    }
-
-    @Override
-    public boolean isChecked() {
-        return getAmbientConfig().wakeScreenGestureEnabled(mUserId);
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        return Settings.Secure.putInt(mContext.getContentResolver(), DOZE_WAKE_SCREEN_GESTURE,
-                isChecked ? ON : OFF);
-    }
-
-    private AmbientDisplayConfiguration getAmbientConfig() {
-        if (mAmbientConfig == null) {
-            mAmbientConfig = new AmbientDisplayConfiguration(mContext);
-        }
-
-        return mAmbientConfig;
-    }
-
-    @VisibleForTesting
-    public void setConfig(AmbientDisplayConfiguration config) {
-        mAmbientConfig = config;
-    }
-}
diff --git a/src/com/android/settings/gestures/WakeScreenGestureSettings.java b/src/com/android/settings/gestures/WakeScreenGestureSettings.java
deleted file mode 100644
index b8a782a..0000000
--- a/src/com/android/settings/gestures/WakeScreenGestureSettings.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2018 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.settings.gestures;
-
-import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.provider.SearchIndexableResource;
-
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.search.SearchIndexable;
-
-import java.util.Arrays;
-import java.util.List;
-
-@SearchIndexable
-public class WakeScreenGestureSettings extends DashboardFragment {
-
-    private static final String TAG = "WakeScreenGestureSettings";
-
-    public static final String PREF_KEY_SUGGESTION_COMPLETE =
-            "pref_wake_screen_gesture_suggestion_complete";
-
-    @Override
-    public int getMetricsCategory() {
-        return SettingsEnums.SETTINGS_GESTURE_WAKE_SCREEN;
-    }
-
-    @Override
-    protected String getLogTag() {
-        return TAG;
-    }
-
-    @Override
-    protected int getPreferenceScreenResId() {
-        return R.xml.wake_screen_gesture_settings;
-    }
-
-    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider() {
-                @Override
-                public List<SearchIndexableResource> getXmlResourcesToIndex(
-                        Context context, boolean enabled) {
-                    final SearchIndexableResource sir = new SearchIndexableResource(context);
-                    sir.xmlResId = R.xml.wake_screen_gesture_settings;
-                    return Arrays.asList(sir);
-                }
-            };
-
-}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index ff2ee91..32f505e 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -17,8 +17,8 @@
 package com.android.settings.homepage.contextualcards;
 
 import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI;
 import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI;
-import static com.android.settings.slices.CustomSliceRegistry.NOTIFICATION_CHANNEL_SLICE_URI;
 
 import android.content.Context;
 import android.database.ContentObserver;
@@ -187,7 +187,6 @@
         // Collect future and eligible cards
         for (Future<ContextualCard> cardFuture : eligibleCards) {
             try {
-                //TODO(b/124492762): Log latency and timeout occurrence.
                 final ContextualCard card = cardFuture.get(ELIGIBILITY_CHECKER_TIMEOUT_MS,
                         TimeUnit.MILLISECONDS);
                 if (card != null) {
@@ -209,7 +208,7 @@
     private boolean isLargeCard(ContextualCard card) {
         return card.getSliceUri().equals(CONTEXTUAL_WIFI_SLICE_URI)
                 || card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI)
-                || card.getSliceUri().equals(NOTIFICATION_CHANNEL_SLICE_URI);
+                || card.getSliceUri().equals(CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI);
     }
 
     public interface CardContentLoaderListener {
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 8f7e84a..92108f0 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -22,6 +22,7 @@
 
 import static java.util.stream.Collectors.groupingBy;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.os.Bundle;
 import android.provider.Settings;
@@ -38,9 +39,12 @@
 
 import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -96,7 +100,6 @@
         mLifecycleObservers = new ArrayList<>();
         mControllerRendererPool = new ControllerRendererPool();
         mLifecycle.addObserver(this);
-
         if (savedInstanceState == null) {
             mIsFirstLaunch = true;
             mSavedCards = null;
@@ -195,8 +198,8 @@
     @Override
     public void onFinishCardLoading(List<ContextualCard> cards) {
         final long loadTime = System.currentTimeMillis() - mStartTime;
-        //TODO(b/123668403): remove the log here once we do the change with FutureTask
         Log.d(TAG, "Total loading time = " + loadTime);
+
         final List<ContextualCard> cardsToKeep = getCardsToKeep(cards);
 
         //navigate back to the homepage, screen rotate or after card dismissal
@@ -206,15 +209,25 @@
             return;
         }
 
-        //only log homepage display upon a fresh launch
+        final MetricsFeatureProvider metricsFeatureProvider =
+                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
         final long timeoutLimit = getCardLoaderTimeout(mContext);
         if (loadTime <= timeoutLimit) {
             onContextualCardUpdated(cards.stream()
                     .collect(groupingBy(ContextualCard::getCardType)));
+        } else {
+            // log timeout occurrence
+            metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_CONTEXTUAL_CARD_LOAD_TIMEOUT,
+                    SettingsEnums.SETTINGS_HOMEPAGE,
+                    null /* key */, (int) loadTime /* value */);
         }
+        //only log homepage display upon a fresh launch
         final long totalTime = System.currentTimeMillis() - mStartTime;
         FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext)
                 .logHomepageDisplay(totalTime);
+        metricsFeatureProvider.action(mContext,
+                SettingsEnums.ACTION_CONTEXTUAL_HOME_SHOW, (int) totalTime);
 
         mIsFirstLaunch = false;
     }
@@ -228,6 +241,21 @@
         outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards);
     }
 
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        // Duplicate a list to avoid java.util.ConcurrentModificationException.
+        final List<ContextualCard> cards = new ArrayList<>(mContextualCards);
+        for (ContextualCard card : cards) {
+            final ContextualCardController controller = mControllerRendererPool
+                    .getController(mContext, card.getCardType());
+            if (hasWindowFocus && controller instanceof OnStart) {
+                ((OnStart) controller).onStart();
+            }
+            if (!hasWindowFocus && controller instanceof OnStop) {
+                ((OnStop) controller).onStop();
+            }
+        }
+    }
+
     public ControllerRendererPool getControllerRendererPool() {
         return mControllerRendererPool;
     }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index 72ddb50..bd25866 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -27,17 +27,17 @@
 
 import androidx.loader.app.LoaderManager;
 import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.overlay.FeatureFactory;
 
-public class ContextualCardsFragment extends InstrumentedFragment {
+public class ContextualCardsFragment extends InstrumentedFragment implements
+        FocusRecyclerView.FocusListener {
 
     private static final String TAG = "ContextualCardsFragment";
 
-    private RecyclerView mCardsContainer;
+    private FocusRecyclerView mCardsContainer;
     private GridLayoutManager mLayoutManager;
     private ContextualCardsAdapter mContextualCardsAdapter;
     private ContextualCardManager mContextualCardManager;
@@ -72,11 +72,17 @@
                 this /* lifecycleOwner */, mContextualCardManager);
         mCardsContainer.setAdapter(mContextualCardsAdapter);
         mContextualCardManager.setListener(mContextualCardsAdapter);
+        mCardsContainer.setListener(this);
 
         return rootView;
     }
 
     @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        mContextualCardManager.onWindowFocusChanged(hasWindowFocus);
+    }
+
+    @Override
     public int getMetricsCategory() {
         return SettingsEnums.SETTINGS_HOMEPAGE;
     }
diff --git a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
index fe68d02..811aaa2 100644
--- a/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
+++ b/src/com/android/settings/homepage/contextualcards/EligibleCardChecker.java
@@ -18,6 +18,7 @@
 
 import static android.app.slice.Slice.HINT_ERROR;
 
+import android.app.settings.SettingsEnums;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.net.Uri;
@@ -27,6 +28,9 @@
 import androidx.slice.Slice;
 import androidx.slice.SliceViewManager;
 
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -46,7 +50,32 @@
 
     @Override
     public ContextualCard call() throws Exception {
-        return isCardEligibleToDisplay(mCard) ? mCard : null;
+        final long startTime = System.currentTimeMillis();
+        final MetricsFeatureProvider metricsFeatureProvider =
+                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
+        ContextualCard result;
+
+        if (isCardEligibleToDisplay(mCard)) {
+            metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_CONTEXTUAL_CARD_ELIGIBILITY,
+                    SettingsEnums.SETTINGS_HOMEPAGE,
+                    mCard.getTextSliceUri() /* key */, 1 /* true */);
+            result = mCard;
+        } else {
+            metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                    SettingsEnums.ACTION_CONTEXTUAL_CARD_ELIGIBILITY,
+                    SettingsEnums.SETTINGS_HOMEPAGE,
+                    mCard.getTextSliceUri() /* key */, 0 /* false */);
+            result = null;
+        }
+        // Log individual card loading time
+        metricsFeatureProvider.action(SettingsEnums.PAGE_UNKNOWN,
+                SettingsEnums.ACTION_CONTEXTUAL_CARD_LOAD,
+                SettingsEnums.SETTINGS_HOMEPAGE,
+                mCard.getTextSliceUri() /* key */,
+                (int) (System.currentTimeMillis() - startTime) /* value */);
+
+        return result;
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java b/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java
new file mode 100644
index 0000000..a2ec9af
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java
@@ -0,0 +1,36 @@
+package com.android.settings.homepage.contextualcards;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+public class FocusRecyclerView extends RecyclerView {
+
+    private FocusListener mListener;
+
+    public FocusRecyclerView(Context context) {
+        super(context);
+    }
+
+    public FocusRecyclerView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        if (mListener != null) {
+            mListener.onWindowFocusChanged(hasWindowFocus);
+        }
+    }
+
+    public void setListener(FocusListener listener) {
+        mListener = listener;
+    }
+
+    public interface FocusListener {
+        void onWindowFocusChanged(boolean hasWindowFocus);
+    }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index 7bbe430..86fee03 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -56,10 +56,12 @@
                         .setCardName(CustomSliceRegistry.BATTERY_FIX_SLICE_URI.toString())
                         .setCardCategory(ContextualCard.Category.IMPORTANT)
                         .build();
+        final String contextualNotificationChannelSliceUri =
+                CustomSliceRegistry.CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI.toString();
         final ContextualCard notificationChannelCard =
                 ContextualCard.newBuilder()
-                        .setSliceUri(CustomSliceRegistry.NOTIFICATION_CHANNEL_SLICE_URI.toString())
-                        .setCardName(CustomSliceRegistry.NOTIFICATION_CHANNEL_SLICE_URI.toString())
+                        .setSliceUri(contextualNotificationChannelSliceUri)
+                        .setCardName(contextualNotificationChannelSliceUri)
                         .setCardCategory(ContextualCard.Category.POSSIBLE)
                         .build();
         final ContextualCardList cards = ContextualCardList.newBuilder()
@@ -72,4 +74,4 @@
 
         return cards;
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java b/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
index c741b98..66f6c81 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/ConditionManager.java
@@ -162,6 +162,7 @@
         mCardControllers.add(new RingerVibrateConditionController(mAppContext, this /* manager */));
         mCardControllers.add(new RingerMutedConditionController(mAppContext, this /* manager */));
         mCardControllers.add(new WorkModeConditionController(mAppContext, this /* manager */));
+        mCardControllers.add(new GrayscaleConditionController(mAppContext, this /* manager */));
     }
 
     /**
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java
new file mode 100644
index 0000000..664707d
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards.conditional;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.display.ColorDisplayManager;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.ContextualCard;
+
+import java.net.URISyntaxException;
+import java.util.Objects;
+
+public class GrayscaleConditionController implements ConditionalCardController {
+    static final int ID = Objects.hash("GrayscaleConditionController");
+
+    private static final String TAG = "GrayscaleCondition";
+
+    private final Context mAppContext;
+    private final ConditionManager mConditionManager;
+    private final ColorDisplayManager mColorDisplayManager;
+
+    private Intent mIntent;
+
+    public GrayscaleConditionController(Context appContext, ConditionManager conditionManager) {
+        mAppContext = appContext;
+        mConditionManager = conditionManager;
+        mColorDisplayManager = mAppContext.getSystemService(ColorDisplayManager.class);
+    }
+
+    @Override
+    public long getId() {
+        return ID;
+    }
+
+    @Override
+    public boolean isDisplayable() {
+        try {
+            mIntent = Intent.parseUri(
+                    mAppContext.getString(R.string.config_grayscale_settings_intent),
+                    Intent.URI_INTENT_SCHEME);
+        } catch (URISyntaxException e) {
+            Log.w(TAG, "Failure parsing grayscale settings intent, skipping", e);
+            return false;
+        }
+        return mColorDisplayManager.isSaturationActivated();
+    }
+
+    @Override
+    public void onPrimaryClick(Context context) {
+        mAppContext.startActivity(mIntent);
+    }
+
+    @Override
+    public void onActionClick() {
+        // Turn off grayscale
+        mColorDisplayManager.setSaturationLevel(100 /* staturationLevel */);
+        mConditionManager.onConditionChanged();
+    }
+
+    @Override
+    public ContextualCard buildContextualCard() {
+        return new ConditionalContextualCard.Builder()
+                .setConditionId(ID)
+                .setMetricsConstant(SettingsEnums.SETTINGS_CONDITION_GRAYSCALE_MODE)
+                .setActionText(mAppContext.getText(R.string.condition_turn_off))
+                .setName(mAppContext.getPackageName() + "/" + mAppContext.getText(
+                        R.string.condition_grayscale_title))
+                .setTitleText(mAppContext.getText(R.string.condition_grayscale_title).toString())
+                .setSummaryText(
+                        mAppContext.getText(R.string.condition_grayscale_summary).toString())
+                .setIconDrawable(mAppContext.getDrawable(R.drawable.ic_gray_scale_24dp))
+                .setViewType(ConditionContextualCardRenderer.VIEW_TYPE_HALF_WIDTH)
+                .build();
+    }
+
+    @Override
+    public void startMonitoringStateChange() {
+
+    }
+
+    @Override
+    public void stopMonitoringStateChange() {
+
+    }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index 99fe219..a760eff 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -46,7 +46,6 @@
 import com.android.settings.slices.CustomSliceable;
 import com.android.settings.slices.SliceBroadcastReceiver;
 import com.android.settings.slices.SliceBuilderUtils;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 
@@ -211,8 +210,9 @@
 
     @VisibleForTesting
     IconCompat getBluetoothDeviceIcon(CachedBluetoothDevice device) {
-        final Pair<Drawable, String> pair = BluetoothUtils
-                .getBtClassDrawableWithDescription(mContext, device);
+        final Pair<Drawable, String> pair =
+                com.android.settings.bluetooth.Utils.getBtRainbowDrawableWithDescription(mContext,
+                        device);
         final Drawable drawable = pair.first;
 
         // Use default bluetooth icon if can't get icon.
@@ -221,14 +221,6 @@
                     com.android.internal.R.drawable.ic_settings_bluetooth);
         }
 
-        // Tint icon: Accent color for connected state; Disable color for busy state.
-        @ColorInt int color = Utils.getColorAccentDefaultColor(mContext);
-        if (device.isBusy()) {
-            color = Utils.getDisabled(mContext,
-                    Utils.getColorAttrDefaultColor(mContext, android.R.attr.colorControlNormal));
-        }
-        drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
-
         return Utils.createIconWithDrawable(drawable);
     }
 
diff --git a/src/com/android/settings/homepage/contextualcards/slices/ContextualNotificationChannelSlice.java b/src/com/android/settings/homepage/contextualcards/slices/ContextualNotificationChannelSlice.java
new file mode 100644
index 0000000..2025a06
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/slices/ContextualNotificationChannelSlice.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards.slices;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.settings.R;
+import com.android.settings.slices.CustomSliceRegistry;
+
+public class ContextualNotificationChannelSlice extends NotificationChannelSlice {
+
+    public ContextualNotificationChannelSlice(Context context) {
+        super(context);
+    }
+
+    @Override
+    public Uri getUri() {
+        return CustomSliceRegistry.CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI;
+    }
+
+    @Override
+    protected CharSequence getSubTitle(String packageName, int uid) {
+        return mContext.getText(R.string.recently_installed_app);
+    }
+}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
index ae8b80a..c319dca 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
@@ -128,7 +128,7 @@
                 return leftChannel.getId().compareTo(rightChannel.getId());
             };
 
-    private final Context mContext;
+    protected final Context mContext;
     @VisibleForTesting
     NotificationBackend mNotificationBackend;
     private String mPackageName;
@@ -413,7 +413,7 @@
         return maxSentCountPackage;
     }
 
-    private CharSequence getSubTitle(String packageName, int uid) {
+    protected CharSequence getSubTitle(String packageName, int uid) {
         final int channelCount = mNotificationBackend.getChannelCount(packageName, uid);
 
         if (channelCount > DEFAULT_EXPANDED_ROW_COUNT) {
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
index ee63536..ef0a67d 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.homepage.contextualcards.slices;
 
-import android.animation.LayoutTransition;
 import android.content.Context;
 import android.view.View;
 
@@ -95,7 +94,6 @@
         public SliceViewHolder(View view) {
             super(view);
             sliceView = view.findViewById(R.id.slice_view);
-            sliceView.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
         }
     }
 }
diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
index a76d381..e4c64f7 100644
--- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
+++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java
@@ -104,7 +104,7 @@
                         .setOnClickListener((v) -> {
                             final Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
                             intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
-                                    Manifest.permission_group.LOCATION);
+                                    Manifest.permission.ACCESS_FINE_LOCATION);
                             intent.putExtra(Intent.EXTRA_PACKAGE_NAME, access.packageName);
                             intent.putExtra(Intent.EXTRA_USER, access.userHandle);
                             mContext.startActivity(intent);
diff --git a/src/com/android/settings/media/MediaOutputIndicatorSlice.java b/src/com/android/settings/media/MediaOutputIndicatorSlice.java
new file mode 100644
index 0000000..eb0c81f
--- /dev/null
+++ b/src/com/android/settings/media/MediaOutputIndicatorSlice.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.media;
+
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+
+import android.annotation.ColorInt;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.builders.ListBuilder;
+import androidx.slice.builders.SliceAction;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settingslib.media.MediaOutputSliceConstants;
+
+public class MediaOutputIndicatorSlice implements CustomSliceable {
+
+    private Context mContext;
+    @VisibleForTesting
+    MediaOutputIndicatorWorker mWorker;
+
+    public MediaOutputIndicatorSlice(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public Slice getSlice() {
+        if (!getWorker().isVisible()) {
+            return null;
+        }
+        final IconCompat icon = IconCompat.createWithResource(mContext,
+                com.android.internal.R.drawable.ic_settings_bluetooth);
+        final CharSequence title = mContext.getText(R.string.media_output_title);
+        final PendingIntent primaryActionIntent = PendingIntent.getActivity(mContext,
+                0 /* requestCode */, getMediaOutputSliceIntent(), 0 /* flags */);
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(
+                primaryActionIntent, icon, ListBuilder.ICON_IMAGE, title);
+        @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
+
+        final ListBuilder listBuilder = new ListBuilder(mContext,
+                MEDIA_OUTPUT_INDICATOR_SLICE_URI,
+                ListBuilder.INFINITY)
+                .setAccentColor(color)
+                .addRow(new ListBuilder.RowBuilder()
+                        .setTitle(title)
+                        .setSubtitle(getWorker().findActiveDeviceName())
+                        .setPrimaryAction(primarySliceAction));
+        return listBuilder.build();
+    }
+
+    private MediaOutputIndicatorWorker getWorker() {
+        if (mWorker == null) {
+            mWorker = (MediaOutputIndicatorWorker) SliceBackgroundWorker.getInstance(getUri());
+        }
+        return mWorker;
+    }
+
+    private Intent getMediaOutputSliceIntent() {
+        final Intent intent = new Intent()
+                .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        return intent;
+    }
+
+    @Override
+    public Uri getUri() {
+        return MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+    }
+
+    @Override
+    public Intent getIntent() {
+        // This Slice reflects active media device information and launch MediaOutputSlice. It does
+        // not contain its owned Slice data
+        return null;
+    }
+
+    @Override
+    public Class getBackgroundWorkerClass() {
+        return MediaOutputIndicatorWorker.class;
+    }
+}
diff --git a/src/com/android/settings/media/MediaOutputIndicatorWorker.java b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
new file mode 100644
index 0000000..adee055
--- /dev/null
+++ b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.media;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.internal.util.CollectionUtils;
+import com.android.settings.R;
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Listener for background change from {@code BluetoothCallback} to update media output indicator.
+ */
+public class MediaOutputIndicatorWorker extends SliceBackgroundWorker implements BluetoothCallback {
+
+    private static final String TAG = "MediaOutputIndicatorWorker";
+
+    private LocalBluetoothManager mLocalBluetoothManager;
+    private LocalBluetoothProfileManager mProfileManager;
+
+    public MediaOutputIndicatorWorker(Context context, Uri uri) {
+        super(context, uri);
+    }
+
+    @Override
+    protected void onSlicePinned() {
+        LocalBluetoothManager mLocalBluetoothManager = Utils.getLocalBtManager(getContext());
+        if (mLocalBluetoothManager == null) {
+            Log.e(TAG, "Bluetooth is not supported on this device");
+            return;
+        }
+        mProfileManager = mLocalBluetoothManager.getProfileManager();
+        mLocalBluetoothManager.getEventManager().registerCallback(this);
+    }
+
+    @Override
+    protected void onSliceUnpinned() {
+        if (mLocalBluetoothManager == null) {
+            Log.e(TAG, "Bluetooth is not supported on this device");
+            return;
+        }
+        mLocalBluetoothManager.getEventManager().unregisterCallback(this);
+    }
+
+    @Override
+    public void close() throws IOException {
+        mLocalBluetoothManager = null;
+        mProfileManager = null;
+    }
+
+    @Override
+    public void onBluetoothStateChanged(int bluetoothState) {
+        // To handle the case that Bluetooth on and no connected devices
+        notifySliceChange();
+    }
+
+    @Override
+    public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {
+        if (bluetoothProfile == BluetoothProfile.A2DP) {
+            notifySliceChange();
+        }
+    }
+
+    /**
+     * To decide Slice's visibility.
+     *
+     * @return true if device is connected or previously connected, false for other cases.
+     */
+    public boolean isVisible() {
+        return !CollectionUtils.isEmpty(getConnectableA2dpDevices())
+                || !CollectionUtils.isEmpty(getConnectableHearingAidDevices());
+    }
+
+    private List<BluetoothDevice> getConnectableA2dpDevices() {
+        // get A2dp devices on all states
+        // (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED,  STATE_DISCONNECTING)
+        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+        if (a2dpProfile == null) {
+            return new ArrayList<>();
+        }
+        return a2dpProfile.getConnectableDevices();
+    }
+
+    private List<BluetoothDevice> getConnectableHearingAidDevices() {
+        // get hearing aid profile devices on all states
+        // (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED,  STATE_DISCONNECTING)
+        final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
+        if (hapProfile == null) {
+            return new ArrayList<>();
+        }
+
+        return hapProfile.getConnectableDevices();
+    }
+
+    /**
+     * Get active devices name.
+     *
+     * @return active Bluetooth device alias, or default summary if no active device.
+     */
+    public CharSequence findActiveDeviceName() {
+        // Return Hearing Aid device name if it is active
+        BluetoothDevice activeDevice = findActiveHearingAidDevice();
+        if (activeDevice != null) {
+            return activeDevice.getAliasName();
+        }
+        // Return A2DP device name if it is active
+        final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+        if (a2dpProfile != null) {
+            activeDevice = a2dpProfile.getActiveDevice();
+            if (activeDevice != null) {
+                return activeDevice.getAliasName();
+            }
+        }
+        // No active device, return default summary
+        return getContext().getText(R.string.media_output_default_summary);
+    }
+
+    private BluetoothDevice findActiveHearingAidDevice() {
+        final HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile();
+        if (hearingAidProfile == null) {
+            return null;
+        }
+
+        final List<BluetoothDevice> activeDevices = hearingAidProfile.getActiveDevices();
+        for (BluetoothDevice btDevice : activeDevices) {
+            if (btDevice != null) {
+                return btDevice;
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index 232986c..e76bc88 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -76,6 +76,11 @@
             return null;
         }
 
+        if (getWorker() == null) {
+            Log.d(TAG, "getSlice() Can not get worker through uri!");
+            return null;
+        }
+
         final List<MediaDevice> devices = getMediaDevices();
         @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
 
@@ -115,13 +120,15 @@
     private MediaDeviceUpdateWorker getWorker() {
         if (mWorker == null) {
             mWorker = (MediaDeviceUpdateWorker) SliceBackgroundWorker.getInstance(getUri());
-            mWorker.setPackageName(mPackageName);
+            if (mWorker != null) {
+                mWorker.setPackageName(mPackageName);
+            }
         }
         return mWorker;
     }
 
     private List<MediaDevice> getMediaDevices() {
-        List<MediaDevice> devices = getWorker().getMediaDevices();
+        final List<MediaDevice> devices = getWorker().getMediaDevices();
         return devices;
     }
 
diff --git a/src/com/android/settings/network/telephony/NetworkSelectSettings.java b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
index d70bd62..47db875 100644
--- a/src/com/android/settings/network/telephony/NetworkSelectSettings.java
+++ b/src/com/android/settings/network/telephony/NetworkSelectSettings.java
@@ -27,7 +27,7 @@
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
-import android.telephony.NetworkRegistrationState;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -304,7 +304,7 @@
      * Config the connected network operator preference when the page was created. When user get
      * into this page, the device might or might not have data connection.
      * - If the device has data:
-     * 1. use {@code ServiceState#getNetworkRegistrationStates()} to get the currently
+     * 1. use {@code ServiceState#getNetworkRegistrationInfoList()} to get the currently
      * registered cellIdentity, wrap it into a CellInfo;
      * 2. set the signal strength level as strong;
      * 3. use {@link TelephonyManager#getNetworkOperatorName()} to get the title of the
@@ -317,8 +317,8 @@
         if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
             // Try to get the network registration states
             ServiceState ss = mTelephonyManager.getServiceState();
-            List<NetworkRegistrationState> networkList =
-                    ss.getNetworkRegistrationStatesForTransportType(
+            List<NetworkRegistrationInfo> networkList =
+                    ss.getNetworkRegistrationInfoListForTransportType(
                             AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
             if (networkList == null || networkList.size() == 0) {
                 // Remove the connected network operators category
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 5fd26a6..3ccca00 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.notification;
 
-import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.settings.SettingsEnums;
@@ -26,8 +24,6 @@
 import android.os.Bundle;
 import android.text.TextUtils;
 import android.util.Log;
-import android.view.Window;
-import android.view.WindowManager;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
@@ -88,8 +84,6 @@
     public void onResume() {
         super.onResume();
 
-        getActivity().getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
-
         if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
             Log.w(TAG, "Missing package or uid or packageinfo");
             finish();
@@ -124,15 +118,6 @@
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
-        final Window window = getActivity().getWindow();
-        final WindowManager.LayoutParams attrs = window.getAttributes();
-        attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
-        window.setAttributes(attrs);
-    }
-
-    @Override
     protected String getLogTag() {
         return TAG;
     }
diff --git a/src/com/android/settings/notification/AssistantCapabilityPreferenceController.java b/src/com/android/settings/notification/AssistantCapabilityPreferenceController.java
new file mode 100644
index 0000000..be90a04
--- /dev/null
+++ b/src/com/android/settings/notification/AssistantCapabilityPreferenceController.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.service.notification.Adjustment;
+
+import com.android.settings.core.TogglePreferenceController;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import java.util.List;
+
+public class AssistantCapabilityPreferenceController extends TogglePreferenceController {
+
+    static final String PRIORITIZER_KEY = "asst_capability_prioritizer";
+    static final String SMART_KEY = "asst_capabilities_actions_replies";
+    private NotificationBackend mBackend;
+
+    public AssistantCapabilityPreferenceController(Context context, String key) {
+        super(context, key);
+        mBackend = new NotificationBackend();
+    }
+
+    @VisibleForTesting
+    void setBackend(NotificationBackend backend) {
+        mBackend = backend;
+    }
+
+    @Override
+    public boolean isChecked() {
+        List<String> capabilities = mBackend.getAssistantCapabilities(mContext.getPackageName());
+        if (PRIORITIZER_KEY.equals(getPreferenceKey())) {
+           return capabilities.contains(Adjustment.KEY_IMPORTANCE);
+        } else if (SMART_KEY.equals(getPreferenceKey())) {
+            return capabilities.contains(Adjustment.KEY_CONTEXTUAL_ACTIONS)
+                    && capabilities.contains(Adjustment.KEY_TEXT_REPLIES);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        if (PRIORITIZER_KEY.equals(getPreferenceKey())) {
+            mBackend.allowAssistantCapability(Adjustment.KEY_IMPORTANCE, isChecked);
+        } else if (SMART_KEY.equals(getPreferenceKey())) {
+            mBackend.allowAssistantCapability(Adjustment.KEY_CONTEXTUAL_ACTIONS, isChecked);
+            mBackend.allowAssistantCapability(Adjustment.KEY_TEXT_REPLIES, isChecked);
+        }
+        return true;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mBackend.getAllowedNotificationAssistant() != null
+                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+    }
+}
+
+
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index ba07438..4227050 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -339,6 +339,27 @@
         }
     }
 
+    public void allowAssistantCapability(String capability, boolean allowed) {
+        try {
+            if (allowed) {
+                sINM.allowAssistantCapability(capability);
+            } else {
+                sINM.disallowAssistantCapability(capability);
+            }
+        } catch (Exception e) {
+            Log.w(TAG, "Error calling NoMan", e);
+        }
+    }
+
+    public List<String> getAssistantCapabilities(String pkg) {
+        try {
+            return sINM.getAllowedAssistantCapabilities(pkg);
+        } catch (Exception e) {
+            Log.w(TAG, "Error calling NoMan", e);
+        }
+        return new ArrayList<>();
+    }
+
     protected void recordAggregatedUsageEvents(Context context, AppRow appRow) {
         long now = System.currentTimeMillis();
         long startTime = now - (DateUtils.DAY_IN_MILLIS * DAYS_TO_CHECK);
diff --git a/src/com/android/settings/notification/ZenAccessSettings.java b/src/com/android/settings/notification/ZenAccessSettings.java
index d057c75..fca8255 100644
--- a/src/com/android/settings/notification/ZenAccessSettings.java
+++ b/src/com/android/settings/notification/ZenAccessSettings.java
@@ -18,56 +18,40 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
-import android.app.AppGlobals;
-import android.app.Dialog;
 import android.app.NotificationManager;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.RemoteException;
 import android.provider.SearchIndexableResource;
-import android.provider.Settings.Secure;
-import android.text.TextUtils;
 import android.util.ArraySet;
-import android.util.Log;
 import android.view.View;
 
-import androidx.annotation.VisibleForTesting;
-import androidx.appcompat.app.AlertDialog;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
 import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
 
 import com.android.settings.R;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessController;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessDetails;
+import com.android.settings.applications.specialaccess.zenaccess.ZenAccessSettingObserverMixin;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
-import com.android.settings.widget.AppSwitchPreference;
 import com.android.settings.widget.EmptyTextSettings;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.apppreference.AppPreference;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 @SearchIndexable
-public class ZenAccessSettings extends EmptyTextSettings {
+public class ZenAccessSettings extends EmptyTextSettings implements
+        ZenAccessSettingObserverMixin.Listener {
     private final String TAG = "ZenAccessSettings";
 
-    private final SettingObserver mObserver = new SettingObserver();
     private Context mContext;
     private PackageManager mPkgMan;
     private NotificationManager mNoMan;
@@ -84,6 +68,8 @@
         mContext = getActivity();
         mPkgMan = mContext.getPackageManager();
         mNoMan = mContext.getSystemService(NotificationManager.class);
+        getSettingsLifecycle().addObserver(
+                new ZenAccessSettingObserverMixin(getContext(), this /* listener */));
     }
 
     @Override
@@ -102,30 +88,22 @@
         super.onResume();
         if (!ActivityManager.isLowRamDeviceStatic()) {
             reloadList();
-            getContentResolver().registerContentObserver(
-                    Secure.getUriFor(Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), false,
-                    mObserver);
-            getContentResolver().registerContentObserver(
-                    Secure.getUriFor(Secure.ENABLED_NOTIFICATION_LISTENERS), false,
-                    mObserver);
         } else {
             setEmptyText(R.string.disabled_low_ram_device);
         }
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
-        if (!ActivityManager.isLowRamDeviceStatic()) {
-            getContentResolver().unregisterContentObserver(mObserver);
-        }
+    public void onZenAccessPolicyChanged() {
+        reloadList();
     }
 
     private void reloadList() {
         final PreferenceScreen screen = getPreferenceScreen();
         screen.removeAll();
         final ArrayList<ApplicationInfo> apps = new ArrayList<>();
-        final ArraySet<String> requesting = getPackagesRequestingNotificationPolicyAccess();
+        final Set<String> requesting =
+                ZenAccessController.getPackagesRequestingNotificationPolicyAccess();
         if (!requesting.isEmpty()) {
             final List<ApplicationInfo> installed = mPkgMan.getInstalledApplications(0);
             if (installed != null) {
@@ -143,204 +121,42 @@
         for (ApplicationInfo app : apps) {
             final String pkg = app.packageName;
             final CharSequence label = app.loadLabel(mPkgMan);
-            final SwitchPreference pref = new AppSwitchPreference(getPrefContext());
+            final AppPreference pref = new AppPreference(getPrefContext());
             pref.setKey(pkg);
-            pref.setPersistent(false);
             pref.setIcon(app.loadIcon(mPkgMan));
             pref.setTitle(label);
-            pref.setChecked(hasAccess(pkg));
             if (autoApproved.contains(pkg)) {
+                //Auto approved, user cannot do anything. Hard code summary and disable preference.
                 pref.setEnabled(false);
                 pref.setSummary(getString(R.string.zen_access_disabled_package_warning));
+            } else {
+                // Not auto approved, update summary according to notification backend.
+                pref.setSummary(getPreferenceSummary(pkg));
             }
-            pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-                @Override
-                public boolean onPreferenceChange(Preference preference, Object newValue) {
-                    final boolean access = (Boolean) newValue;
-                    if (access) {
-                        new ScaryWarningDialogFragment()
-                                .setPkgInfo(pkg, label)
-                                .show(getFragmentManager(), "dialog");
-                    } else {
-                        new FriendlyWarningDialogFragment()
-                                .setPkgInfo(pkg, label)
-                                .show(getFragmentManager(), "dialog");
-                    }
-                    return false;
-                }
+            pref.setOnPreferenceClickListener(preference -> {
+                AppInfoBase.startAppInfoFragment(
+                        ZenAccessDetails.class  /* fragment */,
+                        R.string.manage_zen_access_title /* titleRes */,
+                        pkg,
+                        app.uid,
+                        this /* source */,
+                        -1 /* requestCode */,
+                        getMetricsCategory() /* sourceMetricsCategory */);
+                return true;
             });
+
             screen.addPreference(pref);
         }
     }
 
-    private ArraySet<String> getPackagesRequestingNotificationPolicyAccess() {
-        ArraySet<String> requestingPackages = new ArraySet<>();
-        try {
-            final String[] PERM = {
-                    android.Manifest.permission.ACCESS_NOTIFICATION_POLICY
-            };
-            final ParceledListSlice list = AppGlobals.getPackageManager()
-                    .getPackagesHoldingPermissions(PERM, 0 /*flags*/,
-                            ActivityManager.getCurrentUser());
-            final List<PackageInfo> pkgs = list.getList();
-            if (pkgs != null) {
-                for (PackageInfo info : pkgs) {
-                    requestingPackages.add(info.packageName);
-                }
-            }
-        } catch(RemoteException e) {
-            Log.e(TAG, "Cannot reach packagemanager", e);
-        }
-        return requestingPackages;
-    }
-
-    private boolean hasAccess(String pkg) {
-        return mNoMan.isNotificationPolicyAccessGrantedForPackage(pkg);
-    }
-
-    private static void setAccess(final Context context, final String pkg, final boolean access) {
-        logSpecialPermissionChange(access, pkg, context);
-        AsyncTask.execute(new Runnable() {
-            @Override
-            public void run() {
-                final NotificationManager mgr = context.getSystemService(NotificationManager.class);
-                mgr.setNotificationPolicyAccessGranted(pkg, access);
-            }
-        });
-    }
-
-    @VisibleForTesting
-    static void logSpecialPermissionChange(boolean enable, String packageName, Context context) {
-        int logCategory = enable ? SettingsEnums.APP_SPECIAL_PERMISSION_DND_ALLOW
-                : SettingsEnums.APP_SPECIAL_PERMISSION_DND_DENY;
-        FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
-                logCategory, packageName);
-    }
-
-
-    private static void deleteRules(final Context context, final String pkg) {
-        AsyncTask.execute(new Runnable() {
-            @Override
-            public void run() {
-                final NotificationManager mgr = context.getSystemService(NotificationManager.class);
-                mgr.removeAutomaticZenRules(pkg);
-            }
-        });
-    }
-
-    private final class SettingObserver extends ContentObserver {
-        public SettingObserver() {
-            super(new Handler(Looper.getMainLooper()));
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            reloadList();
-        }
-    }
-
     /**
-     * Warning dialog when allowing zen access warning about the privileges being granted.
+     * @return the summary for the current state of whether the app associated with the given
+     * {@param packageName} is allowed to enter picture-in-picture.
      */
-    public static class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
-        static final String KEY_PKG = "p";
-        static final String KEY_LABEL = "l";
-
-        @Override
-        public int getMetricsCategory() {
-            return SettingsEnums.DIALOG_ZEN_ACCESS_GRANT;
-        }
-
-        public ScaryWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
-            Bundle args = new Bundle();
-            args.putString(KEY_PKG, pkg);
-            args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
-            setArguments(args);
-            return this;
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            final Bundle args = getArguments();
-            final String pkg = args.getString(KEY_PKG);
-            final String label = args.getString(KEY_LABEL);
-
-            final String title = getResources().getString(R.string.zen_access_warning_dialog_title,
-                    label);
-            final String summary = getResources()
-                    .getString(R.string.zen_access_warning_dialog_summary);
-            return new AlertDialog.Builder(getContext())
-                    .setMessage(summary)
-                    .setTitle(title)
-                    .setCancelable(true)
-                    .setPositiveButton(R.string.allow,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    setAccess(getContext(), pkg, true);
-                                }
-                            })
-                    .setNegativeButton(R.string.deny,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    // pass
-                                }
-                            })
-                    .create();
-        }
-    }
-
-    /**
-     * Warning dialog when revoking zen access warning that zen rule instances will be deleted.
-     */
-    public static class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
-        static final String KEY_PKG = "p";
-        static final String KEY_LABEL = "l";
-
-
-        @Override
-        public int getMetricsCategory() {
-            return SettingsEnums.DIALOG_ZEN_ACCESS_REVOKE;
-        }
-
-        public FriendlyWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
-            Bundle args = new Bundle();
-            args.putString(KEY_PKG, pkg);
-            args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
-            setArguments(args);
-            return this;
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            final Bundle args = getArguments();
-            final String pkg = args.getString(KEY_PKG);
-            final String label = args.getString(KEY_LABEL);
-
-            final String title = getResources().getString(
-                    R.string.zen_access_revoke_warning_dialog_title, label);
-            final String summary = getResources()
-                    .getString(R.string.zen_access_revoke_warning_dialog_summary);
-            return new AlertDialog.Builder(getContext())
-                    .setMessage(summary)
-                    .setTitle(title)
-                    .setCancelable(true)
-                    .setPositiveButton(R.string.okay,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    deleteRules(getContext(), pkg);
-                                    setAccess(getContext(), pkg, false);
-                                }
-                            })
-                    .setNegativeButton(R.string.cancel,
-                            new DialogInterface.OnClickListener() {
-                                public void onClick(DialogInterface dialog, int id) {
-                                    // pass
-                                }
-                            })
-                    .create();
-        }
+    private int getPreferenceSummary(String packageName) {
+        final boolean enabled = ZenAccessController.hasAccess(getContext(), packageName);
+        return enabled ? R.string.app_permission_summary_allowed
+                : R.string.app_permission_summary_not_allowed;
     }
 
     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 23136a4..d9af345 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -20,6 +20,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+
 import com.android.settings.R;
 import com.android.settings.accounts.AccountFeatureProvider;
 import com.android.settings.applications.ApplicationFeatureProvider;
@@ -50,6 +52,7 @@
     private static final boolean DEBUG = false;
 
     protected static FeatureFactory sFactory;
+    protected static Context sAppContext;
 
     /**
      * Returns a factory for creating feature controllers. Creates the factory if it does not
@@ -60,6 +63,9 @@
         if (sFactory != null) {
             return sFactory;
         }
+        if (sAppContext == null) {
+            sAppContext = context.getApplicationContext();
+        }
 
         if (DEBUG) Log.d(LOG_TAG, "getFactory");
         final String clsName = context.getString(R.string.config_featureFactory);
@@ -76,6 +82,16 @@
         return sFactory;
     }
 
+    /**
+     * Returns an application {@link Context} used to create this {@link FeatureFactory}. If the
+     * factory has not been properly created yet (aka {@link #getFactory} has not been called), this
+     * will return null.
+     */
+    @Nullable
+    public static Context getAppContext() {
+        return sAppContext;
+    }
+
     public abstract AssistGestureFeatureProvider getAssistGestureFeatureProvider();
 
     public abstract SuggestionFeatureProvider getSuggestionFeatureProvider(Context context);
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index a222d36..20421d0 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -48,16 +48,11 @@
     private RecyclerView mPanelSlices;
 
     private PanelContent mPanel;
-    private final MetricsFeatureProvider mMetricsProvider;
+    private MetricsFeatureProvider mMetricsProvider;
 
     @VisibleForTesting
     PanelSlicesAdapter mAdapter;
 
-    public PanelFragment() {
-        final Context context = getActivity();
-        mMetricsProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
-    }
-
     @Nullable
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@@ -83,6 +78,7 @@
                 .getPanelFeatureProvider()
                 .getPanel(activity, panelType, mediaPackageName);
 
+        mMetricsProvider = FeatureFactory.getFactory(activity).getMetricsFeatureProvider();
         // Log panel opened.
         mMetricsProvider.action(
                 0 /* attribution */,
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
index 62eca53..4ea7fe7 100644
--- a/src/com/android/settings/panel/VolumePanel.java
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.panel;
 
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_ALARM_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_CALL_URI;
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_MEDIA_URI;
@@ -55,6 +56,7 @@
         final List<Uri> uris = new ArrayList<>();
         uris.add(VOLUME_REMOTE_MEDIA_URI);
         uris.add(VOLUME_MEDIA_URI);
+        uris.add(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
         uris.add(VOLUME_CALL_URI);
         uris.add(VOLUME_RINGER_URI);
         uris.add(VOLUME_ALARM_URI);
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index c9d1af3..16cecc8 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -45,10 +45,10 @@
 import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.Log;
+import android.util.Pair;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.inputmethod.EditorInfo;
 import android.widget.LinearLayout;
@@ -1100,12 +1100,11 @@
         }
 
         @Override
-        protected Intent saveAndVerifyInBackground() {
+        protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
+            final boolean success = mUtils.saveLockPassword(
+                    mChosenPassword, mCurrentPassword, mRequestedQuality, mUserId);
             Intent result = null;
-            mUtils.saveLockPassword(mChosenPassword, mCurrentPassword, mRequestedQuality,
-                    mUserId);
-
-            if (mHasChallenge) {
+            if (success && mHasChallenge) {
                 byte[] token;
                 try {
                     token = mUtils.verifyPassword(mChosenPassword, mChallenge, mUserId);
@@ -1120,8 +1119,7 @@
                 result = new Intent();
                 result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
             }
-
-            return result;
+            return Pair.create(success, result);
         }
     }
 }
diff --git a/src/com/android/settings/password/ChooseLockPattern.java b/src/com/android/settings/password/ChooseLockPattern.java
index d5ad1ab..d89ad30 100644
--- a/src/com/android/settings/password/ChooseLockPattern.java
+++ b/src/com/android/settings/password/ChooseLockPattern.java
@@ -24,6 +24,7 @@
 import android.content.res.Resources.Theme;
 import android.os.Bundle;
 import android.util.Log;
+import android.util.Pair;
 import android.util.TypedValue;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -854,12 +855,11 @@
         }
 
         @Override
-        protected Intent saveAndVerifyInBackground() {
-            Intent result = null;
+        protected Pair<Boolean, Intent> saveAndVerifyInBackground() {
             final int userId = mUserId;
-            mUtils.saveLockPattern(mChosenPattern, mCurrentPattern, userId);
-
-            if (mHasChallenge) {
+            final boolean success = mUtils.saveLockPattern(mChosenPattern, mCurrentPattern, userId);
+            Intent result = null;
+            if (success && mHasChallenge) {
                 byte[] token;
                 try {
                     token = mUtils.verifyPattern(mChosenPattern, mChallenge, userId);
@@ -874,8 +874,7 @@
                 result = new Intent();
                 result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
             }
-
-            return result;
+            return Pair.create(success, result);
         }
 
         @Override
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index ec1e835..d3d5c49 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -198,7 +198,7 @@
         } else if (isManagedProfile && isInternalActivity()
                 && !lockPatternUtils.isSeparateProfileChallengeEnabled(mUserId)) {
             mCredentialMode = CREDENTIAL_MANAGED;
-            if (isBiometricAllowed(effectiveUserId)) {
+            if (isBiometricAllowed(effectiveUserId, mUserId)) {
                 showBiometricPrompt(bpBundle);
                 launchedBiometric = true;
             } else {
@@ -207,7 +207,7 @@
             }
         } else {
             mCredentialMode = CREDENTIAL_NORMAL;
-            if (isBiometricAllowed(effectiveUserId)) {
+            if (isBiometricAllowed(effectiveUserId, mUserId)) {
                 // Don't need to check if biometrics / pin/pattern/pass are enrolled. It will go to
                 // onAuthenticationError and do the right thing automatically.
                 showBiometricPrompt(bpBundle);
@@ -273,9 +273,10 @@
         return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_BIOMETRICS) != 0;
     }
 
-    private boolean isBiometricAllowed(int effectiveUserId) {
+    private boolean isBiometricAllowed(int effectiveUserId, int realUserId) {
         return !isStrongAuthRequired(effectiveUserId)
-                && !isBiometricDisabledByAdmin(effectiveUserId);
+                && !isBiometricDisabledByAdmin(effectiveUserId)
+                && !mLockPatternUtils.hasPendingEscrowToken(realUserId);
     }
 
     private void showBiometricPrompt(Bundle bundle) {
@@ -304,9 +305,18 @@
     private void showConfirmCredentials() {
         mCCLaunched = true;
         boolean launched = false;
+        // The only difference between CREDENTIAL_MANAGED and CREDENTIAL_NORMAL is that for
+        // CREDENTIAL_MANAGED, we launch the real confirm credential activity with an explicit
+        // but dummy challenge value (0L). This will result in ConfirmLockPassword calling
+        // verifyTiedProfileChallenge() (if it's a profile with unified challenge), due to the
+        // difference between ConfirmLockPassword.startVerifyPassword() and
+        // ConfirmLockPassword.startCheckPassword(). Calling verifyTiedProfileChallenge() here is
+        // necessary when this is part of the turning on work profile flow, because it forces
+        // unlocking the work profile even before the profile is running.
+        // TODO: Remove the duplication of checkPassword and verifyPassword in ConfirmLockPassword,
+        // LockPatternChecker and LockPatternUtils. verifyPassword should be the only API to use,
+        // which optionally accepts a challenge.
         if (mCredentialMode == CREDENTIAL_MANAGED) {
-            // We set the challenge as 0L, so it will force to unlock managed profile when it
-            // unlocks primary profile screen lock, by calling verifyTiedProfileChallenge()
             launched = mChooseLockSettingsHelper
                     .launchConfirmationActivityWithExternalAndChallenge(
                             0 /* request code */, null /* title */, mTitle, mDetails,
diff --git a/src/com/android/settings/password/SaveChosenLockWorkerBase.java b/src/com/android/settings/password/SaveChosenLockWorkerBase.java
index 5b6a812..2798b3d 100644
--- a/src/com/android/settings/password/SaveChosenLockWorkerBase.java
+++ b/src/com/android/settings/password/SaveChosenLockWorkerBase.java
@@ -21,10 +21,13 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.UserManager;
+import android.util.Pair;
+import android.widget.Toast;
 
 import androidx.fragment.app.Fragment;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
 
 /**
  * An invisible retained worker fragment to track the AsyncWork that saves (and optionally
@@ -84,7 +87,7 @@
 
     protected void start() {
         if (mBlocking) {
-            finish(saveAndVerifyInBackground());
+            finish(saveAndVerifyInBackground().second);
         } else {
             new Task().execute();
         }
@@ -92,9 +95,10 @@
 
     /**
      * Executes the save and verify work in background.
-     * @return Intent with challenge token or null.
+     * @return pair where the first is a boolean confirming whether the change was successful or not
+     * and second is the Intent which has the challenge token or is null.
      */
-    protected abstract Intent saveAndVerifyInBackground();
+    protected abstract Pair<Boolean, Intent> saveAndVerifyInBackground();
 
     protected void finish(Intent resultData) {
         mFinished = true;
@@ -108,19 +112,24 @@
         mBlocking = blocking;
     }
 
-    private class Task extends AsyncTask<Void, Void, Intent> {
+    private class Task extends AsyncTask<Void, Void, Pair<Boolean, Intent>> {
+
         @Override
-        protected Intent doInBackground(Void... params){
+        protected Pair<Boolean, Intent> doInBackground(Void... params){
             return saveAndVerifyInBackground();
         }
 
         @Override
-        protected void onPostExecute(Intent resultData) {
-            finish(resultData);
+        protected void onPostExecute(Pair<Boolean, Intent> resultData) {
+            if (!resultData.first) {
+                Toast.makeText(getContext(), R.string.lockpassword_credential_changed,
+                        Toast.LENGTH_LONG).show();
+            }
+            finish(resultData.second);
         }
     }
 
     interface Listener {
-        public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData);
+        void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData);
     }
 }
diff --git a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
index 704d1e5..7c55b51 100644
--- a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
+++ b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
@@ -182,10 +182,10 @@
         return barViewInfos;
     }
 
-    private Drawable getPermissionGroupIcon(CharSequence permissionGroup) {
+    private Drawable getPermissionGroupIcon(String permissionGroup) {
         Drawable icon = null;
         try {
-            icon = mPackageManager.getPermissionGroupInfo(permissionGroup.toString(), 0)
+            icon = mPackageManager.getPermissionGroupInfo(permissionGroup, 0)
                     .loadIcon(mPackageManager);
             icon.setTintList(Utils.getColorAttr(mContext, android.R.attr.textColorSecondary));
         } catch (PackageManager.NameNotFoundException e) {
@@ -195,10 +195,10 @@
         return icon;
     }
 
-    private CharSequence getPermissionGroupLabel(CharSequence permissionGroup) {
+    private CharSequence getPermissionGroupLabel(String permissionGroup) {
         CharSequence label = null;
         try {
-            label = mPackageManager.getPermissionGroupInfo(permissionGroup.toString(), 0)
+            label = mPackageManager.getPermissionGroupInfo(permissionGroup, 0)
                     .loadLabel(mPackageManager);
         } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, "Cannot find group label for " + permissionGroup, e);
diff --git a/src/com/android/settings/privacy/PrivacyDashboardFragment.java b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
index be6701e..fa21f9d 100644
--- a/src/com/android/settings/privacy/PrivacyDashboardFragment.java
+++ b/src/com/android/settings/privacy/PrivacyDashboardFragment.java
@@ -16,25 +16,22 @@
 
 package com.android.settings.privacy;
 
-import android.app.ActionBar;
-import android.app.Activity;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.os.Bundle;
 import android.provider.SearchIndexableResource;
-import android.util.Log;
 import android.view.View;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settings.R;
+import com.android.settings.Utils;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.notification.LockScreenNotificationPreferenceController;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.widget.ActionBarShadowController;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -87,29 +84,11 @@
     @Override
     public void onViewCreated(View view, Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
-        styleActionBar();
+        Utils.setActionBarShadowAnimation(getActivity(), getSettingsLifecycle(), getListView());
         initLoadingBar();
     }
 
     @VisibleForTesting
-    void styleActionBar() {
-        final Activity activity = getActivity();
-        final ActionBar actionBar = activity.getActionBar();
-        final Lifecycle lifecycle = getSettingsLifecycle();
-        final View scrollView = getListView();
-
-        if (actionBar == null) {
-            Log.w(TAG, "No actionbar, cannot style actionbar.");
-            return;
-        }
-
-        actionBar.setElevation(0);
-        if (lifecycle != null && scrollView != null) {
-            ActionBarShadowController.attachToView(activity, lifecycle, scrollView);
-        }
-    }
-
-    @VisibleForTesting
     void initLoadingBar() {
         mProgressHeader = setPinnedHeaderView(R.layout.progress_header);
         mProgressAnimation = mProgressHeader.findViewById(R.id.progress_bar_animation);
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index dcb4acc..896f6e5 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -39,7 +39,7 @@
  */
 public interface SearchFeatureProvider {
 
-    int REQUEST_CODE = 0;
+    int REQUEST_CODE = 501;
 
     /**
      * Ensures the caller has necessary privilege to launch search result page.
diff --git a/src/com/android/settings/search/actionbar/SearchMenuController.java b/src/com/android/settings/search/actionbar/SearchMenuController.java
index af7141e..25d0d30 100644
--- a/src/com/android/settings/search/actionbar/SearchMenuController.java
+++ b/src/com/android/settings/search/actionbar/SearchMenuController.java
@@ -33,6 +33,7 @@
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.SearchFeatureProvider;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
 
@@ -93,7 +94,7 @@
 
             FeatureFactory.getFactory(context).getMetricsFeatureProvider()
                     .action(context, SettingsEnums.ACTION_SEARCH_RESULTS);
-            mHost.startActivityForResult(intent, 0 /* requestCode */);
+            mHost.startActivityForResult(intent, SearchFeatureProvider.REQUEST_CODE);
             return true;
         });
     }
diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java
index cf67f5e..891d171 100644
--- a/src/com/android/settings/sim/SimSelectNotification.java
+++ b/src/com/android/settings/sim/SimSelectNotification.java
@@ -16,6 +16,12 @@
 
 package com.android.settings.sim;
 
+import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_ID;
+import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES;
+import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE;
+import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA;
+import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE;
+
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -23,19 +29,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
 
-import androidx.core.app.NotificationCompat;
-
-import com.android.internal.telephony.IccCardConstants;
 import com.android.settings.R;
 import com.android.settings.Settings.SimSettingsActivity;
-import com.android.settings.Utils;
 
-import java.util.List;
+import androidx.core.app.NotificationCompat;
 
 public class SimSelectNotification extends BroadcastReceiver {
     private static final String TAG = "SimSelectNotification";
@@ -46,71 +45,24 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        final TelephonyManager telephonyManager = (TelephonyManager)
-                context.getSystemService(Context.TELEPHONY_SERVICE);
-        final SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
-        final int numSlots = telephonyManager.getSimCount();
-
-        // Do not create notifications on single SIM devices or when provisioning i.e. Setup Wizard.
-        if (numSlots < 2 || !Utils.isDeviceProvisioned(context)) {
-            return;
-        }
-
         // Cancel any previous notifications
         cancelNotification(context);
-
-        // If sim state is not ABSENT or LOADED then ignore
-        String simStatus = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
-        if (!(IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(simStatus) ||
-                IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(simStatus))) {
-            Log.d(TAG, "sim state is not Absent or Loaded");
-            return;
-        } else {
-            Log.d(TAG, "simstatus = " + simStatus);
-        }
-
-        int state;
-        for (int i = 0; i < numSlots; i++) {
-            state = telephonyManager.getSimState(i);
-            if (!(state == TelephonyManager.SIM_STATE_ABSENT
-                    || state == TelephonyManager.SIM_STATE_READY
-                    || state == TelephonyManager.SIM_STATE_UNKNOWN)) {
-                Log.d(TAG, "All sims not in valid state yet");
-                return;
-            }
-        }
-
-        List<SubscriptionInfo> sil = subscriptionManager.getActiveSubscriptionInfoList(true);
-        if (sil == null || sil.size() < 1) {
-            Log.d(TAG, "Subscription list is empty");
-            return;
-        }
-
-        // Clear defaults for any subscriptions which no longer exist
-        subscriptionManager.clearDefaultsForInactiveSubIds();
-
-        boolean dataSelected = SubscriptionManager.isUsableSubIdValue(
-                SubscriptionManager.getDefaultDataSubscriptionId());
-        boolean smsSelected = SubscriptionManager.isUsableSubIdValue(
-                SubscriptionManager.getDefaultSmsSubscriptionId());
-
-        // If data and sms defaults are selected, dont show notification (Calls default is optional)
-        if (dataSelected && smsSelected) {
-            Log.d(TAG, "Data & SMS default sims are selected. No notification");
-            return;
-        }
-
         // Create a notification to tell the user that some defaults are missing
         createNotification(context);
 
-        if (sil.size() == 1) {
+        int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
+                EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE);
+        if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_FOR_ALL_TYPES) {
+            int subId = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_ID,
+                    SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+            int slotIndex = SubscriptionManager.getSlotIndex(subId);
             // If there is only one subscription, ask if user wants to use if for everything
             Intent newIntent = new Intent(context, SimDialogActivity.class);
             newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.PREFERRED_PICK);
-            newIntent.putExtra(SimDialogActivity.PREFERRED_SIM, sil.get(0).getSimSlotIndex());
+            newIntent.putExtra(SimDialogActivity.PREFERRED_SIM, slotIndex);
             context.startActivity(newIntent);
-        } else if (!dataSelected) {
+        } else if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA) {
             // If there are mulitple, ensure they pick default data
             Intent newIntent = new Intent(context, SimDialogActivity.class);
             newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/src/com/android/settings/sim/SimSettings.java b/src/com/android/settings/sim/SimSettings.java
index b646b3b..e43c6a5 100644
--- a/src/com/android/settings/sim/SimSettings.java
+++ b/src/com/android/settings/sim/SimSettings.java
@@ -220,7 +220,7 @@
             Log.d(TAG, "Register for call state change");
             for (int i = 0; i < mPhoneCount; i++) {
                 int subId = mSelectableSubInfos.get(i).getSubscriptionId();
-                tm.listen(getPhoneStateListener(i, subId),
+                tm.createForSubscriptionId(subId).listen(getPhoneStateListener(i),
                         PhoneStateListener.LISTEN_CALL_STATE);
             }
         }
@@ -239,13 +239,13 @@
         }
     }
 
-    private PhoneStateListener getPhoneStateListener(int phoneId, int subId) {
+    private PhoneStateListener getPhoneStateListener(int phoneId) {
         // Disable Sim selection for Data when voice call is going on as changing the default data
         // sim causes a modem reset currently and call gets disconnected
         // ToDo : Add subtext on disabled preference to let user know that default data sim cannot
         // be changed while call is going on
         final int i = phoneId;
-        mPhoneStateListener[phoneId]  = new PhoneStateListener(subId) {
+        mPhoneStateListener[phoneId]  = new PhoneStateListener() {
             @Override
             public void onCallStateChanged(int state, String incomingNumber) {
                 if (DBG) log("PhoneStateListener.onCallStateChanged: state=" + state);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 9d88bc5..fe000d1 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -36,9 +36,11 @@
 import com.android.settings.homepage.contextualcards.deviceinfo.StorageSlice;
 import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
 import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
+import com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice;
 import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
 import com.android.settings.homepage.contextualcards.slices.NotificationChannelSlice;
 import com.android.settings.location.LocationSlice;
+import com.android.settings.media.MediaOutputIndicatorSlice;
 import com.android.settings.media.MediaOutputSlice;
 import com.android.settings.network.telephony.MobileDataSlice;
 import com.android.settings.wifi.calling.WifiCallingSliceHelper;
@@ -94,6 +96,16 @@
             .build();
 
     /**
+     * Backing Uri for Contextual Notification channel Slice.
+     */
+    public static final Uri CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+            .appendPath("contextual_notification_channel")
+            .build();
+
+    /**
      * Backing Uri for the Wifi Slice.
      */
     public static final Uri CONTEXTUAL_WIFI_SLICE_URI = new Uri.Builder()
@@ -299,6 +311,16 @@
             .appendPath(MediaOutputSliceConstants.KEY_MEDIA_OUTPUT)
             .build();
 
+    /**
+     * Backing Uri for the Media output indicator Slice.
+     */
+    public static Uri MEDIA_OUTPUT_INDICATOR_SLICE_URI = new Uri.Builder()
+            .scheme(ContentResolver.SCHEME_CONTENT)
+            .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+            .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT)
+            .appendPath("media_output_indicator")
+            .build();
+
     @VisibleForTesting
     static final Map<Uri, Class<? extends CustomSliceable>> sUriToSlice;
 
@@ -307,6 +329,8 @@
 
         sUriToSlice.put(BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
         sUriToSlice.put(BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
+        sUriToSlice.put(CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI,
+                ContextualNotificationChannelSlice.class);
         sUriToSlice.put(CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
         sUriToSlice.put(DATA_USAGE_SLICE_URI, DataUsageSlice.class);
         sUriToSlice.put(DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
@@ -319,6 +343,7 @@
         sUriToSlice.put(STORAGE_SLICE_URI, StorageSlice.class);
         sUriToSlice.put(WIFI_SLICE_URI, WifiSlice.class);
         sUriToSlice.put(MEDIA_OUTPUT_SLICE_URI, MediaOutputSlice.class);
+        sUriToSlice.put(MEDIA_OUTPUT_INDICATOR_SLICE_URI, MediaOutputIndicatorSlice.class);
     }
 
     public static Class<? extends CustomSliceable> getSliceClassByUri(Uri uri) {
@@ -344,5 +369,4 @@
     public static boolean isValidAction(String action) {
         return isValidUri(Uri.parse(action));
     }
-
 }
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 3187d10..3bdcb13 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -28,12 +28,12 @@
 import android.provider.SettingsSlicesContract;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.KeyValueListParser;
 import android.util.Log;
 import android.util.Pair;
 
 import androidx.annotation.VisibleForTesting;
+import androidx.collection.ArraySet;
 import androidx.slice.Slice;
 import androidx.slice.SliceProvider;
 
@@ -53,7 +53,6 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A {@link SliceProvider} for Settings to enabled inline results in system apps.
@@ -123,9 +122,6 @@
     @VisibleForTesting
     Map<Uri, SliceData> mSliceWeakDataCache;
 
-    @VisibleForTesting
-    Map<Uri, SliceData> mSliceDataCache;
-
     final Map<Uri, SliceBackgroundWorker> mPinnedWorkers = new ArrayMap<>();
 
     public SettingsSliceProvider() {
@@ -135,7 +131,6 @@
     @Override
     public boolean onCreateSliceProvider() {
         mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
-        mSliceDataCache = new ConcurrentHashMap<>();
         mSliceWeakDataCache = new WeakHashMap<>();
         return true;
     }
@@ -170,7 +165,6 @@
     public void onSliceUnpinned(Uri sliceUri) {
         SliceBroadcastRelay.unregisterReceivers(getContext(), sliceUri);
         ThreadUtils.postOnMainThread(() -> stopBackgroundWorker(sliceUri));
-        mSliceDataCache.remove(sliceUri);
     }
 
     @Override
@@ -226,7 +220,7 @@
             }
 
             // Remove the SliceData from the cache after it has been used to prevent a memory-leak.
-            if (!mSliceDataCache.containsKey(sliceUri)) {
+            if (!getPinnedSlices().contains(sliceUri)) {
                 mSliceWeakDataCache.remove(sliceUri);
             }
             return SliceBuilderUtils.buildSlice(getContext(), cachedSliceData);
@@ -396,11 +390,6 @@
 
         ThreadUtils.postOnMainThread(() -> startBackgroundWorker(controller, uri));
 
-        final List<Uri> pinnedSlices = getContext().getSystemService(
-                SliceManager.class).getPinnedSlices();
-        if (pinnedSlices.contains(uri)) {
-            mSliceDataCache.put(uri, sliceData);
-        }
         mSliceWeakDataCache.put(uri, sliceData);
         getContext().getContentResolver().notifyChange(uri, null /* content observer */);
 
diff --git a/src/com/android/settings/slices/SlicesIndexer.java b/src/com/android/settings/slices/SlicesIndexer.java
index 1b3a25e..5f80047 100644
--- a/src/com/android/settings/slices/SlicesIndexer.java
+++ b/src/com/android/settings/slices/SlicesIndexer.java
@@ -84,7 +84,6 @@
         } finally {
             database.endTransaction();
         }
-        database.close();
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/widget/AdaptiveHomepageIcon.java b/src/com/android/settings/widget/AdaptiveIcon.java
similarity index 76%
rename from src/com/android/settings/widget/AdaptiveHomepageIcon.java
rename to src/com/android/settings/widget/AdaptiveIcon.java
index bc7aaa7..04b33ae 100644
--- a/src/com/android/settings/widget/AdaptiveHomepageIcon.java
+++ b/src/com/android/settings/widget/AdaptiveIcon.java
@@ -35,14 +35,15 @@
 import com.android.settings.homepage.AdaptiveIconShapeDrawable;
 import com.android.settingslib.drawer.Tile;
 
-public class AdaptiveHomepageIcon extends LayerDrawable {
+public class AdaptiveIcon extends LayerDrawable {
 
     private static final String TAG = "AdaptiveHomepageIcon";
 
     @VisibleForTesting(otherwise = NONE)
     int mBackgroundColor = -1;
+    private AdaptiveConstantState mAdaptiveConstantState;
 
-    public AdaptiveHomepageIcon(Context context, Drawable foreground) {
+    public AdaptiveIcon(Context context, Drawable foreground) {
         super(new Drawable[]{
                 new AdaptiveIconShapeDrawable(context.getResources()),
                 foreground
@@ -50,6 +51,7 @@
         final int insetPx = context.getResources()
                 .getDimensionPixelSize(R.dimen.dashboard_tile_foreground_image_inset);
         setLayerInset(1 /* index */, insetPx, insetPx, insetPx, insetPx);
+        mAdaptiveConstantState = new AdaptiveConstantState(context, foreground);
     }
 
     public void setBackgroundColor(Context context, Tile tile) {
@@ -85,5 +87,36 @@
         mBackgroundColor = color;
         getDrawable(0).setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
         Log.d(TAG, "Setting background color " + mBackgroundColor);
+        mAdaptiveConstantState.color = color;
+    }
+
+    @Override
+    public ConstantState getConstantState() {
+        return mAdaptiveConstantState;
+    }
+
+    @VisibleForTesting
+    static class AdaptiveConstantState extends ConstantState {
+        Context context;
+        Drawable drawable;
+        int color;
+
+        public AdaptiveConstantState(Context context, Drawable drawable) {
+            this.context = context;
+            this.drawable = drawable;
+        }
+
+        @Override
+        public Drawable newDrawable() {
+            final AdaptiveIcon icon = new AdaptiveIcon(context, drawable);
+            icon.setBackgroundColor(color);
+
+            return icon;
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return 0;
+        }
     }
 }
diff --git a/src/com/android/settings/widget/AppCheckBoxPreference.java b/src/com/android/settings/widget/AppCheckBoxPreference.java
index e56efd9..3ce67eb 100644
--- a/src/com/android/settings/widget/AppCheckBoxPreference.java
+++ b/src/com/android/settings/widget/AppCheckBoxPreference.java
@@ -21,7 +21,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import androidx.preference.CheckBoxPreference;
 import androidx.preference.PreferenceViewHolder;
@@ -46,11 +45,6 @@
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
 
-        final TextView appendix = (TextView) holder.findViewById(R.id.appendix);
-        if (appendix != null) {
-            appendix.setVisibility(View.GONE);
-        }
-
         final LinearLayout layout = (LinearLayout) holder.findViewById(R.id.summary_container);
         if (layout != null) {
             // If summary doesn't exist, make it gone
diff --git a/src/com/android/settings/widget/AppSwitchPreference.java b/src/com/android/settings/widget/AppSwitchPreference.java
index 288096e..506ab76 100644
--- a/src/com/android/settings/widget/AppSwitchPreference.java
+++ b/src/com/android/settings/widget/AppSwitchPreference.java
@@ -17,10 +17,7 @@
 package com.android.settings.widget;
 
 import android.content.Context;
-import android.text.TextUtils;
-import android.view.View;
 
-import androidx.preference.PreferenceViewHolder;
 import androidx.preference.SwitchPreference;
 
 import com.android.settings.R;
@@ -31,12 +28,4 @@
         super(context);
         setLayoutResource(R.layout.preference_app);
     }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder view) {
-        super.onBindViewHolder(view);
-
-        view.findViewById(R.id.summary_container)
-                .setVisibility(TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE);
-    }
 }
diff --git a/src/com/android/settings/wifi/AddWifiNetworkPreference.java b/src/com/android/settings/wifi/AddWifiNetworkPreference.java
new file mode 100644
index 0000000..cd2e4a8
--- /dev/null
+++ b/src/com/android/settings/wifi/AddWifiNetworkPreference.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.wifi;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageButton;
+
+import androidx.annotation.DrawableRes;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settings.wifi.dpp.WifiDppUtils;
+
+/**
+ * The Preference for users to add Wi-Fi networks in WifiSettings
+ */
+public class AddWifiNetworkPreference extends Preference {
+
+    private static final String TAG = "AddWifiNetworkPreference";
+
+    private boolean mInitialized;
+
+    public AddWifiNetworkPreference(Context context) {
+        super(context);
+
+        setLayoutResource(com.android.settingslib.R.layout.preference_access_point);
+        setWidgetLayoutResource(R.layout.wifi_button_preference_widget);
+        setIcon(R.drawable.ic_menu_add);
+        setTitle(R.string.wifi_add_network);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        if (!mInitialized) {
+            mInitialized = true;
+
+            final ImageButton imageButton = (ImageButton) holder.findViewById(R.id.button_icon);
+            imageButton.setImageDrawable(getDrawable(R.drawable.ic_scan_24dp));
+            imageButton.setContentDescription(
+                    getContext().getString(R.string.wifi_dpp_scan_qr_code));
+            imageButton.setOnClickListener(view -> {
+                getContext().startActivity(
+                    WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
+            });
+
+            final View divider = (View) holder.findViewById(
+                    com.android.settingslib.R.id.two_target_divider);
+            divider.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    private Drawable getDrawable(@DrawableRes int iconResId) {
+        Drawable buttonIcon = null;
+
+        try {
+            buttonIcon = getContext().getDrawable(iconResId);
+        } catch (Resources.NotFoundException exception) {
+            Log.e(TAG, "Resource does not exist: " + iconResId);
+        }
+        return buttonIcon;
+    }
+}
diff --git a/src/com/android/settings/wifi/ButtonPreference.java b/src/com/android/settings/wifi/ButtonPreference.java
deleted file mode 100644
index 5169d7a..0000000
--- a/src/com/android/settings/wifi/ButtonPreference.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2018 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.settings.wifi;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-import android.widget.ImageButton;
-
-import androidx.annotation.DrawableRes;
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/**
- * This preference provides one button layout with Settings style.
- * It looks like below
- *
- * --------------------------------------------------------------
- * | icon | title                                    |  button  |
- * --------------------------------------------------------------
- *
- * User can set icon / click listener for button.
- * By default, the button is invisible.
- */
-public class ButtonPreference extends Preference {
-
-    private static final String TAG = "ButtonPreference";
-
-    private ImageButton mImageButton;
-    private Drawable mButtonIcon;
-    private View.OnClickListener mClickListener;
-    private String mContentDescription;
-
-    // Used for dummy pref.
-    public ButtonPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        setWidgetLayoutResource(R.layout.wifi_button_preference_widget);
-        mImageButton = null;
-        mButtonIcon = null;
-        mClickListener = null;
-        mContentDescription = null;
-    }
-
-    public ButtonPreference(Context context) {
-        this(context, /* attrs */ null);
-    }
-
-    @Override
-    public void onBindViewHolder(final PreferenceViewHolder view) {
-        super.onBindViewHolder(view);
-        initButton(view);
-    }
-
-    @Override
-    public void setOrder(int order) {
-        super.setOrder(order);
-        setButtonVisibility();
-    }
-
-    @VisibleForTesting
-    protected void initButton(final PreferenceViewHolder view) {
-        if (mImageButton == null) {
-            mImageButton = (ImageButton) view.findViewById(R.id.button_icon);
-        }
-        if (mImageButton != null) {
-            mImageButton.setImageDrawable(mButtonIcon);
-            mImageButton.setOnClickListener(mClickListener);
-            mImageButton.setContentDescription(mContentDescription);
-        }
-        setButtonVisibility();
-    }
-
-    private void setButtonVisibility() {
-        if(mImageButton != null) {
-            mImageButton.setVisibility(mButtonIcon == null ? View.GONE : View.VISIBLE);
-        }
-    }
-
-    /**
-     * Sets the drawable to be displayed in button.
-     */
-    public void setButtonIcon(@DrawableRes int iconResId) {
-        if (iconResId == 0) {
-            return;
-        }
-
-        try {
-            mButtonIcon = getContext().getDrawable(iconResId);
-            notifyChanged();
-        } catch (Resources.NotFoundException exception) {
-            Log.e(TAG, "Resource does not exist: " + iconResId);
-        }
-    }
-
-    /**
-     * Register a callback to be invoked when button is clicked.
-     */
-    public void setButtonOnClickListener(View.OnClickListener listener) {
-        if (listener != mClickListener) {
-            mClickListener = listener;
-            notifyChanged();
-        }
-    }
-
-    /**
-     * A content description briefly describes the button and is primarily used for accessibility
-     * support to determine how a button should be presented to the user.
-     */
-    public void setButtonContentDescription(String contentDescription) {
-        if (contentDescription != mContentDescription) {
-            mContentDescription = contentDescription;
-            notifyChanged();
-        }
-    }
-}
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index ba29e3a..e9057e6 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -82,11 +82,15 @@
 
     @VisibleForTesting
     final static String EXTRA_APP_NAME = "com.android.settings.wifi.extra.APP_NAME";
+    final static String EXTRA_IS_SPECIFIED_SSID =
+            "com.android.settings.wifi.extra.REQUEST_IS_FOR_SINGLE_NETWORK";
 
     private List<AccessPoint> mAccessPointList;
     private FilterWifiTracker mFilterWifiTracker;
     private AccessPointAdapter mDialogAdapter;
     private NetworkRequestUserSelectionCallback mUserSelectionCallback;
+    private boolean mIsSpecifiedSsid;
+    private boolean mWaitingConnectCallback;
 
     public static NetworkRequestDialogFragment newInstance() {
         NetworkRequestDialogFragment dialogFragment = new NetworkRequestDialogFragment();
@@ -104,6 +108,11 @@
         final TextView title = customTitle.findViewById(R.id.network_request_title_text);
         title.setText(getTitle());
 
+        final Intent intent = getActivity().getIntent();
+        if (intent != null) {
+            mIsSpecifiedSsid = intent.getBooleanExtra(EXTRA_IS_SPECIFIED_SSID, false);
+        }
+
         final ProgressBar progressBar = customTitle.findViewById(
                 R.id.network_request_title_progress);
         progressBar.setVisibility(View.VISIBLE);
@@ -115,10 +124,13 @@
         final AlertDialog.Builder builder = new AlertDialog.Builder(context)
                 .setCustomTitle(customTitle)
                 .setAdapter(mDialogAdapter, this)
-                .setPositiveButton(R.string.cancel, (dialog, which) -> getActivity().finish())
+                .setNegativeButton(R.string.cancel, (dialog, which) -> onCancel(dialog))
                 // Do nothings, will replace the onClickListener to avoid auto closing dialog.
                 .setNeutralButton(R.string.network_connection_request_dialog_showall,
                         null /* OnClickListener */);
+        if (mIsSpecifiedSsid) {
+            builder.setPositiveButton(R.string.wifi_connect, null /* OnClickListener */);
+        }
 
         // Clicking list item is to connect wifi ap.
         final AlertDialog dialog = builder.create();
@@ -126,6 +138,10 @@
                 .setOnItemClickListener(
                         (parent, view, position, id) -> this.onClick(dialog, position));
 
+        // Don't dismiss dialog when touching outside. User report it is easy to touch outside.
+        // This causes dialog to close. Which is concerned as a bad UX (b/128877712).
+        dialog.setCanceledOnTouchOutside(false);
+
         dialog.setOnShowListener((dialogInterface) -> {
             // Replace NeutralButton onClickListener to avoid closing dialog
             final Button neutralBtn = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
@@ -136,8 +152,19 @@
                 notifyAdapterRefresh();
                 neutralBtn.setVisibility(View.GONE);
             });
-        });
 
+            // Replace Positive onClickListener to avoid closing dialog
+            if (mIsSpecifiedSsid) {
+                final Button positiveBtn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
+                positiveBtn.setOnClickListener(v -> {
+                    // When clicking connect button, should connect to the first and the only one
+                    // list item.
+                    this.onClick(dialog, 0 /* position */);
+                });
+                // Disable button in first, and enable it after there are some accesspoints in list.
+                positiveBtn.setEnabled(false);
+            }
+        });
         return dialog;
     }
 
@@ -184,6 +211,9 @@
 
             if (wifiConfig != null) {
                 mUserSelectionCallback.select(wifiConfig);
+
+                mWaitingConnectCallback = true;
+                updateConnectButton(false);
             }
         }
     }
@@ -195,6 +225,9 @@
         if (getActivity() != null) {
             getActivity().finish();
         }
+        if (mUserSelectionCallback != null) {
+            mUserSelectionCallback.reject();
+        }
     }
 
     @Override
@@ -223,7 +256,7 @@
         }
     }
 
-    private void showNeutralButton() {
+    private void showAllButton() {
         final AlertDialog alertDialog = (AlertDialog) getDialog();
         if (alertDialog == null) {
             return;
@@ -235,6 +268,35 @@
         }
     }
 
+    private void updateConnectButton(boolean enabled) {
+        // The button is only showed in single SSID mode.
+        if (!mIsSpecifiedSsid) {
+            return;
+        }
+
+        final AlertDialog alertDialog = (AlertDialog) getDialog();
+        if (alertDialog == null) {
+            return;
+        }
+
+        final Button positiveBtn = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
+        if (positiveBtn != null) {
+            positiveBtn.setEnabled(enabled);
+        }
+    }
+
+    private void hideProgressIcon() {
+        final AlertDialog alertDialog = (AlertDialog) getDialog();
+        if (alertDialog == null) {
+            return;
+        }
+
+        final View progress = alertDialog.findViewById(R.id.network_request_title_progress);
+        if (progress != null) {
+            progress.setVisibility(View.GONE);
+        }
+    }
+
     @Override
     public void onResume() {
         super.onResume();
@@ -403,7 +465,9 @@
 
     @Override
     public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
-        stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
+        // Do nothing when selection is failed, let user could try again easily.
+        mWaitingConnectCallback = false;
+        updateConnectButton(true);
     }
 
     private final class FilterWifiTracker {
@@ -427,10 +491,6 @@
                     mAccessPointKeys.add(key);
                 }
             }
-
-            if (mShowLimitedItem && (mAccessPointKeys.size() > MAX_NUMBER_LIST_ITEM)) {
-                showNeutralButton();
-            }
         }
 
         /**
@@ -457,6 +517,21 @@
                 }
             }
 
+            // Update related UI buttons
+            if (mShowLimitedItem && (count >= MAX_NUMBER_LIST_ITEM)) {
+                showAllButton();
+            }
+            if (count > 0) {
+                hideProgressIcon();
+            }
+            // Enable connect button if there is Accesspoint item, except for the situation that
+            // user click but connected status doesn't come back yet.
+            if (count < 0) {
+                updateConnectButton(false);
+            } else if (!mWaitingConnectCallback) {
+                updateConnectButton(true);
+            }
+
             return result;
         }
 
diff --git a/src/com/android/settings/wifi/WifiNoInternetDialog.java b/src/com/android/settings/wifi/WifiNoInternetDialog.java
index e12529d..e33cab6 100644
--- a/src/com/android/settings/wifi/WifiNoInternetDialog.java
+++ b/src/com/android/settings/wifi/WifiNoInternetDialog.java
@@ -17,6 +17,7 @@
 package com.android.settings.wifi;
 
 import static android.net.ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
+import static android.net.ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
 import static android.net.ConnectivityManager.ACTION_PROMPT_UNVALIDATED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 
@@ -53,8 +54,9 @@
     private String mAction;
 
     private boolean isKnownAction(Intent intent) {
-        return intent.getAction().equals(ACTION_PROMPT_UNVALIDATED) ||
-                intent.getAction().equals(ACTION_PROMPT_LOST_VALIDATION);
+        return intent.getAction().equals(ACTION_PROMPT_UNVALIDATED)
+                || intent.getAction().equals(ACTION_PROMPT_LOST_VALIDATION)
+                || intent.getAction().equals(ACTION_PROMPT_PARTIAL_CONNECTIVITY);
     }
 
     @Override
@@ -131,6 +133,11 @@
             ap.mMessage = getString(R.string.no_internet_access_text);
             ap.mPositiveButtonText = getString(R.string.yes);
             ap.mNegativeButtonText = getString(R.string.no);
+        } else if (ACTION_PROMPT_PARTIAL_CONNECTIVITY.equals(mAction)) {
+            ap.mTitle = mNetworkName;
+            ap.mMessage = getString(R.string.partial_connectivity_text);
+            ap.mPositiveButtonText = getString(R.string.yes);
+            ap.mNegativeButtonText = getString(R.string.no);
         } else {
             ap.mTitle = getString(R.string.lost_internet_access_title);
             ap.mMessage = getString(R.string.lost_internet_access_text);
@@ -146,7 +153,8 @@
         ap.mView = checkbox;
         mAlwaysAllow = (CheckBox) checkbox.findViewById(com.android.internal.R.id.alwaysUse);
 
-        if (ACTION_PROMPT_UNVALIDATED.equals(mAction)) {
+        if (ACTION_PROMPT_UNVALIDATED.equals(mAction)
+                || ACTION_PROMPT_PARTIAL_CONNECTIVITY.equals(mAction)) {
             mAlwaysAllow.setText(getString(R.string.no_internet_access_remember));
         } else {
             mAlwaysAllow.setText(getString(R.string.lost_internet_access_persist));
@@ -174,6 +182,11 @@
             final boolean accept = (which == BUTTON_POSITIVE);
             action = (accept ? "Connect" : "Ignore");
             mCM.setAcceptUnvalidated(mNetwork, accept, always);
+        } else if (ACTION_PROMPT_PARTIAL_CONNECTIVITY.equals(mAction)) {
+            what = "PARTIAL_CONNECTIVITY";
+            final boolean accept = (which == BUTTON_POSITIVE);
+            action = (accept ? "Connect" : "Ignore");
+            mCM.setAcceptPartialConnectivity(mNetwork, accept, always);
         } else {
             what = "LOST_INTERNET";
             final boolean avoid = (which == BUTTON_POSITIVE);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index a8fc34d..585cf71 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -179,7 +179,8 @@
 
     private PreferenceCategory mConnectedAccessPointPreferenceCategory;
     private PreferenceCategory mAccessPointsPreferenceCategory;
-    private ButtonPreference mAddPreference;
+    @VisibleForTesting
+    AddWifiNetworkPreference mAddWifiNetworkPreference;
     @VisibleForTesting
     Preference mConfigureWifiSettingsPreference;
     @VisibleForTesting
@@ -237,20 +238,8 @@
                 (PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
         mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS);
         mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);
-
-        Context prefContext = getPrefContext();
-        mAddPreference = new ButtonPreference(prefContext);
-        mAddPreference.setIcon(R.drawable.ic_menu_add);
-        mAddPreference.setTitle(R.string.wifi_add_network);
-        mAddPreference.setButtonIcon(R.drawable.ic_scan_24dp);
-        mAddPreference.setButtonOnClickListener((View v) -> {
-            // Launch QR code scanner to join a network.
-            getContext().startActivity(
-                    WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
-        });
-        mAddPreference.setButtonContentDescription(getString(R.string.wifi_dpp_scan_qr_code));
+        mAddWifiNetworkPreference = new AddWifiNetworkPreference(getPrefContext());
         mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
-
         mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
     }
 
@@ -590,7 +579,7 @@
                     showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
                     break;
             }
-        } else if (preference == mAddPreference) {
+        } else if (preference == mAddWifiNetworkPreference) {
             onAddNetworkPressed();
         } else {
             return super.onPreferenceTreeClick(preference);
@@ -809,8 +798,8 @@
             }
         }
         removeCachedPrefs(mAccessPointsPreferenceCategory);
-        mAddPreference.setOrder(index);
-        mAccessPointsPreferenceCategory.addPreference(mAddPreference);
+        mAddWifiNetworkPreference.setOrder(index);
+        mAccessPointsPreferenceCategory.addPreference(mAddWifiNetworkPreference);
         setAdditionalSettingsSummaries();
 
         if (!hasAvailableAccessPoints) {
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 89565df..cf59dbd 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -16,6 +16,7 @@
 package com.android.settings.wifi.details;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
@@ -66,6 +67,7 @@
 import com.android.settings.wifi.WifiDialog.WifiDialogListener;
 import com.android.settings.wifi.WifiUtils;
 import com.android.settings.wifi.dpp.WifiDppUtils;
+import com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -75,6 +77,8 @@
 import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -136,7 +140,9 @@
     private WifiConfiguration mWifiConfig;
     private WifiInfo mWifiInfo;
     private final WifiManager mWifiManager;
+    private final WifiTracker mWifiTracker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
+    private boolean mIsOutOfRange;
 
     // UI elements - in order of appearance
     private ActionButtonsPreference mButtonsPref;
@@ -176,7 +182,7 @@
                     // fall through
                 case WifiManager.NETWORK_STATE_CHANGED_ACTION:
                 case WifiManager.RSSI_CHANGED_ACTION:
-                    updateLiveNetworkInfo();
+                    updateNetworkInfo();
                     break;
             }
         }
@@ -205,15 +211,19 @@
 
         @Override
         public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
-            // If the network just validated or lost Internet access, refresh network state.
-            // Don't do this on every NetworkCapabilities change because refreshNetworkState
-            // sends IPCs to the system server from the UI thread, which can cause jank.
+            // If the network just validated or lost Internet access or detected partial internet
+            // connectivity, refresh network state. Don't do this on every NetworkCapabilities
+            // change because refreshNetworkState sends IPCs to the system server from the UI
+            // thread, which can cause jank.
             if (network.equals(mNetwork) && !nc.equals(mNetworkCapabilities)) {
-                if (hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED) ||
-                        hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)) {
-                    refreshNetworkState();
+                if (hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED)
+                        || hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)
+                        || hasCapabilityChanged(nc, NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
+                    mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+                    refreshEntityHeader();
                 }
                 mNetworkCapabilities = nc;
+                refreshButtons();
                 updateIpLayerInfo();
             }
         }
@@ -226,6 +236,29 @@
         }
     };
 
+    private final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
+        /** Called when the state of Wifi has changed. */
+        public void onWifiStateChanged(int state) {
+            Log.d(TAG, "onWifiStateChanged(" + state + ")");
+            // Do nothing.
+        }
+
+        /** Called when the connection state of wifi has changed. */
+        public void onConnectedChanged() {
+            Log.d(TAG, "onConnectedChanged");
+            // Do nothing.
+        }
+
+        /**
+         * Called to indicate the list of AccessPoints has been updated and
+         * {@link WifiTracker#getAccessPoints()} should be called to get the updated list.
+         */
+        public void onAccessPointsChanged() {
+            Log.d(TAG, "onAccessPointsChanged");
+            updateNetworkInfo();
+        }
+    };
+
     public static WifiDetailPreferenceController newInstance(
             AccessPoint accessPoint,
             ConnectivityManager connectivityManager,
@@ -270,6 +303,17 @@
 
         mLifecycle = lifecycle;
         lifecycle.addObserver(this);
+
+        if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)) {
+            mWifiTracker = WifiTrackerFactory.create(
+                    mFragment.getActivity(),
+                    mWifiListener,
+                    mLifecycle,
+                    true /*includeSaved*/,
+                    true /*includeScans*/);
+        } else {
+            mWifiTracker = null;
+        }
     }
 
     @Override
@@ -360,7 +404,7 @@
         mNetwork = mWifiManager.getCurrentNetwork();
         mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
         mNetworkCapabilities = mConnectivityManager.getNetworkCapabilities(mNetwork);
-        updateLiveNetworkInfo();
+        updateNetworkInfo();
         mContext.registerReceiver(mReceiver, mFilter);
         mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
                 mHandler);
@@ -377,72 +421,73 @@
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
     }
 
-    // TODO(b/124707751): Refactoring the code later, keeping it currently for stability.
-    protected void updateSavedNetworkInfo() {
-        mSignalStrengthPref.setVisible(false);
-        mFrequencyPref.setVisible(false);
-        mTxLinkSpeedPref.setVisible(false);
-        mRxLinkSpeedPref.setVisible(false);
-
-        // MAC Address Pref
-        mMacAddressPref.setSummary(mWifiConfig.getRandomizedMacAddress().toString());
-
-        refreshEntityHeader();
-
-        updateIpLayerInfo();
-
-        // Update whether the forget button should be displayed.
-        mButtonsPref.setButton1Visible(canForgetNetwork());
-    }
-
-    private void updateLiveNetworkInfo() {
-        // No need to fetch LinkProperties and NetworkCapabilities, they are updated by the
-        // callbacks. mNetwork doesn't change except in onResume.
-        mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
-        mWifiInfo = mWifiManager.getConnectionInfo();
-        if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
-            exitActivity();
+    private void updateNetworkInfo() {
+        if(!updateAccessPoint()) {
             return;
         }
 
-        // Update whether the forget button should be displayed.
-        mButtonsPref.setButton1Visible(canForgetNetwork());
+        // refresh header
+        refreshEntityHeader();
 
-        refreshNetworkState();
+        // refresh Buttons
+        refreshButtons();
 
         // Update Connection Header icon and Signal Strength Preference
         refreshRssiViews();
-
-        // MAC Address Pref
-        mMacAddressPref.setSummary(mWifiInfo.getMacAddress());
-
-        // Transmit Link Speed Pref
-        int txLinkSpeedMbps = mWifiInfo.getTxLinkSpeedMbps();
-        mTxLinkSpeedPref.setVisible(txLinkSpeedMbps >= 0);
-        mTxLinkSpeedPref.setSummary(mContext.getString(
-                R.string.tx_link_speed, mWifiInfo.getTxLinkSpeedMbps()));
-
-        // Receive Link Speed Pref
-        int rxLinkSpeedMbps = mWifiInfo.getRxLinkSpeedMbps();
-        mRxLinkSpeedPref.setVisible(rxLinkSpeedMbps >= 0);
-        mRxLinkSpeedPref.setSummary(mContext.getString(
-                R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
-
         // Frequency Pref
-        final int frequency = mWifiInfo.getFrequency();
-        String band = null;
-        if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
-            band = mContext.getResources().getString(R.string.wifi_band_24ghz);
-        } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
-                && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
-            band = mContext.getResources().getString(R.string.wifi_band_5ghz);
-        } else {
-            Log.e(TAG, "Unexpected frequency " + frequency);
-        }
-        mFrequencyPref.setSummary(band);
-
+        refreshFrequency();
+        // Transmit Link Speed Pref
+        refreshTxSpeed();
+        // Receive Link Speed Pref
+        refreshRxSpeed();
+        // IP related information
         updateIpLayerInfo();
+        // MAC Address Pref
+        refreshMacAddress();
+
+    }
+
+    private boolean updateAccessPoint() {
+        boolean changed = false;
+        if (mWifiTracker != null) {
+            updateAccessPointFromScannedList();
+            // refresh UI if signal level changed for disconnect network.
+            changed = mRssiSignalLevel != mAccessPoint.getLevel();
+        }
+
+        if (mAccessPoint.isActive()) {
+            // No need to fetch LinkProperties and NetworkCapabilities, they are updated by the
+            // callbacks. mNetwork doesn't change except in onResume.
+            mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
+            mWifiInfo = mWifiManager.getConnectionInfo();
+            if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
+                exitActivity();
+                return false;
+            }
+
+            changed |= mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
+            // If feature for saved network not enabled, always return true.
+            return mWifiTracker == null || changed;
+        }
+
+        return changed;
+    }
+
+    private void updateAccessPointFromScannedList() {
+        mIsOutOfRange = true;
+
+        if (mAccessPoint.getConfig() == null) {
+            return;
+        }
+
+        for (AccessPoint ap : mWifiTracker.getAccessPoints()) {
+            if (ap.getConfig() != null
+                    && mAccessPoint.matches(ap.getConfig())) {
+                mAccessPoint = ap;
+                mIsOutOfRange = false;
+                return;
+            }
+        }
     }
 
     private void exitActivity() {
@@ -452,14 +497,16 @@
         mFragment.getActivity().finish();
     }
 
-    private void refreshNetworkState() {
-        mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
-        refreshEntityHeader();
-    }
-
     private void refreshRssiViews() {
         int signalLevel = mAccessPoint.getLevel();
 
+        // Disappears signal view if not in range. e.g. for saved networks.
+        if (mIsOutOfRange) {
+            mSignalStrengthPref.setVisible(false);
+            mRssiSignalLevel = -1;
+            return;
+        }
+
         if (mRssiSignalLevel == signalLevel) {
             return;
         }
@@ -477,6 +524,84 @@
         mSignalStrengthPref.setIcon(wifiIconDark);
 
         mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
+        mSignalStrengthPref.setVisible(true);
+    }
+
+    private void refreshFrequency() {
+        if (mWifiInfo == null) {
+            mFrequencyPref.setVisible(false);
+            return;
+        }
+
+        final int frequency = mWifiInfo.getFrequency();
+        String band = null;
+        if (frequency >= AccessPoint.LOWER_FREQ_24GHZ
+                && frequency < AccessPoint.HIGHER_FREQ_24GHZ) {
+            band = mContext.getResources().getString(R.string.wifi_band_24ghz);
+        } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ
+                && frequency < AccessPoint.HIGHER_FREQ_5GHZ) {
+            band = mContext.getResources().getString(R.string.wifi_band_5ghz);
+        } else {
+            Log.e(TAG, "Unexpected frequency " + frequency);
+        }
+        mFrequencyPref.setSummary(band);
+        mFrequencyPref.setVisible(true);
+    }
+
+    private void refreshTxSpeed() {
+        if (mWifiInfo == null) {
+            mTxLinkSpeedPref.setVisible(false);
+            return;
+        }
+
+        int txLinkSpeedMbps = mWifiInfo.getTxLinkSpeedMbps();
+        mTxLinkSpeedPref.setVisible(txLinkSpeedMbps >= 0);
+        mTxLinkSpeedPref.setSummary(mContext.getString(
+                R.string.tx_link_speed, mWifiInfo.getTxLinkSpeedMbps()));
+    }
+
+    private void refreshRxSpeed() {
+        if (mWifiInfo == null) {
+            mRxLinkSpeedPref.setVisible(false);
+            return;
+        }
+
+        int rxLinkSpeedMbps = mWifiInfo.getRxLinkSpeedMbps();
+        mRxLinkSpeedPref.setVisible(rxLinkSpeedMbps >= 0);
+        mRxLinkSpeedPref.setSummary(mContext.getString(
+                R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
+    }
+
+    private void refreshMacAddress() {
+        String macAddress = getMacAddress();
+        if (macAddress == null) {
+            mMacAddressPref.setVisible(false);
+            return;
+        }
+
+        mMacAddressPref.setVisible(true);
+        mMacAddressPref.setSummary(macAddress);
+    }
+
+    private String getMacAddress() {
+        if (mWifiInfo != null) {
+            // get MAC address from connected network information
+            return mWifiInfo.getMacAddress();
+        }
+
+        // return randomized MAC address
+        if (mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
+            return mWifiConfig.getRandomizedMacAddress().toString();
+        }
+
+        // return device MAC address
+        final String[] macAddresses = mWifiManager.getFactoryMacAddresses();
+        if (macAddresses != null && macAddresses.length > 0) {
+            return macAddresses[0];
+        }
+
+        Log.e(TAG, "Can't get device MAC address!");
+        return null;
     }
 
     private void updatePreference(Preference pref, String detailText) {
@@ -488,13 +613,17 @@
         }
     }
 
-    private void updateIpLayerInfo() {
+    private void refreshButtons() {
+        mButtonsPref.setButton1Visible(canForgetNetwork());
         mButtonsPref.setButton2Visible(canSignIntoNetwork());
         mButtonsPref.setButton3Visible(canShareNetwork());
         mButtonsPref.setVisible(
                 canSignIntoNetwork() || canForgetNetwork() || canShareNetwork());
+    }
 
-        if (mNetwork == null || mLinkProperties == null) {
+    private void updateIpLayerInfo() {
+        // Hide IP layer info if not a connected network.
+        if (!mAccessPoint.isActive() || mNetwork == null || mLinkProperties == null) {
             mIpAddressPref.setVisible(false);
             mSubnetPref.setVisible(false);
             mGatewayPref.setVisible(false);
@@ -642,14 +771,7 @@
      * Share the wifi network with QR code.
      */
     private void shareNetwork() {
-        final String title = mContext.getString(
-                R.string.lockpassword_confirm_your_pattern_header);
-        final String description = String.format(
-                mContext.getString(R.string.wifi_sharing_message),
-                mAccessPoint.getSsidStr());
-
-        WifiDppUtils.showLockScreen(mContext, title, description,
-                () -> launchWifiDppConfiguratorActivity());
+        WifiDppUtils.showLockScreen(mContext, () -> launchWifiDppConfiguratorActivity());
     }
 
     /**
diff --git a/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java
deleted file mode 100644
index 3407890..0000000
--- a/src/com/android/settings/wifi/details/WifiDetailSavedNetworkPreferenceController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi.details;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-
-import androidx.fragment.app.Fragment;
-
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.wifi.AccessPoint;
-
-public class WifiDetailSavedNetworkPreferenceController extends WifiDetailPreferenceController {
-
-    WifiDetailSavedNetworkPreferenceController(AccessPoint accessPoint,
-            ConnectivityManager connectivityManager, Context context,
-            Fragment fragment, Handler handler,
-            Lifecycle lifecycle,
-            WifiManager wifiManager,
-            MetricsFeatureProvider metricsFeatureProvider,
-            IconInjector injector) {
-        super(accessPoint, connectivityManager, context, fragment, handler, lifecycle, wifiManager,
-                metricsFeatureProvider, injector);
-    }
-
-    public static WifiDetailSavedNetworkPreferenceController newInstance(
-            AccessPoint accessPoint,
-            ConnectivityManager connectivityManager,
-            Context context,
-            Fragment fragment,
-            Handler handler,
-            Lifecycle lifecycle,
-            WifiManager wifiManager,
-            MetricsFeatureProvider metricsFeatureProvider) {
-        return new WifiDetailSavedNetworkPreferenceController(
-                accessPoint, connectivityManager, context, fragment, handler, lifecycle,
-                wifiManager, metricsFeatureProvider, new IconInjector(context));
-    }
-
-    @Override
-    public void onPause() {
-        // Do nothing
-    }
-
-    @Override
-    public void onResume() {
-        updateSavedNetworkInfo();
-    }
-}
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index 7edd227..66587ed 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -51,9 +51,6 @@
 
     private static final String TAG = "WifiNetworkDetailsFrg";
 
-    // Extra for if current fragment shows saved network status or not.
-    public static final String EXTRA_IS_SAVED_NETWORK = "SavedNetwork";
-
     private AccessPoint mAccessPoint;
     private WifiDetailPreferenceController mWifiDetailPreferenceController;
 
@@ -126,30 +123,15 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
 
-        final boolean isDisplaySavedNetworkDetails =
-                getArguments().getBoolean(EXTRA_IS_SAVED_NETWORK, false /* defaultValue */);
-        if (isDisplaySavedNetworkDetails) {
-            mWifiDetailPreferenceController =
-                    WifiDetailSavedNetworkPreferenceController.newInstance(
-                            mAccessPoint,
-                            cm,
-                            context,
-                            this,
-                            new Handler(Looper.getMainLooper()),  // UI thread.
-                            getSettingsLifecycle(),
-                            context.getSystemService(WifiManager.class),
-                            mMetricsFeatureProvider);
-        } else {
-            mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance(
-                    mAccessPoint,
-                    cm,
-                    context,
-                    this,
-                    new Handler(Looper.getMainLooper()),  // UI thread.
-                    getSettingsLifecycle(),
-                    context.getSystemService(WifiManager.class),
-                    mMetricsFeatureProvider);
-        }
+        mWifiDetailPreferenceController = WifiDetailPreferenceController.newInstance(
+                mAccessPoint,
+                cm,
+                context,
+                this,
+                new Handler(Looper.getMainLooper()),  // UI thread.
+                getSettingsLifecycle(),
+                context.getSystemService(WifiManager.class),
+                mMetricsFeatureProvider);
 
         controllers.add(mWifiDetailPreferenceController);
         controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig()));
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index 2cd5e23..4e6a0d6 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -29,6 +30,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
+import android.widget.TextView;
 
 import com.android.settings.R;
 import com.android.settings.wifi.qrcode.QrCodeGenerator;
@@ -43,6 +45,7 @@
     private static final String TAG = "WifiDppQrCodeGeneratorFragment";
 
     private ImageView mQrCodeView;
+    private TextView mPasswordView;
     private String mQrCode;
 
     @Override
@@ -138,12 +141,27 @@
         final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
         if (wifiNetworkConfig.isHotspot()) {
             mTitle.setText(R.string.wifi_dpp_share_hotspot);
-            mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_to_share_hotspot,
-                    wifiNetworkConfig.getSsid()));
         } else {
             mTitle.setText(R.string.wifi_dpp_share_wifi);
+        }
+
+        final String password = wifiNetworkConfig.getPreSharedKey();
+        mPasswordView = view.findViewById(R.id.password);
+        if (TextUtils.isEmpty(password)) {
+            mSummary.setText(getString(
+                    R.string.wifi_dpp_scan_open_network_qr_code_with_another_device,
+                    wifiNetworkConfig.getSsid()));
+
+            mPasswordView.setVisibility(View.GONE);
+        } else {
             mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
                     wifiNetworkConfig.getSsid()));
+
+            if (wifiNetworkConfig.isHotspot()) {
+               mPasswordView.setText(getString(R.string.wifi_dpp_hotspot_password, password));
+            } else {
+                mPasswordView.setText(getString(R.string.wifi_dpp_wifi_password, password));
+            }
         }
 
         mQrCode = wifiNetworkConfig.getQrCode();
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 4535599..905d3a0 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -45,6 +45,7 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import androidx.annotation.StringRes;
 import androidx.lifecycle.ViewModelProviders;
 
 import com.android.settings.R;
@@ -52,12 +53,17 @@
 import com.android.settings.wifi.qrcode.QrCamera;
 import com.android.settings.wifi.qrcode.QrDecorateView;
 
+import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
+
 import java.util.List;
 
 public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
         SurfaceTextureListener,
         QrCamera.ScannerCallback,
-        WifiManager.ActionListener {
+        WifiManager.ActionListener,
+        WifiTracker.WifiListener {
     private static final String TAG = "WifiDppQrCodeScannerFragment";
 
     /** Message sent to hide error message */
@@ -80,6 +86,8 @@
     private static final String KEY_LATEST_ERROR_CODE = "key_latest_error_code";
     private static final String KEY_WIFI_CONFIGURATION = "key_wifi_configuration";
 
+    private static final int ARG_RESTART_CAMERA = 1;
+
     private ProgressBar mProgressBar;
     private QrCamera mCamera;
     private TextureView mTextureView;
@@ -100,6 +108,68 @@
 
     private int mLatestStatusCode = WifiDppUtils.EASY_CONNECT_EVENT_FAILURE_NONE;
 
+    private WifiTracker mWifiTracker;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MESSAGE_HIDE_ERROR_MESSAGE:
+                    mErrorMessage.setVisibility(View.INVISIBLE);
+                    break;
+
+                case MESSAGE_SHOW_ERROR_MESSAGE:
+                    final String errorMessage = (String) msg.obj;
+
+                    mErrorMessage.setVisibility(View.VISIBLE);
+                    mErrorMessage.setText(errorMessage);
+                    mErrorMessage.sendAccessibilityEvent(
+                            AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+
+                    // Cancel any pending messages to hide error view and requeue the message so
+                    // user has time to see error
+                    removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
+                    sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
+                            SHOW_ERROR_MESSAGE_INTERVAL);
+
+                    if (msg.arg1 == ARG_RESTART_CAMERA) {
+                        mProgressBar.setVisibility(View.INVISIBLE);
+                        restartCamera();
+                    }
+                    break;
+
+                case MESSAGE_SCAN_WIFI_DPP_SUCCESS:
+                    mErrorMessage.setVisibility(View.INVISIBLE);
+
+                    if (mScanWifiDppSuccessListener == null) {
+                        return;
+                    }
+                    mScanWifiDppSuccessListener.onScanWifiDppSuccess((WifiQrCode)msg.obj);
+
+                    if (!mIsConfiguratorMode) {
+                        mProgressBar.setVisibility(View.VISIBLE);
+                        startWifiDppEnrolleeInitiator((WifiQrCode)msg.obj);
+                        updateEnrolleeSummary();
+                        mSummary.sendAccessibilityEvent(
+                                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+                    }
+                    break;
+
+                case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
+                    mErrorMessage.setVisibility(View.INVISIBLE);
+
+                    final WifiNetworkConfig wifiNetworkConfig = (WifiNetworkConfig)msg.obj;
+                    mWifiConfiguration = wifiNetworkConfig.getWifiConfigurationOrNull();
+                    wifiNetworkConfig.connect(getContext(),
+                            /* listener */ WifiDppQrCodeScannerFragment.this);
+                    break;
+
+                default:
+                    return;
+            }
+        }
+    };
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -175,6 +245,9 @@
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
 
+        mWifiTracker = WifiTrackerFactory.create(getActivity(), /* wifiListener */ this,
+                getSettingsLifecycle(), /* includeSaved */ false, /* includeScans */ true);
+
         // setTitle for Talkback
         if (mIsConfiguratorMode) {
             getActivity().setTitle(R.string.wifi_dpp_add_device_to_network);
@@ -291,7 +364,7 @@
         try {
             mWifiQrCode = new WifiQrCode(qrCode);
         } catch (IllegalArgumentException e) {
-            mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
+            showErrorMessage(R.string.wifi_dpp_could_not_detect_valid_qr_code);
             return false;
         }
 
@@ -301,14 +374,14 @@
         if (!mIsConfiguratorMode && WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG.equals(scheme)) {
             final String ssidQrCode = mWifiQrCode.getWifiNetworkConfig().getSsid();
             if (!TextUtils.isEmpty(mSsid) && !mSsid.equals(ssidQrCode)) {
-                mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
+                showErrorMessage(R.string.wifi_dpp_could_not_detect_valid_qr_code);
                 return false;
             }
         }
 
         // It's impossible to provision other device with ZXing Wi-Fi Network config format
         if (mIsConfiguratorMode && WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG.equals(scheme)) {
-            mHandler.sendEmptyMessage(MESSAGE_SHOW_ERROR_MESSAGE);
+            showErrorMessage(R.string.wifi_dpp_could_not_detect_valid_qr_code);
             return false;
         }
 
@@ -385,59 +458,18 @@
         }
     }
 
-    public void showErrorMessage(String message) {
-        mErrorMessage.setVisibility(View.VISIBLE);
-        mErrorMessage.setText(message);
-        mErrorMessage.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-
-        mHandler.removeMessages(MESSAGE_HIDE_ERROR_MESSAGE);
-        mHandler.sendEmptyMessageDelayed(MESSAGE_HIDE_ERROR_MESSAGE,
-                SHOW_ERROR_MESSAGE_INTERVAL);
+    private void showErrorMessage(@StringRes int messageResId) {
+        final Message message = mHandler.obtainMessage(MESSAGE_SHOW_ERROR_MESSAGE,
+                getString(messageResId));
+        message.sendToTarget();
     }
 
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MESSAGE_HIDE_ERROR_MESSAGE:
-                    mErrorMessage.setVisibility(View.INVISIBLE);
-                    break;
-
-                case MESSAGE_SHOW_ERROR_MESSAGE:
-                    showErrorMessage(getString(R.string.wifi_dpp_could_not_detect_valid_qr_code));
-                    break;
-
-                case MESSAGE_SCAN_WIFI_DPP_SUCCESS:
-                    mErrorMessage.setVisibility(View.INVISIBLE);
-
-                    if (mScanWifiDppSuccessListener == null) {
-                        return;
-                    }
-                    mScanWifiDppSuccessListener.onScanWifiDppSuccess((WifiQrCode)msg.obj);
-
-                    if (!mIsConfiguratorMode) {
-                        mProgressBar.setVisibility(View.VISIBLE);
-                        startWifiDppEnrolleeInitiator((WifiQrCode)msg.obj);
-                        updateEnrolleeSummary();
-                        mSummary.sendAccessibilityEvent(
-                                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
-                    }
-                    break;
-
-                case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS:
-                    mErrorMessage.setVisibility(View.INVISIBLE);
-
-                    final WifiNetworkConfig wifiNetworkConfig = (WifiNetworkConfig)msg.obj;
-                    mWifiConfiguration = wifiNetworkConfig.getWifiConfigurationOrNull();
-                    wifiNetworkConfig.connect(getContext(),
-                            /* listener */ WifiDppQrCodeScannerFragment.this);
-                    break;
-
-                default:
-                    return;
-            }
-        }
-    };
+    private void showErrorMessageAndRestartCamera(@StringRes int messageResId) {
+        final Message message = mHandler.obtainMessage(MESSAGE_SHOW_ERROR_MESSAGE,
+                getString(messageResId));
+        message.arg1 = ARG_RESTART_CAMERA;
+        message.sendToTarget();
+    }
 
     @Override
     public void onSaveInstanceState(Bundle outState) {
@@ -468,9 +500,7 @@
             Log.e(TAG, "Invalid networkId " + newNetworkId);
             mLatestStatusCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC;
             updateEnrolleeSummary();
-            mProgressBar.setVisibility(View.INVISIBLE);
-            showErrorMessage(getString(R.string.wifi_dpp_check_connection_try_again));
-            restartCamera();
+            showErrorMessageAndRestartCamera(R.string.wifi_dpp_check_connection_try_again);
         }
 
         @Override
@@ -482,23 +512,22 @@
         public void onFailure(int code) {
             Log.d(TAG, "EasyConnectEnrolleeStatusCallback.onFailure " + code);
 
+            int errorMessageResId = 0;
             switch (code) {
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI:
-                    showErrorMessage(getString(R.string.wifi_dpp_could_not_detect_valid_qr_code));
+                    errorMessageResId = R.string.wifi_dpp_could_not_detect_valid_qr_code;
                     break;
 
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION:
-                    showErrorMessage(
-                            getString(R.string.wifi_dpp_failure_authentication_or_configuration));
+                    errorMessageResId = R.string.wifi_dpp_failure_authentication_or_configuration;
                     break;
 
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE:
-                    showErrorMessage(getString(R.string.wifi_dpp_failure_not_compatible));
+                    errorMessageResId = R.string.wifi_dpp_failure_not_compatible;
                     break;
 
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION:
-                    showErrorMessage(
-                            getString(R.string.wifi_dpp_failure_authentication_or_configuration));
+                    errorMessageResId = R.string.wifi_dpp_failure_authentication_or_configuration;
                     break;
 
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY:
@@ -515,11 +544,11 @@
                     return;
 
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT:
-                    showErrorMessage(getString(R.string.wifi_dpp_failure_timeout));
+                    errorMessageResId = R.string.wifi_dpp_failure_timeout;
                     break;
 
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC:
-                    showErrorMessage(getString(R.string.wifi_dpp_failure_generic));
+                    errorMessageResId = R.string.wifi_dpp_failure_generic;
                     break;
 
                 case EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED:
@@ -536,8 +565,7 @@
 
             mLatestStatusCode = code;
             updateEnrolleeSummary();
-            mProgressBar.setVisibility(View.INVISIBLE);
-            restartCamera();
+            showErrorMessageAndRestartCamera(errorMessageResId);
         }
 
         @Override
@@ -555,21 +583,39 @@
 
     @Override
     public void onSuccess() {
-        final Intent resultIntent = new Intent();
-        resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION, mWifiConfiguration);
+        if (isEnrollingWifiNetworkReachable()) {
+            final Intent resultIntent = new Intent();
+            resultIntent.putExtra(WifiDialogActivity.KEY_WIFI_CONFIGURATION, mWifiConfiguration);
 
-        final Activity hostActivity = getActivity();
-        hostActivity.setResult(Activity.RESULT_OK, resultIntent);
-        hostActivity.finish();
+            final Activity hostActivity = getActivity();
+            hostActivity.setResult(Activity.RESULT_OK, resultIntent);
+            hostActivity.finish();
+        } else {
+            Log.d(TAG, "Enroll Wi-Fi network succeeded but it's not reachable");
+            showErrorMessageAndRestartCamera(R.string.wifi_dpp_check_connection_try_again);
+        }
     }
 
     @Override
     public void onFailure(int reason) {
         Log.d(TAG, "Wi-Fi connect onFailure reason - " + reason);
+        showErrorMessageAndRestartCamera(R.string.wifi_dpp_check_connection_try_again);
+    }
 
-        mProgressBar.setVisibility(View.INVISIBLE);
-        showErrorMessage(getString(R.string.wifi_dpp_check_connection_try_again));
-        restartCamera();
+    private boolean isEnrollingWifiNetworkReachable() {
+        if (mWifiConfiguration == null) {
+            Log.e(TAG, "Connect succeeded but lost WifiConfiguration");
+            return false;
+        }
+
+        final List<AccessPoint> scannedAccessPoints = mWifiTracker.getAccessPoints();
+        for (AccessPoint accessPoint : scannedAccessPoints) {
+            if (accessPoint.matches(mWifiConfiguration) &&
+                    accessPoint.isReachable()) {
+                return true;
+            }
+        }
+        return false;
     }
 
     // Check is Easy Connect handshaking or not
@@ -610,4 +656,25 @@
             mSummary.setText(description);
         }
     }
+
+    /** Called when the state of Wifi has changed. */
+    @Override
+    public void onWifiStateChanged(int state) {
+        // Do nothing.
+    }
+
+    /** Called when the connection state of wifi has changed. */
+    @Override
+    public void onConnectedChanged() {
+        // Do nothing.
+    }
+
+    /**
+     * Called to indicate the list of AccessPoints has been updated and
+     * getAccessPoints should be called to get the latest information.
+     */
+    @Override
+    public void onAccessPointsChanged() {
+        // Do nothing.
+    }
 }
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index fe7af27..bf78b3f 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -29,6 +29,8 @@
 import android.text.TextUtils;
 import android.util.FeatureFlagUtils;
 
+import com.android.settings.R;
+
 import com.android.settingslib.wifi.AccessPoint;
 
 import java.util.List;
@@ -273,13 +275,10 @@
      * user of the device.
      *
      * @param context The {@code Context} used to get {@code KeyguardManager} service
-     * @param title The title on lock screen
-     * @param description The description on lock screen
      * @param successRunnable The {@code Runnable} which will be executed if the user does not setup
      *                        device security or if lock screen is unlocked
      */
-    public static void showLockScreen(Context context, String title, String description,
-            Runnable successRunnable) {
+    public static void showLockScreen(Context context, Runnable successRunnable) {
         final KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(
                 Context.KEYGUARD_SERVICE);
 
@@ -299,8 +298,7 @@
             };
 
             final BiometricPrompt.Builder builder = new BiometricPrompt.Builder(context)
-                    .setTitle(title)
-                    .setDescription(description);
+                    .setTitle(context.getText(R.string.wifi_dpp_lockscreen_title));
 
             if (keyguardManager.isDeviceSecure()) {
                 builder.setDeviceCredentialAllowed(true);
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
index 4688d76..84f1c36 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkListFragment.java
@@ -34,11 +34,14 @@
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.wifi.AddNetworkFragment;
+import com.android.settings.wifi.savedaccesspoints.SavedNetworkComparator;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.settingslib.wifi.AccessPointPreference;
+import com.android.settingslib.wifi.WifiSavedConfigUtils;
 import com.android.settingslib.wifi.WifiTracker;
 import com.android.settingslib.wifi.WifiTrackerFactory;
 
+import java.util.Collections;
 import java.util.List;
 
 public class WifiNetworkListFragment extends SettingsPreferenceFragment implements
@@ -256,17 +259,6 @@
             return false;
         }
 
-        // Can only use saved network for DPP configuration. For ephemeral connections networkId
-        // is invalid.
-        if (!accessPoint.isSaved()) {
-            return false;
-        }
-
-        // Ignore access points that are out of range.
-        if (!accessPoint.isReachable()) {
-            return false;
-        }
-
         return true;
     }
 
@@ -290,44 +282,47 @@
             return;
         }
 
-        // AccessPoints are sorted by the WifiTracker
-        final List<AccessPoint> accessPoints = mWifiTracker.getAccessPoints();
-
-        mAccessPointsPreferenceCategory.setVisible(true);
-
-        cacheRemoveAllPrefs(mAccessPointsPreferenceCategory);
+        // TODO(b/128942314): Lists reachable AccessPoints on top of the list
+        final List<AccessPoint> savedAccessPoints =
+                WifiSavedConfigUtils.getAllConfigs(getContext(), mWifiManager);
+        Collections.sort(savedAccessPoints, SavedNetworkComparator.INSTANCE);
 
         int index = 0;
-        for (; index < accessPoints.size(); index++) {
-            AccessPoint accessPoint = accessPoints.get(index);
-            // Check if this access point is valid for DPP.
-            if (isValidForDppConfiguration(accessPoint)) {
-                final String key = accessPoint.getKey();
+        mAccessPointsPreferenceCategory.removeAll();
+        for (AccessPoint savedAccessPoint : savedAccessPoints) {
+            if (isValidForDppConfiguration(savedAccessPoint)) {
+                // Replaces with an AccessPoint from scanned result for signal information
+                savedAccessPoint = getScannedAccessPointIfAvailable(savedAccessPoint);
+                final AccessPointPreference preference =
+                        createAccessPointPreference(savedAccessPoint);
 
-                final AccessPointPreference pref = (AccessPointPreference) getCachedPreference(key);
-                if (pref != null) {
-                    pref.setOrder(index);
-                    continue;
-                }
-                final AccessPointPreference preference = createAccessPointPreference(accessPoint);
-                preference.setKey(key);
-                preference.setOrder(index);
+                preference.setOrder(index++);
+                preference.setEnabled(savedAccessPoint.isReachable());
+                savedAccessPoint.setListener(this);
 
-                mAccessPointsPreferenceCategory.addPreference(preference);
-                accessPoint.setListener(this);
                 preference.refresh();
+                mAccessPointsPreferenceCategory.addPreference(preference);
             }
         }
-        removeCachedPrefs(mAccessPointsPreferenceCategory);
         mAddPreference.setOrder(index);
         mAccessPointsPreferenceCategory.addPreference(mAddPreference);
 
         if (mIsTest) {
-            mFakeNetworkPreference.setOrder(index + 1);
             mAccessPointsPreferenceCategory.addPreference(mFakeNetworkPreference);
         }
     }
 
+    private AccessPoint getScannedAccessPointIfAvailable(AccessPoint savedAccessPoint) {
+        final List<AccessPoint> scannedAccessPoints = mWifiTracker.getAccessPoints();
+        final WifiConfiguration savedWifiConfiguration = savedAccessPoint.getConfig();
+        for (AccessPoint scannedAccessPoint : scannedAccessPoints) {
+            if (scannedAccessPoint.matches(savedWifiConfiguration)) {
+                return scannedAccessPoint;
+            }
+        }
+        return savedAccessPoint;
+    }
+
     private AccessPointPreference createAccessPointPreference(AccessPoint accessPoint) {
         return new AccessPointPreference(accessPoint, getPrefContext(), mUserBadgeCache,
                 R.drawable.ic_wifi_signal_0, /* forSavedNetworks */ false);
diff --git a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
index ea858f3..3f600e6 100644
--- a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsWifiSettings.java
@@ -108,7 +108,6 @@
             }
             final Bundle savedState = new Bundle();
             mSelectedAccessPoint.saveWifiState(savedState);
-            savedState.putBoolean(WifiNetworkDetailsFragment.EXTRA_IS_SAVED_NETWORK, true);
 
             new SubSettingLauncher(getContext())
                     .setTitleText(mSelectedAccessPoint.getTitle())
diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
index 1c44204..f2c919b 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -33,6 +33,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
+import android.net.NetworkInfo.DetailedState;
 import android.net.Uri;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -64,7 +65,10 @@
 import com.android.settingslib.wifi.WifiTracker;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * {@link CustomSliceable} for Wi-Fi, used by generic clients.
@@ -93,26 +97,7 @@
         mContext.getTheme().applyStyle(R.style.Theme_Settings_Home, true /* force */);
 
         final boolean isWifiEnabled = isWifiEnabled();
-
-        final IconCompat icon = IconCompat.createWithResource(mContext,
-                R.drawable.ic_settings_wireless);
-        final String title = mContext.getString(R.string.wifi_settings);
-        final CharSequence summary = getSummary();
-        final PendingIntent toggleAction = getBroadcastIntent(mContext);
-        final PendingIntent primaryAction = getPrimaryAction();
-        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
-                ListBuilder.ICON_IMAGE, title);
-        final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
-                null /* actionTitle */, isWifiEnabled);
-
-        final ListBuilder listBuilder = new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
-                .setAccentColor(COLOR_NOT_TINTED)
-                .addRow(new ListBuilder.RowBuilder()
-                        .setTitle(title)
-                        .setSubtitle(summary)
-                        .addEndItem(toggleSliceAction)
-                        .setPrimaryAction(primarySliceAction));
-
+        ListBuilder listBuilder = getListBuilder(isWifiEnabled, null /* accessPoint */);
         if (!isWifiEnabled) {
             return listBuilder.build();
         }
@@ -137,7 +122,12 @@
         final CharSequence placeholder = mContext.getText(R.string.summary_placeholder);
         for (int i = 0; i < DEFAULT_EXPANDED_ROW_COUNT; i++) {
             if (i < apCount) {
-                listBuilder.addRow(getAccessPointRow(results.get(i)));
+                final AccessPoint accessPoint = results.get(i);
+                if (accessPoint.isActive()) {
+                    // update summary
+                    listBuilder = getListBuilder(isWifiEnabled, accessPoint);
+                }
+                listBuilder.addRow(getAccessPointRow(accessPoint));
             } else if (needLoadingRow) {
                 listBuilder.addRow(getLoadingRow());
                 needLoadingRow = false;
@@ -149,6 +139,28 @@
         return listBuilder.build();
     }
 
+    private ListBuilder getListBuilder(boolean isWifiEnabled, AccessPoint accessPoint) {
+        final IconCompat icon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_settings_wireless);
+        final String title = mContext.getString(R.string.wifi_settings);
+        final CharSequence summary = getSummary(accessPoint);
+        final PendingIntent toggleAction = getBroadcastIntent(mContext);
+        final PendingIntent primaryAction = getPrimaryAction();
+        final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryAction, icon,
+                ListBuilder.ICON_IMAGE, title);
+        final SliceAction toggleSliceAction = SliceAction.createToggle(toggleAction,
+                null /* actionTitle */, isWifiEnabled);
+
+        return new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
+                .setAccentColor(COLOR_NOT_TINTED)
+                .setKeywords(getKeywords())
+                .addRow(new ListBuilder.RowBuilder()
+                        .setTitle(title)
+                        .setSubtitle(summary)
+                        .addEndItem(toggleSliceAction)
+                        .setPrimaryAction(primarySliceAction));
+    }
+
     private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
         final CharSequence title = getAccessPointName(accessPoint);
         final IconCompat levelIcon = getAccessPointLevelIcon(accessPoint);
@@ -167,7 +179,7 @@
     }
 
     private CharSequence getAccessPointName(AccessPoint accessPoint) {
-        final CharSequence name = accessPoint.getConfigName();
+        final CharSequence name = accessPoint.getTitle();
         final Spannable span = new SpannableString(name);
         @ColorInt final int color = Utils.getColorAttrDefaultColor(mContext,
                 android.R.attr.textColorPrimary);
@@ -306,12 +318,46 @@
         }
     }
 
+    private CharSequence getSummary(AccessPoint accessPoint) {
+        if (accessPoint == null) {
+            return getSummary();
+        }
+
+        final NetworkInfo networkInfo = accessPoint.getNetworkInfo();
+        if (networkInfo == null) {
+            return getSummary();
+        }
+
+        final State state = networkInfo.getState();
+        DetailedState detailedState;
+        if (state == State.CONNECTING) {
+            detailedState = DetailedState.CONNECTING;
+        } else if (state == State.CONNECTED) {
+            detailedState = DetailedState.CONNECTED;
+        } else {
+            return getSummary();
+        }
+
+        final String[] formats = mContext.getResources().getStringArray(
+                R.array.wifi_status_with_ssid);
+        final int index = detailedState.ordinal();
+        return String.format(formats[index], accessPoint.getTitle());
+    }
+
     private PendingIntent getPrimaryAction() {
         final Intent intent = getIntent();
         return PendingIntent.getActivity(mContext, 0 /* requestCode */,
                 intent, 0 /* flags */);
     }
 
+    private Set<String> getKeywords() {
+        final String keywords = mContext.getString(R.string.keywords_wifi);
+        return Arrays.asList(TextUtils.split(keywords, ","))
+                .stream()
+                .map(String::trim)
+                .collect(Collectors.toSet());
+    }
+
     @Override
     public Class getBackgroundWorkerClass() {
         return WifiScanWorker.class;
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
index 10f3e56..b7ddcae 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
@@ -104,13 +104,7 @@
     }
 
     private void shareHotspotNetwork(Intent intent) {
-        final String title = mContext.getString(
-                R.string.lockpassword_confirm_your_pattern_header);
-        final String description = String.format(
-                mContext.getString(R.string.wifi_sharing_message), mSSID);
-
-        WifiDppUtils.showLockScreen(mContext, title, description,
-                () -> mContext.startActivity(intent));
+        WifiDppUtils.showLockScreen(mContext, () -> mContext.startActivity(intent));
     }
 
     @VisibleForTesting
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 776a4d0..1fe4bbe 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -91,4 +91,7 @@
 
     <!-- Email address for the homepage contextual cards feedback -->
     <string name="config_contextual_card_feedback_email" translatable="false">test@test.test</string>
+
+    <!-- Grayscale settings intent -->
+    <string name="config_grayscale_settings_intent" translate="false">intent:#Intent;action=test.test;end</string>
 </resources>
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index 37186ca..3d3aff4 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -28,6 +28,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.ActionBar;
+import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -51,15 +53,18 @@
 import android.os.storage.VolumeInfo;
 import android.util.IconDrawableFactory;
 import android.widget.EditText;
+import android.widget.ScrollView;
 import android.widget.TextView;
 
 import androidx.core.graphics.drawable.IconCompat;
+import androidx.fragment.app.FragmentActivity;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
@@ -259,4 +264,21 @@
     public void isPackageEnabled_noApp_returnFalse() {
         assertThat(Utils.isPackageEnabled(mContext, PACKAGE_NAME)).isFalse();
     }
+
+    @Test
+    public void setActionBarShadowAnimation_nullParameters_shouldNotCrash() {
+        // no crash here
+        Utils.setActionBarShadowAnimation(null, null, null);
+    }
+
+    @Test
+    public void setActionBarShadowAnimation_shouldSetElevationToZero() {
+        final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class);
+        final ActionBar actionBar = activity.getActionBar();
+
+        Utils.setActionBarShadowAnimation(activity, activity.getLifecycle(),
+                new ScrollView(mContext));
+
+        assertThat(actionBar.getElevation()).isEqualTo(0.f);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
index b8d0f20..c3ae904 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
@@ -46,7 +46,7 @@
     public void seUp() {
         mContext = RuntimeEnvironment.application;
         mView = ApplicationViewHolder.newView(new FrameLayout(mContext));
-        mHolder = new ApplicationViewHolder(mView, false /* useStableHeight */);
+        mHolder = new ApplicationViewHolder(mView);
     }
 
     @Test
@@ -67,10 +67,6 @@
 
         mHolder.setSummary(R.string.disabled);
         assertThat(mHolder.mSummary.getText()).isEqualTo(mContext.getText(R.string.disabled));
-        assertThat(mHolder.mSummaryContainer.getVisibility()).isEqualTo(View.VISIBLE);
-
-        mHolder.setSummary(null);
-        assertThat(mHolder.mSummaryContainer.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
@@ -104,7 +100,7 @@
     @Test
     public void twoTouchTarget() {
         mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true);
-        mHolder = new ApplicationViewHolder(mView, false /* useStableHeight */);
+        mHolder = new ApplicationViewHolder(mView);
         assertThat(mHolder.mSwitch).isNotNull();
         assertThat(mHolder.mWidgetContainer.getChildCount()).isEqualTo(1);
     }
@@ -112,8 +108,9 @@
     @Test
     public void updateSwitch() {
         mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true);
-        mHolder = new ApplicationViewHolder(mView, false /* useStableHeight */);
-        mHolder.updateSwitch(v -> {}, true, true);
+        mHolder = new ApplicationViewHolder(mView);
+        mHolder.updateSwitch(v -> {
+        } /* listener */, true, true);
 
         assertThat(mHolder.mSwitch.isChecked()).isTrue();
         assertThat(mHolder.mSwitch.isEnabled()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
index 419fc49..27c3e7d 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
@@ -235,16 +235,6 @@
     }
 
     @Test
-    public void shouldUseStableItemHeight() {
-        assertThat(ManageApplications.ApplicationsAdapter.shouldUseStableItemHeight(
-                LIST_TYPE_MAIN))
-                .isTrue();
-        assertThat(ManageApplications.ApplicationsAdapter.shouldUseStableItemHeight(
-                LIST_TYPE_NOTIFICATION))
-                .isTrue();
-    }
-
-    @Test
     public void onRebuildComplete_shouldHideLoadingView() {
         final Context context = RuntimeEnvironment.application;
         final RecyclerView recyclerView = mock(RecyclerView.class);
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java
index 8f5b0ab..74fb98f 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java
@@ -64,7 +64,7 @@
         mController = new MusicViewHolderController(mContext, mSource, fsUuid, new UserHandle(0));
 
         View view = ApplicationViewHolder.newView(new FrameLayout(mContext));
-        mHolder = new ApplicationViewHolder(view, false /* useStableHeight */);
+        mHolder = new ApplicationViewHolder(view);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java
index c453474..5475b9c 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java
@@ -63,7 +63,7 @@
         mController = new PhotosViewHolderController(mContext, mSource, fsUuid, new UserHandle(0));
 
         final View view = ApplicationViewHolder.newView(new FrameLayout(mContext));
-        mHolder = new ApplicationViewHolder(view, false /* useStableHeight */);
+        mHolder = new ApplicationViewHolder(view);
     }
 
     @Test
@@ -71,19 +71,19 @@
         mController.setupView(mHolder);
 
         assertThat(mHolder.mSummary.getText().toString())
-            .isEqualTo(Formatter.formatFileSize(mContext, 0));
+                .isEqualTo(Formatter.formatFileSize(mContext, 0));
     }
 
     @Test
     public void storageShouldRepresentStorageStatsQuery() throws Exception {
         when(mSource.getExternalStorageStats(nullable(String.class), nullable(UserHandle.class)))
-            .thenReturn(new StorageStatsSource.ExternalStorageStats(1, 0, 1, 10, 0));
+                .thenReturn(new StorageStatsSource.ExternalStorageStats(1, 0, 1, 10, 0));
 
         mController.queryStats();
         mController.setupView(mHolder);
 
         assertThat(mHolder.mSummary.getText().toString())
-            .isEqualTo(Formatter.formatFileSize(mContext, 11));
+                .isEqualTo(Formatter.formatFileSize(mContext, 11));
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessControllerTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessControllerTest.java
index bcb4bb3..6041e9d 100644
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessControllerTest.java
@@ -18,26 +18,41 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.app.NotificationManager;
 import android.content.Context;
 
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowNotificationManager;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 import org.robolectric.shadow.api.Shadow;
 import org.robolectric.shadows.ShadowActivityManager;
 
 @RunWith(RobolectricTestRunner.class)
 public class ZenAccessControllerTest {
 
+    private static final String TEST_PKG = "com.test.package";
+
+    private FakeFeatureFactory mFeatureFactory;
     private Context mContext;
     private ZenAccessController mController;
     private ShadowActivityManager mActivityManager;
 
+
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
+        mFeatureFactory = FakeFeatureFactory.setupForTest();
         mController = new ZenAccessController(mContext, "key");
         mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
     }
@@ -52,4 +67,32 @@
         mActivityManager.setIsLowRamDevice(true);
         assertThat(mController.isAvailable()).isFalse();
     }
+
+    @Test
+    public void logSpecialPermissionChange() {
+        ZenAccessController.logSpecialPermissionChange(true, "app", mContext);
+        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
+                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_ALLOW),
+                eq("app"));
+
+        ZenAccessController.logSpecialPermissionChange(false, "app", mContext);
+        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
+                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_DENY),
+                eq("app"));
+    }
+
+    @Test
+    @Config(shadows = ShadowNotificationManager.class)
+    public void hasAccess_granted_yes() {
+        final ShadowNotificationManager snm = Shadow.extract(mContext.getSystemService(
+                NotificationManager.class));
+        snm.setNotificationPolicyAccessGrantedForPackage(TEST_PKG);
+        assertThat(ZenAccessController.hasAccess(mContext, TEST_PKG)).isTrue();
+    }
+
+    @Test
+    @Config(shadows = ShadowNotificationManager.class)
+    public void hasAccess_notGranted_no() {
+        assertThat(ZenAccessController.hasAccess(mContext, TEST_PKG)).isFalse();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixinTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixinTest.java
new file mode 100644
index 0000000..cba1a51
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/zenaccess/ZenAccessSettingObserverMixinTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.specialaccess.zenaccess;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_START;
+import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowActivityManager;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenAccessSettingObserverMixinTest {
+
+    @Mock
+    private ZenAccessSettingObserverMixin.Listener mListener;
+
+    private Context mContext;
+    private LifecycleOwner mLifecycleOwner;
+    private Lifecycle mLifecycle;
+    private ZenAccessSettingObserverMixin mMixin;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mLifecycleOwner = () -> mLifecycle;
+        mLifecycle = new Lifecycle(mLifecycleOwner);
+
+        mMixin = new ZenAccessSettingObserverMixin(mContext, mListener);
+
+        mLifecycle.addObserver(mMixin);
+    }
+
+    @Test
+    public void onStart_lowMemory_shouldNotRegisterListener() {
+        final ShadowActivityManager sam = Shadow.extract(
+                mContext.getSystemService(ActivityManager.class));
+        sam.setIsLowRamDevice(true);
+
+        mLifecycle.handleLifecycleEvent(ON_START);
+
+        mContext.getContentResolver().notifyChange(Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), null);
+
+        verify(mListener, never()).onZenAccessPolicyChanged();
+    }
+
+    @Test
+    public void onStart_highMemory_shouldRegisterListener() {
+        final ShadowActivityManager sam = Shadow.extract(
+                mContext.getSystemService(ActivityManager.class));
+        sam.setIsLowRamDevice(false);
+
+        mLifecycle.handleLifecycleEvent(ON_START);
+
+        mContext.getContentResolver().notifyChange(Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), null);
+
+        verify(mListener).onZenAccessPolicyChanged();
+    }
+
+    @Test
+    public void onStop_shouldUnregisterListener() {
+        final ShadowActivityManager sam = Shadow.extract(
+                mContext.getSystemService(ActivityManager.class));
+        sam.setIsLowRamDevice(false);
+
+        mLifecycle.handleLifecycleEvent(ON_START);
+        mLifecycle.handleLifecycleEvent(ON_STOP);
+
+        mContext.getContentResolver().notifyChange(Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES), null);
+
+        verify(mListener, never()).onZenAccessPolicyChanged();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java b/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java
index 5587783..b6ef32c 100644
--- a/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java
+++ b/tests/robotests/src/com/android/settings/backup/BackupSettingsHelperTest.java
@@ -256,20 +256,21 @@
 
     @Test
     public void testGetLabelBackupTransport() throws Exception {
-        String label = "test_label";
+        CharSequence label = "test_label";
 
-        when(mBackupManager.getDataManagementLabel(anyString())).thenReturn(label);
+        when(mBackupManager.getDataManagementLabelForUser(anyInt(), anyString())).thenReturn(label);
 
-        String backupLabel = mBackupSettingsHelper.getLabelFromBackupTransport();
+        CharSequence backupLabel = mBackupSettingsHelper.getLabelFromBackupTransport();
 
         assertThat(backupLabel).isEqualTo(label);
     }
 
     @Test
     public void testGetLabelBackupTransport_RemoteException() throws Exception {
-        when(mBackupManager.getDataManagementLabel(anyString())).thenThrow(new RemoteException());
+        when(mBackupManager.getDataManagementLabelForUser(anyInt(), anyString()))
+                .thenThrow(new RemoteException());
 
-        String backupLabel = mBackupSettingsHelper.getLabelFromBackupTransport();
+        CharSequence backupLabel = mBackupSettingsHelper.getLabelFromBackupTransport();
 
         assertThat(backupLabel).isNull();
     }
@@ -291,31 +292,31 @@
 
     @Test
     public void testGetLabelForBackupSettings_WithLabelFromTransport() throws Exception {
-        String label = "test_label";
+        CharSequence label = "test_label";
 
-        when(mBackupManager.getDataManagementLabel(anyString())).thenReturn(label);
+        when(mBackupManager.getDataManagementLabelForUser(anyInt(), anyString())).thenReturn(label);
 
-        String backupLabel = mBackupSettingsHelper.getLabelForBackupSettings();
+        CharSequence backupLabel = mBackupSettingsHelper.getLabelForBackupSettings();
 
         assertThat(backupLabel).isEqualTo(label);
     }
 
     @Test
     public void testGetLabelForBackupSettings_WithEmptyLabelFromTransport() throws Exception {
-        String label = "";
+        CharSequence label = "";
 
-        when(mBackupManager.getDataManagementLabel(anyString())).thenReturn(label);
+        when(mBackupManager.getDataManagementLabelForUser(anyInt(), anyString())).thenReturn(label);
 
-        String backupLabel = mBackupSettingsHelper.getLabelForBackupSettings();
+        CharSequence backupLabel = mBackupSettingsHelper.getLabelForBackupSettings();
 
         assertThat(backupLabel).isEqualTo(mContext.getString(DEFAULT_LABEL_RESOURCE));
     }
 
     @Test
     public void testGetLabelForBackupSettings_WithoutLabelFromTransport() throws Exception {
-        when(mBackupManager.getDataManagementLabel(anyString())).thenReturn(null);
+        when(mBackupManager.getDataManagementLabelForUser(anyInt(), anyString())).thenReturn(null);
 
-        String backupLabel = mBackupSettingsHelper.getLabelForBackupSettings();
+        CharSequence backupLabel = mBackupSettingsHelper.getLabelForBackupSettings();
 
         assertThat(backupLabel).isEqualTo(mContext.getString(DEFAULT_LABEL_RESOURCE));
     }
diff --git a/tests/robotests/src/com/android/settings/backup/DataManagementPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/backup/DataManagementPreferenceControllerTest.java
index ac92fb7..d3688d3 100644
--- a/tests/robotests/src/com/android/settings/backup/DataManagementPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/backup/DataManagementPreferenceControllerTest.java
@@ -43,7 +43,7 @@
     private DataManagementPreferenceController mController;
     private PrivacySettingsConfigData mPSCD;
     private Preference mPreference;
-    private String mTitle;
+    private CharSequence mTitle;
 
     @Mock
     private Intent mIntent;
diff --git a/tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java b/tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java
new file mode 100644
index 0000000..579cba0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/core/HideNonSystemOverlayMixinTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.core;
+
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(RobolectricTestRunner.class)
+public class HideNonSystemOverlayMixinTest {
+
+    private ActivityController<TestActivity> mActivityController;
+
+    @Before
+    public void setUp() {
+        RuntimeEnvironment.application.setTheme(R.style.Theme_AppCompat);
+        mActivityController = Robolectric.buildActivity(TestActivity.class);
+    }
+
+    @Test
+    public void startActivity_shouldHideNonSystemOverlay() {
+        mActivityController.setup();
+        TestActivity activity = mActivityController.get();
+
+        // Activity start: HIDE_NON_SYSTEM_OVERLAY should be set.
+        final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();
+        assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
+                .isNotEqualTo(0);
+    }
+
+    @Test
+    public void stopActivity_shouldUnhideNonSystemOverlay() {
+        mActivityController.setup().stop();
+        TestActivity activity = mActivityController.get();
+
+        final WindowManager.LayoutParams attrs = activity.getWindow().getAttributes();
+        assertThat(attrs.privateFlags & SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS)
+                .isEqualTo(0);
+    }
+
+    public static class TestActivity extends AppCompatActivity {
+        @Override
+        protected void onCreate(@Nullable Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            getLifecycle().addObserver(new HideNonSystemOverlayMixin(this));
+        }
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
index a441864..0ee9cfc 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverStickyPreferenceControllerTest.java
@@ -42,7 +42,7 @@
     }
 
     private int getAutoDisableSetting() {
-        return Settings.System.getInt(mContext.getContentResolver(),
+        return Settings.Global.getInt(mContext.getContentResolver(),
                 LOW_POWER_STICKY_AUTO_DISABLE_ENABLED,
                 1);
     }
diff --git a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java
deleted file mode 100644
index 471914a..0000000
--- a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2018 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.settings.gestures;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
-import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.hardware.display.AmbientDisplayConfiguration;
-
-import com.android.settings.aware.AwareFeatureProvider;
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class WakeScreenGesturePreferenceControllerTest {
-
-    private static final String KEY_WAKE_SCREEN = "gesture_wake_screen";
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-    @Mock
-    private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
-    private WakeScreenGesturePreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        AwareFeatureProvider featureProvider =
-                FakeFeatureFactory.setupForTest().getAwareFeatureProvider();
-        when(featureProvider.isSupported(any())).thenReturn(true);
-        when(featureProvider.isEnabled(any())).thenReturn(true);
-        mController = new WakeScreenGesturePreferenceController(mContext, KEY_WAKE_SCREEN);
-        mController.setConfig(mAmbientDisplayConfiguration);
-    }
-
-    @Test
-    public void testIsChecked_configIsSet_shouldReturnTrue() {
-        // Set the setting to be enabled.
-        when(mAmbientDisplayConfiguration.wakeScreenGestureEnabled(anyInt())).thenReturn(true);
-        assertThat(mController.isChecked()).isTrue();
-    }
-
-    @Test
-    public void testIsChecked_configIsNotSet_shouldReturnFalse() {
-        // Set the setting to be disabled.
-        when(mAmbientDisplayConfiguration.wakeScreenGestureEnabled(anyInt())).thenReturn(false);
-        assertThat(mController.isChecked()).isFalse();
-    }
-
-    @Test
-    public void getAvailabilityStatus_gestureNotSupported_UNSUPPORTED_ON_DEVICE() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
-        when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(false);
-        final int availabilityStatus = mController.getAvailabilityStatus();
-
-        assertThat(availabilityStatus).isEqualTo(UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_gestureSupported_AVAILABLE() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
-        when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(true);
-        final int availabilityStatus = mController.getAvailabilityStatus();
-
-        assertThat(availabilityStatus).isEqualTo(AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_gestureSupported_DISABLED_DEPENDENT_SETTING() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
-        when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(true);
-        final int availabilityStatus = mController.getAvailabilityStatus();
-
-        assertThat(availabilityStatus).isEqualTo(DISABLED_DEPENDENT_SETTING);
-    }
-
-    @Test
-    public void canHandleClicks_onlyWhenAlwaysOn() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
-        assertThat(mController.canHandleClicks()).isEqualTo(false);
-
-        reset(mAmbientDisplayConfiguration);
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
-        assertThat(mController.canHandleClicks()).isEqualTo(true);
-    }
-
-    @Test
-    public void isSliceableCorrectKey_returnsTrue() {
-        final WakeScreenGesturePreferenceController controller =
-                new WakeScreenGesturePreferenceController(mContext, "gesture_wake_screen");
-        assertThat(controller.isSliceable()).isTrue();
-    }
-
-    @Test
-    public void isSliceableIncorrectKey_returnsFalse() {
-        final WakeScreenGesturePreferenceController controller =
-                new WakeScreenGesturePreferenceController(mContext, "bad_key");
-        assertThat(controller.isSliceable()).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/gestures/WakeScreenGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/WakeScreenGestureSettingsTest.java
deleted file mode 100644
index f1d2fcc..0000000
--- a/tests/robotests/src/com/android/settings/gestures/WakeScreenGestureSettingsTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2018 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.settings.gestures;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.provider.SearchIndexableResource;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class WakeScreenGestureSettingsTest {
-
-    private WakeScreenGestureSettings mSettings;
-
-    @Before
-    public void setUp() {
-        mSettings = new WakeScreenGestureSettings();
-    }
-
-    @Test
-    public void testSearchIndexProvider_shouldIndexResource() {
-        final List<SearchIndexableResource> indexRes =
-                WakeScreenGestureSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
-                        RuntimeEnvironment.application, true /* enabled */);
-
-        assertThat(indexRes).isNotNull();
-        assertThat(indexRes.get(0).xmlResId).isEqualTo(mSettings.getPreferenceScreenResId());
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java
new file mode 100644
index 0000000..8c24735
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards.conditional;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+public class GrayscaleConditionControllerTest {
+
+    @Mock
+    private ConditionManager mConditionManager;
+
+    private ColorDisplayManager mColorDisplayManager;
+    private Context mContext;
+    private GrayscaleConditionController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        mColorDisplayManager = spy(mContext.getSystemService(ColorDisplayManager.class));
+        doReturn(mColorDisplayManager).when(mContext).getSystemService(ColorDisplayManager.class);
+        mController = new GrayscaleConditionController(mContext, mConditionManager);
+    }
+
+    @Test
+    public void isDisplayable_noIntent_shouldReturnFalse() {
+        assertThat(mController.isDisplayable()).isFalse();
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void isDisplayable_validIntentAndGrayscaleOn_shouldReturnTrue() {
+        doReturn(true).when(mColorDisplayManager).isSaturationActivated();
+
+        assertThat(mController.isDisplayable()).isTrue();
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void isDisplayable_validIntentAndGrayscaleOff_shouldReturnFalse() {
+        doReturn(false).when(mColorDisplayManager).isSaturationActivated();
+
+        assertThat(mController.isDisplayable()).isFalse();
+    }
+
+    @Test
+    public void onActionClick_shouldRefreshCondition() {
+        mController.onActionClick();
+
+        verify(mConditionManager).onConditionChanged();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ContextualNotificationChannelSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ContextualNotificationChannelSliceTest.java
new file mode 100644
index 0000000..f2b87be
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/ContextualNotificationChannelSliceTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.homepage.contextualcards.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.settings.R;
+import com.android.settings.slices.CustomSliceRegistry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class ContextualNotificationChannelSliceTest {
+
+    private Context mContext;
+    private ContextualNotificationChannelSlice mNotificationChannelSlice;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mNotificationChannelSlice = new ContextualNotificationChannelSlice(mContext);
+    }
+
+    @Test
+    public void getUri_shouldBeContextualNotificationChannelSliceUri() {
+        final Uri uri = mNotificationChannelSlice.getUri();
+
+        assertThat(uri).isEqualTo(CustomSliceRegistry.CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI);
+    }
+
+    @Test
+    public void getSubTitle_shouldBeRecentlyInstalledApp() {
+        final CharSequence subTitle = mNotificationChannelSlice.getSubTitle("com.test.package", 0);
+
+        assertThat(subTitle).isEqualTo(mContext.getText(R.string.recently_installed_app));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java
new file mode 100644
index 0000000..ab3f4de
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorSliceTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.settings.media;
+
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settingslib.media.LocalMediaManager;
+import com.android.settingslib.media.MediaDevice;
+import com.android.settingslib.media.MediaOutputSliceConstants;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class MediaOutputIndicatorSliceTest {
+
+    private static final String TEST_DEVICE_NAME = "test_device_name";
+    private static final int TEST_DEVICE_1_ICON =
+            com.android.internal.R.drawable.ic_bt_headphones_a2dp;
+
+    @Mock
+    private LocalMediaManager mLocalMediaManager;
+
+    private final List<MediaDevice> mDevices = new ArrayList<>();
+
+    private Context mContext;
+    private MediaOutputIndicatorSlice mMediaOutputIndicatorSlice;
+    private MediaOutputIndicatorWorker mMediaOutputIndicatorWorker;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+
+        // Set-up specs for SliceMetadata.
+        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+
+        mMediaOutputIndicatorSlice = new MediaOutputIndicatorSlice(mContext);
+        mMediaOutputIndicatorWorker = spy(new MediaOutputIndicatorWorker(
+                mContext, MEDIA_OUTPUT_INDICATOR_SLICE_URI));
+        mMediaOutputIndicatorSlice.mWorker = mMediaOutputIndicatorWorker;
+    }
+
+    @Test
+    public void getSlice_invisible_returnNull() {
+        when(mMediaOutputIndicatorWorker.isVisible()).thenReturn(false);
+
+        assertThat(mMediaOutputIndicatorSlice.getSlice()).isNull();
+    }
+
+    @Test
+    public void getSlice_withActiveDevice_checkContent() {
+        when(mMediaOutputIndicatorWorker.isVisible()).thenReturn(true);
+        when(mMediaOutputIndicatorWorker.findActiveDeviceName()).thenReturn(TEST_DEVICE_NAME);
+        final Slice mediaSlice = mMediaOutputIndicatorSlice.getSlice();
+        final SliceMetadata metadata = SliceMetadata.from(mContext, mediaSlice);
+        // Verify slice title and subtitle
+        assertThat(metadata.getTitle()).isEqualTo(mContext.getText(R.string.media_output_title));
+        assertThat(metadata.getSubtitle()).isEqualTo(TEST_DEVICE_NAME);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
new file mode 100644
index 0000000..4a5662e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.net.Uri;
+
+import com.android.settings.R;
+import com.android.settings.bluetooth.Utils;
+import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowBluetoothDevice;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothUtils.class,
+        ShadowBluetoothDevice.class})
+public class MediaOutputIndicatorWorkerTest {
+
+    private static final String TEST_A2DP_DEVICE_NAME = "Test_A2DP_BT_Device_NAME";
+    private static final String TEST_HAP_DEVICE_NAME = "Test_HAP_BT_Device_NAME";
+    private static final String TEST_A2DP_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
+    private static final String TEST_HAP_DEVICE_ADDRESS = "00:B2:B2:B2:B2:B2";
+    private static final Uri URI = Uri.parse("content://com.android.settings.slices/test");
+
+    @Mock
+    private A2dpProfile mA2dpProfile;
+    @Mock
+    private HearingAidProfile mHearingAidProfile;
+    @Mock
+    private LocalBluetoothManager mLocalManager;
+    @Mock
+    private BluetoothEventManager mBluetoothEventManager;
+    @Mock
+    private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
+
+    private BluetoothAdapter mBluetoothAdapter;
+    private BluetoothDevice mA2dpDevice;
+    private BluetoothDevice mHapDevice;
+    private BluetoothManager mBluetoothManager;
+    private Context mContext;
+    private List<BluetoothDevice> mDevicesList;
+    private LocalBluetoothManager mLocalBluetoothManager;
+    private MediaOutputIndicatorWorker mMediaDeviceUpdateWorker;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(RuntimeEnvironment.application);
+        ShadowBluetoothUtils.sLocalBluetoothManager = mLocalManager;
+        mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
+        when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
+        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
+        when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
+        when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+        mBluetoothManager = new BluetoothManager(mContext);
+        mBluetoothAdapter = mBluetoothManager.getAdapter();
+
+        // Setup A2dp device
+        mA2dpDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_A2DP_DEVICE_ADDRESS));
+        when(mA2dpDevice.getName()).thenReturn(TEST_A2DP_DEVICE_NAME);
+        when(mA2dpDevice.isConnected()).thenReturn(true);
+        // Setup HearingAid device
+        mHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_HAP_DEVICE_ADDRESS));
+        when(mHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME);
+        when(mHapDevice.isConnected()).thenReturn(true);
+
+        mMediaDeviceUpdateWorker = new MediaOutputIndicatorWorker(mContext, URI);
+        mDevicesList = new ArrayList<>();
+    }
+
+    @Test
+    public void isVisible_noConnectableDevice_returnFalse() {
+        mDevicesList.clear();
+        when(mA2dpProfile.getConnectableDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.isVisible()).isFalse();
+    }
+
+    @Test
+    public void isVisible_withConnectableA2dpDevice_returnTrue() {
+        mDevicesList.clear();
+        mDevicesList.add(mA2dpDevice);
+        when(mHearingAidProfile.getConnectableDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.isVisible()).isTrue();
+    }
+
+    @Test
+    public void isVisible_withConnectableHADevice_returnTrue() {
+        mDevicesList.clear();
+        mDevicesList.add(mHapDevice);
+        when(mA2dpProfile.getConnectableDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.isVisible()).isTrue();
+    }
+
+    @Test
+    public void findActiveDeviceName_A2dpDeviceActive_verifyName() {
+        when(mA2dpProfile.getActiveDevice()).thenReturn(mA2dpDevice);
+
+        assertThat(mMediaDeviceUpdateWorker.findActiveDeviceName())
+                .isEqualTo(mA2dpDevice.getAliasName());
+    }
+
+    @Test
+    public void findActiveDeviceName_HADeviceActive_verifyName() {
+        mDevicesList.add(mHapDevice);
+        when(mHearingAidProfile.getActiveDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.findActiveDeviceName())
+                .isEqualTo(mHapDevice.getAliasName());
+    }
+
+    @Test
+    public void findActiveDeviceName_noActiveDevice_verifyDefaultName() {
+        when(mA2dpProfile.getActiveDevice()).thenReturn(null);
+        mDevicesList.clear();
+        when(mHearingAidProfile.getActiveDevices()).thenReturn(mDevicesList);
+
+        assertThat(mMediaDeviceUpdateWorker.findActiveDeviceName())
+                .isEqualTo(mContext.getText(R.string.media_output_default_summary));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index da0d85b..d26a458 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -94,6 +94,13 @@
     }
 
     @Test
+    public void getSlice_workerIsNull_shouldNotCrash() {
+        mMediaOutputSlice.init(TEST_PACKAGE_NAME, null);
+
+        mMediaOutputSlice.getSlice();
+    }
+
+    @Test
     public void getSlice_shouldHaveActiveDeviceName() {
         mDevices.clear();
         final MediaDevice device = mock(MediaDevice.class);
diff --git a/tests/robotests/src/com/android/settings/notification/AssistantCapabilityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AssistantCapabilityPreferenceControllerTest.java
new file mode 100644
index 0000000..182ce8a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/AssistantCapabilityPreferenceControllerTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+import static com.android.settings.notification.AssistantCapabilityPreferenceController.PRIORITIZER_KEY;
+import static com.android.settings.notification.AssistantCapabilityPreferenceController.SMART_KEY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.service.notification.Adjustment;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(RobolectricTestRunner.class)
+public class AssistantCapabilityPreferenceControllerTest {
+
+    @Mock
+    private NotificationBackend mBackend;
+    @Mock
+    private PreferenceScreen mScreen;
+
+    private Context mContext;
+    private AssistantCapabilityPreferenceController mPrioritizerController;
+    private AssistantCapabilityPreferenceController mChipController;
+    private Preference mPrioritizerPreference;
+    private Preference mChipPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mPrioritizerController = new AssistantCapabilityPreferenceController(
+                mContext, PRIORITIZER_KEY);
+        mPrioritizerController.setBackend(mBackend);
+        mPrioritizerPreference = new Preference(mContext);
+        mPrioritizerPreference.setKey(mPrioritizerController.getPreferenceKey());
+        when(mScreen.findPreference(
+                mPrioritizerController.getPreferenceKey())).thenReturn(mPrioritizerPreference);
+        mChipController = new AssistantCapabilityPreferenceController(mContext, SMART_KEY);
+        mChipController.setBackend(mBackend);
+        mChipPreference = new Preference(mContext);
+        mChipPreference.setKey(mChipController.getPreferenceKey());
+        when(mScreen.findPreference(
+                mChipController.getPreferenceKey())).thenReturn(mChipPreference);
+    }
+
+    @Test
+    public void getAvailabilityStatus_NAS() {
+        when(mBackend.getAllowedNotificationAssistant()).thenReturn(mock(ComponentName.class));
+        assertThat(mPrioritizerController.getAvailabilityStatus())
+                .isEqualTo(AVAILABLE);
+        assertThat(mChipController.getAvailabilityStatus())
+                .isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_noNAS() {
+        when(mBackend.getAllowedNotificationAssistant()).thenReturn(null);
+        assertThat(mPrioritizerController.getAvailabilityStatus())
+                .isEqualTo(DISABLED_DEPENDENT_SETTING);
+        assertThat(mChipController.getAvailabilityStatus())
+                .isEqualTo(DISABLED_DEPENDENT_SETTING);
+    }
+
+    @Test
+    public void isChecked_prioritizerSettingIsOff_false() {
+        List<String> capabilities = new ArrayList<>();
+        capabilities.add(Adjustment.KEY_USER_SENTIMENT);
+        when(mBackend.getAssistantCapabilities(anyString())).thenReturn(capabilities);
+        assertThat(mPrioritizerController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_prioritizerSettingIsOn_true() {
+        List<String> capabilities = new ArrayList<>();
+        capabilities.add(Adjustment.KEY_IMPORTANCE);
+        when(mBackend.getAssistantCapabilities(anyString())).thenReturn(capabilities);
+        assertThat(mPrioritizerController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void isChecked_chipSettingIsOff_false() {
+        List<String> capabilities = new ArrayList<>();
+        capabilities.add(Adjustment.KEY_IMPORTANCE);
+        when(mBackend.getAssistantCapabilities(anyString())).thenReturn(capabilities);
+        assertThat(mChipController.isChecked()).isFalse();
+
+        capabilities = new ArrayList<>();
+        capabilities.add(Adjustment.KEY_CONTEXTUAL_ACTIONS);
+        when(mBackend.getAssistantCapabilities(anyString())).thenReturn(capabilities);
+        assertThat(mChipController.isChecked()).isFalse();
+
+        capabilities = new ArrayList<>();
+        capabilities.add(Adjustment.KEY_TEXT_REPLIES);
+        when(mBackend.getAssistantCapabilities(anyString())).thenReturn(capabilities);
+        assertThat(mChipController.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_chipSettingIsOn_true() {
+        List<String> capabilities = new ArrayList<>();
+        capabilities.add(Adjustment.KEY_TEXT_REPLIES);
+        capabilities.add(Adjustment.KEY_CONTEXTUAL_ACTIONS);
+        when(mBackend.getAssistantCapabilities(anyString())).thenReturn(capabilities);
+        assertThat(mChipController.isChecked()).isTrue();
+    }
+
+    @Test
+    public void onPreferenceChange_prioritizerOn() {
+        mPrioritizerController.onPreferenceChange(mPrioritizerPreference, true);
+        verify(mBackend).allowAssistantCapability(Adjustment.KEY_IMPORTANCE, true);
+    }
+
+    @Test
+    public void onPreferenceChange_prioritizerOff() {
+        mPrioritizerController.onPreferenceChange(mPrioritizerPreference, false);
+        verify(mBackend).allowAssistantCapability(Adjustment.KEY_IMPORTANCE, false);
+    }
+
+    @Test
+    public void onPreferenceChange_chipsOn() {
+        mChipController.onPreferenceChange(mChipPreference, true);
+        verify(mBackend).allowAssistantCapability(Adjustment.KEY_CONTEXTUAL_ACTIONS, true);
+        verify(mBackend).allowAssistantCapability(Adjustment.KEY_TEXT_REPLIES, true);
+    }
+
+    @Test
+    public void onPreferenceChange_chipsOff() {
+        mChipController.onPreferenceChange(mChipPreference, false);
+        verify(mBackend).allowAssistantCapability(Adjustment.KEY_CONTEXTUAL_ACTIONS, false);
+        verify(mBackend).allowAssistantCapability(Adjustment.KEY_TEXT_REPLIES, false);
+    }
+}
+
diff --git a/tests/robotests/src/com/android/settings/notification/ZenAccessSettingsTest.java b/tests/robotests/src/com/android/settings/notification/ZenAccessSettingsTest.java
deleted file mode 100644
index c2a6f4f..0000000
--- a/tests/robotests/src/com/android/settings/notification/ZenAccessSettingsTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings.notification;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class ZenAccessSettingsTest {
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-
-    private FakeFeatureFactory mFeatureFactory;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mFeatureFactory = FakeFeatureFactory.setupForTest();
-    }
-
-    @Test
-    public void logSpecialPermissionChange() {
-        ZenAccessSettings.logSpecialPermissionChange(true, "app", mContext);
-        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
-                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_ALLOW),
-                eq("app"));
-
-        ZenAccessSettings.logSpecialPermissionChange(false, "app", mContext);
-        verify(mFeatureFactory.metricsFeatureProvider).action(any(Context.class),
-                eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_DND_DENY),
-                eq("app"));
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
index 4665dc9..11de7b3 100644
--- a/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
+++ b/tests/robotests/src/com/android/settings/panel/VolumePanelTest.java
@@ -48,6 +48,7 @@
                 CustomSliceRegistry.VOLUME_REMOTE_MEDIA_URI,
                 CustomSliceRegistry.VOLUME_CALL_URI,
                 CustomSliceRegistry.VOLUME_MEDIA_URI,
+                CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI,
                 CustomSliceRegistry.VOLUME_RINGER_URI,
                 CustomSliceRegistry.VOLUME_ALARM_URI);
     }
diff --git a/tests/robotests/src/com/android/settings/privacy/PrivacyDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/privacy/PrivacyDashboardFragmentTest.java
index 482eaeb..80f3900 100644
--- a/tests/robotests/src/com/android/settings/privacy/PrivacyDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/privacy/PrivacyDashboardFragmentTest.java
@@ -80,10 +80,10 @@
     }
 
     @Test
-    public void onViewCreated_shouldCallStyleActionBar() {
+    public void onViewCreated_shouldSetActionBarShadowAnimation() {
         mFragment.onViewCreated(new View(mContext), new Bundle());
 
-        verify(mFragment).styleActionBar();
+        assertThat(mFragment.getActivity().getActionBar().getElevation()).isEqualTo(0.f);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 23025b2..005ffbe 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -133,7 +133,6 @@
         mProvider = spy(new SettingsSliceProvider());
         ShadowStrictMode.reset();
         mProvider.mSliceWeakDataCache = new HashMap<>();
-        mProvider.mSliceDataCache = new HashMap<>();
         mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
         when(mProvider.getContext()).thenReturn(mContext);
 
@@ -198,30 +197,6 @@
     }
 
     @Test
-    public void testLoadSlice_doesNotCacheWithoutPin() {
-        insertSpecialCase(KEY);
-        final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
-
-        mProvider.loadSlice(uri);
-        SliceData data = mProvider.mSliceDataCache.get(uri);
-
-        assertThat(data).isNull();
-    }
-
-    @Test
-    public void testLoadSlice_cachesWithPin() {
-        insertSpecialCase(KEY);
-        final Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
-        when(mManager.getPinnedSlices()).thenReturn(Arrays.asList(uri));
-
-        mProvider.loadSlice(uri);
-        SliceData data = mProvider.mSliceDataCache.get(uri);
-
-        assertThat(data.getKey()).isEqualTo(KEY);
-        assertThat(data.getTitle()).isEqualTo(TITLE);
-    }
-
-    @Test
     public void testLoadSlice_cachedEntryRemovedOnBuild() {
         SliceData data = getDummyData();
         mProvider.mSliceWeakDataCache.put(data.getUri(), data);
@@ -277,18 +252,6 @@
     }
 
     @Test
-    public void testLoadSlice_cachedEntryRemovedOnUnpin() {
-        SliceData data = getDummyData();
-        mProvider.mSliceDataCache.put(data.getUri(), data);
-        mProvider.onSliceUnpinned(data.getUri());
-        insertSpecialCase(data.getKey());
-
-        SliceData cachedData = mProvider.mSliceWeakDataCache.get(data.getUri());
-
-        assertThat(cachedData).isNull();
-    }
-
-    @Test
     public void getDescendantUris_fullActionUri_returnsSelf() {
         final Uri uri = SliceBuilderUtils.getUri(
                 SettingsSlicesContract.PATH_SETTING_ACTION + "/key", true);
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java
index 8325777..78fb23f 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNotificationManager.java
@@ -19,15 +19,19 @@
 import android.app.NotificationManager;
 import android.net.Uri;
 import android.service.notification.ZenModeConfig;
+import android.util.ArraySet;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import java.util.Set;
+
 @Implements(NotificationManager.class)
 public class ShadowNotificationManager {
 
     private int mZenMode;
     private ZenModeConfig mZenModeConfig;
+    private Set<String> mNotificationPolicyGrantedPackages = new ArraySet<>();
 
     @Implementation
     protected void setZenMode(int mode, Uri conditionId, String reason) {
@@ -40,6 +44,11 @@
     }
 
     @Implementation
+    protected boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {
+        return mNotificationPolicyGrantedPackages.contains(pkg);
+    }
+
+    @Implementation
     public ZenModeConfig getZenModeConfig() {
         return mZenModeConfig;
     }
@@ -47,4 +56,8 @@
     public void setZenModeConfig(ZenModeConfig config) {
         mZenModeConfig = config;
     }
+
+    public void setNotificationPolicyAccessGrantedForPackage(String pkg) {
+        mNotificationPolicyGrantedPackages.add(pkg);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/widget/AdaptiveHomepageIconTest.java b/tests/robotests/src/com/android/settings/widget/AdaptiveIconTest.java
similarity index 80%
rename from tests/robotests/src/com/android/settings/widget/AdaptiveHomepageIconTest.java
rename to tests/robotests/src/com/android/settings/widget/AdaptiveIconTest.java
index 05a9cfb..1be3332 100644
--- a/tests/robotests/src/com/android/settings/widget/AdaptiveHomepageIconTest.java
+++ b/tests/robotests/src/com/android/settings/widget/AdaptiveIconTest.java
@@ -48,7 +48,7 @@
 import org.robolectric.RuntimeEnvironment;
 
 @RunWith(RobolectricTestRunner.class)
-public class AdaptiveHomepageIconTest {
+public class AdaptiveIconTest {
 
     private Context mContext;
     private ActivityInfo mActivityInfo;
@@ -64,8 +64,8 @@
 
     @Test
     public void createIcon_shouldSetBackgroundAndInset() {
-        final AdaptiveHomepageIcon icon =
-                new AdaptiveHomepageIcon(mContext, new ColorDrawable(Color.BLACK));
+        final AdaptiveIcon icon =
+                new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK));
 
         assertThat(icon.getNumberOfLayers()).isEqualTo(2);
         assertThat(icon.getDrawable(0)).isInstanceOf(AdaptiveIconShapeDrawable.class);
@@ -73,8 +73,8 @@
 
     @Test
     public void setBackgroundColor_shouldUpdateColorFilter() {
-        final AdaptiveHomepageIcon icon =
-                spy(new AdaptiveHomepageIcon(mContext, new ColorDrawable(Color.BLACK)));
+        final AdaptiveIcon icon =
+                spy(new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK)));
         final ShapeDrawable background = mock(ShapeDrawable.class);
         when(icon.getDrawable(0)).thenReturn(background);
 
@@ -89,8 +89,8 @@
         mActivityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON_BACKGROUND_ARGB, 0xff0000);
         doReturn(Icon.createWithResource(mContext, R.drawable.ic_settings_accent))
                 .when(tile).getIcon(mContext);
-        final AdaptiveHomepageIcon icon =
-                new AdaptiveHomepageIcon(mContext, new ColorDrawable(Color.BLACK));
+        final AdaptiveIcon icon =
+                new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK));
 
         icon.setBackgroundColor(mContext, tile);
         assertThat(icon.mBackgroundColor).isEqualTo(0xff0000);
@@ -101,8 +101,8 @@
         final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE));
         doReturn(Icon.createWithResource(mContext, R.drawable.ic_settings_accent))
             .when(tile).getIcon(mContext);
-        final AdaptiveHomepageIcon icon =
-            new AdaptiveHomepageIcon(mContext, new ColorDrawable(Color.BLACK));
+        final AdaptiveIcon icon =
+            new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK));
 
         icon.setBackgroundColor(mContext, tile);
 
@@ -118,11 +118,24 @@
         doReturn(Icon.createWithResource(mContext, R.drawable.ic_settings_accent))
                 .when(tile).getIcon(mContext);
 
-        final AdaptiveHomepageIcon icon =
-                new AdaptiveHomepageIcon(mContext, new ColorDrawable(Color.BLACK));
+        final AdaptiveIcon icon =
+                new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK));
         icon.setBackgroundColor(mContext, tile);
 
         assertThat(icon.mBackgroundColor)
                 .isEqualTo(mContext.getColor(R.color.material_blue_500));
     }
+
+    @Test
+    public void getConstantState_returnCorrectState() {
+        final AdaptiveIcon icon =
+                new AdaptiveIcon(mContext, new ColorDrawable(Color.BLACK));
+        icon.setBackgroundColor(Color.YELLOW);
+
+        final AdaptiveIcon.AdaptiveConstantState state =
+                (AdaptiveIcon.AdaptiveConstantState) icon.getConstantState();
+
+        assertThat(state.color).isEqualTo(Color.YELLOW);
+        assertThat(state.context).isEqualTo(mContext);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java b/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
deleted file mode 100644
index 7f0598d..0000000
--- a/tests/robotests/src/com/android/settings/wifi/ButtonPreferenceTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2018 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.settings.wifi;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.ImageButton;
-
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class ButtonPreferenceTest {
-
-    private Context mContext;
-    private View mRootView;
-    private ButtonPreference mPref;
-    private PreferenceViewHolder mHolder;
-    private boolean mClicked;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mContext = RuntimeEnvironment.application;
-        mPref = new ButtonPreference(mContext);
-        mRootView = View.inflate(mContext, R.layout.wifi_button_preference_widget, /* parent */
-                null);
-        mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
-    }
-
-    @Test
-    public void initButton_noIcon_shouldInvisible() {
-        mPref.initButton(mHolder);
-        assertThat(mRootView.findViewById(R.id.button_icon).getVisibility()).isEqualTo(View.GONE);
-    }
-
-    @Test
-    public void initButton_withIcon_shouldVisible() {
-        mPref.setButtonIcon(R.drawable.ic_qrcode_24dp);
-        mPref.initButton(mHolder);
-        assertThat(mRootView.findViewById(R.id.button_icon).getVisibility()).isEqualTo(
-                View.VISIBLE);
-    }
-
-    @Test
-    public void initButton_whenClick_shouldCallback() {
-        mClicked = false;
-        mPref.setButtonIcon(R.drawable.ic_qrcode_24dp);
-        mPref.setButtonOnClickListener((View v) -> {
-            mClicked = true;
-        });
-        mPref.initButton(mHolder);
-        ImageButton button = (ImageButton) mRootView.findViewById(R.id.button_icon);
-        button.performClick();
-        assertThat(mClicked).isTrue();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index 21b68f2..4202143 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -106,12 +106,12 @@
     }
 
     @Test
-    public void clickPositiveButton_shouldCloseTheDialog() {
+    public void clickNegativeButton_shouldCloseTheDialog() {
         networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
         AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
         assertThat(alertDialog.isShowing()).isTrue();
 
-        Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+        Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
         assertThat(positiveButton).isNotNull();
 
         positiveButton.performClick();
@@ -186,26 +186,6 @@
     }
 
     @Test
-    public void updateAccessPointList_onUserSelectionConnectFailure_shouldCallAbortDialog() {
-        FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
-        FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
-        List<AccessPoint> accessPointList = createAccessPointList();
-        when(spyFakeFragment.getAccessPointList()).thenReturn(accessPointList);
-        spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
-
-        AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
-        assertThat(alertDialog.isShowing()).isTrue();
-
-        // Test if config would update list.
-        WifiConfiguration config = new WifiConfiguration();
-        config.SSID = "Test AP 3";
-        fakeFragment.onUserSelectionConnectFailure(config);
-
-        assertThat(fakeFragment.bCalledStopAndPop).isTrue();
-        assertThat(fakeFragment.errorType).isEqualTo(ERROR_DIALOG_TYPE.ABORT);
-    }
-
-    @Test
     public void onUserSelectionCallbackRegistration_onClick_shouldCallSelect() {
         // Assert.
         final int indexClickItem = 3;
@@ -267,19 +247,27 @@
         Bundle bundle = new Bundle();
 
         bundle.putString(KEY_SSID, "Test AP 1");
-        bundle.putInt(KEY_SECURITY, 1);
+        bundle.putInt(KEY_SECURITY, 1 /* WEP */);
         accessPointList.add(new AccessPoint(mContext, bundle));
 
         bundle.putString(KEY_SSID, "Test AP 2");
-        bundle.putInt(KEY_SECURITY, 1);
+        bundle.putInt(KEY_SECURITY, 1 /* WEP */);
         accessPointList.add(new AccessPoint(mContext, bundle));
 
         bundle.putString(KEY_SSID, "Test AP 3");
-        bundle.putInt(KEY_SECURITY, 2);
+        bundle.putInt(KEY_SECURITY, 1 /* WEP */);
         accessPointList.add(new AccessPoint(mContext, bundle));
 
         bundle.putString(KEY_SSID, "Test AP 4");
-        bundle.putInt(KEY_SECURITY, 0);
+        bundle.putInt(KEY_SECURITY, 0 /* NONE */);
+        accessPointList.add(new AccessPoint(mContext, bundle));
+
+        bundle.putString(KEY_SSID, "Test AP 5");
+        bundle.putInt(KEY_SECURITY, 1 /* WEP */);
+        accessPointList.add(new AccessPoint(mContext, bundle));
+
+        bundle.putString(KEY_SSID, "Test AP 6");
+        bundle.putInt(KEY_SECURITY, 1 /* WEP */);
         accessPointList.add(new AccessPoint(mContext, bundle));
 
         return accessPointList;
@@ -300,9 +288,13 @@
         networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), /* tag */ null);
         final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
 
+
+        List<AccessPoint> accessPointList = createAccessPointList();
+        when(mWifiTracker.getAccessPoints()).thenReturn(accessPointList);
+
         final String SSID_AP = "Test AP ";
         final List<ScanResult> scanResults = new ArrayList<>();
-        for (int i = 0; i < 6 ; i ++) {
+        for (int i = 0; i < 7 ; i ++) {
             ScanResult scanResult = new ScanResult();
             scanResult.SSID = SSID_AP + i;
             scanResult.capabilities = "WEP";
@@ -338,4 +330,21 @@
         // Check
         assertThat(button.getVisibility()).isEqualTo(View.GONE);
     }
+
+    @Test
+    public void cancelDialog_callsReject() {
+        // Assert
+        networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), /* tag */ null);
+        final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+        final NetworkRequestUserSelectionCallback selectionCallback = mock(
+                NetworkRequestUserSelectionCallback.class);
+        networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
+
+        // Action
+        final Button button = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
+        button.performClick();
+
+        // Check
+        verify(selectionCallback, times(1)).reject();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
index 22ccd3c..c811b0c 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiSettingsTest.java
@@ -69,6 +69,7 @@
         mWifiSettings = spy(new WifiSettings());
         doReturn(mContext).when(mWifiSettings).getContext();
         doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
+        mWifiSettings.mAddWifiNetworkPreference = new AddWifiNetworkPreference(mContext);
         mWifiSettings.mSavedNetworksPreference = new Preference(mContext);
         mWifiSettings.mConfigureWifiSettingsPreference = new Preference(mContext);
         mWifiSettings.mWifiTracker = mWifiTracker;
@@ -151,4 +152,11 @@
         assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
                 mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off));
     }
-}
\ No newline at end of file
+
+    @Test
+    public void checkAddWifiNetworkPrefernce_preferenceVisible() {
+        assertThat(mWifiSettings.mAddWifiNetworkPreference.isVisible()).isTrue();
+        assertThat(mWifiSettings.mAddWifiNetworkPreference.getTitle()).isEqualTo(
+                mContext.getString(R.string.wifi_add_network));
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index db76722..574d0d6 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -649,6 +649,19 @@
         nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
         updateNetworkCapabilities(nc);
         inOrder.verify(mockHeaderController).setSummary(summary);
+
+        // UI will be refreshed when device connects to a partial connectivity network.
+        summary = "Limited connection";
+        when(mockAccessPoint.getSettingsSummary()).thenReturn(summary);
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+        updateNetworkCapabilities(nc);
+        inOrder.verify(mockHeaderController).setSummary(summary);
+
+        // Although UI will be refreshed when network become validated. The Settings should
+        // continue to display "Limited connection" if network still provides partial connectivity.
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+        updateNetworkCapabilities(nc);
+        inOrder.verify(mockHeaderController).setSummary(summary);
     }
 
     @Test