Merge "Clean up tts preference layout." into qt-dev
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1062418
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea/
+*.iml
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a8fa7cc..68a7cbb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1475,7 +1475,7 @@
         <!-- Lock screen settings -->
         <activity android:name=".password.ConfirmDeviceCredentialActivity"
             android:exported="true"
-            android:taskAffinity=".password.ConfirmDeviceCredentialActivity"
+            android:taskAffinity="com.android.settings.workmode"
             android:theme="@android:style/Theme.Translucent.NoTitleBar">
             <intent-filter android:priority="1">
                 <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL" />
@@ -1493,7 +1493,7 @@
             android:exported="false"
             android:permission="android.permission.MANAGE_USERS"
             android:resizeableActivity="false"
-            android:taskAffinity=".password.ConfirmDeviceCredentialActivity"
+            android:taskAffinity="com.android.settings.workmode"
             android:theme="@android:style/Theme.Translucent.NoTitleBar">
             <intent-filter android:priority="1">
                 <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" />
@@ -2810,6 +2810,7 @@
 
         <activity android:name=".enterprise.ActionDisabledByAdminDialog"
                 android:theme="@style/Transparent"
+                android:taskAffinity="com.android.settings.enterprise"
                 android:excludeFromRecents="true"
                 android:launchMode="singleTop">
             <intent-filter android:priority="1">
diff --git a/res/drawable/ic_arrow_back.xml b/res/drawable/ic_arrow_back.xml
new file mode 100644
index 0000000..374f16b
--- /dev/null
+++ b/res/drawable/ic_arrow_back.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"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M20,11H7.83l5.59-5.59L12,4l-8,8l8,8l1.41-1.41L7.83,13H20V11z" />
+</vector>
diff --git a/res/drawable/ic_battery_status_bad_24dp.xml b/res/drawable/ic_battery_status_bad_24dp.xml
index d841f08..584c3b6 100644
--- a/res/drawable/ic_battery_status_bad_24dp.xml
+++ b/res/drawable/ic_battery_status_bad_24dp.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/batteryBadColor"
+        android:fillColor="@android:color/white"
         android:pathData="M15,14l-2,0l0,2l-2,0l0,-2l-2,0l0,-2l2,0l0,-2l2,0l0,2l2,0z"/>
     <path
-        android:fillColor="?attr/batteryBadColor"
+        android:fillColor="@android:color/white"
         android:pathData="M16.2,22.5H7.8c-1.3,0 -2.3,-1 -2.3,-2.3V5.8c0,-1.3 1,-2.3 2.3,-2.3h0.7v-2h7v2h0.7c1.3,0 2.3,1.1 2.3,2.3v14.3C18.5,21.5 17.5,22.5 16.2,22.5zM7.8,5.5c-0.2,0 -0.3,0.2 -0.3,0.3v14.3c0,0.2 0.2,0.3 0.3,0.3h8.3c0.2,0 0.3,-0.1 0.3,-0.3V5.8c0,-0.2 -0.1,-0.3 -0.3,-0.3h-2.7v-2h-3v2H7.8z"/>
 </vector>
diff --git a/res/drawable/ic_battery_status_good_24dp.xml b/res/drawable/ic_battery_status_good_24dp.xml
index 4628ee5..600d4c9 100644
--- a/res/drawable/ic_battery_status_good_24dp.xml
+++ b/res/drawable/ic_battery_status_good_24dp.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/batteryGoodColor"
+        android:fillColor="@android:color/white"
         android:pathData="M16.2,22.5H7.8c-1.3,0 -2.3,-1 -2.3,-2.3V5.8c0,-1.3 1,-2.3 2.3,-2.3h0.7v-2h7v2h0.7c1.3,0 2.3,1.1 2.3,2.3v14.3C18.5,21.5 17.5,22.5 16.2,22.5zM7.8,5.5c-0.2,0 -0.3,0.2 -0.3,0.3v14.3c0,0.2 0.2,0.3 0.3,0.3h8.3c0.2,0 0.3,-0.1 0.3,-0.3V5.8c0,-0.2 -0.1,-0.3 -0.3,-0.3h-2.7v-2h-3v2H7.8z"/>
     <path
-        android:fillColor="?attr/batteryGoodColor"
+        android:fillColor="@android:color/white"
         android:pathData="M16.1,11.1l-1.4,-1.5l-3.9,3.9l-1.5,-1.4l-1.4,1.4l2.9,2.9z"/>
 </vector>
diff --git a/res/drawable/ic_battery_status_maybe_24dp.xml b/res/drawable/ic_battery_status_maybe_24dp.xml
index 64451be..dd9a571 100644
--- a/res/drawable/ic_battery_status_maybe_24dp.xml
+++ b/res/drawable/ic_battery_status_maybe_24dp.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:fillColor="?attr/batteryMaybeColor"
+        android:fillColor="@android:color/white"
         android:pathData="M13,17h-2v-2h2V17zM13,13h-2V8h2V13z"/>
     <path
-        android:fillColor="?attr/batteryMaybeColor"
+        android:fillColor="@android:color/white"
         android:pathData="M16.2,22.5H7.8c-1.3,0 -2.3,-1 -2.3,-2.3V5.8c0,-1.3 1,-2.3 2.3,-2.3h0.7v-2h7v2h0.7c1.3,0 2.3,1.1 2.3,2.3v14.3C18.5,21.5 17.5,22.5 16.2,22.5zM7.8,5.5c-0.2,0 -0.3,0.2 -0.3,0.3v14.3c0,0.2 0.2,0.3 0.3,0.3h8.3c0.2,0 0.3,-0.1 0.3,-0.3V5.8c0,-0.2 -0.1,-0.3 -0.3,-0.3h-2.7v-2h-3v2H7.8z"/>
 </vector>
diff --git a/res/drawable/ic_cellular_1_bar.xml b/res/drawable/ic_cellular_1_bar.xml
index b3d2624..23caacc2 100644
--- a/res/drawable/ic_cellular_1_bar.xml
+++ b/res/drawable/ic_cellular_1_bar.xml
@@ -13,17 +13,17 @@
   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="48dp"
-    android:height="48dp"
-    android:viewportWidth="48"
-    android:viewportHeight="48"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
     android:tint="?android:attr/colorControlNormal">
-  <path
-      android:pathData="M4,44h40V4z"
-      android:fillColor="#000000"
-      android:fillAlpha=".3"/>
-  <path
-      android:pathData="M24,24L4,44h20z"
-      android:fillColor="#000000"/>
-</vector>
+    <path
+        android:fillColor="#000000"
+        android:pathData="M20,7v13H7L20,7 M22,2L2,22h20V2L22,2z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M 11 13 L 2 22 L 11 22 Z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_check_circle_green_24dp.xml b/res/drawable/ic_check_circle_green_24dp.xml
deleted file mode 100644
index 6f2692d..0000000
--- a/res/drawable/ic_check_circle_green_24dp.xml
+++ /dev/null
@@ -1,25 +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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#0F9D58"
-        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10
-        ,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
-</vector>
diff --git a/res/drawable/ic_devices_other_black.xml b/res/drawable/ic_devices_other_black.xml
deleted file mode 100644
index 926f02c..0000000
--- a/res/drawable/ic_devices_other_black.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
-    Copyright 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:viewportWidth="24"
-        android:viewportHeight="24"
-        android:width="24dp"
-        android:height="24dp"
-        android:tint="?android:attr/colorControlNormal">
-    <path
-        android:fillColor="@android:color/white"
-        android:pathData="M3,6h18V4H3C1.9,4 1,4.9 1,6v12c0,1.1 0.9,2 2,2h4v-2H3V6zM13,12H9v1.78C8.39,14.33 8,15.11 8,16c0,0.89 0.39,1.67 1,2.22V20h4v-1.78c0.61,-0.55 1,-1.34 1,-2.22s-0.39,-1.67 -1,-2.22V12zM11,17.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5s1.5,0.67 1.5,1.5S11.83,17.5 11,17.5zM22,8h-6c-0.5,0 -1,0.5 -1,1v10c0,0.5 0.5,1 1,1h6c0.5,0 1,-0.5 1,-1V9C23,8.5 22.5,8 22,8zM21,18h-4v-8h4V18z"/>
-</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_hotspot.xml b/res/drawable/ic_hotspot.xml
index d8528dd..6c12ed1 100644
--- a/res/drawable/ic_hotspot.xml
+++ b/res/drawable/ic_hotspot.xml
@@ -15,48 +15,17 @@
      limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="root"
-    android:alpha="1.0"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48" >
-    <group
-        android:name="ic_hotspot"
-        android:translateX="23.9778"
-        android:translateY="24.26443" >
-        <group
-            android:name="ic_hotspot_pivot"
-            android:translateX="-23.21545"
-            android:translateY="-18.86649" >
-            <clip-path
-                android:name="mask"
-                android:pathData="M 38.8337860107,-40.3974914551 c 0.0,0.0 -38.4077911377,30.8523712158 -38.4077911377,30.8523712158 c 0.0,0.0 6.97125244141,7.33258056641 6.97125244141,7.33258056641 c 0.0,0.0 -2.4169921875,2.57838439941 -2.4169921875,2.57838439941 c 0.0,0.0 -6.77128601074,-6.82850646973 -6.77128601074,-6.82850646973 c 0.0,0.0 -32.6199798584,25.1699066162 -32.6199798584,25.1699066162 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 27.6589050293,-22.6579437256 27.6589050293,-22.6579437256 c 0.0,0.0 -30.8645172119,-34.00390625 -30.8645172119,-34.00390625 c 0.0,0.0 2.70756530762,-1.99278259277 2.70756530762,-1.99278259277 c 0.0,0.0 1.53030395508,-0.876571655273 1.53030395508,-0.876571655274 c 0.0,0.0 2.85780334473,-3.12069702148 2.85780334473,-3.12069702148 c 0.0,0.0 0.659332275391,0.664688110352 0.659332275391,0.664688110351 c 0.0,0.0 -3.13299560547,2.82977294922 -3.13299560547,2.82977294922 c 0.0,0.0 29.0108337402,34.4080963135 29.0108337402,34.4080963135 c 0.0,0.0 42.8175811768,-34.3554534912 42.8175811768,-34.3554534912 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
-            <group
-                android:name="cross" >
-                <path
-                    android:name="cross_1"
-                    android:pathData="M 4.44044494629,2.24310302734 c 0.0,0.0 0.0875396728516,0.112457275391 0.0875396728516,0.112457275391 "
-                    android:strokeColor="#FFFFFFFF"
-                    android:strokeAlpha="0"
-                    android:strokeWidth="3.5"
-                    android:fillColor="#00000000" />
-            </group>
-            <group
-                android:name="hotspot"
-                android:translateX="23.481"
-                android:translateY="18.71151" >
-                <group
-                    android:name="circles"
-                    android:translateX="-0.23909"
-                    android:translateY="-0.10807" >
-                    <path
-                        android:name="path_3"
-                        android:pathData="M -0.0042724609375,-2.64895629883 c -2.20922851562,0.0 -4.0,1.791015625 -4.0,4.0 c 0.0,2.20922851562 1.79077148438,4.0 4.0,4.0 c 2.208984375,0.0 4.0,-1.79077148438 4.0,-4.0 c 0.0,-2.208984375 -1.791015625,-4.0 -4.0,-4.0 Z M 11.9957275391,1.35104370117 c 0.0,-6.626953125 -5.373046875,-12.0 -12.0,-12.0 c -6.62719726562,0.0 -12.0,5.373046875 -12.0,12.0 c 0.0,4.43603515625 2.41381835938,8.30004882812 5.99194335938,10.3771972656 c 0.0,0.0 2.01586914062,-3.48217773438 2.01586914062,-3.48217773438 c -2.38500976562,-1.38500976562 -4.0078125,-3.93798828125 -4.0078125,-6.89501953125 c 0.0,-4.41796875 3.58178710938,-8.0 8.0,-8.0 c 4.41796875,0.0 8.0,3.58203125 8.0,8.0 c 0.0,2.95703125 -1.623046875,5.51000976562 -4.00805664062,6.89501953125 c 0.0,0.0 2.01586914062,3.48217773438 2.01586914062,3.48217773438 c 3.578125,-2.0771484375 5.9921875,-5.94116210938 5.9921875,-10.3771972656 Z M -0.0042724609375,-18.6489562988 c -11.0451660156,0.0 -20.0,8.9541015625 -20.0,20.0 c 0.0,7.39306640625 4.02099609375,13.8330078125 9.98779296875,17.2951660156 c 0.0,0.0 2.00219726562,-3.458984375 2.00219726562,-3.458984375 c -4.77319335938,-2.77001953125 -7.98999023438,-7.92211914062 -7.98999023438,-13.8361816406 c 0.0,-8.8369140625 7.16381835938,-16.0 16.0,-16.0 c 8.83595275879,0.0 16.0000152588,7.1630859375 16.0000152588,16.0 c 0.0,5.9140625 -3.21704101562,11.0661621094 -7.990234375,13.8361816406 c 0.0,0.0 2.00219726562,3.458984375 2.00219726563,3.458984375 c 5.966796875,-3.46215820312 9.98803710937,-9.90209960938 9.98803710938,-17.2951660156 c 0.0,-11.0458984375 -8.955078125,-20.0 -20.0000152588,-20.0 Z"
-                        android:fillColor="#FFFFFFFF"
-                        android:fillAlpha="1" />
-                </group>
-            </group>
-        </group>
-    </group>
-</vector>
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,7c-3.31,0-6,2.69-6,6c0,1.66,0.68,3.15,1.76,4.24l1.42-1.42C8.45,15.1,8,14.11,8,13c0-2.21,1.79-4,4-4s4,1.79,4,4 c0,1.11-0.45,2.1-1.18,2.82l1.42,1.42C17.32,16.15,18,14.66,18,13C18,9.69,15.31,7,12,7z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,3C6.48,3,2,7.48,2,13c0,2.76,1.12,5.26,2.93,7.07l1.41-1.41C4.9,17.21,4,15.21,4,13c0-4.42,3.58-8,8-8s8,3.58,8,8 c0,2.21-0.9,4.2-2.35,5.65l1.41,1.41C20.88,18.26,22,15.76,22,13C22,7.48,17.52,3,12,3z" />
+    <path
+        android:fillColor="#000000"
+        android:pathData="M12,11c-1.1,0-2,0.9-2,2c0,0.55,0.23,1.05,0.59,1.41C10.95,14.77,11.45,15,12,15s1.05-0.23,1.41-0.59 C13.77,14.05,14,13.55,14,13C14,11.9,13.1,11,12,11z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_privacy_shield_24dp.xml b/res/drawable/ic_privacy_shield_24dp.xml
new file mode 100644
index 0000000..6bb69c0
--- /dev/null
+++ b/res/drawable/ic_privacy_shield_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.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z"/>
+</vector>
diff --git a/res/drawable/ic_settings_home.xml b/res/drawable/ic_settings_home.xml
index 1cc9593..3de5f14 100644
--- a/res/drawable/ic_settings_home.xml
+++ b/res/drawable/ic_settings_home.xml
@@ -21,5 +21,4 @@
         android:tint="?android:attr/colorControlNormal">
     <path android:fillColor="#FFFFFFFF"
           android:pathData="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
-    <path android:pathData="M0 0h24v24H0z" />
 </vector>
diff --git a/res/drawable/ic_settings_print.xml b/res/drawable/ic_settings_print.xml
index dc92de0..41f3a24 100644
--- a/res/drawable/ic_settings_print.xml
+++ b/res/drawable/ic_settings_print.xml
@@ -15,8 +15,14 @@
   limitations under the License.
   -->
 
-<!-- Pass through drawable to framework ic_settings_print. This is necessary because this drawable
-     is used in AndroidManifest.xml and aapt cannot find drawable reference from outside of Settings
-      apk. -->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@*android:drawable/ic_settings_print"/>
\ No newline at end of file
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M19,8h-1V3H6v5H5c-1.66,0 -3,1.34 -3,3v6h4v4h12v-4h4v-6C22,9.34 20.66,8 19,8zM16,19H8v-4h8V19zM16,8H8V5h8V8zM18,12.5c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1s1,0.45 1,1S18.55,12.5 18,12.5z"/>
+</vector>
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index 233a01b..3a8045f 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -31,8 +31,6 @@
         android:textColor="?android:attr/colorPrimary"
         android:textSize="20sp"/>
 
-    <include layout="@layout/horizontal_divider"/>
-
     <include layout="@layout/panel_slice_list"/>
 
     <LinearLayout
diff --git a/res/layout/panel_slice_row.xml b/res/layout/panel_slice_row.xml
index 3288c40..4e1184b 100644
--- a/res/layout/panel_slice_row.xml
+++ b/res/layout/panel_slice_row.xml
@@ -26,6 +26,4 @@
         android:layout_height="wrap_content"
         android:paddingStart="20dp"
         android:paddingEnd="20dp"/>
-
-    <include layout="@layout/horizontal_divider"/>
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/preference_widget_add.xml b/res/layout/preference_widget_add.xml
index 6e33a4d..9942bb2 100644
--- a/res/layout/preference_widget_add.xml
+++ b/res/layout/preference_widget_add.xml
@@ -21,10 +21,12 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_gravity="center"
+    android:minWidth="@dimen/two_target_min_width"
     android:paddingStart="?android:attr/listPreferredItemPaddingEnd"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:background="?android:attr/selectableItemBackground"
     android:scaleType="center"
     android:src="@drawable/ic_add_24dp"
+    android:tint="?android:attr/colorAccent"
     android:contentDescription="@string/add" />
 
diff --git a/res/layout/preference_widget_master_switch.xml b/res/layout/preference_widget_master_switch.xml
index 7e28be9..26929ab 100644
--- a/res/layout/preference_widget_master_switch.xml
+++ b/res/layout/preference_widget_master_switch.xml
@@ -20,6 +20,7 @@
     android:id="@+id/switchWidget"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:minWidth="@dimen/two_target_min_width"
     android:gravity="center_vertical"
     android:paddingStart="?android:attr/listPreferredItemPaddingEnd"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index a9797a3..be6345b 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -166,10 +166,6 @@
 
     <attr name="twoStateButtonPreferenceStyle" format="reference" />
 
-    <attr name="batteryGoodColor" format="color" />
-    <attr name="batteryBadColor" format="color" />
-    <attr name="batteryMaybeColor" format="color" />
-
     <attr name="fingerprint_layout_theme" format="reference" />
     <attr name="face_layout_theme" format="reference" />
     <attr name="ic_menu_moreoverflow" format="reference" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f126525..b07865c 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -393,4 +393,6 @@
 
     <!-- Elevation of bluetooth icon -->
     <dimen name="bt_icon_elevation">4dp</dimen>
+
+    <dimen name="two_target_min_width">80dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b6ff1a8..4e1b32e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -925,9 +925,9 @@
     <!-- Button text to exit face wizard after everything is done [CHAR LIMIT=15] -->
     <string name="security_settings_face_enroll_done">Done</string>
     <!-- Title for a category shown for the face settings page. [CHAR LIMIT=20] -->
-    <string name="security_settings_face_settings_use_face_category">Use your face to</string>
+    <string name="security_settings_face_settings_use_face_category">Use your face for</string>
     <!-- Text shown on a toggle which allows or disallows the device to use face for unlocking the device. [CHAR LIMIT=20] -->
-    <string name="security_settings_face_settings_use_face_unlock_phone">Unlock your device</string>
+    <string name="security_settings_face_settings_use_face_unlock_phone">Unlocking your device</string>
     <!-- Text shown on a toggle which allows or disallows the device to use face authentication for apps. This will be presented to the user together with the context of security_settings_face_settings_use_face_category. [CHAR LIMIT=30] -->
     <string name="security_settings_face_settings_use_face_for_apps">App sign-in \u0026 payments</string>
     <!-- Text shown on a toggle which disables/enables face authentication, depending if the user's eyes are open. [CHAR LIMIT=30] -->
@@ -2761,13 +2761,15 @@
     <!-- Display settings screen, display white balance settings title [CHAR LIMIT=30] -->
     <string name="display_white_balance_title">Display white balance</string>
     <!-- Display settings screen, setting option name to enable adaptive sleep [CHAR LIMIT=30] -->
-    <string name="adaptive_sleep_title">Adaptive sleep</string>
+    <string name="adaptive_sleep_title">Screen aware</string>
     <!-- Setting option summary when adaptive sleep is on [CHAR LIMIT=NONE] -->
-    <string name="adaptive_sleep_summary_on">On</string>
+    <string name="adaptive_sleep_summary_on">On / Screen won’t turn off if you’re looking at it</string>
     <!-- Setting option summary when adaptive sleep is off [CHAR LIMIT=NONE] -->
     <string name="adaptive_sleep_summary_off">Off</string>
     <!-- Description about the feature adaptive sleep [CHAR LIMIT=NONE]-->
-    <string name="adaptive_sleep_description">Your screen would not dim and go to sleep if the device detects your present attention.</string>
+    <string name="adaptive_sleep_description">Prevents your screen from turning off if you’re looking at it.</string>
+    <!-- Description feature's privacy sensitive details to make sure users understand what feature users, what it saves/sends etc [CHAR LIMIT=NONE]-->
+    <string name="adaptive_sleep_privacy">Screen aware uses the front camera to see if someone is looking at the screen. It works on device, and images are never stored or sent to Google.</string>
 
 
     <!-- Night display screen, setting option name to enable night display (renamed "Night Light" with title caps). [CHAR LIMIT=30] -->
@@ -2829,6 +2831,8 @@
     <string name="screen_timeout_summary">After <xliff:g id="timeout_description">%1$s</xliff:g> of inactivity</string>
     <!-- Wallpaper settings title [CHAR LIMIT=30] -->
     <string name="wallpaper_settings_title">Wallpaper</string>
+    <!-- Styles & Wallpapers settings title [CHAR LIMIT=30] -->
+    <string name="style_and_wallpaper_settings_title">Styles &amp; Wallpapers</string>
     <!-- Wallpaper settings summary when default wallpaper is used [CHAR LIMIT=NONE] -->
     <string name="wallpaper_settings_summary_default">Default</string>
     <!-- Wallpaper settings summary when wallpaper has been updated [CHAR LIMIT=NONE] -->
@@ -3616,7 +3620,7 @@
     <!-- 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=30] -->
+    <!-- SD card & phone storage settings screen, title for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=50] -->
     <string name="reset_esim_title">Erase downloaded SIMs</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">To download replacement SIMs, contact your carrier. This won\u2019t cancel any mobile service plans.</string>
@@ -7784,9 +7788,9 @@
     <!-- 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>
+    <string name="bubbles_feature_disabled_dialog_text">To turn on bubbles for this app, first you need to turn them on for your device. This affects other apps in which you previously turned on bubbles.</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>
+    <string name="bubbles_feature_disabled_button_approve">Turn on for device</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>
 
@@ -9304,6 +9308,9 @@
     <string name="display_dashboard_summary">Wallpaper, sleep, font size</string>
 
     <!-- Summary for Display settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
+    <string name="display_dashboard_summary_with_style">Styles &amp; Wallpapers, sleep, font size</string>
+
+    <!-- Summary for Display settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
     <string name="display_dashboard_nowallpaper_summary">Sleep, font size</string>
 
     <!-- Example summary of display used in Setup Wizard preview screen [CHAR LIMIT=NONE] -->
@@ -9439,10 +9446,10 @@
     <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>
+    <string name="condition_grayscale_title">Grayscale</string>
 
     <!-- Summary of condition that gray scale is on [CHAR LIMIT=NONE] -->
-    <string name="condition_grayscale_summary">Display only in grey color</string>
+    <string name="condition_grayscale_summary">Display only in gray 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>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 59b2b9e..196e85b 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -28,6 +28,7 @@
     <style name="Theme.Settings" parent="Theme.SettingsBase">
         <item name="preferenceTheme">@style/PreferenceTheme</item>
         <item name="android:listPreferredItemHeight">72dip</item>
+        <item name="homeAsUpIndicator">@drawable/ic_arrow_back</item>
 
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
         <item name="face_layout_theme">@style/FaceLayoutTheme</item>
@@ -53,11 +54,6 @@
 
         <item name="*android:lockPatternStyle">@style/LockPatternStyle.Setup</item>
 
-        <!-- For battery status icons in -->
-        <item name="batteryGoodColor">@color/battery_good_color_light</item>
-        <item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
-        <item name="batteryBadColor">@color/battery_bad_color_light</item>
-
         <!-- For AppBarLayout -->
         <item name="colorPrimary">@*android:color/primary_device_default_settings_light</item>
         <item name="colorPrimaryVariant">@android:color/white</item>
@@ -192,10 +188,6 @@
         <!-- action bar, needed for search bar icon tinting -->
         <item name="android:actionBarTheme">@*android:style/ThemeOverlay.DeviceDefault.ActionBar</item>
 
-        <!-- For battery status icons in -->
-        <item name="batteryGoodColor">@color/battery_good_color_light</item>
-        <item name="batteryMaybeColor">@color/battery_maybe_color_light</item>
-        <item name="batteryBadColor">@color/battery_bad_color_light</item>
         <!-- Define this color for material design -->
         <item name="colorPrimaryVariant">@android:color/white</item>
     </style>
diff --git a/res/xml/adaptive_sleep_detail.xml b/res/xml/adaptive_sleep_detail.xml
index b7dabbb..e97a758 100644
--- a/res/xml/adaptive_sleep_detail.xml
+++ b/res/xml/adaptive_sleep_detail.xml
@@ -32,6 +32,7 @@
     <com.android.settingslib.RestrictedSwitchPreference
         android:key="adaptive_sleep"
         android:title="@string/adaptive_sleep_title"
+        android:summary="@string/adaptive_sleep_description"
         settings:keywords="@string/keywords_display_adaptive_sleep"
         settings:controller="com.android.settings.display.AdaptiveSleepPreferenceController"
         settings:useAdminDisabledSummary="true"
diff --git a/res/xml/security_dashboard_settings.xml b/res/xml/security_dashboard_settings.xml
index 38bc2d0..9fe3d5b 100644
--- a/res/xml/security_dashboard_settings.xml
+++ b/res/xml/security_dashboard_settings.xml
@@ -87,6 +87,11 @@
             android:title="@string/security_settings_fingerprint_preference_title"
             android:summary="@string/summary_placeholder" />
 
+        <Preference
+            android:key="face_settings_profile"
+            android:title="@string/security_settings_face_preference_title"
+            android:summary="@string/summary_placeholder" />
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 90b7528..e610df2 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -103,14 +103,14 @@
         settings:useAdminDisabledSummary="true"
         settings:keywords="@string/keywords_sounds_and_notifications_interruptions"
         settings:allowDividerAbove="true"
-        settings:controller="com.android.settings.notification.ZenModePreferenceController" />
+        settings:controller="com.android.settings.notification.ZenModeSoundSettingsPreferenceController"/>
 
     <Preference
         android:key="gesture_prevent_ringing_sound"
         android:title="@string/gesture_prevent_ringing_sound_title"
         android:order="-110"
         android:fragment="com.android.settings.gestures.PreventRingingGestureSettings"
-        settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController" />
+        settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController"/>
 
     <!-- Phone ringtone -->
     <com.android.settings.DefaultRingtonePreference
@@ -150,27 +150,27 @@
         <!-- Dial pad tones -->
         <SwitchPreference
           android:key="dial_pad_tones"
-          android:title="@string/dial_pad_tones_title" />
+          android:title="@string/dial_pad_tones_title"/>
 
         <!-- Screen locking sounds -->
         <SwitchPreference
           android:key="screen_locking_sounds"
-          android:title="@string/screen_locking_sounds_title" />
+          android:title="@string/screen_locking_sounds_title"/>
 
         <!-- Charging sounds -->
         <SwitchPreference
           android:key="charging_sounds"
-          android:title="@string/charging_sounds_title" />
+          android:title="@string/charging_sounds_title"/>
 
         <!-- Docking sounds -->
         <SwitchPreference
           android:key="docking_sounds"
-          android:title="@string/docking_sounds_title" />
+          android:title="@string/docking_sounds_title"/>
 
         <!-- Touch sounds -->
         <SwitchPreference
           android:key="touch_sounds"
-          android:title="@string/touch_sounds_title" />
+          android:title="@string/touch_sounds_title"/>
 
         <!-- Vibrate on touch -->
         <SwitchPreference
@@ -183,18 +183,18 @@
         <DropDownPreference
           android:key="dock_audio_media"
           android:title="@string/dock_audio_media_title"
-          android:summary="%s" />
+          android:summary="%s"/>
 
         <!-- Boot sounds -->
         <SwitchPreference
           android:key="boot_sounds"
-          android:title="@string/boot_sounds_title" />
+          android:title="@string/boot_sounds_title"/>
 
         <!-- Emergency tone -->
         <DropDownPreference
           android:key="emergency_tone"
           android:title="@string/emergency_tone_title"
-          android:summary="%s" />
+          android:summary="%s"/>
     </PreferenceCategory>
 
     <com.android.settings.widget.WorkOnlyCategory
@@ -207,7 +207,7 @@
                     android:key="work_use_personal_sounds"
                     android:title="@string/work_use_personal_sounds_title"
                     android:summary="@string/work_use_personal_sounds_summary"
-                    android:disableDependentsState="true" />
+                    android:disableDependentsState="true"/>
 
                 <!-- Work phone ringtone -->
                 <com.android.settings.DefaultRingtonePreference
@@ -215,7 +215,7 @@
                     android:title="@string/work_ringtone_title"
                     android:dialogTitle="@string/work_alarm_ringtone_title"
                     android:ringtoneType="ringtone"
-                    android:dependency="work_use_personal_sounds" />
+                    android:dependency="work_use_personal_sounds"/>
 
                 <!-- Default work notification ringtone -->
                 <com.android.settings.DefaultRingtonePreference
@@ -223,7 +223,7 @@
                     android:title="@string/work_notification_ringtone_title"
                     android:dialogTitle="@string/work_alarm_ringtone_title"
                     android:ringtoneType="notification"
-                    android:dependency="work_use_personal_sounds" />
+                    android:dependency="work_use_personal_sounds"/>
 
                 <!-- Default work alarm ringtone -->
                 <com.android.settings.DefaultRingtonePreference
@@ -232,7 +232,7 @@
                     android:dialogTitle="@string/work_alarm_ringtone_title"
                     android:persistent="false"
                     android:ringtoneType="alarm"
-                    android:dependency="work_use_personal_sounds" />
+                    android:dependency="work_use_personal_sounds"/>
 
     </com.android.settings.widget.WorkOnlyCategory>
 </PreferenceScreen>
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index ee66b12..6315ab1 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -952,6 +952,7 @@
             mContext = manageApplications.getActivity();
             mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
             mAppFilter = appFilter;
+            mBackend = PowerWhitelistBackend.getInstance(mContext);
             if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                 mExtraInfoBridge = new AppStateNotificationBridge(mContext, mState, this,
                         manageApplications.mUsageStatsManager,
diff --git a/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java
new file mode 100644
index 0000000..196992d
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.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.biometrics.face;
+
+import android.content.Context;
+import android.os.UserHandle;
+
+public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceController {
+
+    public static final String KEY_FACE_SETTINGS = "face_settings_profile";
+
+    public FaceProfileStatusPreferenceController(Context context) {
+        super(context, KEY_FACE_SETTINGS);
+    }
+
+    @Override
+    protected boolean isUserSupported() {
+        return mProfileChallengeUserId != UserHandle.USER_NULL
+                && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId);
+    }
+
+    @Override
+    protected int getUserId() {
+        return mProfileChallengeUserId;
+    }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index 9651eec..b65a31d 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -27,6 +27,7 @@
 import android.hardware.face.FaceManager;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.SearchIndexableResource;
 import android.util.Log;
 
@@ -53,11 +54,13 @@
     private static final String TAG = "FaceSettings";
     private static final String KEY_TOKEN = "key_token";
 
+    private UserManager mUserManager;
     private FaceManager mFaceManager;
     private int mUserId;
     private byte[] mToken;
     private FaceSettingsAttentionPreferenceController mAttentionController;
     private FaceSettingsRemoveButtonPreferenceController mRemoveController;
+    private List<AbstractPreferenceController> mControllers;
 
     private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
         if (getActivity() != null) {
@@ -95,10 +98,24 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        mUserManager = getPrefContext().getSystemService(UserManager.class);
         mFaceManager = getPrefContext().getSystemService(FaceManager.class);
         mUserId = getActivity().getIntent().getIntExtra(
                 Intent.EXTRA_USER_ID, UserHandle.myUserId());
 
+        // There is no better way to do this :/
+        for (AbstractPreferenceController controller : mControllers) {
+            if (controller instanceof  FaceSettingsPreferenceController) {
+                ((FaceSettingsPreferenceController) controller).setUserId(mUserId);
+            }
+        }
+        mRemoveController.setUserId(mUserId);
+
+        // Don't show keyguard controller for work profile settings.
+        if (mUserManager.isManagedProfile(mUserId)) {
+            removePreference(FaceSettingsKeyguardPreferenceController.KEY);
+        }
+
         if (savedInstanceState != null) {
             mToken = savedInstanceState.getByteArray(KEY_TOKEN);
         }
@@ -128,6 +145,7 @@
         super.onActivityResult(requestCode, resultCode, data);
         if (requestCode == CONFIRM_REQUEST) {
             if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
+                mFaceManager.setActiveUser(mUserId);
                 // The pin/pattern/password was set.
                 if (data != null) {
                     mToken = data.getByteArrayExtra(
@@ -161,10 +179,9 @@
         if (!isAvailable(context)) {
             return null;
         }
-        final List<AbstractPreferenceController> controllers =
-                buildPreferenceControllers(context, getSettingsLifecycle());
+        mControllers = buildPreferenceControllers(context, getSettingsLifecycle());
         // There's no great way of doing this right now :/
-        for (AbstractPreferenceController controller : controllers) {
+        for (AbstractPreferenceController controller : mControllers) {
             if (controller instanceof FaceSettingsAttentionPreferenceController) {
                 mAttentionController = (FaceSettingsAttentionPreferenceController) controller;
             } else if (controller instanceof FaceSettingsRemoveButtonPreferenceController) {
@@ -174,7 +191,7 @@
             }
         }
 
-        return controllers;
+        return mControllers;
     }
 
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
index 038dbd8..78389b6 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAppPreferenceController.java
@@ -21,13 +21,11 @@
 import android.content.Context;
 import android.provider.Settings;
 
-import com.android.settings.core.TogglePreferenceController;
-
 /**
  * Preference controller for Face settings page controlling the ability to use
  * Face authentication in apps (through BiometricPrompt).
  */
-public class FaceSettingsAppPreferenceController extends TogglePreferenceController {
+public class FaceSettingsAppPreferenceController extends FaceSettingsPreferenceController {
 
     private static final String KEY = "security_settings_face_app";
 
@@ -48,14 +46,14 @@
         if (!FaceSettings.isAvailable(mContext)) {
             return false;
         }
-        return Settings.Secure.getInt(
-                mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED, DEFAULT) == ON;
+        return Settings.Secure.getIntForUser(
+                mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED, DEFAULT, getUserId()) == ON;
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
-        return Settings.Secure.putInt(mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED,
-                isChecked ? ON : OFF);
+        return Settings.Secure.putIntForUser(mContext.getContentResolver(), FACE_UNLOCK_APP_ENABLED,
+                isChecked ? ON : OFF, getUserId());
     }
 
     @Override
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
index 77e1532..9e4fd38 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
@@ -20,6 +20,7 @@
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceManager.GetFeatureCallback;
 import android.hardware.face.FaceManager.SetFeatureCallback;
+import android.provider.Settings;
 
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
@@ -31,7 +32,7 @@
  * Preference controller that manages the ability to use face authentication with/without
  * user attention. See {@link FaceManager#setRequireAttention(boolean, byte[])}.
  */
-public class FaceSettingsAttentionPreferenceController extends TogglePreferenceController {
+public class FaceSettingsAttentionPreferenceController extends FaceSettingsPreferenceController {
 
     public static final String KEY = "security_settings_face_require_attention";
 
@@ -46,6 +47,10 @@
                 mPreference.setEnabled(true);
                 if (!success) {
                     mPreference.setChecked(!mPreference.isChecked());
+                } else {
+                    Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                            Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+                            mPreference.isChecked() ? 1 : 0, getUserId());
                 }
             }
         }
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
index 08740cf..b721072 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsConfirmPreferenceController.java
@@ -26,7 +26,7 @@
 /**
  * Preference controller giving the user an option to always require confirmation.
  */
-public class FaceSettingsConfirmPreferenceController extends TogglePreferenceController {
+public class FaceSettingsConfirmPreferenceController extends FaceSettingsPreferenceController {
 
     private static final String KEY = "security_settings_face_require_confirmation";
 
@@ -45,14 +45,14 @@
 
     @Override
     public boolean isChecked() {
-        return Settings.Secure.getInt(mContext.getContentResolver(),
-                FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, DEFAULT) == ON;
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, DEFAULT, getUserId()) == ON;
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
-        return Settings.Secure.putInt(mContext.getContentResolver(),
-                FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, isChecked ? ON : OFF);
+        return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, isChecked ? ON : OFF, getUserId());
     }
 
     @Override
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
index fe7d398..3a7865d 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
@@ -31,9 +31,9 @@
  * Preference controller for Face settings page controlling the ability to unlock the phone
  * with face.
  */
-public class FaceSettingsKeyguardPreferenceController extends TogglePreferenceController {
+public class FaceSettingsKeyguardPreferenceController extends FaceSettingsPreferenceController {
 
-    private static final String KEY = "security_settings_face_keyguard";
+    static final String KEY = "security_settings_face_keyguard";
 
     private static final int ON = 1;
     private static final int OFF = 0;
@@ -54,14 +54,14 @@
         } else if (adminDisabled()) {
             return false;
         }
-        return Settings.Secure.getInt(
-                mContext.getContentResolver(), FACE_UNLOCK_KEYGUARD_ENABLED, DEFAULT) == ON;
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                FACE_UNLOCK_KEYGUARD_ENABLED, DEFAULT, getUserId()) == ON;
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
-        return Settings.Secure.putInt(mContext.getContentResolver(), FACE_UNLOCK_KEYGUARD_ENABLED,
-                isChecked ? ON : OFF);
+        return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                FACE_UNLOCK_KEYGUARD_ENABLED, isChecked ? ON : OFF, getUserId());
     }
 
     @Override
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
new file mode 100644
index 0000000..b8ac118
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
@@ -0,0 +1,41 @@
+/*
+ * 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.biometrics.face;
+
+import android.content.Context;
+
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * Abstract base class for all face settings toggles.
+ */
+public abstract class FaceSettingsPreferenceController extends TogglePreferenceController {
+
+    private int mUserId;
+
+    public FaceSettingsPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    public void setUserId(int userId) {
+        mUserId = userId;
+    }
+
+    protected int getUserId() {
+        return mUserId;
+    }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
index 5174482..600ea37 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
@@ -82,12 +82,11 @@
     }
 
     private Button mButton;
-    private List<Face> mFaces;
     private Listener mListener;
     private SettingsActivity mActivity;
+    private int mUserId;
 
     private final Context mContext;
-    private final int mUserId;
     private final FaceManager mFaceManager;
     private final FaceManager.RemovalCallback mRemovalCallback = new FaceManager.RemovalCallback() {
         @Override
@@ -100,8 +99,8 @@
         @Override
         public void onRemovalSucceeded(Face face, int remaining) {
             if (remaining == 0) {
-                mFaces = mFaceManager.getEnrolledFaces(mUserId);
-                if (!mFaces.isEmpty()) {
+                final List<Face> faces = mFaceManager.getEnrolledFaces(mUserId);
+                if (!faces.isEmpty()) {
                     mButton.setEnabled(true);
                 } else {
                     mListener.onRemoved();
@@ -117,16 +116,17 @@
         @Override
         public void onClick(DialogInterface dialog, int which) {
             if (which == DialogInterface.BUTTON_POSITIVE) {
-                if (mFaces.isEmpty()) {
+                final List<Face> faces = mFaceManager.getEnrolledFaces(mUserId);
+                if (faces.isEmpty()) {
                     Log.e(TAG, "No faces");
                     return;
                 }
-                if (mFaces.size() > 1) {
-                    Log.e(TAG, "Multiple enrollments: " + mFaces.size());
+                if (faces.size() > 1) {
+                    Log.e(TAG, "Multiple enrollments: " + faces.size());
                 }
 
                 // Remove the first/only face
-                mFaceManager.remove(mFaces.get(0), mUserId, mRemovalCallback);
+                mFaceManager.remove(faces.get(0), mUserId, mRemovalCallback);
             } else {
                 mButton.setEnabled(true);
             }
@@ -137,17 +137,16 @@
         super(context, preferenceKey);
         mContext = context;
         mFaceManager = context.getSystemService(FaceManager.class);
-        // TODO: Use the profile-specific userId instead
-        mUserId = UserHandle.myUserId();
-        if (mFaceManager != null) {
-            mFaces = mFaceManager.getEnrolledFaces(mUserId);
-        }
     }
 
     public FaceSettingsRemoveButtonPreferenceController(Context context) {
         this(context, KEY);
     }
 
+    public void setUserId(int userId) {
+        mUserId = userId;
+    }
+
     @Override
     public void updateState(Preference preference) {
         super.updateState(preference);
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index b07635f..55b31d2 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -26,7 +26,6 @@
     public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
     public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
     public static final String SLICE_INJECTION = "settings_slice_injection";
-    public static final String MAINLINE_MODULE = "settings_mainline_module";
     public static final String WIFI_DETAILS_SAVED_SCREEN = "settings_wifi_details_saved_screen";
     public static final String WIFI_DETAILS_DATAUSAGE_HEADER =
             "settings_wifi_details_datausage_header";
diff --git a/src/com/android/settings/development/DeviceIdentifierAccessRestrictionsPreferenceController.java b/src/com/android/settings/development/DeviceIdentifierAccessRestrictionsPreferenceController.java
index 05ac8c7..f709771 100644
--- a/src/com/android/settings/development/DeviceIdentifierAccessRestrictionsPreferenceController.java
+++ b/src/com/android/settings/development/DeviceIdentifierAccessRestrictionsPreferenceController.java
@@ -16,8 +16,10 @@
 
 package com.android.settings.development;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.provider.DeviceConfig;
+import android.provider.Settings;
 
 import androidx.preference.Preference;
 import androidx.preference.SwitchPreference;
@@ -32,8 +34,30 @@
     private static final String DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_KEY =
             "device_identifier_access_restrictions";
 
+    // The settings that should be set when the new device identifier access restrictions are
+    // disabled.
+    private static final String[] RELAX_DEVICE_IDENTIFIER_CHECK_SETTINGS = {
+            Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED,
+            Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_NON_PRIV_CHECK_RELAXED,
+            Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_PRIV_CHECK_RELAXED
+    };
+
+    private ContentResolver mContentResolver;
+
     public DeviceIdentifierAccessRestrictionsPreferenceController(Context context) {
         super(context);
+        mContentResolver = context.getContentResolver();
+    }
+
+    @Override
+    public boolean isAvailable() {
+        // If the new access restrictions have been disabled from the server side then do not
+        // display the option.
+        boolean disabledFromServerSide = Boolean.parseBoolean(
+                DeviceConfig.getProperty(DeviceConfig.Privacy.NAMESPACE,
+                        DeviceConfig.Privacy.
+                                PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED));
+        return !disabledFromServerSide;
     }
 
     @Override
@@ -48,16 +72,20 @@
     }
 
     private void writeSetting(boolean isEnabled) {
-        DeviceConfig.setProperty(DeviceConfig.Privacy.NAMESPACE,
-                DeviceConfig.Privacy.PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED,
-                String.valueOf(isEnabled), false);
+        for (String relaxCheckSetting : RELAX_DEVICE_IDENTIFIER_CHECK_SETTINGS) {
+            Settings.Global.putInt(mContentResolver, relaxCheckSetting, isEnabled ? 1 : 0);
+        }
     }
 
     @Override
     public void updateState(Preference preference) {
-        boolean isEnabled = Boolean.parseBoolean(
-                DeviceConfig.getProperty(DeviceConfig.Privacy.NAMESPACE,
-                        DeviceConfig.Privacy.PROPERTY_DEVICE_IDENTIFIER_ACCESS_RESTRICTIONS_DISABLED));
+        boolean isEnabled = true;
+        for (String relaxCheckSetting : RELAX_DEVICE_IDENTIFIER_CHECK_SETTINGS) {
+            if (Settings.Global.getInt(mContentResolver, relaxCheckSetting, 0) == 0) {
+                isEnabled = false;
+                break;
+            }
+        }
         ((SwitchPreference) mPreference).setChecked(isEnabled);
     }
 
@@ -65,6 +93,6 @@
     protected void onDeveloperOptionsSwitchDisabled() {
         super.onDeveloperOptionsSwitchDisabled();
         writeSetting(false);
-        ((SwitchPreference) mPreference).setChecked(true);
+        ((SwitchPreference) mPreference).setChecked(false);
     }
 }
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java b/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
index 174cb8c..ff9352a 100644
--- a/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceController.java
@@ -21,14 +21,12 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
 import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.FeatureFlags;
 
 public class MainlineModuleVersionPreferenceController extends BasePreferenceController {
 
@@ -49,16 +47,10 @@
 
     @Override
     public int getAvailabilityStatus() {
-        if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlags.MAINLINE_MODULE)) {
-            return UNSUPPORTED_ON_DEVICE;
-        }
         return !TextUtils.isEmpty(mModuleVersion) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     private void initModules() {
-        if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlags.MAINLINE_MODULE)) {
-            return;
-        }
         final String moduleProvider = mContext.getString(
                 com.android.internal.R.string.config_defaultModuleMetadataProvider);
         if (!TextUtils.isEmpty(moduleProvider)) {
diff --git a/src/com/android/settings/display/AdaptiveSleepSettings.java b/src/com/android/settings/display/AdaptiveSleepSettings.java
index 097d7dc..4c17a67 100644
--- a/src/com/android/settings/display/AdaptiveSleepSettings.java
+++ b/src/com/android/settings/display/AdaptiveSleepSettings.java
@@ -25,6 +25,7 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.widget.FooterPreference;
 
 import java.util.Arrays;
 import java.util.List;
@@ -37,8 +38,10 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        mFooterPreferenceMixin.createFooterPreference()
-                .setTitle(R.string.adaptive_sleep_description);
+        final FooterPreference footerPreference =
+                mFooterPreferenceMixin.createFooterPreference();
+        footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp);
+        footerPreference.setTitle(R.string.adaptive_sleep_privacy);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/HighPowerDetail.java b/src/com/android/settings/fuelgauge/HighPowerDetail.java
index a7a9812..6448d9a 100644
--- a/src/com/android/settings/fuelgauge/HighPowerDetail.java
+++ b/src/com/android/settings/fuelgauge/HighPowerDetail.java
@@ -173,10 +173,18 @@
     }
 
     public static CharSequence getSummary(Context context, String pkg) {
-        PowerWhitelistBackend powerWhitelist = PowerWhitelistBackend.getInstance(context);
-        return context.getString(powerWhitelist.isSysWhitelisted(pkg) ? R.string.high_power_system
-                : powerWhitelist.isWhitelisted(pkg) ? R.string.high_power_on
-                        : R.string.high_power_off);
+        return getSummary(context, PowerWhitelistBackend.getInstance(context), pkg);
+    }
+
+    @VisibleForTesting
+    static CharSequence getSummary(Context context, PowerWhitelistBackend powerWhitelist,
+            String pkg) {
+        return context.getString(
+                powerWhitelist.isSysWhitelisted(pkg) || powerWhitelist.isDefaultActiveApp(pkg)
+                        ? R.string.high_power_system
+                        : powerWhitelist.isWhitelisted(pkg)
+                                ? R.string.high_power_on
+                                : R.string.high_power_off);
     }
 
     public static void show(Fragment caller, int uid, String packageName, int requestCode) {
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
index 54eb913..55bb9b2 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
@@ -16,11 +16,14 @@
 
 package com.android.settings.fuelgauge.batterytip.tips;
 
+import android.annotation.Nullable;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.SparseIntArray;
 
+import androidx.annotation.ColorInt;
 import androidx.annotation.IdRes;
 import androidx.annotation.IntDef;
 import androidx.annotation.VisibleForTesting;
@@ -151,6 +154,15 @@
         preference.setTitle(getTitle(context));
         preference.setSummary(getSummary(context));
         preference.setIcon(getIconId());
+        ColorStateList tint = getIconTint();
+        if (tint != null) {
+            preference.getIcon().setTintList(tint);
+        }
+    }
+
+    /** Returns the {@link ColorStateList} for tinting {@link #getIconId()} or null if none. */
+    protected @Nullable ColorStateList getIconTint() {
+        return null;
     }
 
     public boolean shouldShowDialog() {
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
index 7674c09..fe06507 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/EarlyWarningTip.java
@@ -18,6 +18,7 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.os.Parcel;
 
 import com.android.settings.R;
@@ -63,6 +64,13 @@
     }
 
     @Override
+    public ColorStateList getIconTint() {
+        return ColorStateList.valueOf(mState == StateType.HANDLED
+                ? R.color.battery_maybe_color_light
+                : R.color.battery_bad_color_light);
+    }
+
+    @Override
     public void updateState(BatteryTip tip) {
         final EarlyWarningTip earlyWarningTip = (EarlyWarningTip) tip;
         if (earlyWarningTip.mState == StateType.NEW) {
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
index aec6456..c21df2c 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
@@ -18,6 +18,7 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -59,6 +60,11 @@
     }
 
     @Override
+    public ColorStateList getIconTint() {
+        return ColorStateList.valueOf(R.color.battery_good_color_light);
+    }
+
+    @Override
     public void updateState(BatteryTip tip) {
         mState = tip.mState;
     }
diff --git a/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java b/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java
index c6466e8..f847612 100644
--- a/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java
+++ b/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionController.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.hardware.display.ColorDisplayManager;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.settings.R;
@@ -115,7 +116,8 @@
     private void sendBroadcast() {
         final Intent intent = new Intent(ACTION_GRAYSCALE_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-        mAppContext.sendBroadcast(intent, Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS);
+        mAppContext.sendBroadcastAsUser(intent, UserHandle.CURRENT,
+                Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS);
     }
 
     public class Receiver extends BroadcastReceiver {
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
index 96521ea..574b7dd 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java
@@ -35,6 +35,7 @@
 
 import com.android.ims.ImsConfig;
 import com.android.ims.ImsManager;
+import com.android.settings.R;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -116,6 +117,9 @@
             preference.setSummary(null);
             preference.setIntent(intent);
         } else {
+            final String title = SubscriptionManager.getResourcesForSubId(mContext, mSubId)
+                    .getString(R.string.wifi_calling_settings_title);
+            preference.setTitle(title);
             int resId = com.android.internal.R.string.wifi_calling_off_summary;
             if (mImsManager.isWfcEnabledByUser()) {
                 boolean wfcRoamingEnabled = mEditableWfcRoamingMode && !mUseWfcHomeModeForRoaming;
diff --git a/src/com/android/settings/notification/AppBubbleNotificationSettings.java b/src/com/android/settings/notification/AppBubbleNotificationSettings.java
index 17909c0..f55c262 100644
--- a/src/com/android/settings/notification/AppBubbleNotificationSettings.java
+++ b/src/com/android/settings/notification/AppBubbleNotificationSettings.java
@@ -18,22 +18,23 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.provider.SearchIndexableResource;
 import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.settings.R;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 @SearchIndexable
-public class AppBubbleNotificationSettings extends NotificationSettingsBase {
+public class AppBubbleNotificationSettings extends NotificationSettingsBase implements
+        GlobalBubblePermissionObserverMixin.Listener {
     private static final String TAG = "AppBubNotiSettings";
+    private GlobalBubblePermissionObserverMixin mObserverMixin;
 
     @Override
     public int getMetricsCategory() {
@@ -65,6 +66,11 @@
     }
 
     @Override
+    public void onGlobalBubblePermissionChanged() {
+        updatePreferenceStates();
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
 
@@ -79,19 +85,23 @@
             controller.displayPreference(getPreferenceScreen());
         }
         updatePreferenceStates();
+
+        mObserverMixin = new GlobalBubblePermissionObserverMixin(getContext(), this);
+        mObserverMixin.onStart();
     }
 
-    /**
-     * For Search.
-     */
-    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+    @Override
+    public void onPause() {
+        mObserverMixin.onStop();
+        super.onPause();
+    }
+
+    public static final Indexable.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.app_bubble_notification_settings;
-                    return Arrays.asList(sir);
+                protected boolean isPageSearchEnabled(Context context) {
+                    return false;
                 }
 
                 @Override
diff --git a/src/com/android/settings/notification/BubblePreferenceController.java b/src/com/android/settings/notification/BubblePreferenceController.java
index 5dab374..e5a1a62 100644
--- a/src/com/android/settings/notification/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/BubblePreferenceController.java
@@ -25,6 +25,7 @@
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settingslib.RestrictedSwitchPreference;
 
+import androidx.fragment.app.FragmentManager;
 import androidx.preference.Preference;
 
 public class BubblePreferenceController extends NotificationPreferenceController
@@ -35,10 +36,18 @@
     private static final int SYSTEM_WIDE_ON = 1;
     private static final int SYSTEM_WIDE_OFF = 0;
 
+    private FragmentManager mFragmentManager;
+
     public BubblePreferenceController(Context context, NotificationBackend backend) {
         super(context, backend);
     }
 
+    public BubblePreferenceController(Context context, FragmentManager fragmentManager,
+            NotificationBackend backend) {
+        super(context, backend);
+        mFragmentManager = fragmentManager;
+    }
+
     @Override
     public String getPreferenceKey() {
         return KEY;
@@ -52,11 +61,11 @@
         if (mAppRow == null && mChannel == null) {
             return false;
         }
-        if (Settings.Secure.getInt(mContext.getContentResolver(),
-                NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
-            return false;
-        }
         if (mChannel != null) {
+            if (Settings.Secure.getInt(mContext.getContentResolver(),
+                    NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
+                return false;
+            }
             if (isDefaultChannel()) {
                 return true;
             } else {
@@ -74,7 +83,9 @@
                 pref.setChecked(mChannel.canBubble());
                 pref.setEnabled(isChannelConfigurable() && !pref.isDisabledByAdmin());
             } else {
-                pref.setChecked(mAppRow.allowBubbles);
+                pref.setChecked(mAppRow.allowBubbles
+                        && Settings.Secure.getInt(mContext.getContentResolver(),
+                        NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_ON);
                 pref.setSummary(mContext.getString(
                         R.string.bubbles_app_toggle_summary, mAppRow.label));
             }
@@ -87,11 +98,44 @@
         if (mChannel != null) {
             mChannel.setAllowBubbles(value);
             saveChannel();
-        } else if (mAppRow != null){
-            mAppRow.allowBubbles = value;
-            mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value);
+            return true;
+        } else if (mAppRow != null) {
+            RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
+            // if the global setting is off, toggling app level permission requires extra
+            // confirmation
+            if (Settings.Secure.getInt(mContext.getContentResolver(),
+                    NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF
+                    && !pref.isChecked()) {
+                new BubbleWarningDialogFragment()
+                        .setPkgInfo(mAppRow.pkg, mAppRow.uid)
+                        .show(mFragmentManager, "dialog");
+                return false;
+            } else {
+                mAppRow.allowBubbles = value;
+                mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value);
+            }
         }
         return true;
     }
 
+    // Used in app level prompt that confirms the user is ok with turning on bubbles
+    // globally. If they aren't, undo what
+    public static void revertBubblesApproval(Context mContext, String pkg, int uid) {
+        NotificationBackend backend = new NotificationBackend();
+        backend.setAllowBubbles(pkg, uid, false);
+        // changing the global settings will cause the observer on the host page to reload
+        // correct preference state
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF);
+    }
+
+    // Apply global bubbles approval
+    public static void applyBubblesApproval(Context mContext, String pkg, int uid) {
+        NotificationBackend backend = new NotificationBackend();
+        backend.setAllowBubbles(pkg, uid, true);
+        // changing the global settings will cause the observer on the host page to reload
+        // correct preference state
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
+    }
 }
diff --git a/src/com/android/settings/notification/BubbleSummaryPreferenceController.java b/src/com/android/settings/notification/BubbleSummaryPreferenceController.java
index 708bbcd..5f58f67 100644
--- a/src/com/android/settings/notification/BubbleSummaryPreferenceController.java
+++ b/src/com/android/settings/notification/BubbleSummaryPreferenceController.java
@@ -52,11 +52,11 @@
         if (mAppRow == null && mChannel == null) {
             return false;
         }
-        if (Settings.Secure.getInt(mContext.getContentResolver(),
-                NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
-            return false;
-        }
         if (mChannel != null) {
+            if (Settings.Secure.getInt(mContext.getContentResolver(),
+                    NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
+                return false;
+            }
             if (isDefaultChannel()) {
                 return true;
             } else {
@@ -91,7 +91,9 @@
             if (mChannel != null) {
                 canBubble |= mChannel.canBubble();
             } else {
-               canBubble |= mAppRow.allowBubbles;
+               canBubble |= mAppRow.allowBubbles
+                       && (Settings.Secure.getInt(mContext.getContentResolver(),
+                       NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_ON);
             }
         }
         return mContext.getString(canBubble ? R.string.switch_on_text : R.string.switch_off_text);
diff --git a/src/com/android/settings/notification/BubbleWarningDialogFragment.java b/src/com/android/settings/notification/BubbleWarningDialogFragment.java
new file mode 100644
index 0000000..5086fb0
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleWarningDialogFragment.java
@@ -0,0 +1,70 @@
+/*
+ * 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.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AlertDialog;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class BubbleWarningDialogFragment extends InstrumentedDialogFragment {
+    static final String KEY_PKG = "p";
+    static final String KEY_UID = "u";
+
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_APP_BUBBLE_SETTINGS;
+    }
+
+    public BubbleWarningDialogFragment setPkgInfo(String pkg, int uid) {
+        Bundle args = new Bundle();
+        args.putString(KEY_PKG, pkg);
+        args.putInt(KEY_UID, uid);
+        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 int uid = args.getInt(KEY_UID);
+
+        final String title =
+                getResources().getString(R.string.bubbles_feature_disabled_dialog_title);
+        final String summary = getResources()
+                .getString(R.string.bubbles_feature_disabled_dialog_text);
+        return new AlertDialog.Builder(getContext())
+                .setMessage(summary)
+                .setTitle(title)
+                .setCancelable(true)
+                .setPositiveButton(R.string.bubbles_feature_disabled_button_approve,
+                        (dialog, id) ->
+                                BubblePreferenceController.applyBubblesApproval(
+                                        getContext(), pkg, uid))
+                .setNegativeButton(R.string.bubbles_feature_disabled_button_cancel,
+                        (dialog, id) ->
+                                BubblePreferenceController.revertBubblesApproval(
+                                        getContext(), pkg, uid))
+                .create();
+    }
+}
diff --git a/src/com/android/settings/notification/GlobalBubblePermissionObserverMixin.java b/src/com/android/settings/notification/GlobalBubblePermissionObserverMixin.java
new file mode 100644
index 0000000..398931d
--- /dev/null
+++ b/src/com/android/settings/notification/GlobalBubblePermissionObserverMixin.java
@@ -0,0 +1,59 @@
+/*
+ * 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.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+
+public class GlobalBubblePermissionObserverMixin extends ContentObserver {
+
+    public interface Listener {
+        void onGlobalBubblePermissionChanged();
+    }
+
+    private final Context mContext;
+    private final Listener mListener;
+
+    public GlobalBubblePermissionObserverMixin(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.onGlobalBubblePermissionChanged();
+        }
+    }
+
+    public void onStart() {
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(
+                        Settings.Secure.NOTIFICATION_BUBBLES),
+                false /* notifyForDescendants */,
+                this /* observer */);
+    }
+
+    public void onStop() {
+        mContext.getContentResolver().unregisterContentObserver(this /* observer */);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/HeaderPreferenceController.java b/src/com/android/settings/notification/HeaderPreferenceController.java
index 0c091b4..d942113 100644
--- a/src/com/android/settings/notification/HeaderPreferenceController.java
+++ b/src/com/android/settings/notification/HeaderPreferenceController.java
@@ -68,9 +68,13 @@
                 activity = mFragment.getActivity();
             }
 
+            if (activity == null) {
+                return;
+            }
+
             LayoutPreference pref = (LayoutPreference) preference;
             mHeaderController = EntityHeaderController.newInstance(
-                    mFragment.getActivity(), mFragment, pref.findViewById(R.id.entity_header));
+                    activity, mFragment, pref.findViewById(R.id.entity_header));
             pref = mHeaderController.setIcon(mAppRow.icon)
                     .setLabel(getLabel())
                     .setSummary(getSummary())
diff --git a/src/com/android/settings/notification/ZenModePreferenceController.java b/src/com/android/settings/notification/ZenModePreferenceController.java
index 22eb0c0..44ad2ff 100644
--- a/src/com/android/settings/notification/ZenModePreferenceController.java
+++ b/src/com/android/settings/notification/ZenModePreferenceController.java
@@ -35,9 +35,6 @@
 public class ZenModePreferenceController extends BasePreferenceController
         implements LifecycleObserver, OnResume, OnPause {
 
-
-    public static final String ZEN_MODE_KEY = "zen_mode";
-
     private SettingObserver mSettingObserver;
     private ZenModeSettings.SummaryBuilder mSummaryBuilder;
 
diff --git a/src/com/android/settings/notification/ZenModeSliceBuilder.java b/src/com/android/settings/notification/ZenModeSliceBuilder.java
index ceb36fe..e8b181a 100644
--- a/src/com/android/settings/notification/ZenModeSliceBuilder.java
+++ b/src/com/android/settings/notification/ZenModeSliceBuilder.java
@@ -18,7 +18,7 @@
 
 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
 
-import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
+import static com.android.settings.notification.ZenModeSoundSettingsPreferenceController.ZEN_MODE_KEY;
 
 import android.annotation.ColorInt;
 import android.app.NotificationManager;
diff --git a/src/com/android/settings/notification/ZenModeSoundSettingsPreferenceController.java b/src/com/android/settings/notification/ZenModeSoundSettingsPreferenceController.java
new file mode 100644
index 0000000..842c49d
--- /dev/null
+++ b/src/com/android/settings/notification/ZenModeSoundSettingsPreferenceController.java
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+public class ZenModeSoundSettingsPreferenceController extends ZenModePreferenceController {
+
+    public static final String ZEN_MODE_KEY = "zen_mode";
+
+    public ZenModeSoundSettingsPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index 20421d0..f1391dc 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -37,6 +37,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.panel.PanelLoggingContract.PanelClosedKeys;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.google.android.setupdesign.DividerItemDecoration;
 
 public class PanelFragment extends Fragment {
 
@@ -93,6 +94,10 @@
         mPanelSlices.setLayoutManager(new LinearLayoutManager((activity)));
         mPanelSlices.setAdapter(mAdapter);
 
+        DividerItemDecoration itemDecoration = new DividerItemDecoration(getActivity());
+        itemDecoration.setDividerCondition(DividerItemDecoration.DIVIDER_CONDITION_BOTH);
+        mPanelSlices.addItemDecoration(itemDecoration);
+
         mTitleView.setText(mPanel.getTitle());
 
         mSeeMoreButton.setOnClickListener(getSeeMoreListener());
diff --git a/src/com/android/settings/panel/PanelSlicesAdapter.java b/src/com/android/settings/panel/PanelSlicesAdapter.java
index 47ff631..0eec534 100644
--- a/src/com/android/settings/panel/PanelSlicesAdapter.java
+++ b/src/com/android/settings/panel/PanelSlicesAdapter.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.panel;
 
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.net.Uri;
@@ -33,6 +35,7 @@
 
 import com.android.settings.R;
 import com.android.settings.overlay.FeatureFactory;
+import com.google.android.setupdesign.DividerItemDecoration;
 
 import java.util.List;
 
@@ -80,10 +83,13 @@
     /**
      * ViewHolder for binding Slices to SliceViews.
      */
-    public static class SliceRowViewHolder extends RecyclerView.ViewHolder {
+    public static class SliceRowViewHolder extends RecyclerView.ViewHolder
+            implements DividerItemDecoration.DividedViewHolder {
 
         private final PanelContent mPanelContent;
 
+        private boolean mDividerAllowedAbove = true;
+
         @VisibleForTesting
         LiveData<Slice> sliceLiveData;
 
@@ -103,6 +109,11 @@
             sliceLiveData = SliceLiveData.fromUri(context, sliceUri);
             sliceLiveData.observe(fragment.getViewLifecycleOwner(), sliceView);
 
+            // Do not show the divider above media devices switcher slice per request
+            if (sliceUri.equals(MEDIA_OUTPUT_INDICATOR_SLICE_URI)) {
+                mDividerAllowedAbove = false;
+            }
+
             // Log Panel interaction
             sliceView.setOnSliceActionListener(
                     ((eventInfo, sliceItem) -> {
@@ -116,5 +127,15 @@
                     })
             );
         }
+
+        @Override
+        public boolean isDividerAllowedAbove() {
+            return mDividerAllowedAbove;
+        }
+
+        @Override
+        public boolean isDividerAllowedBelow() {
+            return true;
+        }
     }
 }
diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
index 660eab5..7c3391c 100644
--- a/src/com/android/settings/security/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -23,6 +23,7 @@
 import android.provider.SearchIndexableResource;
 
 import com.android.settings.R;
+import com.android.settings.biometrics.face.FaceProfileStatusPreferenceController;
 import com.android.settings.biometrics.face.FaceStatusPreferenceController;
 import com.android.settings.biometrics.fingerprint.FingerprintProfileStatusPreferenceController;
 import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
@@ -125,6 +126,7 @@
         profileSecurityControllers.add(new LockUnificationPreferenceController(context, host));
         profileSecurityControllers.add(new VisiblePatternProfilePreferenceController(
                 context, lifecycle));
+        profileSecurityControllers.add(new FaceProfileStatusPreferenceController(context));
         profileSecurityControllers.add(new FingerprintProfileStatusPreferenceController(context));
         controllers.add(new PreferenceCategoryController(context, WORK_PROFILE_SECURITY_CATEGORY)
                 .setChildren(profileSecurityControllers));
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index fe000d1..e400815 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -19,7 +19,7 @@
 import static android.provider.SettingsSlicesContract.KEY_LOCATION;
 import static android.provider.SettingsSlicesContract.KEY_WIFI;
 
-import static com.android.settings.notification.ZenModePreferenceController.ZEN_MODE_KEY;
+import static com.android.settings.notification.ZenModeSoundSettingsPreferenceController.ZEN_MODE_KEY;
 
 import android.content.ContentResolver;
 import android.net.Uri;
diff --git a/src/com/android/settings/slices/SliceBackgroundWorker.java b/src/com/android/settings/slices/SliceBackgroundWorker.java
index f19b1df..6bafc00 100644
--- a/src/com/android/settings/slices/SliceBackgroundWorker.java
+++ b/src/com/android/settings/slices/SliceBackgroundWorker.java
@@ -68,16 +68,17 @@
     }
 
     /**
-     * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link Uri}
-     * if exists
+     * Returns the singleton instance of {@link SliceBackgroundWorker} for specified {@link Uri} if
+     * exists
      */
     @Nullable
-    public static SliceBackgroundWorker getInstance(Uri uri) {
-        return LIVE_WORKERS.get(uri);
+    @SuppressWarnings("TypeParameterUnusedInFormals")
+    public static <T extends SliceBackgroundWorker> T getInstance(Uri uri) {
+        return (T) LIVE_WORKERS.get(uri);
     }
 
     /**
-     * Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link
+     * Returns the singleton instance of {@link SliceBackgroundWorker} for specified {@link
      * CustomSliceable}
      */
     static SliceBackgroundWorker getInstance(Context context, Sliceable sliceable, Uri uri) {
@@ -165,4 +166,4 @@
     protected final void notifySliceChange() {
         mContext.getContentResolver().notifyChange(mUri, null);
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 89c1575..718f7fb 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -74,7 +74,8 @@
 
     @Override
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
-        mWifiWakeupPreferenceController = new WifiWakeupPreferenceController(context, this);
+        mWifiWakeupPreferenceController = new WifiWakeupPreferenceController(context, this,
+                getSettingsLifecycle());
         mUseOpenWifiPreferenceController = new UseOpenWifiPreferenceController(context, this,
                 getSettingsLifecycle());
         final WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
diff --git a/src/com/android/settings/wifi/WifiWakeupPreferenceController.java b/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
index 15bffd9..2726de4 100644
--- a/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
+++ b/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
@@ -19,8 +19,10 @@
 import static com.android.settings.wifi.ConfigureWifiSettings.WIFI_WAKEUP_REQUEST_CODE;
 
 import android.app.Service;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.location.LocationManager;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -36,12 +38,17 @@
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.utils.AnnotationSpan;
 import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
 
 /**
  * {@link PreferenceControllerMixin} that controls whether the Wi-Fi Wakeup feature should be
  * enabled.
  */
-public class WifiWakeupPreferenceController extends AbstractPreferenceController {
+public class WifiWakeupPreferenceController extends AbstractPreferenceController implements
+        LifecycleObserver, OnPause, OnResume {
 
     private static final String TAG = "WifiWakeupPrefController";
     private static final String KEY_ENABLE_WIFI_WAKEUP = "enable_wifi_wakeup";
@@ -52,11 +59,21 @@
     SwitchPreference mPreference;
     @VisibleForTesting
     LocationManager mLocationManager;
+    private final BroadcastReceiver mLocationReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            updateState(mPreference);
+        }
+    };
+    private final IntentFilter mLocationFilter =
+            new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
 
-    public WifiWakeupPreferenceController(Context context, DashboardFragment fragment) {
+    public WifiWakeupPreferenceController(Context context, DashboardFragment fragment,
+            Lifecycle lifecycle) {
         super(context);
         mFragment = fragment;
         mLocationManager = (LocationManager) context.getSystemService(Service.LOCATION_SERVICE);
+        lifecycle.addObserver(this);
     }
 
     @Override
@@ -155,4 +172,14 @@
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.WIFI_WAKEUP_ENABLED,
                 enabled ? 1 : 0);
     }
+
+    @Override
+    public void onResume() {
+        mContext.registerReceiver(mLocationReceiver, mLocationFilter);
+    }
+
+    @Override
+    public void onPause() {
+        mContext.unregisterReceiver(mLocationReceiver);
+    }
 }
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java b/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java
index 4f3b7fd..86cce1e 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pPreferenceController.java
@@ -15,10 +15,12 @@
  */
 package com.android.settings.wifi.p2p;
 
+import android.app.Service;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.location.LocationManager;
 import android.net.wifi.WifiManager;
 
 import androidx.annotation.VisibleForTesting;
@@ -49,6 +51,17 @@
         }
     };
     private final IntentFilter mFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
+    private final LocationManager mLocationManager;
+    private final BroadcastReceiver mLocationReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (mWifiDirectPref != null) {
+                updateState(mWifiDirectPref);
+            }
+        }
+    };
+    private final IntentFilter mLocationFilter =
+            new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
 
     private Preference mWifiDirectPref;
 
@@ -57,6 +70,7 @@
         super(context);
         mWifiManager = wifiManager;
         lifecycle.addObserver(this);
+        mLocationManager = (LocationManager) context.getSystemService(Service.LOCATION_SERVICE);
     }
 
     @Override
@@ -67,13 +81,21 @@
     }
 
     @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+        preference.setEnabled(mLocationManager.isLocationEnabled() && mWifiManager.isWifiEnabled());
+    }
+
+    @Override
     public void onResume() {
         mContext.registerReceiver(mReceiver, mFilter);
+        mContext.registerReceiver(mLocationReceiver, mLocationFilter);
     }
 
     @Override
     public void onPause() {
         mContext.unregisterReceiver(mReceiver);
+        mContext.unregisterReceiver(mLocationReceiver);
     }
 
     @Override
@@ -88,7 +110,9 @@
 
     private void togglePreferences() {
         if (mWifiDirectPref != null) {
-            mWifiDirectPref.setEnabled(mWifiManager.isWifiEnabled());
+            mWifiDirectPref.setEnabled(
+                    mWifiManager.isWifiEnabled()
+                    && mLocationManager.isLocationEnabled());
         }
     }
 }
diff --git a/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java b/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java
index 6cf55d2..ee15820 100644
--- a/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java
+++ b/src/com/android/settings/wifi/slice/ConnectToWifiHandler.java
@@ -17,6 +17,8 @@
 package com.android.settings.wifi.slice;
 
 import android.app.Activity;
+import android.net.ConnectivityManager;
+import android.net.Network;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
 
@@ -36,10 +38,15 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        final Network network = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
         final Bundle accessPointState = getIntent().getBundleExtra(
                 WifiDialogActivity.KEY_ACCESS_POINT_STATE);
 
-        if (accessPointState != null) {
+        if (network != null) {
+            final ConnectivityManager cm = getSystemService(ConnectivityManager.class);
+            // start captive portal app to sign in to network
+            cm.startCaptivePortalApp(network);
+        } else if (accessPointState != null) {
             connect(new AccessPoint(this, accessPointState));
         }
         finish();
diff --git a/src/com/android/settings/wifi/slice/ContextualWifiSlice.java b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
index 4a799d1..7dbba41 100644
--- a/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
+++ b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
@@ -57,7 +57,7 @@
             sActiveUiSession = currentUiSession;
             sPreviouslyDisplayed = false;
         }
-        if (!sPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) {
+        if (!sPreviouslyDisplayed && hasWorkingNetwork()) {
             Log.d(TAG, "Wifi is connected, no point showing any suggestion.");
             return null;
         }
@@ -67,4 +67,8 @@
 
         return super.getSlice();
     }
+
+    private boolean hasWorkingNetwork() {
+        return !TextUtils.equals(getActiveSSID(), WifiSsid.NONE) && !isCaptivePortal();
+    }
 }
diff --git a/src/com/android/settings/wifi/slice/WifiScanWorker.java b/src/com/android/settings/wifi/slice/WifiScanWorker.java
index cf45d08..b846228 100644
--- a/src/com/android/settings/wifi/slice/WifiScanWorker.java
+++ b/src/com/android/settings/wifi/slice/WifiScanWorker.java
@@ -16,14 +16,27 @@
 
 package com.android.settings.wifi.slice;
 
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
 
 import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
+import android.net.NetworkRequest;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.util.Preconditions;
 import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settings.wifi.WifiUtils;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.settingslib.wifi.WifiTracker;
 
@@ -33,16 +46,23 @@
 /**
  * {@link SliceBackgroundWorker} for Wi-Fi, used by WifiSlice.
  */
-public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint>
-        implements WifiTracker.WifiListener {
+public class WifiScanWorker extends SliceBackgroundWorker<AccessPoint> implements
+        WifiTracker.WifiListener {
+
+    private static final String TAG = "WifiScanWorker";
+
+    @VisibleForTesting
+    CaptivePortalNetworkCallback mCaptivePortalNetworkCallback;
 
     private final Context mContext;
 
     private WifiTracker mWifiTracker;
+    private ConnectivityManager mConnectivityManager;
 
     public WifiScanWorker(Context context, Uri uri) {
         super(context, uri);
         mContext = context;
+        mConnectivityManager = context.getSystemService(ConnectivityManager.class);
     }
 
     @Override
@@ -58,6 +78,7 @@
     @Override
     protected void onSliceUnpinned() {
         mWifiTracker.onStop();
+        unregisterCaptivePortalNetworkCallback();
     }
 
     @Override
@@ -124,4 +145,71 @@
         }
         return null;
     }
-}
\ No newline at end of file
+
+    public void registerCaptivePortalNetworkCallback(Network wifiNetwork) {
+        if (wifiNetwork == null) {
+            return;
+        }
+
+        if (mCaptivePortalNetworkCallback != null
+                && mCaptivePortalNetworkCallback.isSameNetwork(wifiNetwork)) {
+            return;
+        }
+
+        unregisterCaptivePortalNetworkCallback();
+
+        mCaptivePortalNetworkCallback = new CaptivePortalNetworkCallback(wifiNetwork);
+        mConnectivityManager.registerNetworkCallback(
+                new NetworkRequest.Builder()
+                        .clearCapabilities()
+                        .addTransportType(TRANSPORT_WIFI)
+                        .build(),
+                mCaptivePortalNetworkCallback,
+                new Handler(Looper.getMainLooper()));
+    }
+
+    public void unregisterCaptivePortalNetworkCallback() {
+        if (mCaptivePortalNetworkCallback != null) {
+            try {
+                mConnectivityManager.unregisterNetworkCallback(mCaptivePortalNetworkCallback);
+            } catch (RuntimeException e) {
+                Log.e(TAG, "Unregistering CaptivePortalNetworkCallback failed.", e);
+            }
+            mCaptivePortalNetworkCallback = null;
+        }
+    }
+
+    class CaptivePortalNetworkCallback extends NetworkCallback {
+
+        private final Network mNetwork;
+        private boolean mIsCaptivePortal;
+
+        CaptivePortalNetworkCallback(Network network) {
+            mNetwork = Preconditions.checkNotNull(network);
+        }
+
+        @Override
+        public void onCapabilitiesChanged(Network network,
+                NetworkCapabilities networkCapabilities) {
+            if (!mNetwork.equals(network)) {
+                return;
+            }
+
+            final boolean isCaptivePortal = WifiUtils.canSignIntoNetwork(networkCapabilities);
+            if (mIsCaptivePortal == isCaptivePortal) {
+                return;
+            }
+
+            mIsCaptivePortal = isCaptivePortal;
+            notifySliceChange();
+        }
+
+        /**
+         * Returns true if the supplied network is not null and is the same as the originally
+         * supplied value.
+         */
+        public boolean isSameNetwork(Network network) {
+            return mNetwork.equals(network);
+        }
+    }
+}
diff --git a/src/com/android/settings/wifi/slice/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
index d3df5fc..3fe2950 100644
--- a/src/com/android/settings/wifi/slice/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -31,6 +31,8 @@
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
 import android.net.NetworkInfo.DetailedState;
@@ -78,10 +80,12 @@
 
     protected final Context mContext;
     protected final WifiManager mWifiManager;
+    protected final ConnectivityManager mConnectivityManager;
 
     public WifiSlice(Context context) {
         mContext = context;
         mWifiManager = mContext.getSystemService(WifiManager.class);
+        mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
     }
 
     @Override
@@ -100,13 +104,16 @@
             return listBuilder.build();
         }
 
-        final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(getUri());
+        final WifiScanWorker worker = SliceBackgroundWorker.getInstance(getUri());
         final List<AccessPoint> results = worker != null ? worker.getResults() : null;
         final int apCount = results == null ? 0 : results.size();
+        final boolean isFirstApActive = apCount > 0 && results.get(0).isActive();
+        handleCaptivePortalCallback(worker, isFirstApActive);
 
         // Need a loading text when results are not ready or out of date.
         boolean needLoadingRow = true;
-        int index = apCount > 0 && results.get(0).isActive() ? 1 : 0;
+        // Skip checking the existence of the first access point if it's active
+        int index = isFirstApActive ? 1 : 0;
         // This loop checks the existence of reachable APs to determine the validity of the current
         // AP list.
         for (; index < apCount; index++) {
@@ -159,19 +166,35 @@
                         .setPrimaryAction(primarySliceAction));
     }
 
+    private void handleCaptivePortalCallback(WifiScanWorker worker, boolean isFirstApActive) {
+        if (worker == null) {
+            return;
+        }
+        if (isFirstApActive) {
+            worker.registerCaptivePortalNetworkCallback(mWifiManager.getCurrentNetwork());
+        } else {
+            worker.unregisterCaptivePortalNetworkCallback();
+        }
+    }
+
     private ListBuilder.RowBuilder getAccessPointRow(AccessPoint accessPoint) {
         final CharSequence title = getAccessPointName(accessPoint);
         final IconCompat levelIcon = getAccessPointLevelIcon(accessPoint);
+        final boolean isCaptivePortal = accessPoint.isActive() && isCaptivePortal();
         final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
                 .setTitleItem(levelIcon, ListBuilder.ICON_IMAGE)
                 .setSubtitle(title)
-                .setPrimaryAction(SliceAction.create(
-                        getAccessPointAction(accessPoint), levelIcon, ListBuilder.ICON_IMAGE,
-                        title));
+                .setPrimaryAction(SliceAction.createDeeplink(
+                        getAccessPointAction(accessPoint, isCaptivePortal), levelIcon,
+                        ListBuilder.ICON_IMAGE, title));
 
-        final IconCompat endIcon = getEndIcon(accessPoint);
-        if (endIcon != null) {
-            rowBuilder.addEndItem(endIcon, ListBuilder.ICON_IMAGE);
+        if (isCaptivePortal) {
+            rowBuilder.addEndItem(getCaptivePortalEndAction(accessPoint, title));
+        } else {
+            final IconCompat endIcon = getEndIcon(accessPoint);
+            if (endIcon != null) {
+                rowBuilder.addEndItem(endIcon, ListBuilder.ICON_IMAGE);
+            }
         }
         return rowBuilder;
     }
@@ -218,12 +241,22 @@
         return null;
     }
 
-    private PendingIntent getAccessPointAction(AccessPoint accessPoint) {
+    private SliceAction getCaptivePortalEndAction(AccessPoint accessPoint, CharSequence title) {
+        return SliceAction.createDeeplink(
+                getAccessPointAction(accessPoint, false /* isCaptivePortal */),
+                IconCompat.createWithResource(mContext, R.drawable.ic_settings_accent),
+                ListBuilder.ICON_IMAGE, title);
+    }
+
+    private PendingIntent getAccessPointAction(AccessPoint accessPoint, boolean isCaptivePortal) {
         final Bundle extras = new Bundle();
         accessPoint.saveWifiState(extras);
 
         Intent intent;
-        if (accessPoint.isActive()) {
+        if (isCaptivePortal) {
+            intent = new Intent(mContext, ConnectToWifiHandler.class);
+            intent.putExtra(ConnectivityManager.EXTRA_NETWORK, mWifiManager.getCurrentNetwork());
+        } else if (accessPoint.isActive()) {
             intent = new SubSettingLauncher(mContext)
                     .setTitleRes(R.string.pref_title_network_details)
                     .setDestination(WifiNetworkDetailsFragment.class.getName())
@@ -253,6 +286,12 @@
                 .setSubtitle(title);
     }
 
+    protected boolean isCaptivePortal() {
+        final NetworkCapabilities nc = mConnectivityManager.getNetworkCapabilities(
+                mWifiManager.getCurrentNetwork());
+        return WifiUtils.canSignIntoNetwork(nc);
+    }
+
     /**
      * Update the current wifi status to the boolean value keyed by
      * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
@@ -317,6 +356,12 @@
     }
 
     private CharSequence getSummary(AccessPoint accessPoint) {
+        if (isCaptivePortal()) {
+            final int id = mContext.getResources()
+                    .getIdentifier("network_available_sign_in", "string", "android");
+            return mContext.getText(id);
+        }
+
         if (accessPoint == null) {
             return getSummary();
         }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
index f391aac..adddc96 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/MainlineModuleVersionPreferenceControllerTest.java
@@ -60,18 +60,6 @@
         mContext = spy(RuntimeEnvironment.application);
         mPreference = new Preference(mContext);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
-
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.MAINLINE_MODULE, true);
-    }
-
-    @Test
-    public void getAvailabilityStatus_featureDisabled_unavailable() {
-        FeatureFlagUtils.setEnabled(mContext, FeatureFlags.MAINLINE_MODULE, false);
-
-        final MainlineModuleVersionPreferenceController controller =
-                new MainlineModuleVersionPreferenceController(mContext, "key");
-
-        assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java
index 5716b27..e613684 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/HighPowerDetailTest.java
@@ -16,8 +16,11 @@
 
 package com.android.settings.fuelgauge;
 
+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.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -27,6 +30,7 @@
 import android.content.DialogInterface;
 
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settingslib.fuelgauge.PowerWhitelistBackend;
 
@@ -46,6 +50,7 @@
     private FakeFeatureFactory mFeatureFactory;
     private HighPowerDetail mFragment;
 
+    private Context mContext;
     @Mock
     private PowerWhitelistBackend mPowerWhitelistBackend;
     @Mock
@@ -56,6 +61,7 @@
         mFeatureFactory = FakeFeatureFactory.setupForTest();
 
         MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
         mFragment = spy(new HighPowerDetail());
         mFragment.mBackend = mPowerWhitelistBackend;
         mFragment.mBatteryUtils = mBatteryUtils;
@@ -84,4 +90,12 @@
         verify(mBatteryUtils).setForceAppStandby(TEST_UID, TEST_PACKAGE,
                 AppOpsManager.MODE_ALLOWED);
     }
+
+    @Test
+    public void getSummary_defaultActivePackage_returnUnavailable() {
+        doReturn(true).when(mPowerWhitelistBackend).isDefaultActiveApp(TEST_PACKAGE);
+
+        assertThat(HighPowerDetail.getSummary(mContext, mPowerWhitelistBackend, TEST_PACKAGE))
+                .isEqualTo(mContext.getString(R.string.high_power_system));
+    }
 }
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
index 2fe4697..58a8d5b 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/conditional/GrayscaleConditionControllerTest.java
@@ -26,6 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.hardware.display.ColorDisplayManager;
+import android.os.UserHandle;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -87,6 +88,7 @@
     public void onActionClick_shouldSendBroadcast() {
         mController.onActionClick();
 
-        verify(mContext).sendBroadcast(any(Intent.class), any(String.class));
+        verify(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class),
+                any(String.class));
     }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
index 6d13798..54bbd08 100644
--- a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
@@ -29,6 +29,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -53,6 +54,8 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.shadows.ShadowApplication;
 
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
@@ -68,6 +71,8 @@
     private UserManager mUm;
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private PreferenceScreen mScreen;
+    @Mock
+    private FragmentManager mFragmentManager;
 
     private BubblePreferenceController mController;
 
@@ -78,7 +83,8 @@
         shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
         shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
         mContext = RuntimeEnvironment.application;
-        mController = spy(new BubblePreferenceController(mContext, mBackend));
+        when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class));
+        mController = spy(new BubblePreferenceController(mContext, mFragmentManager, mBackend));
     }
 
     @Test
@@ -117,7 +123,16 @@
     }
 
     @Test
-    public void testIsAvailable_notIfOffGlobally() {
+    public void testIsAvailable_ifOffGlobally_app() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        mController.onResume(appRow, null, null, null);
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_notIfOffGlobally_channel() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         NotificationChannel channel = mock(NotificationChannel.class);
         when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
@@ -243,6 +258,19 @@
     }
 
     @Test
+    public void testUpdateState_app_offGlobally() {
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.label = "App!";
+        appRow.allowBubbles = true;
+        mController.onResume(appRow, null, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+        mController.updateState(pref);
+        assertFalse(pref.isChecked());
+    }
+
+    @Test
     public void testOnPreferenceChange_on_channel() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         appRow.allowBubbles = true;
@@ -313,4 +341,23 @@
         assertFalse(appRow.allowBubbles);
         verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(false));
     }
+
+    @Test
+    public void testOnPreferenceChange_on_app_offGlobally() {
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        appRow.allowBubbles = false;
+        mController.onResume(appRow, null, null, null);
+
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+        mController.displayPreference(mScreen);
+        mController.updateState(pref);
+
+        mController.onPreferenceChange(pref, true);
+
+        assertFalse(appRow.allowBubbles);
+        verify(mBackend, never()).setAllowBubbles(any(), anyInt(), eq(true));
+        verify(mFragmentManager, times(1)).beginTransaction();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java
index 5158e82..0a0addc 100644
--- a/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java
@@ -110,6 +110,15 @@
     }
 
     @Test
+    public void testIsAvailable_app_globalOff() {
+        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+        mController.onResume(appRow, null, null, null);
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+
+        assertTrue(mController.isAvailable());
+    }
+
+    @Test
     public void testIsAvailable_defaultChannel() {
         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
         appRow.allowBubbles = true;
@@ -141,6 +150,10 @@
 
         assertEquals("On", mController.getSummary());
 
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+        assertEquals("Off", mController.getSummary());
+
+        Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
         appRow.allowBubbles = false;
         mController.onResume(appRow, null, null, null);
 
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSoundSettingsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSoundSettingsPreferenceControllerTest.java
new file mode 100644
index 0000000..a08a4d7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSoundSettingsPreferenceControllerTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+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 ZenModeSoundSettingsPreferenceControllerTest {
+
+    private Context mContext;
+    private ZenModeSoundSettingsPreferenceController mController;
+    private static final String KEY_ZEN_MODE = "zen_mode";
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mController = new ZenModeSoundSettingsPreferenceController(mContext, KEY_ZEN_MODE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_available() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
index 4dce15e..9795b55 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
@@ -16,13 +16,18 @@
 
 package com.android.settings.panel;
 
+import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
@@ -39,6 +44,9 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.android.controller.ActivityController;
 
+import java.util.Arrays;
+import java.util.List;
+
 @RunWith(RobolectricTestRunner.class)
 public class PanelSlicesAdapterTest {
 
@@ -48,8 +56,6 @@
     private FakeFeatureFactory mFakeFeatureFactory;
     private PanelFeatureProvider mPanelFeatureProvider;
 
-    private PanelSlicesAdapter mAdapter;
-
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
@@ -70,28 +76,83 @@
                                 .get()
                                 .getSupportFragmentManager()
                                 .findFragmentById(R.id.main_content));
-
-        mAdapter = new PanelSlicesAdapter(mPanelFragment, mFakePanelContent);
     }
 
     @Test
     public void onCreateViewHolder_returnsSliceRowViewHolder() {
+        final PanelSlicesAdapter adapter =
+                new PanelSlicesAdapter(mPanelFragment, mFakePanelContent);
         final ViewGroup view = new FrameLayout(mContext);
         final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
-                mAdapter.onCreateViewHolder(view, 0);
+                adapter.onCreateViewHolder(view, 0);
 
         assertThat(viewHolder.sliceView).isNotNull();
     }
 
     @Test
     public void onBindViewHolder_bindsSlice() {
+        final PanelSlicesAdapter adapter =
+                new PanelSlicesAdapter(mPanelFragment, mFakePanelContent);
         final int position = 0;
         final ViewGroup view = new FrameLayout(mContext);
         final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
-                mAdapter.onCreateViewHolder(view, 0 /* view type*/);
+                adapter.onCreateViewHolder(view, 0 /* view type*/);
 
-        mAdapter.onBindViewHolder(viewHolder, position);
+        adapter.onBindViewHolder(viewHolder, position);
 
         assertThat(viewHolder.sliceLiveData).isNotNull();
     }
+
+    @Test
+    public void nonMediaOutputIndicatorSlice_shouldAllowDividerAboveAndBelow() {
+        final PanelSlicesAdapter adapter =
+                new PanelSlicesAdapter(mPanelFragment, mFakePanelContent);
+        final int position = 0;
+        final ViewGroup view = new FrameLayout(mContext);
+        final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
+                adapter.onCreateViewHolder(view, 0 /* view type*/);
+
+        adapter.onBindViewHolder(viewHolder, position);
+
+        assertThat(viewHolder.isDividerAllowedAbove()).isTrue();
+        assertThat(viewHolder.isDividerAllowedBelow()).isTrue();
+    }
+
+    @Test
+    public void mediaOutputIndicatorSlice_shouldNotAllowDividerAbove() {
+        PanelContent mediaOutputIndicatorSlicePanelContent = new PanelContent() {
+            @Override
+            public CharSequence getTitle() {
+                return "title";
+            }
+
+            @Override
+            public List<Uri> getSlices() {
+                return Arrays.asList(
+                        MEDIA_OUTPUT_INDICATOR_SLICE_URI
+                );
+            }
+
+            @Override
+            public Intent getSeeMoreIntent() {
+                return new Intent();
+            }
+
+            @Override
+            public int getMetricsCategory() {
+                return SettingsEnums.TESTING;
+            }
+        };
+
+        final PanelSlicesAdapter adapter =
+                new PanelSlicesAdapter(mPanelFragment, mediaOutputIndicatorSlicePanelContent);
+        final int position = 0;
+        final ViewGroup view = new FrameLayout(mContext);
+        final PanelSlicesAdapter.SliceRowViewHolder viewHolder =
+                adapter.onCreateViewHolder(view, 0 /* view type*/);
+
+        adapter.onBindViewHolder(viewHolder, position);
+
+        assertThat(viewHolder.isDividerAllowedAbove()).isFalse();
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index fdd4475..6fb2c49 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -18,6 +18,7 @@
 
 import static android.app.slice.Slice.HINT_TITLE;
 import static android.app.slice.Slice.SUBTYPE_COLOR;
+import static android.app.slice.SliceItem.FORMAT_IMAGE;
 import static android.app.slice.SliceItem.FORMAT_INT;
 import static android.app.slice.SliceItem.FORMAT_TEXT;
 
@@ -284,6 +285,31 @@
         return hasText;
     }
 
+    /**
+     * Assert any slice item contains icon.
+     *
+     * @param sliceItems All slice items of a Slice.
+     * @param icon Icon for asserting.
+     */
+    public static void assertAnySliceItemContainsIcon(List<SliceItem> sliceItems, IconCompat icon) {
+        boolean hasIcon = false;
+        for (SliceItem item : sliceItems) {
+            List<SliceItem> iconItems = SliceQuery.findAll(item, FORMAT_IMAGE,
+                    (String) null /* hints */, null /* non-hints */);
+            if (iconItems == null) {
+                continue;
+            }
+
+            for (SliceItem iconItem : iconItems) {
+                if (icon.toString().equals(iconItem.getIcon().toString())) {
+                    hasIcon = true;
+                    break;
+                }
+            }
+        }
+        assertThat(hasIcon).isTrue();
+    }
+
     private static void assertKeywords(SliceMetadata metadata, SliceData data) {
         final List<String> keywords = metadata.getSliceKeywords();
         final Set<String> expectedKeywords = Arrays.stream(data.getKeywords().split(","))
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java
index 166b29b..ab5f4ea 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java
@@ -34,6 +34,7 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 
+import com.android.settingslib.core.lifecycle.Lifecycle;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,12 +54,14 @@
     private LocationManager mLocationManager;
     @Mock
     private SwitchPreference mPreference;
+    @Mock
+    private Lifecycle mLifecycle;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
-        mController = new WifiWakeupPreferenceController(mContext, mFragment);
+        mController = new WifiWakeupPreferenceController(mContext, mFragment, mLifecycle);
         mController.mLocationManager = mLocationManager;
         mController.mPreference = mPreference;
 
diff --git a/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2PPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2PPreferenceControllerTest.java
index 0968803..ec8d168 100644
--- a/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2PPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/p2p/WifiP2PPreferenceControllerTest.java
@@ -22,20 +22,24 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Service;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.location.LocationManager;
 import android.net.wifi.WifiManager;
 
 import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -57,6 +61,8 @@
     private PreferenceScreen mScreen;
     @Mock
     private Preference mWifiDirectPreference;
+    @Mock
+    private LocationManager mLocationManager;
 
     private Lifecycle mLifecycle;
     private LifecycleOwner mLifecycleOwner;
@@ -69,6 +75,7 @@
         mLifecycle = new Lifecycle(mLifecycleOwner);
         when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
         when(mScreen.findPreference(anyString())).thenReturn(mWifiDirectPreference);
+        when(mContext.getSystemService(eq(Service.LOCATION_SERVICE))).thenReturn(mLocationManager);
         mController = new WifiP2pPreferenceController(mContext, mLifecycle, mWifiManager);
     }
 
@@ -80,19 +87,21 @@
     @Test
     public void testOnResume_shouldRegisterListener() {
         mLifecycle.handleLifecycleEvent(ON_RESUME);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+        verify(mContext, times(2)).registerReceiver(
+                any(BroadcastReceiver.class), any(IntentFilter.class));
     }
 
     @Test
     public void testOnPause_shouldUnregisterListener() {
         mLifecycle.handleLifecycleEvent(ON_RESUME);
         mLifecycle.handleLifecycleEvent(ON_PAUSE);
-        verify(mContext).unregisterReceiver(any(BroadcastReceiver.class));
+        verify(mContext, times(2)).unregisterReceiver(any(BroadcastReceiver.class));
     }
 
     @Test
     public void testWifiStateChange_shouldToggleEnabledState() {
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mLocationManager.isLocationEnabled()).thenReturn(true);
 
         //Sets the preferences.
         mController.displayPreference(mScreen);
@@ -110,11 +119,17 @@
     @Test
     public void testDisplayPreference_shouldToggleEnabledState() {
         when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mLocationManager.isLocationEnabled()).thenReturn(true);
         mController.displayPreference(mScreen);
         verify(mWifiDirectPreference).setEnabled(true);
 
         when(mWifiManager.isWifiEnabled()).thenReturn(false);
         mController.displayPreference(mScreen);
         verify(mWifiDirectPreference).setEnabled(false);
+
+        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mLocationManager.isLocationEnabled()).thenReturn(false);
+        mController.displayPreference(mScreen);
+        verify(mWifiDirectPreference, times(2)).setEnabled(false);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
index 520d988..55bf2d3 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.wifi.slice;
 
+import static org.mockito.ArgumentMatchers.any;
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.doReturn;
@@ -24,6 +25,7 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.net.ConnectivityManager;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 
@@ -53,6 +55,7 @@
     private Context mContext;
     private ContentResolver mResolver;
     private WifiManager mWifiManager;
+    private ConnectivityManager mConnectivityManager;
     private ContextualWifiSlice mWifiSlice;
     private FakeFeatureFactory mFeatureFactory;
 
@@ -70,6 +73,9 @@
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
         mWifiManager.setWifiEnabled(true);
 
+        mConnectivityManager = spy(mContext.getSystemService(ConnectivityManager.class));
+        doReturn(mConnectivityManager).when(mContext).getSystemService(ConnectivityManager.class);
+
         mWifiSlice = new ContextualWifiSlice(mContext);
         mWifiSlice.sPreviouslyDisplayed = false;
     }
@@ -125,6 +131,29 @@
     }
 
     @Test
+    public void getWifiSlice_isCaptivePortal_shouldHaveTitleAndToggle() {
+        mWifiSlice.sPreviouslyDisplayed = false;
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "123";
+        mWifiManager.connect(config, null /* listener */);
+        doReturn(WifiSliceTest.makeCaptivePortalNetworkCapabilities()).when(mConnectivityManager)
+                .getNetworkCapabilities(any());
+
+        final Slice wifiSlice = mWifiSlice.getSlice();
+
+        final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice);
+        assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.wifi_settings));
+
+        final List<SliceAction> toggles = metadata.getToggles();
+        assertThat(toggles).hasSize(1);
+
+        final SliceAction primaryAction = metadata.getPrimaryAction();
+        final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_settings_wireless);
+        assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
+    }
+
+    @Test
     public void getWifiSlice_contextualWifiSlice_shouldReturnContextualWifiSliceUri() {
         mWifiSlice.sActiveUiSession = mFeatureFactory.slicesFeatureProvider.getUiSessionToken();
         mWifiSlice.sPreviouslyDisplayed = true;
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java
index 7ddbce4..30e289b 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiScanWorkerTest.java
@@ -27,6 +27,8 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
 import android.net.wifi.WifiManager;
@@ -55,6 +57,7 @@
     private Context mContext;
     private ContentResolver mResolver;
     private WifiManager mWifiManager;
+    private ConnectivityManager mConnectivityManager;
     private WifiScanWorker mWifiScanWorker;
 
     @Before
@@ -68,6 +71,7 @@
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
         mWifiManager.setWifiEnabled(true);
 
+        mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
         mWifiScanWorker = new WifiScanWorker(mContext, WIFI_SLICE_URI);
     }
 
@@ -89,7 +93,7 @@
     }
 
     @Test
-    public void SliceAccessPoint_sameState_shouldBeTheSame() {
+    public void AccessPointList_sameState_shouldBeTheSame() {
         final AccessPoint ap1 = createAccessPoint(AP_NAME, State.CONNECTED);
         final AccessPoint ap2 = createAccessPoint(AP_NAME, State.CONNECTED);
 
@@ -98,7 +102,7 @@
     }
 
     @Test
-    public void SliceAccessPoint_differentState_shouldBeDifferent() {
+    public void AccessPointList_differentState_shouldBeDifferent() {
         final AccessPoint ap1 = createAccessPoint(AP_NAME, State.CONNECTING);
         final AccessPoint ap2 = createAccessPoint(AP_NAME, State.CONNECTED);
 
@@ -107,7 +111,7 @@
     }
 
     @Test
-    public void SliceAccessPoint_differentLength_shouldBeDifferent() {
+    public void AccessPointList_differentLength_shouldBeDifferent() {
         final AccessPoint ap1 = createAccessPoint(AP_NAME, State.CONNECTED);
         final AccessPoint ap2 = createAccessPoint(AP_NAME, State.CONNECTED);
         final List<AccessPoint> list = new ArrayList<>();
@@ -116,4 +120,15 @@
 
         assertThat(mWifiScanWorker.areListsTheSame(list, Arrays.asList(ap1))).isFalse();
     }
+
+    @Test
+    public void NetworkCallback_onCapabilitiesChanged_shouldNotifyChange() {
+        final Network network = mConnectivityManager.getActiveNetwork();
+        mWifiScanWorker.registerCaptivePortalNetworkCallback(network);
+
+        mWifiScanWorker.mCaptivePortalNetworkCallback.onCapabilitiesChanged(network,
+                WifiSliceTest.makeCaptivePortalNetworkCapabilities());
+
+        verify(mResolver).notifyChange(WIFI_SLICE_URI, null);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
index b2718fc..b8c7a8c 100644
--- a/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
@@ -23,6 +23,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -30,6 +31,8 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
@@ -70,6 +73,7 @@
     private Context mContext;
     private ContentResolver mResolver;
     private WifiManager mWifiManager;
+    private ConnectivityManager mConnectivityManager;
     private WifiSlice mWifiSlice;
 
     @Before
@@ -83,6 +87,9 @@
         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
         mWifiManager.setWifiEnabled(true);
 
+        mConnectivityManager = spy(mContext.getSystemService(ConnectivityManager.class));
+        doReturn(mConnectivityManager).when(mContext).getSystemService(ConnectivityManager.class);
+
         mWifiSlice = new WifiSlice(mContext);
     }
 
@@ -227,6 +234,37 @@
     }
 
     @Test
+    public void getWifiSlice_isCaptivePortal_shouldHaveCaptivePortalItems() {
+        setWorkerResults(createAccessPoint(AP1_NAME, true, true));
+        doReturn(makeCaptivePortalNetworkCapabilities()).when(mConnectivityManager)
+                .getNetworkCapabilities(any());
+
+        final Slice wifiSlice = mWifiSlice.getSlice();
+        final List<SliceItem> sliceItems = wifiSlice.getItems();
+
+        SliceTester.assertAnySliceItemContainsTitle(sliceItems, AP1_NAME);
+        assertCaptivePortalItems(sliceItems);
+    }
+
+    private void assertCaptivePortalItems(List<SliceItem> sliceItems) {
+        final String expectedSummary = mContext.getString(mContext.getResources()
+                .getIdentifier("network_available_sign_in", "string", "android"));
+        SliceTester.assertAnySliceItemContainsSubtitle(sliceItems, expectedSummary);
+
+        final IconCompat expectedIcon = IconCompat.createWithResource(mContext,
+                R.drawable.ic_settings_accent);
+        SliceTester.assertAnySliceItemContainsIcon(sliceItems, expectedIcon);
+    }
+
+    static NetworkCapabilities makeCaptivePortalNetworkCapabilities() {
+        final NetworkCapabilities nc = new NetworkCapabilities();
+        nc.clearAll();
+        nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+        return nc;
+    }
+
+    @Test
     public void handleUriChange_updatesWifi() {
         final Intent intent = mWifiSlice.getIntent();
         intent.putExtra(android.app.slice.Slice.EXTRA_TOGGLE_STATE, true);