Merge "Disable EntityHeaderController animation for item move down issue" into sc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c4bf977..0a40c89 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -182,6 +182,7 @@
 
         <activity android:name=".Settings$CreateShortcutActivity"
                   android:exported="true"
+                  android:theme="@style/Theme.SubSettings"
                   android:label="@string/settings_shortcut">
             <intent-filter>
                 <action android:name="android.intent.action.CREATE_SHORTCUT" />
@@ -3713,6 +3714,7 @@
             android:name="Settings$GestureNavigationSettingsActivity"
             android:label="@string/gesture_settings_activity_title"
             android:exported="true"
+            android:theme="@style/Theme.SubSettings"
             android:enabled="true">
             <intent-filter android:priority="32">
                 <action android:name="android.intent.action.MAIN" />
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 48a204f..bb414ad 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -1125,22 +1125,6 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="    &lt;color name=&quot;contextual_card_stroke_color&quot;>#1f000000&lt;/color>"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="res/values/colors.xml"
-            line="106"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="    &lt;color name=&quot;switchbar_switch_track_tint&quot;>#BFFFFFFF&lt;/color>"
         errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2424,7 +2408,7 @@
         errorLine1="        android:fillColor=&quot;@color/face_intro_outline&quot;"
         errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
-            file="res/drawable/face_enroll_introduction.xml"
+            file="res/drawable/face_enroll_icon_large.xml"
             line="25"
             column="9"/>
     </issue>
@@ -4293,22 +4277,6 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
-        errorLine1="        &lt;item name=&quot;strokeColor&quot;>@color/contextual_card_stroke_color&lt;/item>"
-        errorLine2="                                 ^">
-        <location
-            file="res/values/styles.xml"
-            line="475"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="HardCodedColor"
-        severity="Error"
-        message="Avoid using hardcoded color"
-        category="Correctness"
-        priority="4"
-        summary="Using hardcoded color"
-        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="        &lt;item name=&quot;android:trackTint&quot;>@color/switchbar_switch_track_tint&lt;/item>"
         errorLine2="                                       ^">
         <location
diff --git a/res/drawable/face_enroll_introduction.xml b/res/drawable/face_enroll_icon_large.xml
similarity index 86%
rename from res/drawable/face_enroll_introduction.xml
rename to res/drawable/face_enroll_icon_large.xml
index 217b13c..578a4a9 100644
--- a/res/drawable/face_enroll_introduction.xml
+++ b/res/drawable/face_enroll_icon_large.xml
@@ -19,26 +19,27 @@
     android:width="300dp"
     android:height="300dp"
     android:viewportWidth="300"
-    android:viewportHeight="300">
+    android:viewportHeight="300"
+    android:tint="@color/face_enroll_icon_color">
 
     <path
-        android:fillColor="@color/face_intro_outline"
+        android:fillColor="#FF000000"
         android:fillType="evenOdd"
         android:pathData="M150,0C67.16,0,0,67.16,0,150s67.16,150,150,150 s150-67.16,150-150S232.84,0,150,0 M150,4c39,0,75.66,15.19,103.24,42.76C280.81,74.34,296,111,296,150s-15.19,75.66-42.76,103.24 C225.66,280.81,189,296,150,296s-75.66-15.19-103.24-42.76C19.19,225.66,4,189,4,150S19.19,74.34,46.76,46.76 C74.34,19.19,111,4,150,4" />
     <path
-        android:fillColor="?android:attr/colorAccent"
+        android:fillColor="#FF000000"
         android:fillType="evenOdd"
         android:pathData="M220,120c0,5.52-4.48,10-10,10s-10-4.48-10-10 s4.48-10,10-10S220,114.48,220,120" />
     <path
-        android:fillColor="?android:attr/colorAccent"
+        android:fillColor="#FF000000"
         android:fillType="evenOdd"
         android:pathData="M90,130c-5.52,0-10-4.48-10-10s4.48-10,10-10 s10,4.48,10,10S95.52,130,90,130" />
     <path
-        android:fillColor="?android:attr/colorAccent"
+        android:fillColor="#FF000000"
         android:fillType="evenOdd"
         android:pathData="M164.2,215.88c-3.83,3.25-8.79,5.22-14.2,5.22 c-12.13,0-22-9.87-22-22c0-0.03,0-0.06,0-0.09l-8-0.03c0,0.04,0,0.08,0,0.13c0,6.24,1.9,12.03,5.16,16.83 c5.4,7.95,14.51,13.17,24.84,13.17c1.04,0,2.06-0.05,3.08-0.15c6.18-0.63,11.81-3.14,16.3-6.95L164.2,215.88z" />
     <path
-        android:fillColor="?android:attr/colorAccent"
+        android:fillColor="#FF000000"
         android:fillType="evenOdd"
         android:pathData="M 153 140 L 153 166 L 137 166 L 137 174 L 161 174 L 161 140 Z" />
 </vector>
\ No newline at end of file
diff --git a/res/drawable/ic_no_internet_airplane.xml b/res/drawable/ic_no_internet_airplane.xml
deleted file mode 100644
index 3b22811..0000000
--- a/res/drawable/ic_no_internet_airplane.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-    Copyright (C) 2021 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.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10c0.34,0 0.68,-0.02 1.01,-0.05V20h-1v-0.04c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96H13v-2H9.66c-0.09,-0.66 -0.16,-1.32 -0.16,-2s0.07,-1.35 0.16,-2H21.8C20.87,5.44 16.83,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56C16.43,5.07 17.96,6.35 18.92,8zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82C10.52,6.57 11.17,5.24 12,4.04zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2s0.06,1.34 0.14,2H4.26zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56C7.57,18.93 6.04,17.66 5.08,16zM8.03,8H5.08c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8z"
-        android:fillAlpha="0.3"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M22,19.3v-0.9l-3.37,-2.25v-2.47C18.63,13.3 18.35,13 18,13s-0.63,0.3 -0.63,0.68v2.47L14,18.4v0.9l3.37,-1.12v2.48l-0.84,0.68V22L18,21.55L19.47,22v-0.67l-0.84,-0.68v-2.48L22,19.3z"/>
-</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_no_internet_unavailable.xml b/res/drawable/ic_no_internet_unavailable.xml
new file mode 100644
index 0000000..049034a
--- /dev/null
+++ b/res/drawable/ic_no_internet_unavailable.xml
@@ -0,0 +1,28 @@
+<!--
+    Copyright (C) 2021 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="M2,12C2,6.48 6.47,2 11.99,2C17.52,2 22,6.48 22,12c0,0.34 -0.02,0.67 -0.05,1h-2.02c0.04,-0.33 0.07,-0.66 0.07,-1c0,-0.69 -0.1,-1.36 -0.26,-2h-3.38c0.08,0.66 0.14,1.32 0.14,2c0,0.34 -0.01,0.67 -0.04,1h-2.01c0.03,-0.33 0.05,-0.66 0.05,-1c0,-0.68 -0.07,-1.35 -0.16,-2H9.66c-0.09,0.65 -0.16,1.32 -0.16,2s0.07,1.34 0.16,2H13v2h-2.91c0.43,1.43 1.08,2.76 1.91,3.96V20h1v1.95C12.67,21.98 12.33,22 11.99,22C6.47,22 2,17.52 2,12zM15.97,8h2.95c-0.96,-1.65 -2.49,-2.93 -4.33,-3.56C15.19,5.55 15.65,6.75 15.97,8zM13.91,8C13.48,6.57 12.83,5.24 12,4.04c-0.83,1.2 -1.48,2.53 -1.91,3.96H13.91zM4,12c0,0.69 0.1,1.36 0.26,2h3.38c-0.08,-0.66 -0.14,-1.32 -0.14,-2s0.06,-1.34 0.14,-2H4.26C4.1,10.64 4,11.31 4,12zM8.03,16H5.08c0.96,1.66 2.49,2.93 4.33,3.56C8.81,18.45 8.35,17.25 8.03,16zM5.08,8h2.95c0.32,-1.25 0.78,-2.45 1.38,-3.56C7.57,5.07 6.04,6.34 5.08,8z"
+        android:fillAlpha="0.3"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+</vector>
diff --git a/res/drawable/ic_password.xml b/res/drawable/ic_password.xml
index 1924f6e..341e544 100644
--- a/res/drawable/ic_password.xml
+++ b/res/drawable/ic_password.xml
@@ -20,15 +20,15 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0">
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M21.5,9.39l-1.63,0l0.81,-1.42l-0.86,-0.5l-0.82,1.42l-0.82,-1.42l-0.86,0.5l0.81,1.42l-1.63,0l0,1l1.63,0l-0.81,1.41l0.86,0.5l0.82,-1.41l0.82,1.41l0.86,-0.5l-0.81,-1.41l1.63,0z" />
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M13.68,7.97l-0.86,-0.5l-0.82,1.42l-0.82,-1.42l-0.86,0.5l0.81,1.42l-1.63,0l0,1l1.63,0l-0.81,1.41l0.86,0.5l0.82,-1.41l0.82,1.41l0.86,-0.5l-0.81,-1.41l1.63,0l0,-1l-1.63,0z" />
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M6.68,7.97l-0.86,-0.5l-0.82,1.42l-0.82,-1.42l-0.86,0.5l0.81,1.42l-1.63,0l0,1l1.63,0l-0.81,1.41l0.86,0.5l0.82,-1.41l0.82,1.41l0.86,-0.5l-0.81,-1.41l1.63,0l0,-1l-1.63,0z" />
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M21,17.89H3c-0.28,0 -0.5,-0.22 -0.5,-0.5v-1c0,-0.28 0.22,-0.5 0.5,-0.5h18c0.28,0 0.5,0.22 0.5,0.5v1C21.5,17.66 21.28,17.89 21,17.89z" />
 </vector>
diff --git a/res/drawable/ic_pattern.xml b/res/drawable/ic_pattern.xml
index 3320aea..788eaa7 100644
--- a/res/drawable/ic_pattern.xml
+++ b/res/drawable/ic_pattern.xml
@@ -20,18 +20,18 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0">
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M4,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M4,12m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M20,12m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0" />
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M20,18c-0.93,0 -1.7,0.64 -1.93,1.5h-4.14c-0.22,-0.86 -1,-1.5 -1.93,-1.5s-1.7,0.64 -1.93,1.5H5.93c-0.05,-0.18 -0.12,-0.35 -0.21,-0.51l5.28,-5.28C11.29,13.89 11.63,14 12,14c1.1,0 2,-0.9 2,-2c0,-0.37 -0.11,-0.71 -0.28,-1.01l5.28,-5.28C19.29,5.89 19.63,6 20,6c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2s-2,0.9 -2,2c0,0.37 0.11,0.71 0.28,1.01l-5.28,5.28C12.71,10.11 12.37,10 12,10c-1.1,0 -2,0.9 -2,2c0,0.37 0.11,0.71 0.28,1.01l-5.28,5.28C4.71,18.11 4.37,18 4,18c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c0.93,0 1.7,-0.64 1.93,-1.5h4.14c0.22,0.86 1,1.5 1.93,1.5s1.7,-0.64 1.93,-1.5h4.14c0.22,0.86 1,1.5 1.93,1.5c1.1,0 2,-0.9 2,-2S21.1,18 20,18z" />
 </vector>
diff --git a/res/drawable/ic_pin.xml b/res/drawable/ic_pin.xml
index d8c3ae3..682e934 100644
--- a/res/drawable/ic_pin.xml
+++ b/res/drawable/ic_pin.xml
@@ -20,6 +20,6 @@
     android:viewportHeight="24.0"
     android:viewportWidth="24.0">
     <path
-        android:fillColor="?attr/colorAccent"
+        android:fillColor="?android:attr/colorAccent"
         android:pathData="M20,4L4,4A2,2 0,0 0,2 6L2,18a2,2 0,0 0,2 2L20,20a2,2 0,0 0,2 -2L22,6A2,2 0,0 0,20 4ZM7.1,15L5.9,15L5.9,10.2L4.7,10.2L4.7,9L7.1,9v6ZM13.2,11.4A1.2,1.2 0,0 1,12 12.6L10.8,12.6v1.2h2.4L13.2,15L9.6,15L9.6,12.6a1.2,1.2 0,0 1,1.2 -1.2L12,11.4L12,10.2L9.6,10.2L9.6,9L12,9a1.2,1.2 0,0 1,1.2 1.2v1.2ZM19.3,11.1a0.9,0.9 0,0 1,-0.9 0.9,0.9 0.9,0 0,1 0.9,0.9v0.9A1.2,1.2 0,0 1,18.1 15L15.7,15L15.7,13.8h2.4L18.1,12.6L16.9,12.6L16.9,11.4h1.2L18.1,10.2L15.7,10.2L15.7,9h2.4a1.2,1.2 0,0 1,1.2 1.2v0.9Z" />
 </vector>
diff --git a/res/drawable/ic_power_settings.xml b/res/drawable/ic_power_settings.xml
new file mode 100644
index 0000000..b56e332
--- /dev/null
+++ b/res/drawable/ic_power_settings.xml
@@ -0,0 +1,26 @@
+<!--
+    Copyright (C) 2021 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:pathData="M11,2h2v10h-2zM18.37,5.64l-1.41,1.41c2.73,2.73 2.72,7.16 -0.01,9.89 -2.73,2.73 -7.17,2.73 -9.89,0.01 -2.73,-2.73 -2.74,-7.18 -0.01,-9.91l-1.41,-1.4c-3.51,3.51 -3.51,9.21 0.01,12.73 3.51,3.51 9.21,3.51 12.72,-0.01 3.51,-3.51 3.51,-9.2 0,-12.72z"
+        android:fillColor="@android:color/white"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_upload.xml b/res/drawable/ic_upload.xml
new file mode 100644
index 0000000..f95ffd4
--- /dev/null
+++ b/res/drawable/ic_upload.xml
@@ -0,0 +1,25 @@
+<!--
+  ~ Copyright (C) 2021 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="24.0dp"
+    android:height="24.0dp"
+    android:tint="?android:attr/colorControlNormal"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M18,15v3H6v-3H4v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3H18z M7,9l1.41,1.41L11,7.83V16h2V7.83l2.59,2.58L17,9l-5-5L7,9z" />
+</vector>
diff --git a/res/drawable/progress_horizontal.xml b/res/drawable/progress_horizontal.xml
deleted file mode 100644
index f2a4cc4..0000000
--- a/res/drawable/progress_horizontal.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-
-<layer-list
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-
-    <item
-        android:id="@android:id/background">
-        <shape>
-            <corners android:radius="8dp" />
-            <solid android:color="?androidprv:attr/colorSurfaceVariant" />
-        </shape>
-    </item>
-
-    <item
-        android:id="@android:id/progress">
-        <clip>
-            <shape>
-                <corners android:radius="8dp" />
-                <solid android:color="?android:attr/textColorPrimary" />
-            </shape>
-        </clip>
-    </item>
-</layer-list>
diff --git a/res/layout-land/request_manage_credentials.xml b/res/layout-land/request_manage_credentials.xml
new file mode 100644
index 0000000..0c7bded
--- /dev/null
+++ b/res/layout-land/request_manage_credentials.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+    android:weightSum="2">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        style="@style/RequestManageCredentialsHeaderLandscape">
+
+        <ScrollView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:scrollbars="none">
+
+            <LinearLayout
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+
+                <ImageView
+                    android:id="@+id/credential_management_app_icon"
+                    android:layout_width="48dp"
+                    android:layout_height="48dp"
+                    android:contentDescription="@null" />
+
+                <TextView
+                    android:id="@+id/credential_management_app_title"
+                    style="@style/RequestManageCredentialsTitle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+
+                <TextView
+                    android:id="@+id/credential_management_app_description"
+                    style="@style/RequestManageCredentialsDescription"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/request_manage_credentials_description" />
+
+            </LinearLayout>
+
+        </ScrollView>
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_weight="1">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <androidx.coordinatorlayout.widget.CoordinatorLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:clipChildren="true">
+
+                <RelativeLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent">
+
+                    <androidx.recyclerview.widget.RecyclerView
+                        android:id="@+id/apps_list"
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent" />
+
+                    <LinearLayout
+                        android:id="@+id/button_panel"
+                        style="@style/RequestManageCredentialsButtonPanel"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content">
+
+                        <Button
+                            android:id="@+id/dont_allow_button"
+                            style="@style/RequestManageCredentialsDontAllowButton"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/request_manage_credentials_dont_allow" />
+
+                        <Space
+                            android:layout_width="0dp"
+                            android:layout_height="0dp"
+                            android:layout_weight="1"
+                            android:visibility="invisible" />
+
+                        <Button
+                            android:id="@+id/allow_button"
+                            style="@style/RequestManageCredentialsAllowButton"
+                            android:theme="@style/RoundedCornerButtonTheme"
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:text="@string/request_manage_credentials_allow" />
+
+                    </LinearLayout>
+
+                </RelativeLayout>
+
+                <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
+                    android:id="@+id/extended_fab"
+                    style="@style/RequestManageCredentialsFab"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/request_manage_credentials_more"
+                    android:theme="@style/Theme.CollapsingToolbar.Settings"
+                    app:backgroundTint="?android:attr/colorAccent"
+                    app:elevation="3dp"
+                    app:icon="@drawable/ic_arrow_downward"
+                    app:iconTint="?android:attr/textColorPrimary"
+                    app:layout_anchor="@id/apps_list"
+                    app:layout_anchorGravity="bottom|center" />
+
+            </androidx.coordinatorlayout.widget.CoordinatorLayout>
+
+        </RelativeLayout>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/battery_saver_schedule_percentage_seekbar.xml b/res/layout/battery_saver_schedule_percentage_seekbar.xml
new file mode 100644
index 0000000..7862822
--- /dev/null
+++ b/res/layout/battery_saver_schedule_percentage_seekbar.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<!-- Layout used by BatterySaverScheduleSeekBarController for the seekbar widget. -->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginVertical="6dp"
+    android:gravity="center_vertical"
+    android:orientation="vertical"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+  <TextView
+      android:id="@android:id/title"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:ellipsize="marquee"
+      android:layout_marginStart="18dp"
+      android:singleLine="true"
+      android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+      android:textColor="?android:attr/textColorPrimary" />
+
+  <com.android.settings.widget.DefaultIndicatorSeekBar
+      android:id="@*android:id/seekbar"
+      style="@android:style/Widget.Material.SeekBar.Discrete"
+      android:layout_width="match_parent"
+      android:layout_height="48dp"
+      android:layout_marginStart="18dp"
+      android:layout_marginEnd="9dp" />
+
+</LinearLayout>
diff --git a/res/layout/card_preference_layout.xml b/res/layout/card_preference_layout.xml
index bcaeb86..90e3388 100644
--- a/res/layout/card_preference_layout.xml
+++ b/res/layout/card_preference_layout.xml
@@ -29,6 +29,6 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginStart="-8dp"
-            layout="@layout/preference_material" />
+            layout="@layout/settingslib_preference" />
     </com.google.android.material.card.MaterialCardView>
 </FrameLayout>
diff --git a/res/layout/face_enroll_education.xml b/res/layout/face_enroll_education.xml
index 0149479..53a584e 100644
--- a/res/layout/face_enroll_education.xml
+++ b/res/layout/face_enroll_education.xml
@@ -38,7 +38,7 @@
         <FrameLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginVertical="12dp">
+            android:layout_marginTop="-32dp">
 
             <com.google.android.setupdesign.view.IllustrationVideoView
                 android:id="@+id/illustration_default"
@@ -51,11 +51,13 @@
             <com.airbnb.lottie.LottieAnimationView
                 android:id="@+id/illustration_lottie"
                 android:layout_width="match_parent"
-                android:layout_height="340dp"
-                android:scaleType="fitCenter"
-                android:visibility="invisible"
+                android:layout_height="400dp"
+                android:layout_marginTop="-48dp"
+                android:scaleType="centerCrop"
+                android:visibility="gone"
                 app:lottie_autoPlay="true"
-                app:lottie_loop="true" />
+                app:lottie_loop="true"
+                app:lottie_speed="1.5" />
 
             <ImageView
                 android:id="@+id/illustration_accessibility"
@@ -63,7 +65,7 @@
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
                 android:visibility="invisible"
-                android:background="@drawable/face_enroll_introduction"/>
+                android:background="@drawable/face_enroll_icon_large"/>
 
         </FrameLayout>
 
diff --git a/res/layout/face_enroll_finish.xml b/res/layout/face_enroll_finish.xml
index d3c0479..30a6957 100644
--- a/res/layout/face_enroll_finish.xml
+++ b/res/layout/face_enroll_finish.xml
@@ -47,7 +47,7 @@
                     android:layout_width="match_parent"
                     android:layout_height="match_parent"
                     android:contentDescription="@null"
-                    android:src="@drawable/face_enroll_introduction" />
+                    android:src="@drawable/face_enroll_icon_large" />
 
             </com.google.android.setupdesign.view.FillContentLayout>
 
diff --git a/res/layout/manage_apps_filter_spinner.xml b/res/layout/manage_apps_filter_spinner.xml
new file mode 100644
index 0000000..8283bb8
--- /dev/null
+++ b/res/layout/manage_apps_filter_spinner.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2021 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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@android:color/transparent">
+
+    <com.android.settingslib.widget.settingsspinner.SettingsSpinner
+        android:id="@+id/filter_spinner"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginBottom="8dp"
+        android:theme="@style/Widget.PopupWindow.Settings"/>
+</FrameLayout>
diff --git a/res/layout/preference_animated_image.xml b/res/layout/preference_animated_image.xml
index e7d9b52..0ab8adf 100644
--- a/res/layout/preference_animated_image.xml
+++ b/res/layout/preference_animated_image.xml
@@ -31,4 +31,14 @@
         android:focusable="false"
         android:clickable="false"
         android:adjustViewBounds="true"/>
+
+    <com.airbnb.lottie.LottieAnimationView
+        android:id="@+id/lottie_view"
+        android:layout_width="412dp"
+        android:layout_height="300dp"
+        android:layout_gravity="center"
+        android:background="@drawable/protection_background"
+        android:scaleType="fitCenter"
+        android:adjustViewBounds="true"
+        android:clipToOutline="true"/>
 </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/preference_labeled_slider.xml b/res/layout/preference_labeled_slider.xml
new file mode 100644
index 0000000..42ad988
--- /dev/null
+++ b/res/layout/preference_labeled_slider.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:gravity="center_vertical"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingStart="56dp"
+    android:paddingEnd="8dp"
+    android:paddingTop="16dp"
+    android:paddingBottom="8dp">
+
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_alignParentTop="true"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        android:singleLine="true"
+        android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+        android:textColor="?android:attr/textColorPrimary" />
+
+    <SeekBar
+        android:id="@*android:id/seekbar"
+        android:layout_below="@android:id/title"
+        android:layout_gravity="center_vertical"
+        android:layout_width="match_parent"
+        android:layout_height="70dp"
+        android:layout_marginTop="-20dp"
+        android:layout_marginBottom="-28dp"
+        style="@android:style/Widget.Material.SeekBar.Discrete" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@*android:id/seekbar"
+        android:paddingBottom="8dp"
+        android:orientation="horizontal">
+
+        <TextView
+            android:id="@android:id/text1"
+            android:layout_marginStart="16dp"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|top"
+            android:gravity="start"
+            android:layout_weight="1"/>
+
+        <TextView
+            android:id="@android:id/text2"
+            android:layout_marginEnd="16dp"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end|top"
+            android:gravity="end"
+            android:layout_weight="1"/>
+
+    </LinearLayout>
+
+</RelativeLayout>
+
diff --git a/res/layout/preference_volume_slider.xml b/res/layout/preference_volume_slider.xml
index 018506f..7c07d5e 100644
--- a/res/layout/preference_volume_slider.xml
+++ b/res/layout/preference_volume_slider.xml
@@ -25,13 +25,28 @@
     android:clickable="false"
     android:orientation="horizontal">
 
-    <include layout="@layout/settingslib_icon_frame"/>
+    <LinearLayout
+        android:id="@+id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:minWidth="44dp"
+        android:gravity="start|center_vertical"
+        android:orientation="horizontal"
+        android:paddingEnd="12dp"
+        android:paddingTop="4dp"
+        android:paddingBottom="4dp">
+        <com.android.internal.widget.PreferenceImageView
+            android:id="@android:id/icon"
+            android:layout_width="24dp"
+            android:layout_height="24dp"/>
+    </LinearLayout>
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:paddingTop="16dp">
+        android:layout_marginTop="8dp"
+        android:layout_marginBottom="8dp">
 
         <LinearLayout
             android:layout_width="match_parent"
diff --git a/res/layout/preference_widget_seekbar_settings.xml b/res/layout/preference_widget_seekbar_settings.xml
new file mode 100644
index 0000000..9893a1b
--- /dev/null
+++ b/res/layout/preference_widget_seekbar_settings.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Layout used by SeekBarPreference for the seekbar widget style. -->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginTop="6dp"
+    android:layout_marginBottom="6dp"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+    <TextView
+        android:id="@android:id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:ellipsize="marquee"
+        android:fadingEdge="horizontal"
+        android:paddingStart="56dp"
+        android:paddingEnd="8dp"
+        android:singleLine="true"
+        android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+        android:textColor="?android:attr/textColorPrimary" />
+
+    <TextView
+        android:id="@android:id/summary"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignStart="@android:id/title"
+        android:layout_below="@android:id/title"
+        android:maxLines="4"
+        android:paddingStart="56dp"
+        android:paddingEnd="8dp"
+        android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+        android:textColor="?android:attr/textColorSecondary" />
+
+    <com.android.settings.widget.DefaultIndicatorSeekBar
+        android:id="@*android:id/seekbar"
+        style="@android:style/Widget.Material.SeekBar.Discrete"
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:layout_alignParentEnd="true"
+        android:layout_below="@android:id/summary"
+        android:paddingStart="56dp"
+        android:paddingEnd="12dp" />
+
+</RelativeLayout>
diff --git a/res/layout/remove_account_button.xml b/res/layout/remove_account_button.xml
index 6b47c37..070ecc5 100644
--- a/res/layout/remove_account_button.xml
+++ b/res/layout/remove_account_button.xml
@@ -20,13 +20,14 @@
     android:orientation="vertical">
 
     <Button
-      android:id="@+id/button"
-      android:text="@string/remove_account_label"
-      android:layout_width="wrap_content"
-      android:layout_height="wrap_content"
-      android:layout_gravity="center_horizontal"
-      android:layout_marginTop="20dip"
-      android:layout_marginBottom="12dip"
-      android:gravity="center" />
+        android:id="@+id/button"
+        android:text="@string/remove_account_label"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:layout_marginTop="20dp"
+        android:layout_marginBottom="12dp"
+        android:gravity="center"
+        style="@style/ActionPrimaryButton" />
 
 </LinearLayout>
diff --git a/res/layout/request_manage_credentials.xml b/res/layout/request_manage_credentials.xml
index ee3751c..c8167b6 100644
--- a/res/layout/request_manage_credentials.xml
+++ b/res/layout/request_manage_credentials.xml
@@ -52,6 +52,7 @@
             <Button
                 android:id="@+id/allow_button"
                 style="@style/RequestManageCredentialsAllowButton"
+                android:theme="@style/RoundedCornerButtonTheme"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/request_manage_credentials_allow"/>
@@ -70,8 +71,8 @@
         app:layout_anchorGravity="bottom|center"
         app:elevation="3dp"
         app:icon="@drawable/ic_arrow_downward"
-        app:iconTint="?android:attr/colorAccent"
-        app:backgroundTint="?android:attr/colorPrimary"
+        app:iconTint="?android:attr/textColorPrimary"
+        app:backgroundTint="?android:attr/colorAccent"
         android:theme="@style/Theme.CollapsingToolbar.Settings"/>
 
 </androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/res/values-mcc234/strings.xml b/res/values-mcc234/strings.xml
new file mode 100644
index 0000000..f7d0d33
--- /dev/null
+++ b/res/values-mcc234/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="cell_broadcast_settings">Emergency alerts</string>
+</resources>
\ No newline at end of file
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 3cc23c3..f262104 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -27,7 +27,7 @@
     <color name="notification_importance_button_selected">#AECBFA</color> <!-- material blue 200 -->
     <color name="notification_importance_button_unselected">#5F6368</color>
     <color name="notification_history_background">#202124</color>
-    <color name="face_intro_outline">?android:attr/colorAccent</color>
+
     <!-- Palette list preference colors. -->
     <color name="palette_list_gradient_background">@android:color/black</color>
     <color name="palette_list_color_red">@color/palette_list_dark_mode_color_red</color>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index a5611f0..573d906 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -157,6 +157,13 @@
         <attr name="textOff" format="reference" />
     </declare-styleable>
 
+    <!-- For LabeledSeekBarPreference -->
+    <declare-styleable name="LabeledSeekBarPreference">
+        <attr name="textStart" format="reference" />
+        <attr name="textEnd" format="reference" />
+        <attr name="tickMark" format="reference" />
+    </declare-styleable>
+
     <declare-styleable name="TintDrawable">
         <attr name="android:tint" />
         <attr name="android:drawable" />
diff --git a/res/values/colors.xml b/res/values/colors.xml
index edef6ef..db525d5 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -103,9 +103,7 @@
     <color name="homepage_wallpaper_background">#E51AD1</color>
     <color name="homepage_notification_background">#DD4C9D</color>
 
-    <color name="contextual_card_stroke_color">#1f000000</color>
     <color name="contextual_card_dismissal_background">@*android:color/material_grey_100</color>
-    <color name="contextual_card_background">@*android:color/background_device_default_light</color>
     <!-- End of dashboard/homepage icon background colors -->
 
     <color name="switchbar_background_color">@*android:color/material_grey_600</color>
@@ -152,7 +150,7 @@
     <!-- Search bar background color -->
     <color name="search_bar_background">?androidprv:attr/colorSurfaceHighlight</color>
 
-    <color name="face_intro_outline">#ffdadce0</color>
+    <color name="face_enroll_icon_color">#42a5f5</color> <!-- Blue 400 -->
 
     <color name="back_gesture_indicator">#4182ef</color>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 05d2b4f..90708da 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -856,8 +856,6 @@
     <!-- Button text in face settings which lets the user enroll their face [CHAR LIMIT=40] -->
     <string name="security_settings_face_settings_enroll">Set up Face Unlock</string>
     <!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
-    <string name="security_settings_face_settings_top_intro">Use Face Unlock to unlock your device, sign in to apps, and confirm payments.</string>
-    <!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
     <string name="security_settings_face_settings_footer">Use your face to unlock your phone or for authentication in apps, like when you sign in or approve a purchase.\n\nKeep in mind:\nYou can only have one face set up at a time. To add another face, delete the current one.\n\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face.\n\nYour phone can be unlocked by someone who looks a lot like you, like an identical sibling.</string>
     <!-- Text shown in face settings explaining what your face can be used for. Used when attention checking is not supported. [CHAR LIMIT=NONE] -->
     <string name="security_settings_face_settings_footer_attention_not_supported">Use your face to unlock your phone or for authentication in apps, like when you sign in or approve a purchase.\n\nKeep in mind:\nYou can only have one face set up at a time. To add another face, delete the current one.\n\nLooking at the phone can unlock it when you don\u2019t intend to.\n\nYour phone can be unlocked by someone else if it\u2019s held up to your face, even if your eyes are closed.\n\nYour phone can be unlocked by someone who looks a lot like you, like an identical sibling.</string>
@@ -5179,7 +5177,7 @@
     <!-- Settings title for accessibility settings screen -->
     <string name="accessibility_settings_title">Accessibility settings</string>
     <!-- Summary for Accessibility settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
-    <string name="accessibility_settings_summary">Screen readers, interaction controls</string>
+    <string name="accessibility_settings_summary">Display, interaction, audio</string>
     <!-- Settings title for a brief version of Vision-Related Accessibility Settings. Displayed in Setup Wizard only. [CHAR LIMIT=35] -->
     <string name="vision_settings_title">Vision Settings</string>
     <!-- Settings description for a brief version of Vision-Related Accessibility Settings. Tells the user that they can adjust these settings now to help them through the remainder of the Setup Wizard and that they can later be changed in Settings. Displayed in Setup Wizard only. [CHAR LIMIT=none] -->
@@ -6791,9 +6789,9 @@
     <string name="cert_not_installed">Certificate not installed</string>
 
     <!-- Title of screen shown to the user when an app requests to manage the user's KeyChain credentials [CHAR LIMIT=NONE] -->
-    <string name="request_manage_credentials_title">Allow <xliff:g id="app_name" example="Ping">%s</xliff:g> to install certificates on this device?</string>
+    <string name="request_manage_credentials_title">Allow <b><xliff:g id="app_name" example="Ping">^1</xliff:g></b> to install certificates on this device?</string>
     <!-- Description of screen shown to the user when an app requests to manage the user's KeyChain credentials [CHAR LIMIT=NONE] -->
-    <string name="request_manage_credentials_description">These certificates will identify you to the apps and URLs below</string>
+    <string name="request_manage_credentials_description">These certificates will verify you by sharing your device\u2019s unique ID with the apps and URLs below</string>
     <!-- Label for button to not allow an app to manage the user's KeyChain credentials [CHAR_LIMIT=50] -->
     <string name="request_manage_credentials_dont_allow">Don\u2019t allow</string>
     <!-- Label for button to allow an app to manage the user's KeyChain credentials [CHAR_LIMIT=50] -->
@@ -6805,7 +6803,9 @@
     <!-- Summary if there is no certificate management app [CHAR_LIMIT=NONE] -->
     <string name="no_certificate_management_app">None</string>
     <!-- Summary of preference if there is a certificate management app [CHAR LIMIT=NONE] -->
-    <string name="certificate_management_app_description">Certificates installed by this app identify you to the apps and URLs below</string>
+    <string name="certificate_management_app_description">Certificates will verify you when you use the apps and URLs below</string>
+    <!-- Label for button to uninstall all certificates installed by the credential management app [CHAR LIMIT=30] -->
+    <string name="uninstall_certs_credential_management_app">Uninstall certificates</string>
     <!-- Label for button to remove the credential management app [CHAR LIMIT=30] -->
     <string name="remove_credential_management_app">Remove</string>
     <!-- List item found in the credential management app's authentication policy [CHAR LIMIT=NONE] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 6021a7c..63ea86e 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -13,7 +13,8 @@
      limitations under the License.
 -->
 
-<resources>
+<resources
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
 
     <style name="Widget.ActionBar.Base"
            parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid"/>
@@ -404,12 +405,6 @@
         <item name="android:progressDrawable">@drawable/ring_progress</item>
     </style>
 
-    <style name="HorizontalProgressBarStyle"
-           parent="android:style/Widget.Material.ProgressBar.Horizontal">
-        <item name="android:progressDrawable">@drawable/progress_horizontal</item>
-        <item name="android:scaleY">0.5</item>
-    </style>
-
     <style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button.Colored">
         <item name="android:theme">@style/RoundedCornerThemeOverlay</item>
     </style>
@@ -417,6 +412,8 @@
 
     <style name="RoundedCornerThemeOverlay">
         <item name="android:buttonCornerRadius">24dp</item>
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
     </style>
 
     <style name="LockPatternContainerStyle">
@@ -470,11 +467,9 @@
         <item name="android:layout_marginBottom">@dimen/contextual_card_vertical_margin</item>
         <item name="android:layout_marginStart">@dimen/contextual_card_side_margin</item>
         <item name="android:layout_marginEnd">@dimen/contextual_card_side_margin</item>
-        <item name="cardBackgroundColor">@color/contextual_card_background</item>
+        <item name="cardBackgroundColor">?androidprv:attr/colorSurface</item>
         <item name="cardCornerRadius">@dimen/contextual_card_corner_radius</item>
         <item name="cardElevation">0dp</item>
-        <item name="strokeColor">@color/contextual_card_stroke_color</item>
-        <item name="strokeWidth">1dp</item>
         <item name="rippleColor">?android:attr/colorControlHighlight</item>
     </style>
 
@@ -799,10 +794,19 @@
         <item name="android:background">?android:colorBackground</item>
     </style>
 
+    <style name="RoundedCornerButtonTheme">
+        <item name="android:buttonCornerRadius">50dp</item>
+        <item name="android:paddingStart">20dp</item>
+        <item name="android:paddingEnd">20dp</item>
+        <item name="android:paddingTop">18dp</item>
+        <item name="android:paddingBottom">18dp</item>
+    </style>
+
     <style name="RequestManageCredentialsAllowButton" parent="@style/ActionPrimaryButton">
         <item name="android:fontFamily">google-sans-medium</item>
         <item name="android:textSize">14sp</item>
         <item name="android:textAllCaps">false</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
     <style name="RequestManageCredentialsDontAllowButton"
@@ -810,13 +814,13 @@
         <item name="android:fontFamily">google-sans-medium</item>
         <item name="android:textSize">14sp</item>
         <item name="android:textAllCaps">false</item>
-        <item name="android:textColor">?android:attr/colorAccent</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
     <style name="RequestManageCredentialsFab">
         <item name="android:textSize">14sp</item>
         <item name="android:textAllCaps">false</item>
-        <item name="android:textColor">?android:attr/colorAccent</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:layout_marginBottom">12dp</item>
     </style>
 
@@ -828,6 +832,13 @@
         <item name="android:orientation">vertical</item>
     </style>
 
+    <style name="RequestManageCredentialsHeaderLandscape">
+        <item name="android:paddingStart">24dp</item>
+        <item name="android:paddingEnd">24dp</item>
+        <item name="android:paddingTop">24dp</item>
+        <item name="android:paddingBottom">24dp</item>
+    </style>
+
     <style name="RequestManageCredentialsTitle">
         <item name="android:layout_marginTop">24dp</item>
         <item name="android:textSize">36sp</item>
@@ -838,6 +849,7 @@
         <item name="android:layout_marginTop">24dp</item>
         <item name="android:textSize">18sp</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:alpha">0.7</item>
     </style>
 
     <style name="AppAuthenticationPolicyItem">
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index 620eec6..1c8d015 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -23,6 +23,7 @@
         <item name="apnPreferenceStyle">@style/ApnPreference</item>
         <item name="cardPreferenceStyle">@style/CardPreference</item>
         <item name="slicePreferenceStyle">@style/SlicePreference</item>
+        <item name="seekBarPreferenceStyle">@style/SettingsSeekBarPreference</item>
         <item name="twoStateButtonPreferenceStyle">@style/TwoStateButtonPreference</item>
         <item name="preferenceFragmentCompatStyle">@style/SettingsPreferenceFragmentStyle</item>
     </style>
@@ -43,6 +44,10 @@
         <item name="android:layout">@layout/slice_preference_layout</item>
     </style>
 
+    <style name="SettingsSeekBarPreference" parent="@style/Preference.Material">
+        <item name="android:layout">@layout/preference_widget_seekbar_settings</item>
+    </style>
+
     <style name="SyncSwitchPreference" parent="@style/SettingsSwitchPreference.SettingsLib">
         <item name="android:widgetLayout">@layout/preference_widget_sync_toggle</item>
     </style>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index df7d433..4c5cdb7 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -32,7 +32,6 @@
         <item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
         <item name="android:navigationBarColor">@android:color/transparent</item>
         <item name="android:datePickerDialogTheme">@style/PickerDialogTheme.Settings</item>
-        <item name="android:progressBarStyleHorizontal">@style/HorizontalProgressBarStyle</item>
 
         <item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
         <item name="face_layout_theme">@style/FaceLayoutTheme</item>
diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml
index 47ea896..02b1c7d 100644
--- a/res/xml/accessibility_button_settings.xml
+++ b/res/xml/accessibility_button_settings.xml
@@ -53,7 +53,7 @@
         android:persistent="false"
         settings:controller="com.android.settings.accessibility.FloatingMenuFadePreferenceController"/>
 
-    <com.android.settingslib.RestrictedSeekBarPreference
+    <com.android.settings.widget.SeekBarPreference
         android:key="accessibility_button_opacity"
         android:title="@string/accessibility_button_opacity_title"
         android:persistent="false"
diff --git a/res/xml/credential_management_app_fragment.xml b/res/xml/credential_management_app_fragment.xml
index d4b61ac..7a5403b 100644
--- a/res/xml/credential_management_app_fragment.xml
+++ b/res/xml/credential_management_app_fragment.xml
@@ -27,19 +27,11 @@
         android:order="-10000"
         settings:controller="com.android.settings.security.CredentialManagementAppHeaderController"/>
 
-    <com.android.settingslib.widget.TopIntroPreference
-        android:key="top_intro_request_manage_credentials"
-        android:order="-9999"
-        android:title="@string/request_manage_credentials_description"
-        settings:searchable="false"/>
-
     <!-- Buttons -->
     <com.android.settingslib.widget.ActionButtonsPreference
         android:key="buttons"
         android:selectable="true"
         android:order="-9998"
-        settings:allowDividerAbove="true"
-        settings:allowDividerBelow="true"
         settings:controller="com.android.settings.security.CredentialManagementAppButtonsController"/>
 
     <!-- Authentication Policy -->
@@ -47,7 +39,6 @@
         android:key="authentication_policy"
         android:layout="@layout/preference_category_no_label"
         android:title="@string/summary_placeholder"
-        settings:allowDividerAbove="true"
         settings:controller="com.android.settings.security.CredentialManagementAppPolicyController"/>
 
 </PreferenceScreen>
diff --git a/res/xml/gesture_navigation_settings.xml b/res/xml/gesture_navigation_settings.xml
index dbb859f..09bb870 100644
--- a/res/xml/gesture_navigation_settings.xml
+++ b/res/xml/gesture_navigation_settings.xml
@@ -42,7 +42,7 @@
         android:persistent="false"
         android:title="@string/back_sensitivity_dialog_title">
 
-        <com.android.settingslib.widget.LabeledSeekBarPreference
+        <com.android.settings.widget.LabeledSeekBarPreference
             android:key="gesture_left_back_sensitivity"
             android:title="@string/left_edge"
             android:max="2"
@@ -50,7 +50,7 @@
             settings:textStart="@string/low_label"
             settings:textEnd="@string/high_label"/>
 
-        <com.android.settingslib.widget.LabeledSeekBarPreference
+        <com.android.settings.widget.LabeledSeekBarPreference
             android:key="gesture_right_back_sensitivity"
             android:title="@string/right_edge"
             android:max="2"
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index f18d8a5..1f4895e 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -93,10 +93,4 @@
         android:title="@string/gesture_prevent_ringing_screen_title"
         android:fragment="com.android.settings.gestures.PreventRingingGestureSettings"
         settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController" />
-
-    <Preference
-        android:key="gesture_power_menu_summary"
-        android:title="@string/power_menu_setting_name"
-        android:fragment="com.android.settings.gestures.PowerMenuSettings"
-        settings:controller="com.android.settings.gestures.PowerMenuPreferenceController" />
 </PreferenceScreen>
diff --git a/res/xml/night_display_settings.xml b/res/xml/night_display_settings.xml
index 42138e2..95d5034 100644
--- a/res/xml/night_display_settings.xml
+++ b/res/xml/night_display_settings.xml
@@ -52,7 +52,7 @@
         android:title="@string/night_display_end_time_title"
         settings:controller="com.android.settings.display.NightDisplayCustomEndTimePreferenceController"/>
 
-    <com.android.settingslib.RestrictedSeekBarPreference
+    <com.android.settings.widget.SeekBarPreference
         android:key="night_display_temperature"
         android:title="@string/night_display_temperature_title"
         settings:keywords="@string/keywords_display_night_display"
diff --git a/res/xml/reduce_bright_colors_settings.xml b/res/xml/reduce_bright_colors_settings.xml
index 3a47c17..b9ca854 100644
--- a/res/xml/reduce_bright_colors_settings.xml
+++ b/res/xml/reduce_bright_colors_settings.xml
@@ -20,7 +20,7 @@
     android:persistent="false"
     android:title="@string/reduce_bright_colors_preference_title">
 
-    <com.android.settingslib.RestrictedSeekBarPreference
+    <com.android.settings.widget.SeekBarPreference
         android:key="rbc_intensity"
         android:persistent="false"
         android:title="@string/reduce_bright_colors_intensity_preference_title"/>
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index 6d7c0ba..4529a01 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -19,10 +19,6 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/security_settings_face_preference_title">
 
-    <com.android.settingslib.widget.TopIntroPreference
-        android:title="@string/security_settings_face_settings_top_intro"
-        settings:searchable="false"/>
-
     <PreferenceCategory
         android:key="security_settings_face_unlock_category"
         android:title="@string/security_settings_face_settings_use_face_category"
diff --git a/res/xml/storage_category_fragment.xml b/res/xml/storage_category_fragment.xml
index fb62bee..08f3f27 100644
--- a/res/xml/storage_category_fragment.xml
+++ b/res/xml/storage_category_fragment.xml
@@ -19,7 +19,7 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/storage_settings">
-    <Preference
+    <com.android.settings.widget.CardPreference
         android:key="free_up_space"
         android:order="4"
         android:title="@string/storage_free_up_space_title"
diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml
index fff3235..8edf4bf 100644
--- a/res/xml/storage_dashboard_fragment.xml
+++ b/res/xml/storage_dashboard_fragment.xml
@@ -38,7 +38,7 @@
         android:icon="@drawable/ic_storage"
         android:order="3"
         settings:controller="com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController"/>
-    <Preference
+    <com.android.settings.widget.CardPreference
         android:key="free_up_space"
         android:order="4"
         android:title="@string/storage_free_up_space_title"
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index 9228ddd..6737775 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -43,6 +43,14 @@
         android:fragment="com.android.settings.datetime.DateTimeSettings"
         settings:controller="com.android.settings.datetime.DateTimePreferenceController"/>
 
+    <Preference
+        android:key="gesture_power_menu_summary"
+        android:title="@string/power_menu_setting_name"
+        android:icon="@drawable/ic_power_settings"
+        android:order="-220"
+        android:fragment="com.android.settings.gestures.PowerMenuSettings"
+        settings:controller="com.android.settings.gestures.PowerMenuPreferenceController" />
+
     <!-- System updates -->
     <Preference
         android:key="additional_system_update_settings"
diff --git a/res/xml/tts_settings.xml b/res/xml/tts_settings.xml
index 9201938..bcc9c85 100644
--- a/res/xml/tts_settings.xml
+++ b/res/xml/tts_settings.xml
@@ -34,14 +34,14 @@
 
         <!-- The max value for seek bars here should be kept in sync
              with the max value specified in TextToSpeechSettings class. -->
-        <com.android.settingslib.RestrictedSeekBarPreference
+        <com.android.settings.widget.SeekBarPreference
             android:key="tts_default_rate"
             android:title="@string/tts_default_rate_title"
             android:summary="@string/tts_default_rate_summary"
             android:defaultValue="50"
             android:max="600"/>
 
-        <com.android.settingslib.RestrictedSeekBarPreference
+        <com.android.settings.widget.SeekBarPreference
             android:key="tts_default_pitch"
             android:title="@string/tts_default_pitch_title"
             android:summary="@string/tts_default_pitch_summary"
diff --git a/src/com/android/settings/RestrictedListPreference.java b/src/com/android/settings/RestrictedListPreference.java
index d64504d..bd3cd17 100644
--- a/src/com/android/settings/RestrictedListPreference.java
+++ b/src/com/android/settings/RestrictedListPreference.java
@@ -39,17 +39,13 @@
 import androidx.preference.ListPreferenceDialogFragmentCompat;
 import androidx.preference.PreferenceViewHolder;
 
-import com.android.settingslib.Restrictable;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedPreferenceHelper;
 
 import java.util.ArrayList;
 import java.util.List;
 
-/**
- * List preference that can be disabled by a device admin using a user restriction.
- */
-public class RestrictedListPreference extends CustomListPreference implements Restrictable {
+public class RestrictedListPreference extends CustomListPreference {
     private final RestrictedPreferenceHelper mHelper;
     private final List<RestrictedItem> mRestrictedItems = new ArrayList<>();
     private boolean mRequiresActiveUnlockedProfile = false;
@@ -67,10 +63,6 @@
         mHelper = new RestrictedPreferenceHelper(context, this, attrs);
     }
 
-    public RestrictedListPreference(Context context) {
-        this(context, /* attrs= */ null);
-    }
-
     @Override
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
@@ -115,14 +107,14 @@
         super.setEnabled(enabled);
     }
 
-    @Override
-    public RestrictedPreferenceHelper getHelper() {
-        return mHelper;
+    public void setDisabledByAdmin(EnforcedAdmin admin) {
+        if (mHelper.setDisabledByAdmin(admin)) {
+            notifyChanged();
+        }
     }
 
-    @Override
-    public void notifyPreferenceChanged() {
-        notifyChanged();
+    public boolean isDisabledByAdmin() {
+        return mHelper.isDisabledByAdmin();
     }
 
     public void setRequiresActiveUnlockedProfile(boolean reqState) {
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityDialogUtils.java
similarity index 91%
rename from src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
rename to src/com/android/settings/accessibility/AccessibilityDialogUtils.java
index c1ac604..ffe5d6d 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityDialogUtils.java
@@ -62,7 +62,57 @@
 /**
  * Utility class for creating the edit dialog.
  */
-public class AccessibilityEditDialogUtils {
+public class AccessibilityDialogUtils {
+
+    /** Denotes the dialog emuns for show dialog. */
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DialogEnums {
+
+        /** OPEN: Settings > Accessibility > Any toggle service > Shortcut > Settings. */
+        int EDIT_SHORTCUT = 1;
+
+        /** OPEN: Settings > Accessibility > Magnification > Shortcut > Settings. */
+        int MAGNIFICATION_EDIT_SHORTCUT = 1001;
+
+        /**
+         * OPEN: Settings > Accessibility > Downloaded toggle service > Toggle use service to
+         * enable service.
+         */
+        int ENABLE_WARNING_FROM_TOGGLE = 1002;
+
+        /** OPEN: Settings > Accessibility > Downloaded toggle service > Shortcut checkbox. */
+        int ENABLE_WARNING_FROM_SHORTCUT = 1003;
+
+        /**
+         * OPEN: Settings > Accessibility > Downloaded toggle service > Shortcut checkbox
+         * toggle.
+         */
+        int ENABLE_WARNING_FROM_SHORTCUT_TOGGLE = 1004;
+
+        /**
+         * OPEN: Settings > Accessibility > Downloaded toggle service > Toggle use service to
+         * disable service.
+         */
+        int DISABLE_WARNING_FROM_TOGGLE = 1005;
+
+        /**
+         * OPEN: Settings > Accessibility > Magnification > Toggle user service in button
+         * navigation.
+         */
+        int ACCESSIBILITY_BUTTON_TUTORIAL = 1006;
+
+        /**
+         * OPEN: Settings > Accessibility > Magnification > Toggle user service in gesture
+         * navigation.
+         */
+        int GESTURE_NAVIGATION_TUTORIAL = 1007;
+
+        /**
+         * OPEN: Settings > Accessibility > Downloaded toggle service > Toggle user service > Show
+         * launch tutorial.
+         */
+        int LAUNCH_ACCESSIBILITY_TUTORIAL = 1008;
+    }
 
     /**
      * IntDef enum for dialog type that indicates different dialog for user to choose the shortcut
@@ -77,7 +127,7 @@
          DialogType.EDIT_MAGNIFICATION_SWITCH_SHORTCUT,
     })
 
-    public  @interface DialogType {
+    public @interface DialogType {
         int EDIT_SHORTCUT_GENERIC = 0;
         int EDIT_SHORTCUT_GENERIC_SUW = 1;
         int EDIT_SHORTCUT_MAGNIFICATION = 2;
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
new file mode 100644
index 0000000..709e165
--- /dev/null
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2021 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.accessibility;
+
+import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.icu.text.CaseMap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.Settings;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.CheckBox;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.utils.LocaleUtils;
+
+import com.google.android.setupcompat.util.WizardManagerHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Base class for accessibility fragments shortcut functions and dialog management.
+ */
+public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPreferenceFragment
+        implements ShortcutPreference.OnClickCallback {
+    private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference";
+    protected static final String KEY_SAVED_USER_SHORTCUT_TYPE = "shortcut_type";
+    protected static final int NOT_SET = -1;
+    // Save user's shortcutType value when savedInstance has value (e.g. device rotated).
+    protected int mSavedCheckBoxValue = NOT_SET;
+
+    protected ShortcutPreference mShortcutPreference;
+    private AccessibilityManager.TouchExplorationStateChangeListener
+            mTouchExplorationStateChangeListener;
+    private SettingsContentObserver mSettingsContentObserver;
+    private CheckBox mSoftwareTypeCheckBox;
+    private CheckBox mHardwareTypeCheckBox;
+
+    /** Returns the accessibility component name. */
+    protected abstract ComponentName getComponentName();
+
+    /** Returns the accessibility feature name. */
+    protected abstract CharSequence getLabelName();
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Restore the user shortcut type.
+        if (savedInstanceState != null && savedInstanceState.containsKey(
+                KEY_SAVED_USER_SHORTCUT_TYPE)) {
+            mSavedCheckBoxValue = savedInstanceState.getInt(KEY_SAVED_USER_SHORTCUT_TYPE, NOT_SET);
+        }
+
+        final int resId = getPreferenceScreenResId();
+        if (resId <= 0) {
+            final PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
+                    getPrefContext());
+            setPreferenceScreen(preferenceScreen);
+        }
+
+        final List<String> shortcutFeatureKeys = new ArrayList<>();
+        shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS);
+        shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
+        mSettingsContentObserver = new SettingsContentObserver(new Handler(), shortcutFeatureKeys) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri) {
+                updateShortcutPreferenceData();
+                updateShortcutPreference();
+            }
+        };
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        mShortcutPreference = new ShortcutPreference(getPrefContext(), /* attrs= */ null);
+        mShortcutPreference.setPersistent(false);
+        mShortcutPreference.setKey(getShortcutPreferenceKey());
+        mShortcutPreference.setOnClickCallback(this);
+
+        final CharSequence title = getString(R.string.accessibility_shortcut_title, getLabelName());
+        mShortcutPreference.setTitle(title);
+        getPreferenceScreen().addPreference(mShortcutPreference);
+
+        mTouchExplorationStateChangeListener = isTouchExplorationEnabled -> {
+            removeDialog(DialogEnums.EDIT_SHORTCUT);
+            mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
+        };
+
+        return super.onCreateView(inflater, container, savedInstanceState);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        final AccessibilityManager am = getPrefContext().getSystemService(
+                AccessibilityManager.class);
+        am.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
+        mSettingsContentObserver.register(getContentResolver());
+        updateShortcutPreferenceData();
+        updateShortcutPreference();
+    }
+
+    @Override
+    public void onPause() {
+        final AccessibilityManager am = getPrefContext().getSystemService(
+                AccessibilityManager.class);
+        am.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
+        mSettingsContentObserver.unregister(getContentResolver());
+        super.onPause();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        final int value = getShortcutTypeCheckBoxValue();
+        if (value != NOT_SET) {
+            outState.putInt(KEY_SAVED_USER_SHORTCUT_TYPE, value);
+        }
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
+    public Dialog onCreateDialog(int dialogId) {
+        switch (dialogId) {
+            case DialogEnums.EDIT_SHORTCUT:
+                final CharSequence dialogTitle = getPrefContext().getString(
+                        R.string.accessibility_shortcut_title, getLabelName());
+                final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent())
+                        ? AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC_SUW :
+                        AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC;
+                final Dialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
+                        getPrefContext(), dialogType, dialogTitle,
+                        this::callOnAlertDialogCheckboxClicked);
+                setupEditShortcutDialog(dialog);
+                return dialog;
+            default:
+                throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+        }
+    }
+
+    @Override
+    public int getDialogMetricsCategory(int dialogId) {
+        switch (dialogId) {
+            case DialogEnums.EDIT_SHORTCUT:
+                return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT;
+            default:
+                return SettingsEnums.ACTION_UNKNOWN;
+        }
+    }
+
+    @Override
+    public void onSettingsClicked(ShortcutPreference preference) {
+        showDialog(DialogEnums.EDIT_SHORTCUT);
+    }
+
+    @Override
+    public void onToggleClicked(ShortcutPreference preference) {
+        if (getComponentName() == null) {
+            return;
+        }
+
+        final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(getPrefContext(),
+                getComponentName().flattenToString(), AccessibilityUtil.UserShortcutType.SOFTWARE);
+        if (preference.isChecked()) {
+            AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes,
+                    getComponentName());
+            showDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
+        } else {
+            AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), shortcutTypes,
+                    getComponentName());
+        }
+        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
+    }
+
+    protected String getShortcutPreferenceKey() {
+        return KEY_SHORTCUT_PREFERENCE;
+    }
+
+    @VisibleForTesting
+    void setupEditShortcutDialog(Dialog dialog) {
+        final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut);
+        mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox);
+        setDialogTextAreaClickListener(dialogSoftwareView, mSoftwareTypeCheckBox);
+
+        final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut);
+        mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox);
+        setDialogTextAreaClickListener(dialogHardwareView, mHardwareTypeCheckBox);
+
+        updateEditShortcutDialogCheckBox();
+    }
+
+    /**
+     * Returns accumulated {@link AccessibilityUtil.UserShortcutType} checkbox value or
+     * {@code NOT_SET} if checkboxes did not exist.
+     */
+    protected int getShortcutTypeCheckBoxValue() {
+        if (mSoftwareTypeCheckBox == null || mHardwareTypeCheckBox == null) {
+            return NOT_SET;
+        }
+
+        int value = AccessibilityUtil.UserShortcutType.EMPTY;
+        if (mSoftwareTypeCheckBox.isChecked()) {
+            value |= AccessibilityUtil.UserShortcutType.SOFTWARE;
+        }
+        if (mHardwareTypeCheckBox.isChecked()) {
+            value |= AccessibilityUtil.UserShortcutType.HARDWARE;
+        }
+        return value;
+    }
+
+
+    /**
+     * This method will be invoked when a button in the edit shortcut dialog is clicked.
+     *
+     * @param dialog The dialog that received the click
+     * @param which  The button that was clicked
+     */
+    protected void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
+        if (getComponentName() == null) {
+            return;
+        }
+
+        final int value = getShortcutTypeCheckBoxValue();
+
+        saveNonEmptyUserShortcutType(value);
+        AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), value, getComponentName());
+        AccessibilityUtil.optOutAllValuesFromSettings(getPrefContext(), ~value, getComponentName());
+        mShortcutPreference.setChecked(value != AccessibilityUtil.UserShortcutType.EMPTY);
+        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
+    }
+
+    @VisibleForTesting
+    void saveNonEmptyUserShortcutType(int type) {
+        if (type == AccessibilityUtil.UserShortcutType.EMPTY) {
+            return;
+        }
+
+        final PreferredShortcut shortcut = new PreferredShortcut(
+                getComponentName().flattenToString(), type);
+        PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut);
+    }
+
+    private void setDialogTextAreaClickListener(View dialogView, CheckBox checkBox) {
+        final View dialogTextArea = dialogView.findViewById(R.id.container);
+        dialogTextArea.setOnClickListener(v -> checkBox.toggle());
+    }
+
+    protected CharSequence getShortcutTypeSummary(Context context) {
+        if (!mShortcutPreference.isSettingsEditable()) {
+            return context.getText(R.string.accessibility_shortcut_edit_dialog_title_hardware);
+        }
+
+        if (!mShortcutPreference.isChecked()) {
+            return context.getText(R.string.switch_off_text);
+        }
+
+        final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(context,
+                getComponentName().flattenToString(), AccessibilityUtil.UserShortcutType.SOFTWARE);
+
+        final List<CharSequence> list = new ArrayList<>();
+        final CharSequence softwareTitle = context.getText(
+                R.string.accessibility_shortcut_edit_summary_software);
+
+        if (hasShortcutType(shortcutTypes, AccessibilityUtil.UserShortcutType.SOFTWARE)) {
+            list.add(softwareTitle);
+        }
+        if (hasShortcutType(shortcutTypes, AccessibilityUtil.UserShortcutType.HARDWARE)) {
+            final CharSequence hardwareTitle = context.getText(
+                    R.string.accessibility_shortcut_hardware_keyword);
+            list.add(hardwareTitle);
+        }
+
+        // Show software shortcut if first time to use.
+        if (list.isEmpty()) {
+            list.add(softwareTitle);
+        }
+
+        return CaseMap.toTitle().wholeString().noLowercase().apply(Locale.getDefault(), /* iter= */
+                null, LocaleUtils.getConcatenatedString(list));
+    }
+
+    private void updateEditShortcutDialogCheckBox() {
+        // If it is during onConfigChanged process then restore the value, or get the saved value
+        // when shortcutPreference is checked.
+        int value = restoreOnConfigChangedValue();
+        if (value == NOT_SET) {
+            final int lastNonEmptyUserShortcutType = PreferredShortcuts.retrieveUserShortcutType(
+                    getPrefContext(), getComponentName().flattenToString(),
+                    AccessibilityUtil.UserShortcutType.SOFTWARE);
+            value = mShortcutPreference.isChecked() ? lastNonEmptyUserShortcutType
+                    : AccessibilityUtil.UserShortcutType.EMPTY;
+        }
+
+        mSoftwareTypeCheckBox.setChecked(
+                hasShortcutType(value, AccessibilityUtil.UserShortcutType.SOFTWARE));
+        mHardwareTypeCheckBox.setChecked(
+                hasShortcutType(value, AccessibilityUtil.UserShortcutType.HARDWARE));
+    }
+
+    private int restoreOnConfigChangedValue() {
+        final int savedValue = mSavedCheckBoxValue;
+        mSavedCheckBoxValue = NOT_SET;
+        return savedValue;
+    }
+
+    private boolean hasShortcutType(int value, @AccessibilityUtil.UserShortcutType int type) {
+        return (value & type) == type;
+    }
+
+    protected void updateShortcutPreferenceData() {
+        if (getComponentName() == null) {
+            return;
+        }
+
+        final int shortcutTypes = AccessibilityUtil.getUserShortcutTypesFromSettings(
+                getPrefContext(), getComponentName());
+        if (shortcutTypes != AccessibilityUtil.UserShortcutType.EMPTY) {
+            final PreferredShortcut shortcut = new PreferredShortcut(
+                    getComponentName().flattenToString(), shortcutTypes);
+            PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut);
+        }
+    }
+
+    protected void updateShortcutPreference() {
+        if (getComponentName() == null) {
+            return;
+        }
+
+        final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(getPrefContext(),
+                getComponentName().flattenToString(), AccessibilityUtil.UserShortcutType.SOFTWARE);
+        mShortcutPreference.setChecked(
+                AccessibilityUtil.hasValuesInSettings(getPrefContext(), shortcutTypes,
+                        getComponentName()));
+        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
+    }
+}
diff --git a/src/com/android/settings/accessibility/AnimatedImagePreference.java b/src/com/android/settings/accessibility/AnimatedImagePreference.java
index 2ca13f3..c707e5c 100644
--- a/src/com/android/settings/accessibility/AnimatedImagePreference.java
+++ b/src/com/android/settings/accessibility/AnimatedImagePreference.java
@@ -17,9 +17,14 @@
 package com.android.settings.accessibility;
 
 import android.content.Context;
-import android.graphics.drawable.AnimatedImageDrawable;
+import android.graphics.drawable.Animatable;
+import android.graphics.drawable.Animatable2;
+import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ImageView;
 
 import androidx.preference.Preference;
@@ -27,15 +32,31 @@
 
 import com.android.settings.R;
 
+import com.airbnb.lottie.LottieAnimationView;
+import com.airbnb.lottie.LottieDrawable;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.Objects;
+
 /**
  * A custom {@link ImageView} preference for showing animated or static image, such as <a
  * href="https://developers.google.com/speed/webp/">animated webp</a> and static png.
  */
 public class AnimatedImagePreference extends Preference {
 
+    private static final String TAG = "AnimatedImagePreference";
     private Uri mImageUri;
     private int mMaxHeight = -1;
 
+    private final Animatable2.AnimationCallback mAnimationCallback =
+            new Animatable2.AnimationCallback() {
+        @Override
+        public void onAnimationEnd(Drawable drawable) {
+            ((Animatable2) drawable).start();
+        }
+    };
+
     AnimatedImagePreference(Context context) {
         super(context);
         setLayoutResource(R.layout.preference_animated_image);
@@ -46,21 +67,27 @@
         super.onBindViewHolder(holder);
 
         final ImageView imageView = holder.itemView.findViewById(R.id.animated_img);
-        if (imageView == null) {
+        final LottieAnimationView lottieView = holder.itemView.findViewById(R.id.lottie_view);
+        if (imageView == null || lottieView == null) {
             return;
         }
 
         if (mImageUri != null) {
-            imageView.setImageURI(mImageUri);
+            resetAnimations(imageView, lottieView);
+            hideAllChildViews(holder.itemView);
 
-            final Drawable drawable = imageView.getDrawable();
-            if (drawable instanceof AnimatedImageDrawable) {
-                ((AnimatedImageDrawable) drawable).start();
+            imageView.setImageURI(mImageUri);
+            if (imageView.getDrawable() != null) {
+                startAnimationWith(imageView);
+            } else {
+                // The lottie image from the raw folder also returns null.
+                startLottieAnimationWith(lottieView);
             }
         }
 
         if (mMaxHeight > -1) {
             imageView.setMaxHeight(mMaxHeight);
+            lottieView.setMaxHeight(mMaxHeight);
         }
     }
 
@@ -87,4 +114,68 @@
             notifyChanged();
         }
     }
+
+    private void startAnimationWith(ImageView imageView) {
+        startAnimation(imageView.getDrawable());
+
+        imageView.setVisibility(View.VISIBLE);
+    }
+
+    private void startLottieAnimationWith(LottieAnimationView lottieView) {
+        final InputStream inputStream = getInputStreamFromUri(mImageUri);
+        Objects.requireNonNull(inputStream, "Invalid resource.");
+        lottieView.setAnimation(inputStream, /* cacheKey= */ null);
+        lottieView.setRepeatCount(LottieDrawable.INFINITE);
+        lottieView.playAnimation();
+
+        lottieView.setVisibility(View.VISIBLE);
+    }
+
+    private void startAnimation(Drawable drawable) {
+        if (!(drawable instanceof Animatable)) {
+            return;
+        }
+
+        if (drawable instanceof Animatable2) {
+            ((Animatable2) drawable).registerAnimationCallback(mAnimationCallback);
+        } else if (drawable instanceof AnimationDrawable) {
+            ((AnimationDrawable) drawable).setOneShot(false);
+        }
+
+        ((Animatable) drawable).start();
+    }
+
+    private void resetAnimations(ImageView imageView, LottieAnimationView lottieView) {
+        resetAnimation(imageView.getDrawable());
+
+        lottieView.cancelAnimation();
+    }
+
+    private void resetAnimation(Drawable drawable) {
+        if (!(drawable instanceof Animatable)) {
+            return;
+        }
+
+        if (drawable instanceof Animatable2) {
+            ((Animatable2) drawable).clearAnimationCallbacks();
+        }
+
+        ((Animatable) drawable).stop();
+    }
+
+    private InputStream getInputStreamFromUri(Uri uri) {
+        try {
+            return getContext().getContentResolver().openInputStream(uri);
+        } catch (FileNotFoundException e) {
+            Log.w(TAG, "Cannot find content uri: " + uri, e);
+            return null;
+        }
+    }
+
+    private void hideAllChildViews(View itemView) {
+        final ViewGroup viewGroup = (ViewGroup) itemView;
+        for (int i = 0; i < viewGroup.getChildCount(); i++) {
+            viewGroup.getChildAt(i).setVisibility(View.GONE);
+        }
+    }
 }
diff --git a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
index ef779d1..b03c8ab 100644
--- a/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
+++ b/src/com/android/settings/accessibility/BalanceSeekBarPreference.java
@@ -17,19 +17,23 @@
 package com.android.settings.accessibility;
 
 import android.content.Context;
+import android.media.AudioSystem;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.ImageView;
+import android.widget.SeekBar;
 
 import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
-import com.android.settingslib.RestrictedSeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 
 /** A slider preference that directly controls audio balance **/
-public class BalanceSeekBarPreference extends RestrictedSeekBarPreference {
+public class BalanceSeekBarPreference extends SeekBarPreference {
     private static final int BALANCE_CENTER_VALUE = 100;
     private static final int BALANCE_MAX_VALUE = 200;
 
diff --git a/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceController.java b/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceController.java
index e9572d6..894d3ae 100644
--- a/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceController.java
+++ b/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceController.java
@@ -28,10 +28,10 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.SliderPreferenceController;
+import com.android.settings.widget.SeekBarPreference;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnPause;
 import com.android.settingslib.core.lifecycle.events.OnResume;
-import com.android.settingslib.widget.SeekBarPreference;
 
 /** Preference controller that controls the transparency seekbar in accessibility button page. */
 public class FloatingMenuTransparencyPreferenceController extends SliderPreferenceController
diff --git a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java
index ef85834..7110656 100644
--- a/src/com/android/settings/accessibility/MagnificationModePreferenceController.java
+++ b/src/com/android/settings/accessibility/MagnificationModePreferenceController.java
@@ -17,7 +17,7 @@
 package com.android.settings.accessibility;
 
 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
-import static com.android.settings.accessibility.AccessibilityEditDialogUtils.CustomButton;
+import static com.android.settings.accessibility.AccessibilityDialogUtils.CustomButton;
 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
 
@@ -166,7 +166,7 @@
     }
 
     private Dialog createMagnificationModeDialog() {
-        mMagnificationModesListView = AccessibilityEditDialogUtils.createSingleChoiceListView(
+        mMagnificationModesListView = AccessibilityDialogUtils.createSingleChoiceListView(
                 mContext, mModeInfos, this::onMagnificationModeSelected);
 
         final View headerView = LayoutInflater.from(mContext).inflate(
@@ -179,7 +179,7 @@
         final CharSequence title = mContext.getString(
                 R.string.accessibility_magnification_mode_dialog_title);
 
-        return AccessibilityEditDialogUtils.createCustomDialog(mContext, title,
+        return AccessibilityDialogUtils.createCustomDialog(mContext, title,
                 mMagnificationModesListView, this::onMagnificationModeDialogPositiveButtonClicked);
     }
 
@@ -235,7 +235,7 @@
     }
 
     private Dialog createMagnificationShortCutConfirmDialog() {
-        return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext,
+        return AccessibilityDialogUtils.createMagnificationSwitchShortcutDialog(mContext,
                 this::onSwitchShortcutDialogButtonClicked);
     }
 
diff --git a/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceController.java b/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceController.java
index d1dd50a..7e6b42d 100644
--- a/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceController.java
+++ b/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceController.java
@@ -23,7 +23,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.SliderPreferenceController;
-import com.android.settingslib.widget.SeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 
 /** PreferenceController for feature intensity. */
 public class ReduceBrightColorsIntensityPreferenceController extends SliderPreferenceController {
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index 7902ec6..9d94858 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
 import static com.android.settings.accessibility.AccessibilityStatsLogUtils.logAccessibilityServiceEnabled;
 import static com.android.settings.accessibility.PreferredShortcuts.retrieveUserShortcutType;
 
@@ -49,7 +50,6 @@
 import android.widget.Switch;
 
 import androidx.annotation.Nullable;
-import androidx.preference.Preference;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
@@ -232,14 +232,18 @@
 
     @Override
     protected void updateSwitchBarToggleSwitch() {
-        final boolean checked = AccessibilityUtils.getEnabledServicesFromSettings(getPrefContext())
-                .contains(mComponentName);
+        final boolean checked = isAccessibilityServiceEnabled();
         if (mToggleServiceSwitchPreference.isChecked() == checked) {
             return;
         }
         mToggleServiceSwitchPreference.setChecked(checked);
     }
 
+    private boolean isAccessibilityServiceEnabled() {
+        return AccessibilityUtils.getEnabledServicesFromSettings(getPrefContext())
+                .contains(mComponentName);
+    }
+
     /**
      * Return whether the device is encrypted with legacy full disk encryption. Newer devices
      * should be using File Based Encryption.
@@ -314,7 +318,6 @@
     }
 
     private void handleConfirmServiceEnabled(boolean confirmed) {
-        mToggleServiceSwitchPreference.setChecked(confirmed);
         getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED, confirmed);
         onPreferenceToggled(mPreferenceKey, confirmed);
     }
@@ -338,8 +341,8 @@
 
     @Override
     public void onSwitchChanged(Switch switchView, boolean isChecked) {
-        if (isChecked != mToggleServiceSwitchPreference.isChecked()) {
-            onPreferenceClick(mToggleServiceSwitchPreference);
+        if (isChecked != isAccessibilityServiceEnabled()) {
+            onPreferenceClick(isChecked);
         }
     }
 
@@ -533,14 +536,8 @@
         mDialog.dismiss();
     }
 
-    private boolean onPreferenceClick(Preference preference) {
-        boolean checked = ((SettingsMainSwitchPreference) preference).isChecked();
-        if (checked) {
-            mToggleServiceSwitchPreference.setChecked(true);
-            getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED,
-                    /* enableService */ true);
-            showDialog(DialogEnums.DISABLE_WARNING_FROM_TOGGLE);
-        } else {
+    private boolean onPreferenceClick(boolean isChecked) {
+        if (isChecked) {
             mToggleServiceSwitchPreference.setChecked(false);
             getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED,
                     /* disableService */ false);
@@ -552,6 +549,11 @@
                     showPopupDialog(DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL);
                 }
             }
+        } else {
+            mToggleServiceSwitchPreference.setChecked(true);
+            getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED,
+                    /* enableService */ true);
+            showDialog(DialogEnums.DISABLE_WARNING_FROM_TOGGLE);
         }
         return true;
     }
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 7c18943..1002a84 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.accessibility;
 
+import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
+
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
@@ -50,7 +52,7 @@
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
+import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
 import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
 import com.android.settings.utils.LocaleUtils;
 import com.android.settings.widget.SettingsMainSwitchBar;
@@ -61,8 +63,6 @@
 
 import com.google.android.setupcompat.util.WizardManagerHelper;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -136,7 +136,7 @@
         setupDefaultShortcutIfNecessary(getPrefContext());
         final int resId = getPreferenceScreenResId();
         if (resId <= 0) {
-            PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
+            final PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
                     getPrefContext());
             setPreferenceScreen(preferenceScreen);
         }
@@ -228,7 +228,7 @@
                         R.string.accessibility_shortcut_title, mPackageName);
                 final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent())
                         ? DialogType.EDIT_SHORTCUT_GENERIC_SUW : DialogType.EDIT_SHORTCUT_GENERIC;
-                dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+                dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                         getPrefContext(), dialogType, dialogTitle,
                         this::callOnAlertDialogCheckboxClicked);
                 setupEditShortcutDialog(dialog);
@@ -256,56 +256,6 @@
         }
     }
 
-    /** Denotes the dialog emuns for show dialog */
-    @Retention(RetentionPolicy.SOURCE)
-    protected @interface DialogEnums {
-
-        /** OPEN: Settings > Accessibility > Any toggle service > Shortcut > Settings. */
-        int EDIT_SHORTCUT = 1;
-
-        /** OPEN: Settings > Accessibility > Magnification > Shortcut > Settings. */
-        int MAGNIFICATION_EDIT_SHORTCUT = 1001;
-
-        /**
-         * OPEN: Settings > Accessibility > Downloaded toggle service > Toggle use service to
-         * enable service.
-         */
-        int ENABLE_WARNING_FROM_TOGGLE = 1002;
-
-        /** OPEN: Settings > Accessibility > Downloaded toggle service > Shortcut checkbox. */
-        int ENABLE_WARNING_FROM_SHORTCUT = 1003;
-
-        /**
-         * OPEN: Settings > Accessibility > Downloaded toggle service > Shortcut checkbox
-         * toggle.
-         */
-        int ENABLE_WARNING_FROM_SHORTCUT_TOGGLE = 1004;
-
-        /**
-         * OPEN: Settings > Accessibility > Downloaded toggle service > Toggle use service to
-         * disable service.
-         */
-        int DISABLE_WARNING_FROM_TOGGLE = 1005;
-
-        /**
-         * OPEN: Settings > Accessibility > Magnification > Toggle user service in button
-         * navigation.
-         */
-        int ACCESSIBILITY_BUTTON_TUTORIAL = 1006;
-
-        /**
-         * OPEN: Settings > Accessibility > Magnification > Toggle user service in gesture
-         * navigation.
-         */
-        int GESTURE_NAVIGATION_TUTORIAL = 1007;
-
-        /**
-         * OPEN: Settings > Accessibility > Downloaded toggle service > Toggle user service > Show
-         * launch tutorial.
-         */
-        int LAUNCH_ACCESSIBILITY_TUTORIAL = 1008;
-    }
-
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.ACCESSIBILITY_SERVICE;
diff --git a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
index 632d449..b629eaa 100644
--- a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
@@ -34,9 +34,9 @@
 import com.android.internal.accessibility.AccessibilityShortcutController;
 import com.android.settings.R;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.SeekBarPreference;
 import com.android.settings.widget.SettingsMainSwitchPreference;
 import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.widget.SeekBarPreference;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 57fd7ea..ca33a96 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -17,6 +17,7 @@
 package com.android.settings.accessibility;
 
 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
+import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
 import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
 import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
 
@@ -44,7 +45,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.DialogCreatable;
 import com.android.settings.R;
-import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
+import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
 import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
 import com.android.settings.utils.LocaleUtils;
 
@@ -134,7 +135,7 @@
                 final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent())
                         ? DialogType.EDIT_SHORTCUT_MAGNIFICATION_SUW
                         : DialogType.EDIT_SHORTCUT_MAGNIFICATION;
-                dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getPrefContext(),
+                dialog = AccessibilityDialogUtils.showEditShortcutDialog(getPrefContext(),
                         dialogType, dialogTitle, this::callOnAlertDialogCheckboxClicked);
                 setupMagnificationEditShortcutDialog(dialog);
                 return dialog;
diff --git a/src/com/android/settings/accounts/AccountRestrictionHelper.java b/src/com/android/settings/accounts/AccountRestrictionHelper.java
index 8c4d220..c67f5d1 100644
--- a/src/com/android/settings/accounts/AccountRestrictionHelper.java
+++ b/src/com/android/settings/accounts/AccountRestrictionHelper.java
@@ -27,11 +27,9 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 
-import androidx.preference.Preference;
-
 import com.android.settings.AccessiblePreferenceCategory;
-import com.android.settingslib.Restrictable;
 import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedPreference;
 
 import java.util.ArrayList;
 
@@ -44,74 +42,34 @@
     }
 
     /**
-     * Checks if the account should be shown based on the required authorities for the account type
-     *
-     * @param authorities given authority that is passed as activity extra
-     * @param auths       list of authorities for particular account type
-     * @return true if the activity has the required authority to show the account
-     */
-    public static boolean showAccount(String[] authorities, ArrayList<String> auths) {
-        boolean showAccount = true;
-        if (authorities != null && auths != null) {
-            showAccount = false;
-            for (String requestedAuthority : authorities) {
-                if (auths.contains(requestedAuthority)) {
-                    return true;
-                }
-            }
-        }
-        return showAccount;
-    }
-
-    /**
      * Configure the UI of the preference by checking user restriction.
-     *
-     * @param preference      The preference we are configuring.
+     * @param preference The preference we are configuring.
      * @param userRestriction The user restriction related to the preference.
-     * @param userId          The user that we retrieve user restriction of.
+     * @param userId The user that we retrieve user restriction of.
      */
-    public void enforceRestrictionOnPreference(Preference preference,
-            String userRestriction, @UserIdInt int userId) {
+    public void enforceRestrictionOnPreference(RestrictedPreference preference,
+        String userRestriction, @UserIdInt int userId) {
         if (preference == null) {
             return;
         }
-        if (!(preference instanceof Restrictable)) {
-            return;
-        }
-
-        final Restrictable restrictedPreference = (Restrictable) preference;
-
         if (hasBaseUserRestriction(userRestriction, userId)) {
             if (userRestriction.equals(DISALLOW_REMOVE_MANAGED_PROFILE)
                     && isOrganizationOwnedDevice()) {
-                restrictedPreference.setDisabledByAdmin(getEnforcedAdmin(userRestriction, userId));
+                preference.setDisabledByAdmin(getEnforcedAdmin(userRestriction, userId));
             } else {
                 preference.setEnabled(false);
             }
         } else {
-            restrictedPreference.checkRestrictionAndSetDisabled(userRestriction, userId);
+            preference.checkRestrictionAndSetDisabled(userRestriction, userId);
         }
     }
 
-    /**
-     * Check if the system has set the user restriction.
-     * @param userRestriction The user restriction.
-     * @param userId The user that we retrieve user restriction of.
-     * @return {@code true} if set restriction.
-     */
     public boolean hasBaseUserRestriction(String userRestriction, @UserIdInt int userId) {
         return RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext, userRestriction,
                 userId);
     }
 
-    /**
-     * Apps can use this method to find out if the device was provisioned as
-     * organization-owend device.
-     *
-     * @return {@code true} if the device was provisioned as organization-owned device,
-     * {@code false} otherwise.
-     */
-    public boolean isOrganizationOwnedDevice() {
+    private boolean isOrganizationOwnedDevice() {
         final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm == null) {
@@ -120,13 +78,7 @@
         return dpm.isOrganizationOwnedDeviceWithManagedProfile();
     }
 
-    /**
-     * Get the restriction enforced by admin
-     * @param userRestriction The user restriction.
-     * @param userId The user that we retrieve user restriction of.
-     * @return {EnforcedAdmin}
-     */
-    public EnforcedAdmin getEnforcedAdmin(String userRestriction, int userId) {
+    private EnforcedAdmin getEnforcedAdmin(String userRestriction, int userId) {
         final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
                 Context.DEVICE_POLICY_SERVICE);
         if (dpm == null) {
@@ -155,4 +107,23 @@
     public AccessiblePreferenceCategory createAccessiblePreferenceCategory(Context context) {
         return new AccessiblePreferenceCategory(context);
     }
+
+    /**
+     * Checks if the account should be shown based on the required authorities for the account type
+     * @param authorities given authority that is passed as activity extra
+     * @param auths list of authorities for particular account type
+     * @return true if the activity has the required authority to show the account
+     */
+    public static boolean showAccount(String[] authorities, ArrayList<String> auths) {
+        boolean showAccount = true;
+        if (authorities != null && auths != null) {
+            showAccount = false;
+            for (String requestedAuthority : authorities) {
+                if (auths.contains(requestedAuthority)) {
+                    return true;
+                }
+            }
+        }
+        return showAccount;
+    }
 }
diff --git a/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java b/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
index b4dbf3d..238e937 100644
--- a/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
+++ b/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceController.java
@@ -17,16 +17,19 @@
 package com.android.settings.accounts;
 
 import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
 
 import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.widget.FooterPreference;
 
 public class EnterpriseDisclosurePreferenceController extends BasePreferenceController {
-
     private final EnterprisePrivacyFeatureProvider mFeatureProvider;
 
     public EnterpriseDisclosurePreferenceController(Context context, String key) {
@@ -37,6 +40,16 @@
     }
 
     @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        final CharSequence disclosure = getDisclosure();
+        if (disclosure == null) {
+            return;
+        }
+        updateFooterPreference(screen, disclosure);
+    }
+
+    @Override
     public int getAvailabilityStatus() {
         if (getDisclosure() == null) {
             return UNSUPPORTED_ON_DEVICE;
@@ -49,12 +62,18 @@
         return mFeatureProvider.getDeviceOwnerDisclosure();
     }
 
-    @Override
-    public void updateState(Preference preference) {
-        final CharSequence disclosure = getDisclosure();
-        if (disclosure == null) {
-            return;
-        }
-        preference.setTitle(disclosure);
+    void updateFooterPreference(PreferenceScreen screen, CharSequence disclosure) {
+        final FooterPreference footerPreference = screen.findPreference(getPreferenceKey());
+        footerPreference.setTitle(disclosure);
+        footerPreference.setLearnMoreAction(view -> {
+            mContext.startActivity(new Intent(Settings.ACTION_ENTERPRISE_PRIVACY_SETTINGS));
+        });
+        final String learnMoreContentDescription = mContext.getString(
+                R.string.footer_learn_more_content_description, getLabelName());
+        footerPreference.setLearnMoreContentDescription(learnMoreContentDescription);
+    }
+
+    private String getLabelName() {
+        return mContext.getString(R.string.header_add_an_account);
     }
 }
diff --git a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
index 79cae92..1f0777a 100644
--- a/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppBatteryPreferenceController.java
@@ -118,7 +118,8 @@
             final UserManager userManager =
                     (UserManager) mContext.getSystemService(Context.USER_SERVICE);
             final BatteryEntry entry = new BatteryEntry(mContext, /* handler */null, userManager,
-                    mUidBatteryConsumer, /* isHidden */ false, /* packages */ null, mPackageName);
+                    mUidBatteryConsumer, /* isHidden */ false,
+                    mUidBatteryConsumer.getUid(), /* packages */ null, mPackageName);
             AdvancedPowerUsageDetail.startBatteryDetailPage(mParent.getActivity(), mParent,
                     entry, mBatteryPercent);
         } else {
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 62513db..7509a78 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -434,7 +434,7 @@
         final Activity activity = getActivity();
         final FrameLayout pinnedHeader = mRootView.findViewById(R.id.pinned_header);
         mSpinnerHeader = activity.getLayoutInflater()
-                .inflate(R.layout.apps_filter_spinner, pinnedHeader, false);
+                .inflate(R.layout.manage_apps_filter_spinner, pinnedHeader, false);
         mFilterSpinner = mSpinnerHeader.findViewById(R.id.filter_spinner);
         mFilterAdapter = new FilterSpinnerAdapter(this);
         mFilterSpinner.setAdapter(mFilterAdapter);
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 09d8e71..de85067 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -39,6 +39,8 @@
 import com.google.android.setupcompat.template.FooterButton;
 import com.google.android.setupcompat.util.WizardManagerHelper;
 import com.google.android.setupdesign.span.LinkSpan;
+import com.google.android.setupdesign.template.RequireScrollMixin;
+import com.google.android.setupdesign.template.RequireScrollMixin.OnRequireScrollStateChangedListener;
 import com.google.android.setupdesign.util.DynamicColorPalette;
 
 /**
@@ -180,6 +182,35 @@
                 launchConfirmLock(getConfirmLockTitleResId());
             }
         }
+
+        FooterButton primaryButton = getPrimaryFooterButton();
+        FooterButton secondaryButton = getSecondaryFooterButton();
+        if (primaryButton == null) {
+            Log.d(TAG, "getPrimaryFooterButton() was null");
+            return;
+        }
+
+        if (secondaryButton == null) {
+            Log.d(TAG, "getSecondaryFooterButton() was null");
+            return;
+        }
+
+        // Setup scroll mixin
+        final RequireScrollMixin requireScrollMixin = getLayout().getMixin(
+                RequireScrollMixin.class);
+        requireScrollMixin.requireScrollWithButton(this, primaryButton, getScrollCompletedText(),
+                this::onNextButtonClick);
+
+        secondaryButton.setVisibility(View.INVISIBLE);
+        requireScrollMixin.setOnRequireScrollStateChangedListener(
+                new OnRequireScrollStateChangedListener() {
+                    @Override
+                    public void onRequireScrollStateChanged(boolean scrollNeeded) {
+                        if (!scrollNeeded && secondaryButton.getVisibility() == View.INVISIBLE) {
+                            secondaryButton.setVisibility(View.VISIBLE);
+                        }
+                    }
+                });
     }
 
     @Override
@@ -335,4 +366,18 @@
         }
         return mIconColorFilter;
     }
+
+    @Nullable
+    protected FooterButton getPrimaryFooterButton() {
+        return null;
+    }
+
+    @Nullable
+    protected FooterButton getSecondaryFooterButton() {
+        return null;
+    }
+
+    protected int getScrollCompletedText() {
+        return R.string.security_settings_face_enroll_introduction_more;
+    }
 }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index d564547..b29e284 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -38,7 +38,6 @@
 import com.google.android.setupcompat.template.FooterButton;
 import com.google.android.setupcompat.util.WizardManagerHelper;
 import com.google.android.setupdesign.span.LinkSpan;
-import com.google.android.setupdesign.template.RequireScrollMixin;
 
 import java.util.List;
 
@@ -81,32 +80,6 @@
         mFaceFeatureProvider = FeatureFactory.getFactory(getApplicationContext())
                 .getFaceFeatureProvider();
 
-        mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
-        mFooterBarMixin.setSecondaryButton(
-                new FooterButton.Builder(this)
-                        .setText(R.string.security_settings_face_enroll_introduction_no_thanks)
-                        .setListener(this::onSkipButtonClick)
-                        .setButtonType(FooterButton.ButtonType.NEXT)
-                        .setTheme(R.style.SudGlifButton_Primary)
-                        .build(),
-                true /* usePrimaryStyle */);
-
-        FooterButton.Builder nextButtonBuilder = new FooterButton.Builder(this)
-                .setText(R.string.security_settings_face_enroll_introduction_agree)
-                .setButtonType(FooterButton.ButtonType.OPT_IN)
-                .setTheme(R.style.SudGlifButton_Primary);
-        if (maxFacesEnrolled()) {
-            nextButtonBuilder.setListener(this::onNextButtonClick);
-            mFooterBarMixin.setPrimaryButton(nextButtonBuilder.build());
-        } else {
-            final FooterButton agreeButton = nextButtonBuilder.build();
-            mFooterBarMixin.setPrimaryButton(agreeButton);
-            final RequireScrollMixin requireScrollMixin = getLayout().getMixin(
-                    RequireScrollMixin.class);
-            requireScrollMixin.requireScrollWithButton(this, agreeButton,
-                    R.string.security_settings_face_enroll_introduction_more,
-                    this::onNextButtonClick);
-        }
 
         // This path is an entry point for SetNewPasswordController, e.g.
         // adb shell am start -a android.app.action.SET_NEW_PASSWORD
@@ -232,4 +205,40 @@
     public void onClick(LinkSpan span) {
         // TODO(b/110906762)
     }
+
+    @Override
+    protected FooterButton getPrimaryFooterButton() {
+        if (mFooterBarMixin == null) {
+            mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
+        }
+
+        if (mFooterBarMixin.getPrimaryButton() == null) {
+            final FooterButton nextButtonBuilder = new FooterButton.Builder(this)
+                    .setText(R.string.security_settings_face_enroll_introduction_agree)
+                    .setButtonType(FooterButton.ButtonType.OPT_IN)
+                    .setListener(this::onNextButtonClick)
+                    .setTheme(R.style.SudGlifButton_Primary)
+                    .build();
+            mFooterBarMixin.setPrimaryButton(nextButtonBuilder);
+        }
+        return mFooterBarMixin.getPrimaryButton();
+    }
+
+    @Override
+    protected FooterButton getSecondaryFooterButton() {
+        if (mFooterBarMixin == null) {
+            mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
+        }
+
+        if (mFooterBarMixin.getSecondaryButton() == null) {
+            final FooterButton noThanksButton = new FooterButton.Builder(this)
+                    .setText(R.string.security_settings_face_enroll_introduction_no_thanks)
+                    .setListener(this::onSkipButtonClick)
+                    .setButtonType(FooterButton.ButtonType.NEXT)
+                    .setTheme(R.style.SudGlifButton_Primary)
+                    .build();
+            mFooterBarMixin.setSecondaryButton(noThanksButton, true /* usePrimaryStyle */);
+        }
+        return mFooterBarMixin.getSecondaryButton();
+    }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 18b1116..8a070ab 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -38,7 +38,6 @@
 import com.google.android.setupcompat.template.FooterBarMixin;
 import com.google.android.setupcompat.template.FooterButton;
 import com.google.android.setupdesign.span.LinkSpan;
-import com.google.android.setupdesign.template.RequireScrollMixin;
 
 import java.util.List;
 
@@ -69,29 +68,6 @@
         iconDelete.getDrawable().setColorFilter(getIconColorFilter());
         iconInfo.getDrawable().setColorFilter(getIconColorFilter());
         iconLink.getDrawable().setColorFilter(getIconColorFilter());
-
-        mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
-        mFooterBarMixin.setSecondaryButton(
-                new FooterButton.Builder(this)
-                        .setText(getNegativeButtonTextId())
-                        .setListener(this::onSkipButtonClick)
-                        .setButtonType(FooterButton.ButtonType.NEXT)
-                        .setTheme(R.style.SudGlifButton_Primary)
-                        .build(),
-                true /* usePrimaryStyle */);
-
-        final FooterButton nextButton = new FooterButton.Builder(this)
-                .setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
-                .setListener(this::onNextButtonClick)
-                .setButtonType(FooterButton.ButtonType.OPT_IN)
-                .setTheme(R.style.SudGlifButton_Primary)
-                .build();
-
-        mFooterBarMixin.setPrimaryButton(nextButton);
-        final RequireScrollMixin requireScrollMixin =
-                getLayout().getMixin(RequireScrollMixin.class);
-        requireScrollMixin.requireScrollWithButton(this, nextButton,
-                R.string.security_settings_face_enroll_introduction_more, this::onNextButtonClick);
     }
 
     int getNegativeButtonTextId() {
@@ -216,4 +192,45 @@
             }
         }
     }
+
+    @Override
+    protected FooterButton getPrimaryFooterButton() {
+        if (mFooterBarMixin == null) {
+            mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
+        }
+
+        if (mFooterBarMixin.getPrimaryButton() == null) {
+            final FooterButton nextButtonBuilder = new FooterButton.Builder(this)
+                    .setText(R.string.security_settings_fingerprint_enroll_introduction_agree)
+                    .setListener(this::onNextButtonClick)
+                    .setButtonType(FooterButton.ButtonType.OPT_IN)
+                    .setTheme(R.style.SudGlifButton_Primary)
+                    .build();
+            mFooterBarMixin.setPrimaryButton(nextButtonBuilder);
+        }
+        return mFooterBarMixin.getPrimaryButton();
+    }
+
+    @Override
+    protected FooterButton getSecondaryFooterButton() {
+        if (mFooterBarMixin == null) {
+            mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
+        }
+
+        if (mFooterBarMixin.getSecondaryButton() == null) {
+            final FooterButton noThanksButton = new FooterButton.Builder(this)
+                    .setText(getNegativeButtonTextId())
+                    .setListener(this::onSkipButtonClick)
+                    .setButtonType(FooterButton.ButtonType.NEXT)
+                    .setTheme(R.style.SudGlifButton_Primary)
+                    .build();
+            mFooterBarMixin.setSecondaryButton(noThanksButton, true /* usePrimaryStyle */);
+        }
+        return mFooterBarMixin.getSecondaryButton();
+    }
+
+    @Override
+    protected int getScrollCompletedText() {
+        return R.string.security_settings_face_enroll_introduction_more;
+    }
 }
diff --git a/src/com/android/settings/core/SliderPreferenceController.java b/src/com/android/settings/core/SliderPreferenceController.java
index 010036a..0a7ece2 100644
--- a/src/com/android/settings/core/SliderPreferenceController.java
+++ b/src/com/android/settings/core/SliderPreferenceController.java
@@ -19,7 +19,6 @@
 import androidx.preference.Preference;
 
 import com.android.settings.slices.SliceData;
-import com.android.settingslib.widget.SeekBarPreference;
 
 public abstract class SliderPreferenceController extends BasePreferenceController implements
         Preference.OnPreferenceChangeListener {
@@ -35,10 +34,12 @@
 
     @Override
     public void updateState(Preference preference) {
-        if (preference instanceof SeekBarPreference) {
-            ((SeekBarPreference) preference).setProgress(getSliderPosition());
+        if (preference instanceof com.android.settings.widget.SeekBarPreference) {
+            ((com.android.settings.widget.SeekBarPreference) preference)
+                .setProgress(getSliderPosition());
         } else if (preference instanceof androidx.preference.SeekBarPreference) {
-            ((androidx.preference.SeekBarPreference) preference).setValue(getSliderPosition());
+            ((androidx.preference.SeekBarPreference) preference)
+                .setValue(getSliderPosition());
         }
     }
 
diff --git a/src/com/android/settings/core/SubSettingLauncher.java b/src/com/android/settings/core/SubSettingLauncher.java
index 893d592..0a6966f 100644
--- a/src/com/android/settings/core/SubSettingLauncher.java
+++ b/src/com/android/settings/core/SubSettingLauncher.java
@@ -28,6 +28,7 @@
 
 import com.android.settings.SettingsActivity;
 import com.android.settings.SubSettings;
+import com.android.settings.Utils;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.transition.SettingsTransitionHelper.TransitionType;
 
@@ -181,8 +182,10 @@
 
     @VisibleForTesting
     void launchAsUser(Intent intent, UserHandle userHandle) {
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        if (!Utils.isPageTransitionEnabled(mContext)) {
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        }
         mContext.startActivityAsUser(intent, userHandle);
     }
 
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
index 74031c4..a41b582 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccessPreference.java
@@ -24,14 +24,14 @@
 import com.android.settings.R;
 import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
 import com.android.settings.dashboard.DashboardFragment;
-import com.android.settingslib.Restrictable;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 import com.android.settingslib.RestrictedPreferenceHelper;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
 import com.android.settingslib.widget.AppSwitchPreference;
 
 public class UnrestrictedDataAccessPreference extends AppSwitchPreference implements
-        DataSaverBackend.Listener, Restrictable {
+        DataSaverBackend.Listener {
 
     private final ApplicationsState mApplicationsState;
     private final AppEntry mEntry;
@@ -159,14 +159,12 @@
         return mEntry;
     }
 
-    @Override
-    public RestrictedPreferenceHelper getHelper() {
-        return mHelper;
+    public boolean isDisabledByAdmin() {
+        return mHelper.isDisabledByAdmin();
     }
 
-    @Override
-    public void notifyPreferenceChanged() {
-        notifyChanged();
+    public void setDisabledByAdmin(EnforcedAdmin admin) {
+        mHelper.setDisabledByAdmin(admin);
     }
 
     // Sets UI state based on allowlist/denylist status.
diff --git a/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
index dca597f..6032abd 100644
--- a/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
+++ b/src/com/android/settings/datetime/timezone/BaseTimeZonePicker.java
@@ -27,6 +27,7 @@
 import android.widget.SearchView;
 import android.widget.TextView;
 
+import androidx.core.view.ViewCompat;
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
@@ -35,6 +36,8 @@
 import com.android.settings.datetime.timezone.model.TimeZoneData;
 import com.android.settings.datetime.timezone.model.TimeZoneDataLoader;
 
+import com.google.android.material.appbar.AppBarLayout;
+
 import java.util.Locale;
 
 /**
@@ -43,12 +46,15 @@
  * The search matches the prefix of words in the search text.
  */
 public abstract class BaseTimeZonePicker extends InstrumentedFragment
-        implements SearchView.OnQueryTextListener {
+        implements SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener {
 
     public static final String EXTRA_RESULT_REGION_ID =
             "com.android.settings.datetime.timezone.result_region_id";
     public static final String EXTRA_RESULT_TIME_ZONE_ID =
             "com.android.settings.datetime.timezone.result_time_zone_id";
+
+    protected AppBarLayout mAppBarLayout;
+
     private final int mTitleResId;
     private final int mSearchHintResId;
     private final boolean mSearchEnabled;
@@ -88,6 +94,7 @@
         mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext(),
                 LinearLayoutManager.VERTICAL, /* reverseLayout */ false));
         mRecyclerView.setAdapter(mAdapter);
+        mAppBarLayout = getActivity().findViewById(R.id.app_bar);
 
         // Initialize TimeZoneDataLoader only when mRecyclerView is ready to avoid race
         // during onDateLoaderReady callback.
@@ -121,6 +128,7 @@
             inflater.inflate(R.menu.time_zone_base_search_menu, menu);
 
             final MenuItem searchMenuItem = menu.findItem(R.id.time_zone_search_menu);
+            searchMenuItem.setOnActionExpandListener(this);
             mSearchView = (SearchView) searchMenuItem.getActionView();
 
             mSearchView.setQueryHint(getText(mSearchHintResId));
@@ -149,6 +157,21 @@
     }
 
     @Override
+    public boolean onMenuItemActionExpand(MenuItem item) {
+        // To prevent a large space on tool bar.
+        mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/);
+        // To prevent user can expand the collpasing tool bar view.
+        ViewCompat.setNestedScrollingEnabled(mRecyclerView, false);
+        return true;
+    }
+
+    @Override
+    public boolean onMenuItemActionCollapse(MenuItem item) {
+        ViewCompat.setNestedScrollingEnabled(mRecyclerView, true);
+        return true;
+    }
+
+    @Override
     public boolean onQueryTextSubmit(String query) {
         return false;
     }
diff --git a/src/com/android/settings/display/NightDisplayIntensityPreferenceController.java b/src/com/android/settings/display/NightDisplayIntensityPreferenceController.java
index 6b1cdbf..0f8ecc5 100644
--- a/src/com/android/settings/display/NightDisplayIntensityPreferenceController.java
+++ b/src/com/android/settings/display/NightDisplayIntensityPreferenceController.java
@@ -24,7 +24,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.SliderPreferenceController;
-import com.android.settingslib.widget.SeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 
 public class NightDisplayIntensityPreferenceController extends SliderPreferenceController {
 
diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
index 8c25a05..f8d5f96 100644
--- a/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
+++ b/src/com/android/settings/display/SmartAutoRotatePreferenceController.java
@@ -16,15 +16,25 @@
 
 package com.android.settings.display;
 
+import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
 import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;
 
+import static com.android.settings.display.SmartAutoRotateController.hasSufficientPermission;
+import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
+
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.SensorPrivacyManager;
+import android.os.PowerManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.view.RotationPolicy;
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
@@ -41,8 +51,21 @@
     private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
     private Preference mPreference;
 
+    private final SensorPrivacyManager mPrivacyManager;
+    private final PowerManager mPowerManager;
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            refreshSummary(mPreference);
+        }
+    };
+
     public SmartAutoRotatePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
+        mPrivacyManager = SensorPrivacyManager.getInstance(context);
+        mPrivacyManager
+                .addSensorPrivacyListener(CAMERA, (sensor, enabled) -> refreshSummary(mPreference));
+        mPowerManager = context.getSystemService(PowerManager.class);
     }
 
     @Override
@@ -59,6 +82,8 @@
 
     @Override
     public void onStart() {
+        mContext.registerReceiver(mReceiver,
+                new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
         if (mRotationPolicyListener == null) {
             mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() {
                 @Override
@@ -75,12 +100,27 @@
 
     @Override
     public void onStop() {
+        mContext.unregisterReceiver(mReceiver);
         if (mRotationPolicyListener != null) {
             RotationPolicy.unregisterRotationPolicyListener(mContext,
                     mRotationPolicyListener);
         }
     }
 
+    /**
+     * Need this because all controller tests use Roboelectric. No easy way to mock this service,
+     * so we mock the call we need
+     */
+    @VisibleForTesting
+    boolean isCameraLocked() {
+        return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA);
+    }
+
+    @VisibleForTesting
+    boolean isPowerSaveMode() {
+        return mPowerManager.isPowerSaveMode();
+    }
+
     @Override
     public CharSequence getSummary() {
         int activeStringId = R.string.auto_rotate_option_off;
@@ -89,7 +129,11 @@
                     mContext.getContentResolver(),
                     CAMERA_AUTOROTATE,
                     0, UserHandle.USER_CURRENT);
-            activeStringId = cameraRotate == 1 ? R.string.auto_rotate_option_face_based
+            activeStringId = cameraRotate == 1 && isRotationResolverServiceAvailable(mContext)
+                    && hasSufficientPermission(mContext)
+                    && !isCameraLocked()
+                    && !isPowerSaveMode()
+                    ? R.string.auto_rotate_option_face_based
                     : R.string.auto_rotate_option_on;
         }
         return mContext.getString(activeStringId);
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index f461fe1..7d722fc 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -100,9 +100,6 @@
         } else {
             disclosure.append(mResources.getString(R.string.do_disclosure_generic));
         }
-        disclosure.append(mResources.getString(R.string.do_disclosure_learn_more_separator));
-        disclosure.append(mResources.getString(R.string.learn_more),
-                new EnterprisePrivacySpan(mContext), 0);
         return disclosure;
     }
 
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 891b6d6..1dc572d 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -55,6 +55,7 @@
 import com.android.settingslib.utils.StringUtil;
 
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.List;
 
 /**
@@ -66,6 +67,7 @@
     static final boolean USE_FAKE_DATA = false;
     private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20;
     private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
+    private static final String MEDIASERVER_PACKAGE_NAME = "mediaserver";
 
     private final String mPreferenceKey;
     @VisibleForTesting
@@ -303,27 +305,17 @@
         final ArrayList<BatteryEntry> results = new ArrayList<>();
         final List<UidBatteryConsumer> uidBatteryConsumers =
                 mBatteryUsageStats.getUidBatteryConsumers();
+
+        // Sort to have all apps with "real" UIDs first, followed by apps that are supposed
+        // to be combined with the real ones.
+        uidBatteryConsumers.sort(Comparator.comparingInt(
+                consumer -> consumer.getUid() == getRealUid(consumer) ? 0 : 1));
+
         for (int i = 0, size = uidBatteryConsumers.size(); i < size; i++) {
             final UidBatteryConsumer consumer = uidBatteryConsumers.get(i);
-            int realUid = consumer.getUid();
+            final int uid = getRealUid(consumer);
 
-            // Check if this UID is a shared GID. If so, we combine it with the OWNER's
-            // actual app UID.
-            if (isSharedGid(consumer.getUid())) {
-                realUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
-                        UserHandle.getAppIdFromSharedAppGid(consumer.getUid()));
-            }
-
-            // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
-            if (isSystemUid(realUid)
-                    && !"mediaserver".equals(consumer.getPackageWithHighestDrain())) {
-                // Use the system UID for all UIDs running in their own sandbox that
-                // are not apps. We exclude mediaserver because we already are expected to
-                // report that as a separate item.
-                realUid = Process.SYSTEM_UID;
-            }
-
-            final String[] packages = mPackageManager.getPackagesForUid(consumer.getUid());
+            final String[] packages = mPackageManager.getPackagesForUid(uid);
             if (mBatteryUtils.shouldHideUidBatteryConsumerUnconditionally(consumer, packages)) {
                 continue;
             }
@@ -333,11 +325,11 @@
                 continue;
             }
 
-            final int index = batteryEntryList.indexOfKey(realUid);
+            final int index = batteryEntryList.indexOfKey(uid);
             if (index < 0) {
                 // New entry.
-                batteryEntryList.put(realUid, new BatteryEntry(mContext, mHandler, mUserManager,
-                        consumer, isHidden, packages, null, loadDataInBackground));
+                batteryEntryList.put(uid, new BatteryEntry(mContext, mHandler, mUserManager,
+                        consumer, isHidden, uid, packages, null, loadDataInBackground));
             } else {
                 // Combine BatterySippers if we already have one with this UID.
                 final BatteryEntry existingSipper = batteryEntryList.valueAt(index);
@@ -385,7 +377,8 @@
             for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) {
                 final UserBatteryConsumer consumer = userBatteryConsumers.get(i);
                 results.add(new BatteryEntry(mContext, mHandler, mUserManager,
-                        consumer, /* isHidden */ true, null, null, loadDataInBackground));
+                        consumer, /* isHidden */ true, Process.INVALID_UID, null, null,
+                        loadDataInBackground));
             }
         }
 
@@ -400,6 +393,27 @@
         return results;
     }
 
+    private int getRealUid(UidBatteryConsumer consumer) {
+        int realUid = consumer.getUid();
+
+        // Check if this UID is a shared GID. If so, we combine it with the OWNER's
+        // actual app UID.
+        if (isSharedGid(consumer.getUid())) {
+            realUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
+                    UserHandle.getAppIdFromSharedAppGid(consumer.getUid()));
+        }
+
+        // Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
+        if (isSystemUid(realUid)
+                && !MEDIASERVER_PACKAGE_NAME.equals(consumer.getPackageWithHighestDrain())) {
+            // Use the system UID for all UIDs running in their own sandbox that
+            // are not apps. We exclude mediaserver because we already are expected to
+            // report that as a separate item.
+            realUid = Process.SYSTEM_UID;
+        }
+        return realUid;
+    }
+
     @VisibleForTesting
     void setUsageSummary(Preference preference, BatteryEntry entry) {
         // Only show summary when usage time is longer than one minute
diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
index ffbd2d9..3c9cbaa 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
@@ -272,7 +272,7 @@
             final Map<String, BatteryHistEntry> entryMap = batteryHistoryMap.get(timestamp);
             if (entryMap == null || entryMap.isEmpty()) {
                 Log.e(TAG, "abnormal entry list in the timestamp:"
-                    + ConvertUtils.utcToLocalTime(timestamp));
+                    + ConvertUtils.utcToLocalTime(mPrefContext, timestamp));
                 continue;
             }
             // Averages the battery level in each time slot to avoid corner conditions.
@@ -287,7 +287,7 @@
         Log.d(TAG, String.format(
             "setBatteryHistoryMap() size=%d\nkeys=%s\nlevels=%s",
             batteryHistoryMap.size(),
-            utcToLocalTime(mBatteryHistoryKeys),
+            utcToLocalTime(mPrefContext, mBatteryHistoryKeys),
             Arrays.toString(mBatteryHistoryLevels)));
 
         // Loads item icon and label in the background.
@@ -496,9 +496,9 @@
         if (mTrapezoidIndex < 0) {
             return null;
         }
-        final String fromHour = ConvertUtils.utcToLocalTimeHour(
+        final String fromHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
             mBatteryHistoryKeys[mTrapezoidIndex * 2], mIs24HourFormat);
-        final String toHour = ConvertUtils.utcToLocalTimeHour(
+        final String toHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
             mBatteryHistoryKeys[(mTrapezoidIndex + 1) * 2], mIs24HourFormat);
         return String.format("%s - %s", fromHour, toHour);
     }
@@ -584,11 +584,11 @@
         mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
     }
 
-    private static String utcToLocalTime(long[] timestamps) {
+    private static String utcToLocalTime(Context context, long[] timestamps) {
         final StringBuilder builder = new StringBuilder();
         for (int index = 0; index < timestamps.length; index++) {
             builder.append(String.format("%s| ",
-                  ConvertUtils.utcToLocalTime(timestamps[index])));
+                  ConvertUtils.utcToLocalTime(context, timestamps[index])));
         }
         return builder.toString();
     }
diff --git a/src/com/android/settings/fuelgauge/BatteryChartView.java b/src/com/android/settings/fuelgauge/BatteryChartView.java
index ed64177..b721f14 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartView.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartView.java
@@ -56,14 +56,8 @@
     private static final List<String> ACCESSIBILITY_SERVICE_NAMES =
         Arrays.asList("SwitchAccessService", "TalkBackService", "JustSpeakService");
 
-    // For drawing the percentage information.
-    private static final String[] PERCENTAGES = new String[] {
-            formatPercentage(/*percentage=*/ 100, /*round=*/ true),
-            formatPercentage(/*percentage=*/ 50, /*round=*/ true),
-            formatPercentage(/*percentage=*/ 0, /*round=*/ true)};
-
     private static final int DEFAULT_TRAPEZOID_COUNT = 12;
-    private static final int DEFAULT_TIMESTAMP_COUNT = 4;
+    private static final int DEFAULT_TIMESTAMP_COUNT = 5;
     private static final int DIVIDER_COLOR = Color.parseColor("#CDCCC5");
     private static final long UPDATE_STATE_DELAYED_TIME = 500L;
 
@@ -82,6 +76,7 @@
     private float mTrapezoidVOffset;
     private float mTrapezoidHOffset;
     private boolean mIsSlotsClickabled;
+    private String[] mPercentages = getPercentages();
 
     @VisibleForTesting int mSelectedIndex;
     @VisibleForTesting String[] mTimestamps;
@@ -96,7 +91,7 @@
         new Rect[] {new Rect(), new Rect(), new Rect()};
     // For drawing the timestamp information.
     private final Rect[] mTimestampsBounds =
-        new Rect[] {new Rect(), new Rect(), new Rect(), new Rect()};
+        new Rect[] {new Rect(), new Rect(), new Rect(), new Rect(), new Rect()};
 
     @VisibleForTesting
     Handler mHandler = new Handler();
@@ -107,6 +102,7 @@
     private Paint mTextPaint;
     private Paint mDividerPaint;
     private Paint mTrapezoidPaint;
+
     @VisibleForTesting
     Paint mTrapezoidCurvePaint = null;
     private TrapezoidSlot[] mTrapezoidSlots;
@@ -201,12 +197,13 @@
         if (mTimestamps == null) {
             mTimestamps = new String[DEFAULT_TIMESTAMP_COUNT];
         }
-        final long timeSlotOffset = DateUtils.HOUR_IN_MILLIS * 8;
+        final long timeSlotOffset = DateUtils.HOUR_IN_MILLIS * 6;
         final boolean is24HourFormat = DateFormat.is24HourFormat(getContext());
         for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
             mTimestamps[index] =
                 ConvertUtils.utcToLocalTimeHour(
-                    latestTimestamp - (3 - index) * timeSlotOffset,
+                    getContext(),
+                    latestTimestamp - (4 - index) * timeSlotOffset,
                     is24HourFormat);
         }
         requestLayout();
@@ -217,9 +214,9 @@
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         // Measures text bounds and updates indent configuration.
         if (mTextPaint != null) {
-            for (int index = 0; index < PERCENTAGES.length; index++) {
+            for (int index = 0; index < mPercentages.length; index++) {
                 mTextPaint.getTextBounds(
-                    PERCENTAGES[index], 0, PERCENTAGES[index].length(),
+                    mPercentages[index], 0, mPercentages[index].length(),
                     mPercentageBounds[index]);
             }
             // Updates the indent configurations.
@@ -396,7 +393,7 @@
     private void drawPercentage(Canvas canvas, int index, float offsetY) {
         if (mTextPaint != null) {
             canvas.drawText(
-                PERCENTAGES[index],
+                mPercentages[index],
                 getWidth() - mPercentageBounds[index].width() - mPercentageBounds[index].left,
                 offsetY + mPercentageBounds[index].height() *.5f,
                 mTextPaint);
@@ -429,7 +426,7 @@
             final float baselineX = mDividerWidth * .5f;
             final float offsetX = mDividerWidth + unitWidth;
             for (int index = 0; index < DEFAULT_TIMESTAMP_COUNT; index++) {
-                xOffsets[index] = baselineX + index * offsetX * 4;
+                xOffsets[index] = baselineX + index * offsetX * 3;
             }
             drawTimestamp(canvas, xOffsets);
         }
@@ -443,11 +440,11 @@
             getTimestampY(0), mTextPaint);
         // Draws the last timestamp info.
         canvas.drawText(
-            mTimestamps[3],
-            xOffsets[3] - mTimestampsBounds[3].width() - mTimestampsBounds[3].left,
-            getTimestampY(3), mTextPaint);
+            mTimestamps[4],
+            xOffsets[4] - mTimestampsBounds[4].width() - mTimestampsBounds[4].left,
+            getTimestampY(4), mTextPaint);
         // Draws the rest of timestamp info since it is located in the center.
-        for (int index = 1; index <= 2; index++) {
+        for (int index = 1; index <= 3; index++) {
             canvas.drawText(
                 mTimestamps[index],
                 xOffsets[index] -
@@ -544,6 +541,13 @@
                 && mLevels[trapezoidIndex + 1] != 0;
     }
 
+    private static String[] getPercentages() {
+        return new String[] {
+            formatPercentage(/*percentage=*/ 100, /*round=*/ true),
+            formatPercentage(/*percentage=*/ 50, /*round=*/ true),
+            formatPercentage(/*percentage=*/ 0, /*round=*/ true)};
+    }
+
     @VisibleForTesting
     static boolean isAccessibilityEnabled(Context context) {
         final AccessibilityManager accessibilityManager =
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index 78ab962..0478c8b 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -159,12 +159,15 @@
 
     private final Context mContext;
     private final BatteryConsumer mBatteryConsumer;
+    private final int mUid;
     private final boolean mIsHidden;
     @ConvertUtils.ConsumerType
     private final int mConsumerType;
     @BatteryConsumer.PowerComponent
     private final int mPowerComponentId;
     private long mUsageDurationMs;
+    private long mTimeInForegroundMs;
+    private long mTimeInBackgroundMs;
 
     public String name;
     public Drawable icon;
@@ -180,13 +183,13 @@
     }
 
     public BatteryEntry(Context context, Handler handler, UserManager um,
-            @NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages,
+            @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
             String packageName) {
-        this(context, handler, um, batteryConsumer, isHidden, packages, packageName, true);
+        this(context, handler, um, batteryConsumer, isHidden, uid, packages, packageName, true);
     }
 
     public BatteryEntry(Context context, Handler handler, UserManager um,
-            @NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages,
+            @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
             String packageName, boolean loadDataInBackground) {
         sHandler = handler;
         mContext = context;
@@ -196,11 +199,11 @@
         mPowerComponentId = -1;
 
         if (batteryConsumer instanceof UidBatteryConsumer) {
+            mUid = uid;
             mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
             mConsumedPower = batteryConsumer.getConsumedPower();
 
             UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
-            int uid = uidBatteryConsumer.getUid();
             if (mDefaultPackageName == null) {
                 // Apps should only have one package
                 if (packages != null && packages.length == 1) {
@@ -222,7 +225,12 @@
                 }
             }
             getQuickNameIconForUid(uid, packages, loadDataInBackground);
+            mTimeInForegroundMs =
+                    uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND);
+            mTimeInBackgroundMs =
+                    uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND);
         } else if (batteryConsumer instanceof UserBatteryConsumer) {
+            mUid = Process.INVALID_UID;
             mConsumerType = ConvertUtils.CONSUMER_TYPE_USER_BATTERY;
             mConsumedPower = batteryConsumer.getConsumedPower();
             final NameAndIcon nameAndIcon = getNameAndIconFromUserId(
@@ -239,6 +247,7 @@
             double appsPowerMah, long usageDurationMs) {
         mContext = context;
         mBatteryConsumer = null;
+        mUid = Process.INVALID_UID;
         mIsHidden = false;
         mPowerComponentId = powerComponentId;
         mConsumedPower =
@@ -261,6 +270,7 @@
             double devicePowerMah, double appsPowerMah) {
         mContext = context;
         mBatteryConsumer = null;
+        mUid = Process.INVALID_UID;
         mIsHidden = false;
         mPowerComponentId = powerComponentId;
 
@@ -438,7 +448,7 @@
      */
     public String getKey() {
         if (mBatteryConsumer instanceof UidBatteryConsumer) {
-            return Integer.toString(((UidBatteryConsumer) mBatteryConsumer).getUid());
+            return Integer.toString(mUid);
         } else if (mBatteryConsumer instanceof UserBatteryConsumer) {
             return "U|" + ((UserBatteryConsumer) mBatteryConsumer).getUserId();
         } else {
@@ -482,11 +492,7 @@
      * Returns the UID of the app described by this entry.
      */
     public int getUid() {
-        if (mBatteryConsumer instanceof UidBatteryConsumer) {
-            return ((UidBatteryConsumer) mBatteryConsumer).getUid();
-        } else {
-            return Process.INVALID_UID;
-        }
+        return mUid;
     }
 
     /**
@@ -494,8 +500,7 @@
      */
     public long getTimeInForegroundMs() {
         if (mBatteryConsumer instanceof UidBatteryConsumer) {
-            return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
-                    UidBatteryConsumer.STATE_FOREGROUND);
+            return mTimeInForegroundMs;
         } else {
             return mUsageDurationMs;
         }
@@ -506,8 +511,7 @@
      */
     public long getTimeInBackgroundMs() {
         if (mBatteryConsumer instanceof UidBatteryConsumer) {
-            return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
-                    UidBatteryConsumer.STATE_BACKGROUND);
+            return mTimeInBackgroundMs;
         } else {
             return 0;
         }
@@ -526,9 +530,15 @@
      */
     public void add(BatteryConsumer batteryConsumer) {
         mConsumedPower += batteryConsumer.getConsumedPower();
-        if (mDefaultPackageName == null && batteryConsumer instanceof UidBatteryConsumer) {
-            mDefaultPackageName =
-                    ((UidBatteryConsumer) batteryConsumer).getPackageWithHighestDrain();
+        if (batteryConsumer instanceof UidBatteryConsumer) {
+            UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
+            mTimeInForegroundMs += uidBatteryConsumer.getTimeInStateMs(
+                    UidBatteryConsumer.STATE_FOREGROUND);
+            mTimeInBackgroundMs += uidBatteryConsumer.getTimeInStateMs(
+                    UidBatteryConsumer.STATE_BACKGROUND);
+            if (mDefaultPackageName == null) {
+                mDefaultPackageName = uidBatteryConsumer.getPackageWithHighestDrain();
+            }
         }
     }
 
diff --git a/src/com/android/settings/fuelgauge/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
index d83d814..4c8ecee 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistEntry.java
@@ -184,7 +184,8 @@
 
     @Override
     public String toString() {
-        final String recordAtDateTime = ConvertUtils.utcToLocalTime(mTimestamp);
+        final String recordAtDateTime =
+            ConvertUtils.utcToLocalTime(/*context=*/ null, mTimestamp);
         final StringBuilder builder = new StringBuilder()
             .append("\nBatteryHistEntry{")
             .append(String.format("\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b",
diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java
index 1980564..01f510e 100644
--- a/src/com/android/settings/fuelgauge/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/ConvertUtils.java
@@ -17,6 +17,7 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.os.BatteryUsageStats;
+import android.os.LocaleList;
 import android.os.UserHandle;
 import android.text.format.DateUtils;
 import android.util.Log;
@@ -133,8 +134,8 @@
     }
 
     /** Converts UTC timestamp to human readable local time string. */
-    public static String utcToLocalTime(long timestamp) {
-        final Locale currentLocale = Locale.getDefault();
+    public static String utcToLocalTime(Context context, long timestamp) {
+        final Locale currentLocale = getLocale(context);
         final String currentZoneId = TimeZone.getDefault().getID();
         if (!currentZoneId.equals(sZoneId)
                 || !currentLocale.equals(sLocale)
@@ -148,8 +149,9 @@
     }
 
     /** Converts UTC timestamp to local time hour data. */
-    public static String utcToLocalTimeHour(long timestamp, boolean is24HourFormat) {
-        final Locale currentLocale = Locale.getDefault();
+    public static String utcToLocalTimeHour(
+            Context context, long timestamp, boolean is24HourFormat) {
+        final Locale currentLocale = getLocale(context);
         final String currentZoneId = TimeZone.getDefault().getID();
         if (!currentZoneId.equals(sZoneIdForHour)
                 || !currentLocale.equals(sLocaleForHour)
@@ -159,7 +161,7 @@
             sZoneIdForHour = currentZoneId;
             sIs24HourFormat = is24HourFormat;
             sSimpleDateFormatForHour = new SimpleDateFormat(
-                    sIs24HourFormat ? "HH" : "h aa", currentLocale);
+                    sIs24HourFormat ? "HH" : "h", currentLocale);
         }
         return sSimpleDateFormatForHour.format(new Date(timestamp))
             .toLowerCase(currentLocale);
@@ -356,4 +358,15 @@
                 ? entry3 : null;
         }
     }
+
+    @VisibleForTesting
+    static Locale getLocale(Context context) {
+        if (context == null) {
+            return Locale.getDefault();
+        }
+        final LocaleList locales =
+            context.getResources().getConfiguration().getLocales();
+        return locales != null && !locales.isEmpty() ? locales.get(0)
+            : Locale.getDefault();
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
index 04ddb04..3e62ea1 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
@@ -28,7 +28,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.Utils;
-import com.android.settingslib.widget.SeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 
 /**
  * Responds to user actions in the Settings > Battery > Set a Schedule Screen for the seekbar.
@@ -55,6 +55,7 @@
     public BatterySaverScheduleSeekBarController(Context context) {
         mContext = context;
         mSeekBarPreference = new SeekBarPreference(context);
+        mSeekBarPreference.setLayoutResource(R.layout.battery_saver_schedule_percentage_seekbar);
         mSeekBarPreference.setOnPreferenceChangeListener(this);
         mSeekBarPreference.setContinuousUpdates(true);
         mSeekBarPreference.setMax(MAX_SEEKBAR_VALUE);
diff --git a/src/com/android/settings/gestures/GestureNavigationSettingsAssistController.java b/src/com/android/settings/gestures/GestureNavigationSettingsAssistController.java
index 5c49538..95fd9f1 100644
--- a/src/com/android/settings/gestures/GestureNavigationSettingsAssistController.java
+++ b/src/com/android/settings/gestures/GestureNavigationSettingsAssistController.java
@@ -26,18 +26,16 @@
  */
 public class GestureNavigationSettingsAssistController extends TogglePreferenceController {
 
-    // This value is based on SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
-    // behaviour. We assume that the gestures are enabled by default.
-    private static final int ASSIST_TOUCH_GESTURE_DEFAULT_VALUE = 1;
-
     public GestureNavigationSettingsAssistController(Context context, String key) {
         super(context, key);
     }
 
     @Override
     public boolean isChecked() {
+        boolean onByDefault = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_assistTouchGestureEnabledDefault);
         return Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, ASSIST_TOUCH_GESTURE_DEFAULT_VALUE)
+                Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, onByDefault ? 1 : 0)
                 == 1;
     }
 
diff --git a/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
index 9ec7424..546581b 100644
--- a/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
+++ b/src/com/android/settings/gestures/GestureNavigationSettingsFragment.java
@@ -27,9 +27,9 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.LabeledSeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.widget.LabeledSeekBarPreference;
-import com.android.settingslib.widget.SeekBarPreference;
 
 /**
  * A fragment to include all the settings related to Gesture Navigation mode.
diff --git a/src/com/android/settings/location/LocationInjectedServiceBasePreferenceController.java b/src/com/android/settings/location/LocationInjectedServiceBasePreferenceController.java
new file mode 100644
index 0000000..3b593b9
--- /dev/null
+++ b/src/com/android/settings/location/LocationInjectedServiceBasePreferenceController.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2021 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.location;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.location.SettingInjectorService;
+import android.os.UserHandle;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.OnLifecycleEvent;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.Utils;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A abstract class which is responsible for creating the injected location services items.
+ * Developer needs to implement the {@link #injectLocationServices(PreferenceScreen)}.
+ */
+public abstract class LocationInjectedServiceBasePreferenceController
+        extends LocationBasePreferenceController implements LifecycleObserver{
+
+    private static final String TAG = "LocationPrefCtrl";
+    @VisibleForTesting
+    static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED =
+            new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
+
+    @VisibleForTesting
+    AppSettingsInjector mInjector;
+    /** Receives UPDATE_INTENT */
+    @VisibleForTesting
+    BroadcastReceiver mInjectedSettingsReceiver;
+
+    public LocationInjectedServiceBasePreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public void init(DashboardFragment fragment) {
+        super.init(fragment);
+        mInjector = new AppSettingsInjector(mContext, getMetricsCategory());
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        injectLocationServices(screen);
+    }
+
+    /**
+     * Override this method to inject location services in preference screen.
+     * @param screen
+     */
+    protected abstract void injectLocationServices(PreferenceScreen screen);
+
+    @Override
+    public void onLocationModeChanged(int mode, boolean restricted) {
+        // As a safety measure, also reloads on location mode change to ensure the settings are
+        // up-to-date even if an affected app doesn't send the setting changed broadcast.
+        mInjector.reloadStatusMessages();
+    }
+
+    /** @OnLifecycleEvent(ON_RESUME) */
+    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
+    public void onResume() {
+        if (mInjectedSettingsReceiver == null) {
+            mInjectedSettingsReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (Log.isLoggable(TAG, Log.DEBUG)) {
+                        Log.d(TAG, "Received settings change intent: " + intent);
+                    }
+                    mInjector.reloadStatusMessages();
+                }
+            };
+        }
+        mContext.registerReceiver(
+                mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED);
+    }
+
+    /** @OnLifecycleEvent(ON_PAUSE) */
+    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+    public void onPause() {
+        mContext.unregisterReceiver(mInjectedSettingsReceiver);
+    }
+
+    protected Map<Integer, List<Preference>> getLocationServices() {
+        // If location access is locked down by device policy then we only show injected settings
+        // for the primary profile.
+        final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
+
+        return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
+                (profileUserId != UserHandle.USER_NULL
+                        && mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
+                        ? UserHandle.myUserId() : UserHandle.USER_CURRENT);
+    }
+}
diff --git a/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java b/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java
index 571b4a7..b7e6cf2 100644
--- a/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java
+++ b/src/com/android/settings/location/LocationInjectedServicesForWorkPreferenceController.java
@@ -20,6 +20,8 @@
 import android.os.UserHandle;
 
 import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
 
 import com.android.settings.widget.RestrictedAppPreference;
 
@@ -30,7 +32,7 @@
  * Retrieve the Location Services used in work profile user.
  */
 public class LocationInjectedServicesForWorkPreferenceController extends
-        LocationInjectedServicesPreferenceController {
+        LocationInjectedServiceBasePreferenceController {
     private static final String TAG = "LocationWorkPrefCtrl";
 
     public LocationInjectedServicesForWorkPreferenceController(Context context, String key) {
@@ -38,10 +40,10 @@
     }
 
     @Override
-    public void updateState(Preference preference) {
-        mCategoryLocationServices.removeAll();
+    protected void injectLocationServices(PreferenceScreen screen) {
+        final PreferenceCategory categoryLocationServices =
+                screen.findPreference(getPreferenceKey());
         final Map<Integer, List<Preference>> prefs = getLocationServices();
-        boolean show = false;
         for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
             for (Preference pref : entry.getValue()) {
                 if (pref instanceof RestrictedAppPreference) {
@@ -49,11 +51,8 @@
                 }
             }
             if (entry.getKey() != UserHandle.myUserId()) {
-                LocationSettings.addPreferencesSorted(entry.getValue(),
-                        mCategoryLocationServices);
-                show = true;
+                LocationSettings.addPreferencesSorted(entry.getValue(), categoryLocationServices);
             }
         }
-        mCategoryLocationServices.setVisible(show);
     }
 }
diff --git a/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java b/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java
index 8573307..d623bae 100644
--- a/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java
+++ b/src/com/android/settings/location/LocationInjectedServicesPreferenceController.java
@@ -15,25 +15,14 @@
  */
 package com.android.settings.location;
 
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.location.SettingInjectorService;
 import android.os.UserHandle;
-import android.util.Log;
 
-import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
 
-import com.android.settings.Utils;
-import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.widget.RestrictedAppPreference;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnPause;
-import com.android.settingslib.core.lifecycle.events.OnResume;
 
 import java.util.List;
 import java.util.Map;
@@ -41,42 +30,20 @@
 /**
  * Preference controller for the injected Location Services.
  */
-public class LocationInjectedServicesPreferenceController extends LocationBasePreferenceController
-        implements LifecycleObserver, OnResume, OnPause {
+public class LocationInjectedServicesPreferenceController
+        extends LocationInjectedServiceBasePreferenceController {
 
     private static final String TAG = "LocationPrefCtrl";
-    @VisibleForTesting
-    static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED =
-            new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
-
-    protected PreferenceCategory mCategoryLocationServices;
-    @VisibleForTesting
-    AppSettingsInjector mInjector;
-    /** Receives UPDATE_INTENT */
-    @VisibleForTesting
-    BroadcastReceiver mInjectedSettingsReceiver;
 
     public LocationInjectedServicesPreferenceController(Context context, String key) {
         super(context, key);
     }
 
     @Override
-    public void init(DashboardFragment fragment) {
-        super.init(fragment);
-        mInjector = new AppSettingsInjector(mContext, getMetricsCategory());
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mCategoryLocationServices = screen.findPreference(getPreferenceKey());
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        mCategoryLocationServices.removeAll();
+    protected void injectLocationServices(PreferenceScreen screen) {
+        final PreferenceCategory categoryLocationServices =
+                screen.findPreference(getPreferenceKey());
         final Map<Integer, List<Preference>> prefs = getLocationServices();
-        boolean show = false;
         for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
             for (Preference pref : entry.getValue()) {
                 if (pref instanceof RestrictedAppPreference) {
@@ -84,53 +51,11 @@
                 }
             }
             if (entry.getKey() == UserHandle.myUserId()) {
-                if (mCategoryLocationServices != null) {
+                if (categoryLocationServices != null) {
                     LocationSettings.addPreferencesSorted(entry.getValue(),
-                            mCategoryLocationServices);
+                            categoryLocationServices);
                 }
-                show = true;
             }
         }
-        mCategoryLocationServices.setVisible(show);
-    }
-
-    @Override
-    public void onLocationModeChanged(int mode, boolean restricted) {
-        // As a safety measure, also reloads on location mode change to ensure the settings are
-        // up-to-date even if an affected app doesn't send the setting changed broadcast.
-        mInjector.reloadStatusMessages();
-    }
-
-    @Override
-    public void onResume() {
-        if (mInjectedSettingsReceiver == null) {
-            mInjectedSettingsReceiver = new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    if (Log.isLoggable(TAG, Log.DEBUG)) {
-                        Log.d(TAG, "Received settings change intent: " + intent);
-                    }
-                    mInjector.reloadStatusMessages();
-                }
-            };
-        }
-        mContext.registerReceiver(
-                mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED);
-    }
-
-    @Override
-    public void onPause() {
-        mContext.unregisterReceiver(mInjectedSettingsReceiver);
-    }
-
-    protected Map<Integer, List<Preference>> getLocationServices() {
-        // If location access is locked down by device policy then we only show injected settings
-        // for the primary profile.
-        final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
-
-        return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
-                (profileUserId != UserHandle.USER_NULL
-                        && mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
-                        ? UserHandle.myUserId() : UserHandle.USER_CURRENT);
     }
 }
diff --git a/src/com/android/settings/network/InternetPreferenceController.java b/src/com/android/settings/network/InternetPreferenceController.java
index 639bab5..a58e69a 100644
--- a/src/com/android/settings/network/InternetPreferenceController.java
+++ b/src/com/android/settings/network/InternetPreferenceController.java
@@ -65,7 +65,7 @@
     @VisibleForTesting
     static Map<Integer, Integer> sIconMap = new HashMap<>();
     static {
-        sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_airplane);
+        sIconMap.put(INTERNET_OFF, R.drawable.ic_no_internet_unavailable);
         sIconMap.put(INTERNET_NETWORKS_AVAILABLE, R.drawable.ic_no_internet_available);
         sIconMap.put(INTERNET_WIFI, R.drawable.ic_wifi_signal_4);
         sIconMap.put(INTERNET_CELLULAR, R.drawable.ic_network_cell);
diff --git a/src/com/android/settings/network/ProviderModelSlice.java b/src/com/android/settings/network/ProviderModelSlice.java
index b778a05..cfaef53 100644
--- a/src/com/android/settings/network/ProviderModelSlice.java
+++ b/src/com/android/settings/network/ProviderModelSlice.java
@@ -46,6 +46,7 @@
 import com.android.settings.network.telephony.NetworkProviderWorker;
 import com.android.settings.slices.CustomSliceable;
 import com.android.settings.slices.SliceBackgroundWorker;
+import com.android.settings.slices.SliceBroadcastReceiver;
 import com.android.settings.slices.SliceBuilderUtils;
 import com.android.settings.wifi.WifiUtils;
 import com.android.settings.wifi.slice.WifiSlice;
@@ -163,6 +164,18 @@
         return listBuilder.build();
     }
 
+    @Override
+    public PendingIntent getBroadcastIntent(Context context) {
+        final Intent intent = new Intent(getUri().toString())
+                // The FLAG_RECEIVER_FOREGROUND flag is necessary to avoid the intent delay of
+                // the first sending after the device restarts
+                .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+                .setData(getUri())
+                .setClass(context, SliceBroadcastReceiver.class);
+        return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
+                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+    }
+
     /**
      * Update the current carrier's mobile data status.
      */
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index 2d23f1f..8c7347b 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -29,6 +29,7 @@
 import android.content.IntentFilter;
 import android.graphics.drawable.Drawable;
 import android.net.wifi.WifiManager;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -38,6 +39,7 @@
 import android.telephony.TelephonyManager;
 import android.text.Html;
 import android.util.ArraySet;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.collection.ArrayMap;
@@ -55,7 +57,7 @@
 import com.android.settings.network.telephony.MobileNetworkUtils;
 import com.android.settings.network.telephony.SignalStrengthListener;
 import com.android.settings.network.telephony.TelephonyDisplayInfoListener;
-import com.android.settings.widget.GearPreference;
+import com.android.settings.widget.MutableGearPreference;
 import com.android.settings.wifi.WifiPickerTrackerHelper;
 import com.android.settingslib.SignalIcon.MobileIconGroup;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -115,7 +117,7 @@
     // Map of subscription id to Preference
     private Map<Integer, Preference> mSubscriptionPreferences;
     private int mStartOrder;
-    private GearPreference mSubsGearPref;
+    private MutableGearPreference mSubsGearPref;
     private Config mConfig = null;
     private SubsPrefCtrlInjector mSubsPrefCtrlInjector;
     private TelephonyDisplayInfo mTelephonyDisplayInfo =
@@ -196,6 +198,7 @@
         mSignalStrengthListener.pause();
         mTelephonyDisplayInfoListener.pause();
         unRegisterReceiver();
+        resetProviderPreferenceSummary();
     }
 
     @Override
@@ -238,15 +241,20 @@
         }
         if (mSubsGearPref == null) {
             mPreferenceGroup.removeAll();
-            mSubsGearPref = new GearPreference(mContext, null);
+            mSubsGearPref = new MutableGearPreference(mContext, null);
             mSubsGearPref.setOnPreferenceClickListener(preference -> {
                 connectCarrierNetwork();
                 return true;
             });
+
             mSubsGearPref.setOnGearClickListener(p ->
                     startMobileNetworkActivity(mContext, subInfo.getSubscriptionId()));
         }
 
+        if (!(mContext.getSystemService(UserManager.class)).isAdminUser()) {
+            mSubsGearPref.setGearEnabled(false);
+        }
+
         mSubsGearPref.setTitle(SubscriptionUtil.getUniqueSubscriptionDisplayName(
                 subInfo, mContext));
         mSubsGearPref.setOrder(mStartOrder);
@@ -275,6 +283,7 @@
         String result = mSubsPrefCtrlInjector.getNetworkType(
                 mContext, mConfig, mTelephonyDisplayInfo, subId, isActiveCarrierNetwork);
         if (mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext) || isActiveCarrierNetwork) {
+            Log.i(TAG, "Active cellular network or active carrier network.");
             result = mContext.getString(R.string.preference_summary_default_combination,
                     mContext.getString(R.string.mobile_data_connection_active), result);
         } else if (!isDataInService) {
@@ -316,6 +325,13 @@
         return icon;
     }
 
+    private void resetProviderPreferenceSummary() {
+        if (mSubsGearPref == null) {
+            return;
+        }
+        mSubsGearPref.setSummary("");
+    }
+
     private void updateForBase() {
         final Map<Integer, Preference> existingPrefs = mSubscriptionPreferences;
         mSubscriptionPreferences = new ArrayMap<>();
diff --git a/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java b/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
index 3423ad8..b4ab2a0 100644
--- a/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
+++ b/src/com/android/settings/network/telephony/NetworkProviderWifiCallingGroup.java
@@ -47,6 +47,7 @@
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -86,7 +87,8 @@
     }
 
     private void setSubscriptionInfoList(Context context) {
-        mSubInfoListForWfc = SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager);
+        mSubInfoListForWfc = new ArrayList<>(
+                SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager));
         if (mSubInfoListForWfc != null) {
             mSubInfoListForWfc.removeIf(info -> {
                 final int subId = info.getSubscriptionId();
diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
index 0064e6c..146b575 100644
--- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
@@ -30,12 +30,14 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.SidecarFragment;
+import com.android.settings.core.SettingsBaseActivity;
 import com.android.settings.network.EnableMultiSimSidecar;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.network.SwitchToEuiccSubscriptionSidecar;
 import com.android.settings.network.SwitchToRemovableSlotSidecar;
 import com.android.settings.network.UiccSlotUtil;
 import com.android.settings.sim.SimActivationNotifier;
+import com.android.settingslib.transition.SettingsTransitionHelper;
 
 import com.google.common.collect.ImmutableList;
 
@@ -68,6 +70,9 @@
         Intent intent = new Intent(context, ToggleSubscriptionDialogActivity.class);
         intent.putExtra(ARG_SUB_ID, subId);
         intent.putExtra(ARG_enable, enable);
+        // suppress page transition as this is a dialog
+        intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
+                SettingsTransitionHelper.TransitionType.TRANSITION_NONE);
         return intent;
     }
 
diff --git a/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java b/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java
index 651df01..f75fd4b 100644
--- a/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java
+++ b/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceController.java
@@ -27,7 +27,7 @@
 
 import com.android.settings.accounts.AccountRestrictionHelper;
 import com.android.settings.core.SliderPreferenceController;
-import com.android.settingslib.Restrictable;
+import com.android.settingslib.RestrictedPreference;
 
 /**
  * Base class for preference controller that handles preference that enforce adjust volume
@@ -51,10 +51,10 @@
 
     @Override
     public void updateState(Preference preference) {
-        if (!(preference instanceof Restrictable)) {
+        if (!(preference instanceof RestrictedPreference)) {
             return;
         }
-        mHelper.enforceRestrictionOnPreference(preference,
+        mHelper.enforceRestrictionOnPreference((RestrictedPreference) preference,
                 UserManager.DISALLOW_ADJUST_VOLUME, UserHandle.myUserId());
     }
 
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index 04ea6b0..36a4d8a 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -32,12 +32,12 @@
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
-import com.android.settingslib.RestrictedSeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 
 import java.util.Objects;
 
 /** A slider preference that directly controls an audio stream volume (no dialog) **/
-public class VolumeSeekBarPreference extends RestrictedSeekBarPreference {
+public class VolumeSeekBarPreference extends SeekBarPreference {
     private static final String TAG = "VolumeSeekBarPreference";
 
     protected SeekBar mSeekBar;
diff --git a/src/com/android/settings/notification/app/BubblePreference.java b/src/com/android/settings/notification/app/BubblePreference.java
index 2774a84..f0046d7 100644
--- a/src/com/android/settings/notification/app/BubblePreference.java
+++ b/src/com/android/settings/notification/app/BubblePreference.java
@@ -22,6 +22,7 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.ImageView;
@@ -32,13 +33,13 @@
 
 import com.android.settings.Utils;
 import com.android.settingslib.R;
-import com.android.settingslib.Restrictable;
+import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedPreferenceHelper;
 
 /**
  * A tri-state preference allowing a user to specify what gets to bubble.
  */
-public class BubblePreference extends Preference implements View.OnClickListener, Restrictable {
+public class BubblePreference extends Preference implements View.OnClickListener {
     RestrictedPreferenceHelper mHelper;
 
     private int mSelectedPreference;
@@ -80,6 +81,12 @@
         return mSelectedPreference;
     }
 
+    public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
+        if (mHelper.setDisabledByAdmin(admin)) {
+            notifyChanged();
+        }
+    }
+
     public void setSelectedVisibility(boolean visible) {
         mSelectedVisible = visible;
         notifyChanged();
@@ -142,16 +149,6 @@
         mBubbleNoneButton.setSelected(mContext, selected == BUBBLE_PREFERENCE_NONE);
     }
 
-    @Override
-    public RestrictedPreferenceHelper getHelper() {
-        return mHelper;
-    }
-
-    @Override
-    public void notifyPreferenceChanged() {
-        notifyChanged();
-    }
-
     private class ButtonViewHolder {
         private View mView;
         private ImageView mImageView;
diff --git a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java
index 5b2cdb9..d715ce4 100644
--- a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java
+++ b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java
@@ -141,9 +141,9 @@
         int order = 100;
         boolean hasClearable = false;
         for (ConversationChannel conversation : conversations) {
-            if (conversation.getParentNotificationChannel().getImportance() == IMPORTANCE_NONE
-                    || (conversation.getParentNotificationChannelGroup() != null
-                    && conversation.getParentNotificationChannelGroup().isBlocked())) {
+            if (conversation.getNotificationChannel().getImportance() == IMPORTANCE_NONE
+                    || (conversation.getNotificationChannelGroup() != null
+                    && conversation.getNotificationChannelGroup().isBlocked())) {
                 continue;
             }
             RecentConversationPreference pref =
@@ -179,12 +179,12 @@
         pref.setSummary(getSummary(conversation));
         pref.setIcon(mBackend.getConversationDrawable(mContext, conversation.getShortcutInfo(),
                 pkg, uid, false));
-        pref.setKey(conversation.getParentNotificationChannel().getId()
+        pref.setKey(conversation.getNotificationChannel().getId()
                 + ":" + conversationId);
         pref.setOnPreferenceClickListener(preference -> {
             mBackend.createConversationNotificationChannel(
                     pkg, uid,
-                    conversation.getParentNotificationChannel(),
+                    conversation.getNotificationChannel(),
                     conversationId);
             getSubSettingLauncher(conversation, pref.getTitle()).launch();
             return true;
@@ -194,11 +194,11 @@
     }
 
     CharSequence getSummary(ConversationChannel conversation) {
-        return conversation.getParentNotificationChannelGroup() == null
-                ? conversation.getParentNotificationChannel().getName()
+        return conversation.getNotificationChannelGroup() == null
+                ? conversation.getNotificationChannel().getName()
                 : mContext.getString(R.string.notification_conversation_summary,
-                        conversation.getParentNotificationChannel().getName(),
-                        conversation.getParentNotificationChannelGroup().getName());
+                        conversation.getNotificationChannel().getName(),
+                        conversation.getNotificationChannelGroup().getName());
     }
 
     CharSequence getTitle(ConversationChannel conversation) {
@@ -213,7 +213,7 @@
         channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME,
                 conversation.getShortcutInfo().getPackage());
         channelArgs.putString(Settings.EXTRA_CHANNEL_ID,
-                conversation.getParentNotificationChannel().getId());
+                conversation.getNotificationChannel().getId());
         channelArgs.putString(Settings.EXTRA_CONVERSATION_ID,
                 conversation.getShortcutInfo().getId());
 
@@ -235,8 +235,8 @@
                             o2.getShortcutInfo().getLabel());
 
                     if (labelComparison == 0) {
-                        return o1.getParentNotificationChannel().getId().compareTo(
-                                o2.getParentNotificationChannel().getId());
+                        return o1.getNotificationChannel().getId().compareTo(
+                                o2.getNotificationChannel().getId());
                     }
 
                     return labelComparison;
diff --git a/src/com/android/settings/security/CredentialManagementAppAdapter.java b/src/com/android/settings/security/CredentialManagementAppAdapter.java
index eb379d5..3f4eb2a 100644
--- a/src/com/android/settings/security/CredentialManagementAppAdapter.java
+++ b/src/com/android/settings/security/CredentialManagementAppAdapter.java
@@ -21,6 +21,7 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.security.AppUriAuthenticationPolicy;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -85,11 +86,13 @@
                 ApplicationInfo applicationInfo =
                         mPackageManager.getApplicationInfo(mCredentialManagerPackage, 0);
                 mAppIconView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo));
-                mTitleView.setText(mContext.getString(R.string.request_manage_credentials_title,
+                mTitleView.setText(TextUtils.expandTemplate(
+                        mContext.getText(R.string.request_manage_credentials_title),
                         applicationInfo.loadLabel(mPackageManager)));
             } catch (PackageManager.NameNotFoundException e) {
                 mAppIconView.setImageDrawable(null);
-                mTitleView.setText(mContext.getString(R.string.request_manage_credentials_title,
+                mTitleView.setText(TextUtils.expandTemplate(
+                        mContext.getText(R.string.request_manage_credentials_title),
                         mCredentialManagerPackage));
             }
         }
diff --git a/src/com/android/settings/security/CredentialManagementAppButtonsController.java b/src/com/android/settings/security/CredentialManagementAppButtonsController.java
index fe5e45b..b296f37 100644
--- a/src/com/android/settings/security/CredentialManagementAppButtonsController.java
+++ b/src/com/android/settings/security/CredentialManagementAppButtonsController.java
@@ -80,12 +80,29 @@
     private void displayButtons(PreferenceScreen screen) {
         if (mHasCredentialManagerPackage) {
             ((ActionButtonsPreference) screen.findPreference(getPreferenceKey()))
-                    .setButton1Text(R.string.remove_credential_management_app)
-                    .setButton1Icon(R.drawable.ic_undo_24)
-                    .setButton1OnClickListener(view -> removeCredentialManagementApp());
+                    .setButton1Text(R.string.uninstall_certs_credential_management_app)
+                    .setButton1Icon(R.drawable.ic_upload)
+                    .setButton1OnClickListener(view -> uninstallCertificates())
+                    .setButton2Text(R.string.remove_credential_management_app)
+                    .setButton2Icon(R.drawable.ic_delete)
+                    .setButton2OnClickListener(view -> removeCredentialManagementApp());
         }
     }
 
+    private void uninstallCertificates() {
+        mExecutor.execute(() -> {
+            try {
+                IKeyChainService service = KeyChain.bind(mContext).getService();
+                for (String existingAlias :
+                        service.getCredentialManagementAppPolicy().getAliases()) {
+                    service.removeKeyPair(existingAlias);
+                }
+            } catch (InterruptedException | RemoteException e) {
+                Log.e(TAG, "Unable to uninstall certificates");
+            }
+        });
+    }
+
     private void removeCredentialManagementApp() {
         mExecutor.execute(() -> {
             try {
diff --git a/src/com/android/settings/security/CredentialManagementAppHeaderController.java b/src/com/android/settings/security/CredentialManagementAppHeaderController.java
index 7b5ffb2..9361fb9 100644
--- a/src/com/android/settings/security/CredentialManagementAppHeaderController.java
+++ b/src/com/android/settings/security/CredentialManagementAppHeaderController.java
@@ -83,7 +83,6 @@
         TextView titleView = headerPref.findViewById(R.id.entity_header_title);
         TextView summary1 = headerPref.findViewById(R.id.entity_header_summary);
         TextView summary2 = headerPref.findViewById(R.id.entity_header_second_summary);
-        summary1.setVisibility(View.GONE);
         summary2.setVisibility(View.GONE);
 
         try {
@@ -91,6 +90,7 @@
                     mPackageManager.getApplicationInfo(mCredentialManagerPackageName, 0);
             appIconView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo));
             titleView.setText(applicationInfo.loadLabel(mPackageManager));
+            summary1.setText(R.string.certificate_management_app_description);
         } catch (PackageManager.NameNotFoundException e) {
             appIconView.setImageDrawable(null);
             titleView.setText(mCredentialManagerPackageName);
diff --git a/src/com/android/settings/security/RequestManageCredentials.java b/src/com/android/settings/security/RequestManageCredentials.java
index eb7a7d8..cda97da 100644
--- a/src/com/android/settings/security/RequestManageCredentials.java
+++ b/src/com/android/settings/security/RequestManageCredentials.java
@@ -21,7 +21,10 @@
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.content.res.Configuration;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -37,7 +40,9 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.Button;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
@@ -83,6 +88,7 @@
     private KeyChain.KeyChainConnection mKeyChainConnection;
 
     private boolean mDisplayingButtonPanel = false;
+    private boolean mIsLandscapeMode = false;
 
     @Override
     public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -114,6 +120,8 @@
                 .setStrings(mCredentialManagerPackage)
                 .write();
         setContentView(R.layout.request_manage_credentials);
+        mIsLandscapeMode = getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE;
 
         mKeyChainTread = new HandlerThread("KeyChainConnection");
         mKeyChainTread.start();
@@ -134,6 +142,9 @@
                         getNumberOfAuthenticationPolicyUris(mAuthenticationPolicy))
                 .write();
 
+        if (mIsLandscapeMode) {
+            loadHeader();
+        }
         loadRecyclerView();
         loadButtons();
         loadExtendedFloatingActionButton();
@@ -193,7 +204,7 @@
 
         CredentialManagementAppAdapter recyclerViewAdapter = new CredentialManagementAppAdapter(
                 this, mCredentialManagerPackage, mAuthenticationPolicy.getAppAndUriMappings(),
-                /* include header= */ true, /* include expander= */ false);
+                /* include header= */ !mIsLandscapeMode, /* include expander= */ false);
         mRecyclerView.setAdapter(recyclerViewAdapter);
     }
 
@@ -214,12 +225,33 @@
     private void loadExtendedFloatingActionButton() {
         mExtendedFab = findViewById(R.id.extended_fab);
         mExtendedFab.setOnClickListener(v -> {
-            mRecyclerView.scrollToPosition(mAuthenticationPolicy.getAppAndUriMappings().size());
+            final int position = mIsLandscapeMode
+                    ? mAuthenticationPolicy.getAppAndUriMappings().size() - 1
+                    : mAuthenticationPolicy.getAppAndUriMappings().size();
+            mRecyclerView.scrollToPosition(position);
             mExtendedFab.hide();
             showButtonPanel();
         });
     }
 
+    private void loadHeader() {
+        final ImageView mAppIconView = findViewById(R.id.credential_management_app_icon);
+        final TextView mTitleView = findViewById(R.id.credential_management_app_title);
+        try {
+            ApplicationInfo applicationInfo =
+                    getPackageManager().getApplicationInfo(mCredentialManagerPackage, 0);
+            mAppIconView.setImageDrawable(getPackageManager().getApplicationIcon(applicationInfo));
+            mTitleView.setText(TextUtils.expandTemplate(
+                    getText(R.string.request_manage_credentials_title),
+                    applicationInfo.loadLabel(getPackageManager())));
+        } catch (PackageManager.NameNotFoundException e) {
+            mAppIconView.setImageDrawable(null);
+            mTitleView.setText(TextUtils.expandTemplate(
+                    getText(R.string.request_manage_credentials_title),
+                    mCredentialManagerPackage));
+        }
+    }
+
     private void setOrUpdateCredentialManagementAppAndFinish() {
         try {
             mKeyChainConnection.getService().setCredentialManagementApp(
diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java
index 30bc633..30e9967 100644
--- a/src/com/android/settings/tts/TextToSpeechSettings.java
+++ b/src/com/android/settings/tts/TextToSpeechSettings.java
@@ -49,9 +49,9 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.GearPreference;
+import com.android.settings.widget.SeekBarPreference;
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.widget.ActionButtonsPreference;
-import com.android.settingslib.widget.SeekBarPreference;
 
 import java.text.Collator;
 import java.util.ArrayList;
diff --git a/src/com/android/settings/widget/CardPreference.java b/src/com/android/settings/widget/CardPreference.java
index 20ea710..c041552 100644
--- a/src/com/android/settings/widget/CardPreference.java
+++ b/src/com/android/settings/widget/CardPreference.java
@@ -29,6 +29,7 @@
  * Preference that wrapped by {@link MaterialCardView}, only support to set icon, title and summary
  */
 public class CardPreference extends Preference {
+
     public CardPreference(Context context) {
         this(context, null /* attrs */);
     }
diff --git a/src/com/android/settings/widget/DefaultIndicatorSeekBar.java b/src/com/android/settings/widget/DefaultIndicatorSeekBar.java
new file mode 100644
index 0000000..d8edf03
--- /dev/null
+++ b/src/com/android/settings/widget/DefaultIndicatorSeekBar.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+
+public class DefaultIndicatorSeekBar extends SeekBar {
+
+    private int mDefaultProgress = -1;
+
+    public DefaultIndicatorSeekBar(Context context) {
+        super(context);
+    }
+
+    public DefaultIndicatorSeekBar(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public DefaultIndicatorSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public DefaultIndicatorSeekBar(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    /**
+     * N.B. Only draws the default indicator tick mark, NOT equally spaced tick marks.
+     */
+    @Override
+    protected void drawTickMarks(Canvas canvas) {
+        if (isEnabled() && mDefaultProgress <= getMax() && mDefaultProgress >= getMin()) {
+            final Drawable defaultIndicator = getTickMark();
+
+            // Adjust the drawable's bounds to center it at the point where it's drawn.
+            final int w = defaultIndicator.getIntrinsicWidth();
+            final int h = defaultIndicator.getIntrinsicHeight();
+            final int halfW = w >= 0 ? w / 2 : 1;
+            final int halfH = h >= 0 ? h / 2 : 1;
+            defaultIndicator.setBounds(-halfW, -halfH, halfW, halfH);
+
+            // This mimics the computation of the thumb position, to get the true "default."
+            final int availableWidth = getWidth() - mPaddingLeft - mPaddingRight;
+            final int range = getMax() - getMin();
+            final float scale = range > 0f ? mDefaultProgress / (float) range : 0f;
+            final int offset = (int) ((scale * availableWidth) + 0.5f);
+            final int indicatorPosition = isLayoutRtl() && getMirrorForRtl()
+                    ? availableWidth - offset + mPaddingRight : offset + mPaddingLeft;
+
+            final int saveCount = canvas.save();
+            canvas.translate(indicatorPosition, getHeight() / 2);
+            defaultIndicator.draw(canvas);
+            canvas.restoreToCount(saveCount);
+        }
+    }
+
+    /**
+     * N.B. This sets the default *unadjusted* progress, i.e. in the SeekBar's [0 - max] terms.
+     */
+    public void setDefaultProgress(int defaultProgress) {
+        if (mDefaultProgress != defaultProgress) {
+            mDefaultProgress = defaultProgress;
+            invalidate();
+        }
+    }
+
+    public int getDefaultProgress() {
+        return mDefaultProgress;
+    }
+}
diff --git a/src/com/android/settings/widget/GearPreference.java b/src/com/android/settings/widget/GearPreference.java
index 0a30100..82bc1f0 100644
--- a/src/com/android/settings/widget/GearPreference.java
+++ b/src/com/android/settings/widget/GearPreference.java
@@ -29,7 +29,8 @@
  * A preference with a Gear on the side
  */
 public class GearPreference extends RestrictedPreference implements View.OnClickListener {
-
+    // Default true for gear available even if the preference itself is disabled.
+    protected boolean mGearState = true;
     private OnGearClickListener mOnGearClickListener;
 
     public GearPreference(Context context, AttributeSet attrs) {
@@ -41,6 +42,16 @@
         notifyChanged();
     }
 
+    /** Sets state of gear button. */
+    public void setGearEnabled(boolean enabled) {
+        mGearState = enabled;
+    }
+
+    /** Gets state of gear button. */
+    public boolean isGearEnabled() {
+        return mGearState;
+    }
+
     @Override
     protected int getSecondTargetResId() {
         return R.layout.preference_widget_gear;
@@ -62,7 +73,8 @@
             gear.setVisibility(View.GONE);
             gear.setOnClickListener(null);
         }
-        gear.setEnabled(true);  // Make gear available even if the preference itself is disabled.
+        // Make gear available even if the preference itself is disabled.
+        gear.setEnabled(mGearState);
     }
 
     @Override
diff --git a/src/com/android/settings/widget/LabeledSeekBarPreference.java b/src/com/android/settings/widget/LabeledSeekBarPreference.java
new file mode 100644
index 0000000..3a9ac18
--- /dev/null
+++ b/src/com/android/settings/widget/LabeledSeekBarPreference.java
@@ -0,0 +1,94 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+
+/** A slider preference with left and right labels **/
+public class LabeledSeekBarPreference extends SeekBarPreference {
+
+    private final int mTextStartId;
+    private final int mTextEndId;
+    private final int mTickMarkId;
+    private OnPreferenceChangeListener mStopListener;
+
+    public LabeledSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+
+        super(context, attrs, defStyleAttr, defStyleRes);
+        setLayoutResource(R.layout.preference_labeled_slider);
+
+        final TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
+                R.styleable.LabeledSeekBarPreference);
+        mTextStartId = styledAttrs.getResourceId(
+                R.styleable.LabeledSeekBarPreference_textStart,
+                R.string.summary_placeholder);
+        mTextEndId = styledAttrs.getResourceId(
+                R.styleable.LabeledSeekBarPreference_textEnd,
+                R.string.summary_placeholder);
+        mTickMarkId = styledAttrs.getResourceId(
+                R.styleable.LabeledSeekBarPreference_tickMark, /* defValue= */ 0);
+        styledAttrs.recycle();
+    }
+
+    public LabeledSeekBarPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, TypedArrayUtils.getAttr(context,
+                androidx.preference.R.attr.seekBarPreferenceStyle,
+                com.android.internal.R.attr.seekBarPreferenceStyle), 0);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        final TextView startText = (TextView) holder.findViewById(android.R.id.text1);
+        final TextView endText = (TextView) holder.findViewById(android.R.id.text2);
+        startText.setText(mTextStartId);
+        endText.setText(mTextEndId);
+
+        if (mTickMarkId != 0) {
+            final Drawable tickMark = getContext().getDrawable(mTickMarkId);
+            final SeekBar seekBar = (SeekBar) holder.findViewById(
+                    com.android.internal.R.id.seekbar);
+            seekBar.setTickMark(tickMark);
+        }
+    }
+
+    public void setOnPreferenceChangeStopListener(OnPreferenceChangeListener listener) {
+        mStopListener = listener;
+    }
+
+    @Override
+    public void onStopTrackingTouch(SeekBar seekBar) {
+        super.onStopTrackingTouch(seekBar);
+
+        if (mStopListener != null) {
+            mStopListener.onPreferenceChange(this, seekBar.getProgress());
+        }
+    }
+}
+
diff --git a/src/com/android/settings/widget/MutableGearPreference.java b/src/com/android/settings/widget/MutableGearPreference.java
new file mode 100644
index 0000000..b0804eb
--- /dev/null
+++ b/src/com/android/settings/widget/MutableGearPreference.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+import com.android.settingslib.utils.ColorUtil;
+
+/** A preference with a Gear on the side and mutable Gear color. */
+public class MutableGearPreference extends GearPreference {
+    private static final int VALUE_ENABLED_ALPHA = 255;
+
+    private ImageView mGear;
+    private Context mContext;
+    private int mDisabledAlphaValue;
+
+    public MutableGearPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        mDisabledAlphaValue = (int) (ColorUtil.getDisabledAlpha(context) * VALUE_ENABLED_ALPHA);
+    }
+
+    @Override
+    public void setGearEnabled(boolean enabled) {
+        if (mGear != null) {
+            mGear.setEnabled(enabled);
+            mGear.setImageAlpha(enabled ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue);
+        }
+        mGearState = enabled;
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        mGear = (ImageView) holder.findViewById(R.id.settings_button);
+        setGearEnabled(mGearState);
+    }
+}
diff --git a/src/com/android/settings/widget/RestrictedAppPreference.java b/src/com/android/settings/widget/RestrictedAppPreference.java
index 5878fd5..cd95357 100644
--- a/src/com/android/settings/widget/RestrictedAppPreference.java
+++ b/src/com/android/settings/widget/RestrictedAppPreference.java
@@ -26,7 +26,7 @@
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
-import com.android.settingslib.Restrictable;
+import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.RestrictedPreferenceHelper;
 import com.android.settingslib.widget.AppPreference;
 
@@ -35,7 +35,7 @@
  * {@link com.android.settingslib.RestrictedPreferenceHelper}.
  * Used to show policy transparency on {@link AppPreference}.
  */
-public class RestrictedAppPreference extends AppPreference implements Restrictable {
+public class RestrictedAppPreference extends AppPreference {
     private RestrictedPreferenceHelper mHelper;
     private String userRestriction;
 
@@ -85,14 +85,14 @@
         super.setEnabled(enabled);
     }
 
-    @Override
-    public RestrictedPreferenceHelper getHelper() {
-        return mHelper;
+    public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
+        if (mHelper.setDisabledByAdmin(admin)) {
+            notifyChanged();
+        }
     }
 
-    @Override
-    public void notifyPreferenceChanged() {
-        notifyChanged();
+    public boolean isDisabledByAdmin() {
+        return mHelper.isDisabledByAdmin();
     }
 
     public void useAdminDisabledSummary(boolean useSummary) {
@@ -111,4 +111,12 @@
         }
         mHelper.checkRestrictionAndSetDisabled(userRestriction, UserHandle.myUserId());
     }
+
+    public void checkRestrictionAndSetDisabled(String userRestriction) {
+        mHelper.checkRestrictionAndSetDisabled(userRestriction, UserHandle.myUserId());
+    }
+
+    public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
+        mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
+    }
 }
diff --git a/src/com/android/settings/widget/SeekBarPreference.java b/src/com/android/settings/widget/SeekBarPreference.java
new file mode 100644
index 0000000..47bb286
--- /dev/null
+++ b/src/com/android/settings/widget/SeekBarPreference.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2011 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.widget;
+
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import androidx.core.content.res.TypedArrayUtils;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settingslib.RestrictedPreference;
+
+/**
+ * Based on android.preference.SeekBarPreference, but uses support preference as base.
+ */
+public class SeekBarPreference extends RestrictedPreference
+        implements OnSeekBarChangeListener, View.OnKeyListener {
+
+    public static final int HAPTIC_FEEDBACK_MODE_NONE = 0;
+    public static final int HAPTIC_FEEDBACK_MODE_ON_TICKS = 1;
+    public static final int HAPTIC_FEEDBACK_MODE_ON_ENDS = 2;
+
+    private int mProgress;
+    private int mMax;
+    private int mMin;
+    private boolean mTrackingTouch;
+
+    private boolean mContinuousUpdates;
+    private int mHapticFeedbackMode = HAPTIC_FEEDBACK_MODE_NONE;
+    private int mDefaultProgress = -1;
+
+    private SeekBar mSeekBar;
+    private boolean mShouldBlink;
+    private int mAccessibilityRangeInfoType = AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_INT;
+    private CharSequence mSeekBarContentDescription;
+    private CharSequence mSeekBarStateDescription;
+
+    public SeekBarPreference(
+            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+
+        TypedArray a = context.obtainStyledAttributes(
+                attrs, com.android.internal.R.styleable.ProgressBar, defStyleAttr, defStyleRes);
+        setMax(a.getInt(com.android.internal.R.styleable.ProgressBar_max, mMax));
+        setMin(a.getInt(com.android.internal.R.styleable.ProgressBar_min, mMin));
+        a.recycle();
+
+        a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.SeekBarPreference, defStyleAttr, defStyleRes);
+        final int layoutResId = a.getResourceId(
+                com.android.internal.R.styleable.SeekBarPreference_layout,
+                com.android.internal.R.layout.preference_widget_seekbar);
+        a.recycle();
+
+        a = context.obtainStyledAttributes(
+                attrs, com.android.internal.R.styleable.Preference, defStyleAttr, defStyleRes);
+        final boolean isSelectable = a.getBoolean(
+                com.android.settings.R.styleable.Preference_android_selectable, false);
+        setSelectable(isSelectable);
+        a.recycle();
+
+        setLayoutResource(layoutResId);
+    }
+
+    public SeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public SeekBarPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, TypedArrayUtils.getAttr(context,
+                        androidx.preference.R.attr.seekBarPreferenceStyle,
+                        com.android.internal.R.attr.seekBarPreferenceStyle));
+    }
+
+    public SeekBarPreference(Context context) {
+        this(context, null);
+    }
+
+    public void setShouldBlink(boolean shouldBlink) {
+        mShouldBlink = shouldBlink;
+        notifyChanged();
+    }
+
+    @Override
+    public boolean isSelectable() {
+        if(isDisabledByAdmin()) {
+            return true;
+        } else {
+            return super.isSelectable();
+        }
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder view) {
+        super.onBindViewHolder(view);
+        view.itemView.setOnKeyListener(this);
+        mSeekBar = (SeekBar) view.findViewById(
+                com.android.internal.R.id.seekbar);
+        mSeekBar.setOnSeekBarChangeListener(this);
+        mSeekBar.setMax(mMax);
+        mSeekBar.setMin(mMin);
+        mSeekBar.setProgress(mProgress);
+        mSeekBar.setEnabled(isEnabled());
+        final CharSequence title = getTitle();
+        if (!TextUtils.isEmpty(mSeekBarContentDescription)) {
+            mSeekBar.setContentDescription(mSeekBarContentDescription);
+        } else if (!TextUtils.isEmpty(title)) {
+            mSeekBar.setContentDescription(title);
+        }
+        if (!TextUtils.isEmpty(mSeekBarStateDescription)) {
+            mSeekBar.setStateDescription(mSeekBarStateDescription);
+        }
+        if (mSeekBar instanceof DefaultIndicatorSeekBar) {
+            ((DefaultIndicatorSeekBar) mSeekBar).setDefaultProgress(mDefaultProgress);
+        }
+        if (mShouldBlink) {
+            View v = view.itemView;
+            v.post(() -> {
+                if (v.getBackground() != null) {
+                    final int centerX = v.getWidth() / 2;
+                    final int centerY = v.getHeight() / 2;
+                    v.getBackground().setHotspot(centerX, centerY);
+                }
+                v.setPressed(true);
+                v.setPressed(false);
+                mShouldBlink = false;
+            });
+        }
+        mSeekBar.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+            @Override
+            public void onInitializeAccessibilityNodeInfo(View view, AccessibilityNodeInfo info) {
+                super.onInitializeAccessibilityNodeInfo(view, info);
+                // Update the range info with the correct type
+                AccessibilityNodeInfo.RangeInfo rangeInfo = info.getRangeInfo();
+                if (rangeInfo != null) {
+                    info.setRangeInfo(AccessibilityNodeInfo.RangeInfo.obtain(
+                                    mAccessibilityRangeInfoType, rangeInfo.getMin(),
+                                    rangeInfo.getMax(), rangeInfo.getCurrent()));
+                }
+            }
+        });
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return null;
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+        setProgress(restoreValue ? getPersistedInt(mProgress)
+                : (Integer) defaultValue);
+    }
+
+    @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return a.getInt(index, 0);
+    }
+
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        if (event.getAction() != KeyEvent.ACTION_DOWN) {
+            return false;
+        }
+
+        SeekBar seekBar = (SeekBar) v.findViewById(com.android.internal.R.id.seekbar);
+        if (seekBar == null) {
+            return false;
+        }
+        return seekBar.onKeyDown(keyCode, event);
+    }
+
+    public void setMax(int max) {
+        if (max != mMax) {
+            mMax = max;
+            notifyChanged();
+        }
+    }
+
+    public void setMin(int min) {
+        if (min != mMin) {
+            mMin = min;
+            notifyChanged();
+        }
+    }
+
+    public int getMax() {
+        return mMax;
+    }
+
+    public int getMin() {
+        return mMin;
+    }
+
+    public void setProgress(int progress) {
+        setProgress(progress, true);
+    }
+
+    /**
+     * Sets the progress point to draw a single tick mark representing a default value.
+     */
+    public void setDefaultProgress(int defaultProgress) {
+        if (mDefaultProgress != defaultProgress) {
+            mDefaultProgress = defaultProgress;
+            if (mSeekBar instanceof DefaultIndicatorSeekBar) {
+                ((DefaultIndicatorSeekBar) mSeekBar).setDefaultProgress(mDefaultProgress);
+            }
+        }
+    }
+
+    /**
+     * When {@code continuousUpdates} is true, update the persisted setting immediately as the thumb
+     * is dragged along the SeekBar. Otherwise, only update the value of the setting when the thumb
+     * is dropped.
+     */
+    public void setContinuousUpdates(boolean continuousUpdates) {
+        mContinuousUpdates = continuousUpdates;
+    }
+
+    /**
+     * Sets the haptic feedback mode. HAPTIC_FEEDBACK_MODE_ON_TICKS means to perform haptic feedback
+     * as the SeekBar's progress is updated; HAPTIC_FEEDBACK_MODE_ON_ENDS means to perform haptic
+     * feedback as the SeekBar's progress value is equal to the min/max value.
+     *
+     * @param hapticFeedbackMode the haptic feedback mode.
+     */
+    public void setHapticFeedbackMode(int hapticFeedbackMode) {
+        mHapticFeedbackMode = hapticFeedbackMode;
+    }
+
+    private void setProgress(int progress, boolean notifyChanged) {
+        if (progress > mMax) {
+            progress = mMax;
+        }
+        if (progress < mMin) {
+            progress = mMin;
+        }
+        if (progress != mProgress) {
+            mProgress = progress;
+            persistInt(progress);
+            if (notifyChanged) {
+                notifyChanged();
+            }
+        }
+    }
+
+    public int getProgress() {
+        return mProgress;
+    }
+
+    /**
+     * Persist the seekBar's progress value if callChangeListener
+     * returns true, otherwise set the seekBar's progress to the stored value
+     */
+    void syncProgress(SeekBar seekBar) {
+        int progress = seekBar.getProgress();
+        if (progress != mProgress) {
+            if (callChangeListener(progress)) {
+                setProgress(progress, false);
+                switch (mHapticFeedbackMode) {
+                    case HAPTIC_FEEDBACK_MODE_ON_TICKS:
+                        seekBar.performHapticFeedback(CLOCK_TICK);
+                        break;
+                    case HAPTIC_FEEDBACK_MODE_ON_ENDS:
+                        if (progress == mMax || progress == mMin) {
+                            seekBar.performHapticFeedback(CLOCK_TICK);
+                        }
+                        break;
+                }
+            } else {
+                seekBar.setProgress(mProgress);
+            }
+        }
+    }
+
+    @Override
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser && (mContinuousUpdates || !mTrackingTouch)) {
+            syncProgress(seekBar);
+        }
+    }
+
+    @Override
+    public void onStartTrackingTouch(SeekBar seekBar) {
+        mTrackingTouch = true;
+    }
+
+    @Override
+    public void onStopTrackingTouch(SeekBar seekBar) {
+        mTrackingTouch = false;
+        if (seekBar.getProgress() != mProgress) {
+            syncProgress(seekBar);
+        }
+    }
+
+    /**
+     * Specify the type of range this seek bar represents.
+     *
+     * @param rangeInfoType The type of range to be shared with accessibility
+     *
+     * @see android.view.accessibility.AccessibilityNodeInfo.RangeInfo
+     */
+    public void setAccessibilityRangeInfoType(int rangeInfoType) {
+        mAccessibilityRangeInfoType = rangeInfoType;
+    }
+
+    public void setSeekBarContentDescription(CharSequence contentDescription) {
+        mSeekBarContentDescription = contentDescription;
+        if (mSeekBar != null) {
+            mSeekBar.setContentDescription(contentDescription);
+        }
+    }
+
+    /**
+     * Specify the state description for this seek bar represents.
+     *
+     * @param stateDescription the state description of seek bar
+     */
+    public void setSeekBarStateDescription(CharSequence stateDescription) {
+        mSeekBarStateDescription = stateDescription;
+        if (mSeekBar != null) {
+            mSeekBar.setStateDescription(stateDescription);
+        }
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        /*
+         * Suppose a client uses this preference type without persisting. We
+         * must save the instance state so it is able to, for example, survive
+         * orientation changes.
+         */
+
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+
+        // Save the instance state
+        final SavedState myState = new SavedState(superState);
+        myState.progress = mProgress;
+        myState.max = mMax;
+        myState.min = mMin;
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (!state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
+        // Restore the instance state
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        mProgress = myState.progress;
+        mMax = myState.max;
+        mMin = myState.min;
+        notifyChanged();
+    }
+
+    /**
+     * SavedState, a subclass of {@link BaseSavedState}, will store the state
+     * of MyPreference, a subclass of Preference.
+     * <p>
+     * It is important to always call through to super methods.
+     */
+    private static class SavedState extends BaseSavedState {
+        int progress;
+        int max;
+        int min;
+
+        public SavedState(Parcel source) {
+            super(source);
+
+            // Restore the click counter
+            progress = source.readInt();
+            max = source.readInt();
+            min = source.readInt();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+
+            // Save the click counter
+            dest.writeInt(progress);
+            dest.writeInt(max);
+            dest.writeInt(min);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        @SuppressWarnings("unused")
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+}
diff --git a/tests/robotests/res/layout/main_clear.xml b/tests/robotests/res/layout/main_clear.xml
new file mode 100644
index 0000000..868d88f
--- /dev/null
+++ b/tests/robotests/res/layout/main_clear.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<com.google.android.setupdesign.GlifLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/setup_wizard_layout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:theme="@style/GlifV3Theme.Footer"
+    android:orientation="vertical"
+    android:icon="@drawable/ic_delete_accent"
+    app:sucHeaderText="@string/main_clear_title">
+
+    <ScrollView
+        android:id="@+id/main_clear_scrollview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginStart="@dimen/reset_main_clear_margin_start"
+        android:layout_marginEnd="@dimen/reset_main_clear_margin_end">
+
+        <LinearLayout
+            android:id="@+id/main_clear_container"
+            style="@style/SudContentFrame"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+
+            <TextView
+                style="@style/TextAppearance.SudGlifItemSummary"
+                android:id="@+id/sud_layout_description"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/main_clear_desc"/>
+            <TextView
+                android:id="@+id/also_erases_external"
+                style="@style/TextAppearance.SudGlifItemSummary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:text="@string/main_clear_desc_also_erases_external"/>
+            <TextView
+                android:id="@+id/also_erases_esim"
+                style="@style/TextAppearance.SudGlifItemSummary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:text="@string/main_clear_desc_also_erases_esim"/>
+            <TextView
+                android:id="@+id/accounts_label"
+                style="@style/TextAppearance.SudGlifItemSummary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:text="@string/main_clear_accounts"/>
+            <LinearLayout
+                android:id="@+id/accounts"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:visibility="gone">
+                <!-- Do not add any children here as they will be removed in the MainClear.java
+                    code. A list of accounts will be inserted programmatically. -->
+            </LinearLayout>
+            <TextView
+                android:id="@+id/other_users_present"
+                style="@style/TextAppearance.SudGlifItemSummary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:text="@string/main_clear_other_users_present"/>
+            <TextView
+                android:id="@+id/no_cancel_mobile_plan"
+                style="@style/TextAppearance.SudGlifItemSummary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                android:text="@string/main_clear_desc_no_cancel_mobile_plan"/>
+            <TextView
+                android:id="@+id/erase_external_option_text"
+                style="@style/TextAppearance.SudGlifItemSummary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/main_clear_desc_erase_external_storage"/>
+            <LinearLayout
+                android:id="@+id/erase_external_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:focusable="true"
+                android:clickable="true">
+                <CheckBox
+                    android:id="@+id/erase_external"
+                    style="@style/SudCheckBox"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:focusable="false"
+                    android:clickable="false"
+                    android:duplicateParentState="true"/>
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:orientation="vertical">
+                    <TextView
+                        style="@style/TextAppearance.SudGlifItemTitle"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/erase_external_storage"/>
+                    <TextView
+                        style="@style/TextAppearance.SudGlifItemSummary"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/erase_external_storage_description"/>
+                </LinearLayout>
+            </LinearLayout>
+
+            <include layout="@layout/reset_esim_checkbox"/>
+
+        </LinearLayout>
+    </ScrollView>
+</com.google.android.setupdesign.GlifLayout>
diff --git a/tests/robotests/res/layout/main_clear_confirm.xml b/tests/robotests/res/layout/main_clear_confirm.xml
new file mode 100644
index 0000000..341e7bb
--- /dev/null
+++ b/tests/robotests/res/layout/main_clear_confirm.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<com.google.android.setupdesign.GlifLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:theme="@style/SudThemeGlifV3.DayNight"
+    android:orientation="vertical"
+    android:id="@+id/setup_wizard_layout"
+    android:icon="@drawable/ic_delete_accent"
+    app:sucHeaderText="@string/main_clear_confirm_title">
+
+    <LinearLayout
+        style="@style/SudContentFrame"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/sud_layout_description"
+            style="@style/SudItemTitle.GlifDescription"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/main_clear_final_desc"/>
+    </LinearLayout>
+</com.google.android.setupdesign.GlifLayout>
diff --git a/tests/robotests/res/xml-mcc998/seekbar_preference.xml b/tests/robotests/res/xml-mcc998/seekbar_preference.xml
index 3efd3a1..e474c1e 100644
--- a/tests/robotests/res/xml-mcc998/seekbar_preference.xml
+++ b/tests/robotests/res/xml-mcc998/seekbar_preference.xml
@@ -17,7 +17,7 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android">
-    <com.android.settingslib.widget.SeekBarPreference
+    <com.android.settings.widget.SeekBarPreference
         android:key="seek_bar"
         android:title="seek_bar_title"/>
 </PreferenceScreen >
diff --git a/tests/robotests/res/xml-mcc999/seekbar_preference.xml b/tests/robotests/res/xml-mcc999/seekbar_preference.xml
index 68cdbda..77435e8 100644
--- a/tests/robotests/res/xml-mcc999/seekbar_preference.xml
+++ b/tests/robotests/res/xml-mcc999/seekbar_preference.xml
@@ -17,7 +17,7 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android">
-    <com.android.settingslib.widget.SeekBarPreference
+    <com.android.settings.widget.SeekBarPreference
         android:key="seek_bar"
         android:selectable="true"
         android:title="seek_bar_title"/>
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
new file mode 100644
index 0000000..104f335
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2021 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.accessibility;
+
+import static com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment.KEY_SAVED_USER_SHORTCUT_TYPE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.testutils.shadow.ShadowFragment;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+/** Tests for {@link AccessibilityShortcutPreferenceFragment} */
+@RunWith(RobolectricTestRunner.class)
+public class AccessibilityShortcutPreferenceFragmentTest {
+
+    private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example";
+    private static final String PLACEHOLDER_CLASS_NAME = PLACEHOLDER_PACKAGE_NAME + ".placeholder";
+    private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName(
+            PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME);
+    private static final String PLACEHOLDER_DIALOG_TITLE = "title";
+
+    private static final String SOFTWARE_SHORTCUT_KEY =
+            Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
+    private static final String HARDWARE_SHORTCUT_KEY =
+            Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
+
+    private TestAccessibilityShortcutPreferenceFragment mFragment;
+    private PreferenceScreen mScreen;
+    private Context mContext = ApplicationProvider.getApplicationContext();
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private PreferenceManager mPreferenceManager;
+
+    @Before
+    public void setUpTestFragment() {
+        MockitoAnnotations.initMocks(this);
+
+        mFragment = spy(new TestAccessibilityShortcutPreferenceFragment());
+        when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
+        when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
+        when(mFragment.getContext()).thenReturn(mContext);
+        mScreen = spy(new PreferenceScreen(mContext, null));
+        when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager);
+        doReturn(mScreen).when(mFragment).getPreferenceScreen();
+    }
+
+    @Test
+    public void updateShortcutPreferenceData_assignDefaultValueToVariable() {
+        mFragment.updateShortcutPreferenceData();
+
+        final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
+                mFragment.getComponentName().flattenToString(),
+                AccessibilityUtil.UserShortcutType.SOFTWARE);
+        // Compare to default UserShortcutType
+        assertThat(expectedType).isEqualTo(AccessibilityUtil.UserShortcutType.SOFTWARE);
+    }
+
+    @Test
+    public void updateShortcutPreferenceData_hasValueInSettings_assignToVariable() {
+        putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
+        putStringIntoSettings(HARDWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
+
+        mFragment.updateShortcutPreferenceData();
+
+        final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
+                mFragment.getComponentName().flattenToString(),
+                AccessibilityUtil.UserShortcutType.SOFTWARE);
+        assertThat(expectedType).isEqualTo(AccessibilityUtil.UserShortcutType.SOFTWARE
+                | AccessibilityUtil.UserShortcutType.HARDWARE);
+    }
+
+    @Test
+    public void updateShortcutPreferenceData_hasValueInSharedPreference_assignToVariable() {
+        final PreferredShortcut hardwareShortcut = new PreferredShortcut(
+                PLACEHOLDER_COMPONENT_NAME.flattenToString(),
+                AccessibilityUtil.UserShortcutType.HARDWARE);
+
+        putUserShortcutTypeIntoSharedPreference(mContext, hardwareShortcut);
+        mFragment.updateShortcutPreferenceData();
+
+        final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
+                mFragment.getComponentName().flattenToString(),
+                AccessibilityUtil.UserShortcutType.SOFTWARE);
+        assertThat(expectedType).isEqualTo(AccessibilityUtil.UserShortcutType.HARDWARE);
+    }
+
+    @Test
+    public void setupEditShortcutDialog_shortcutPreferenceOff_checkboxIsEmptyValue() {
+        mContext.setTheme(R.style.Theme_AppCompat);
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
+                mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC,
+                PLACEHOLDER_DIALOG_TITLE,
+                this::callEmptyOnClicked);
+        final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
+                null);
+        mFragment.mShortcutPreference = shortcutPreference;
+
+        mFragment.mShortcutPreference.setChecked(false);
+        mFragment.setupEditShortcutDialog(dialog);
+
+        final int checkboxValue = mFragment.getShortcutTypeCheckBoxValue();
+        assertThat(checkboxValue).isEqualTo(AccessibilityUtil.UserShortcutType.EMPTY);
+    }
+
+    @Test
+    public void setupEditShortcutDialog_shortcutPreferenceOn_checkboxIsSavedValue() {
+        mContext.setTheme(R.style.Theme_AppCompat);
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
+                mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC,
+                PLACEHOLDER_DIALOG_TITLE,
+                this::callEmptyOnClicked);
+        final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
+                null);
+        final PreferredShortcut hardwareShortcut = new PreferredShortcut(
+                PLACEHOLDER_COMPONENT_NAME.flattenToString(),
+                AccessibilityUtil.UserShortcutType.HARDWARE);
+        mFragment.mShortcutPreference = shortcutPreference;
+
+        PreferredShortcuts.saveUserShortcutType(mContext, hardwareShortcut);
+        mFragment.mShortcutPreference.setChecked(true);
+        mFragment.setupEditShortcutDialog(dialog);
+
+        final int checkboxValue = mFragment.getShortcutTypeCheckBoxValue();
+        assertThat(checkboxValue).isEqualTo(AccessibilityUtil.UserShortcutType.HARDWARE);
+    }
+
+    @Test
+    @Config(shadows = ShadowFragment.class)
+    public void restoreValueFromSavedInstanceState_assignToVariable() {
+        mContext.setTheme(R.style.Theme_AppCompat);
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
+                mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC,
+                PLACEHOLDER_DIALOG_TITLE,
+                this::callEmptyOnClicked);
+        final Bundle savedInstanceState = new Bundle();
+        final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
+                null);
+        mFragment.mShortcutPreference = shortcutPreference;
+
+        savedInstanceState.putInt(KEY_SAVED_USER_SHORTCUT_TYPE,
+                AccessibilityUtil.UserShortcutType.SOFTWARE
+                        | AccessibilityUtil.UserShortcutType.HARDWARE);
+        mFragment.onCreate(savedInstanceState);
+        mFragment.setupEditShortcutDialog(dialog);
+        final int value = mFragment.getShortcutTypeCheckBoxValue();
+        mFragment.saveNonEmptyUserShortcutType(value);
+
+        final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
+                mFragment.getComponentName().flattenToString(),
+                AccessibilityUtil.UserShortcutType.SOFTWARE);
+        assertThat(expectedType).isEqualTo(
+                AccessibilityUtil.UserShortcutType.SOFTWARE
+                        | AccessibilityUtil.UserShortcutType.HARDWARE);
+    }
+
+    private void callEmptyOnClicked(DialogInterface dialog, int which) {}
+
+    private void putStringIntoSettings(String key, String componentName) {
+        Settings.Secure.putString(mContext.getContentResolver(), key, componentName);
+    }
+
+    private void putUserShortcutTypeIntoSharedPreference(Context context,
+            PreferredShortcut shortcut) {
+        PreferredShortcuts.saveUserShortcutType(context, shortcut);
+    }
+
+    public static class TestAccessibilityShortcutPreferenceFragment
+            extends AccessibilityShortcutPreferenceFragment {
+        @Override
+        protected ComponentName getComponentName() {
+            return PLACEHOLDER_COMPONENT_NAME;
+        }
+
+        @Override
+        protected CharSequence getLabelName() {
+            return PLACEHOLDER_PACKAGE_NAME;
+        }
+
+        @Override
+        public int getMetricsCategory() {
+            return 0;
+        }
+    };
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AnimatedImagePreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/AnimatedImagePreferenceTest.java
index c3dd7b5..4bce0bb 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AnimatedImagePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AnimatedImagePreferenceTest.java
@@ -18,13 +18,19 @@
 
 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.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.graphics.drawable.AnimatedImageDrawable;
+import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.AnimationDrawable;
 import android.net.Uri;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -34,18 +40,22 @@
 
 import com.android.settings.R;
 
+import com.airbnb.lottie.LottieAnimationView;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.io.InputStream;
+
 /** Tests for {@link AnimatedImagePreference}. */
 @RunWith(RobolectricTestRunner.class)
 public class AnimatedImagePreferenceTest {
+    private final Context mContext = RuntimeEnvironment.application;
     private Uri mImageUri;
     private View mRootView;
     private PreferenceViewHolder mViewHolder;
@@ -54,32 +64,53 @@
     @Spy
     private ImageView mImageView;
 
-    @Mock
-    private AnimatedImageDrawable mAnimatedImageDrawable;
-
     @Before
     public void init() {
         MockitoAnnotations.initMocks(this);
 
-        final Context context = RuntimeEnvironment.application;
-        final LayoutInflater inflater = LayoutInflater.from(context);
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
         mRootView = spy(inflater.inflate(R.layout.preference_animated_image, /* root= */ null));
         mViewHolder = spy(PreferenceViewHolder.createInstanceForTests(mRootView));
-        mImageView = spy(new ImageView(context));
+        mImageView = spy(new ImageView(mContext));
 
-        mAnimatedImagePreference = new AnimatedImagePreference(context);
+        mAnimatedImagePreference = new AnimatedImagePreference(mContext);
         mImageUri = new Uri.Builder().build();
     }
 
     @Test
-    public void readImageUri_animatedImage_startAnimation() {
+    public void playAnimation_animatedImageDrawable_success() {
+        final AnimatedImageDrawable drawable = mock(AnimatedImageDrawable.class);
         doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img);
-        doReturn(mAnimatedImageDrawable).when(mImageView).getDrawable();
+        doReturn(drawable).when(mImageView).getDrawable();
 
         mAnimatedImagePreference.setImageUri(mImageUri);
         mAnimatedImagePreference.onBindViewHolder(mViewHolder);
 
-        verify(mAnimatedImageDrawable).start();
+        verify(drawable).start();
+    }
+
+    @Test
+    public void playAnimation_animatedVectorDrawable_success() {
+        final AnimatedVectorDrawable drawable = mock(AnimatedVectorDrawable.class);
+        doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img);
+        doReturn(drawable).when(mImageView).getDrawable();
+
+        mAnimatedImagePreference.setImageUri(mImageUri);
+        mAnimatedImagePreference.onBindViewHolder(mViewHolder);
+
+        verify(drawable).start();
+    }
+
+    @Test
+    public void playAnimation_animationDrawable_success() {
+        final AnimationDrawable drawable = mock(AnimationDrawable.class);
+        doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img);
+        doReturn(drawable).when(mImageView).getDrawable();
+
+        mAnimatedImagePreference.setImageUri(mImageUri);
+        mAnimatedImagePreference.onBindViewHolder(mViewHolder);
+
+        verify(drawable).start();
     }
 
     @Test
@@ -102,4 +133,22 @@
 
         assertThat(mImageView.getMaxHeight()).isEqualTo(maxHeight);
     }
+
+    @Test
+    public void setImageUriAndRebindViewHolder_lottieImageFromRawFolder_setAnimation() {
+        final int fakeLottieResId = 111111;
+        final Uri lottieImageUri =
+                new Uri.Builder().scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                .authority(mContext.getPackageName())
+                .appendPath(String.valueOf(fakeLottieResId))
+                .build();
+        final LottieAnimationView lottieView = spy(new LottieAnimationView(mContext));
+        doReturn(mImageView).when(mRootView).findViewById(R.id.animated_img);
+        doReturn(lottieView).when(mRootView).findViewById(R.id.lottie_view);
+
+        mAnimatedImagePreference.setImageUri(lottieImageUri);
+        mAnimatedImagePreference.onBindViewHolder(mViewHolder);
+
+        verify(lottieView).setAnimation(any(InputStream.class), eq(null));
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java
index 216368e..55637cd 100644
--- a/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuTransparencyPreferenceControllerTest.java
@@ -36,7 +36,7 @@
 
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.settingslib.widget.SeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java
index d4b7ea0..e3940e7 100644
--- a/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/MagnificationModePreferenceControllerTest.java
@@ -16,7 +16,7 @@
 
 package com.android.settings.accessibility;
 
-import static com.android.settings.accessibility.AccessibilityEditDialogUtils.CustomButton;
+import static com.android.settings.accessibility.AccessibilityDialogUtils.CustomButton;
 import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
 import static com.android.settings.accessibility.MagnificationModePreferenceController.MagnificationModeInfo;
 import static com.android.settings.accessibility.MagnificationPreferenceFragment.ON;
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index 4f4185c..c47a793 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -43,7 +43,7 @@
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.R;
-import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
+import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
 import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
 import com.android.settings.testutils.shadow.ShadowFragment;
 
@@ -118,9 +118,9 @@
     @Test
     public void updateShortcutPreferenceData_hasValueInSettings_assignToVariable() {
         mFragment.mComponentName = PLACEHOLDER_COMPONENT_NAME;
-
         putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
         putStringIntoSettings(HARDWARE_SHORTCUT_KEY, PLACEHOLDER_COMPONENT_NAME.flattenToString());
+
         mFragment.updateShortcutPreferenceData();
 
         final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
@@ -145,7 +145,7 @@
     @Test
     public void setupEditShortcutDialog_shortcutPreferenceOff_checkboxIsEmptyValue() {
         mContext.setTheme(R.style.Theme_AppCompat);
-        final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                 mContext, DialogType.EDIT_SHORTCUT_GENERIC, PLACEHOLDER_DIALOG_TITLE,
                 this::callEmptyOnClicked);
         final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
@@ -163,7 +163,7 @@
     @Test
     public void setupEditShortcutDialog_shortcutPreferenceOn_checkboxIsSavedValue() {
         mContext.setTheme(R.style.Theme_AppCompat);
-        final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                 mContext, DialogType.EDIT_SHORTCUT_GENERIC, PLACEHOLDER_DIALOG_TITLE,
                 this::callEmptyOnClicked);
         final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
@@ -185,7 +185,7 @@
     @Config(shadows = ShadowFragment.class)
     public void restoreValueFromSavedInstanceState_assignToVariable() {
         mContext.setTheme(R.style.Theme_AppCompat);
-        final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                 mContext, DialogType.EDIT_SHORTCUT_GENERIC, PLACEHOLDER_DIALOG_TITLE,
                 this::callEmptyOnClicked);
         final Bundle savedInstanceState = new Bundle();
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
index 43f691e..9aa0e03 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentTest.java
@@ -53,7 +53,7 @@
 
 import com.android.settings.DialogCreatable;
 import com.android.settings.R;
-import com.android.settings.accessibility.AccessibilityEditDialogUtils.DialogType;
+import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
 import com.android.settings.testutils.shadow.ShadowFragment;
 import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -186,6 +186,7 @@
     public void updateShortcutPreferenceData_hasValueInSettings_assignToVariable() {
         putStringIntoSettings(SOFTWARE_SHORTCUT_KEY, MAGNIFICATION_CONTROLLER_NAME);
         setMagnificationTripleTapEnabled(/* enabled= */ true);
+
         mFragment.updateShortcutPreferenceData();
 
         final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext,
@@ -209,7 +210,7 @@
     @Test
     public void setupMagnificationEditShortcutDialog_shortcutPreferenceOff_checkboxIsEmptyValue() {
         mContext.setTheme(R.style.Theme_AppCompat);
-        final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                 mContext, DialogType.EDIT_SHORTCUT_MAGNIFICATION, PLACEHOLDER_DIALOG_TITLE,
                 this::callEmptyOnClicked);
         final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
@@ -226,7 +227,7 @@
     @Test
     public void setupMagnificationEditShortcutDialog_shortcutPreferenceOn_checkboxIsSavedValue() {
         mContext.setTheme(R.style.Theme_AppCompat);
-        final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                 mContext, DialogType.EDIT_SHORTCUT_MAGNIFICATION, PLACEHOLDER_DIALOG_TITLE,
                 this::callEmptyOnClicked);
         final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */
@@ -247,7 +248,7 @@
     @Config(shadows = ShadowFragment.class)
     public void restoreValueFromSavedInstanceState_assignToVariable() {
         mContext.setTheme(R.style.Theme_AppCompat);
-        final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+        final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog(
                 mContext, DialogType.EDIT_SHORTCUT_MAGNIFICATION, PLACEHOLDER_DIALOG_TITLE,
                 this::callEmptyOnClicked);
         final Bundle savedInstanceState = new Bundle();
diff --git a/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
index b10a729..8860cfe 100644
--- a/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/EnterpriseDisclosurePreferenceControllerTest.java
@@ -19,20 +19,25 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
 
-import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.FooterPreference;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
@@ -42,13 +47,18 @@
 
     private Context mContext;
     private EnterpriseDisclosurePreferenceController mController;
-    private Preference mPreference;
+    private FooterPreference mPreference;
+
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
 
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         mContext = RuntimeEnvironment.application;
         mController = spy(new EnterpriseDisclosurePreferenceController(mContext, "my_key"));
-        mPreference = spy(new Preference(mContext));
+        mPreference = spy(new FooterPreference(mContext));
+        when(mPreferenceScreen.findPreference(anyString())).thenReturn(mPreference);
     }
 
     @Test
@@ -68,19 +78,19 @@
     }
 
     @Test
-    public void updateState_hasDisclosure_shouldSetTitle() {
+    public void displayPreference_hasDisclosure_shouldSetTitle() {
         doReturn(TEST_DISCLOSURE).when(mController).getDisclosure();
 
-        mController.updateState(mPreference);
+        mController.displayPreference(mPreferenceScreen);
 
         assertThat(mPreference.getTitle()).isEqualTo(TEST_DISCLOSURE);
     }
 
     @Test
-    public void updateState_noDisclosure_shouldBeInvisible() {
+    public void displayPreference_noDisclosure_shouldBeInvisible() {
         doReturn(null).when(mController).getDisclosure();
 
-        mController.updateState(mPreference);
+        mController.displayPreference(mPreferenceScreen);
 
         verify(mPreference, never()).setTitle(any());
     }
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java
index 73e9bed..2115947 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppBatteryPreferenceControllerTest.java
@@ -134,7 +134,7 @@
         mController.updateBattery();
 
         assertThat(mBatteryPreference.getSummary())
-            .isEqualTo("No battery use since last full charge");
+            .isEqualTo("No battery use for past 24 hours");
     }
 
     @Test
@@ -147,7 +147,7 @@
 
         mController.updateBattery();
 
-        assertThat(mBatteryPreference.getSummary()).isEqualTo("60% use since last full charge");
+        assertThat(mBatteryPreference.getSummary()).isEqualTo("60% use for past 24 hours");
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
index c5ea21f..edd85e4 100644
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesDetailsTest.java
@@ -20,11 +20,10 @@
 
 import static org.robolectric.Shadows.shadowOf;
 
-import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.PermissionChecker;
 import android.content.pm.CrossProfileApps;
 import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
 import android.os.UserManager;
 
@@ -37,19 +36,18 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowPermissionChecker;
 
 @RunWith(RobolectricTestRunner.class)
 public class InteractAcrossProfilesDetailsTest {
 
     private static final int PERSONAL_PROFILE_ID = 0;
     private static final int WORK_PROFILE_ID = 10;
-    private static final int PACKAGE_UID = 0;
     private static final String CROSS_PROFILE_PACKAGE_NAME = "crossProfilePackage";
     public static final String INTERACT_ACROSS_PROFILES_PERMISSION =
             "android.permission.INTERACT_ACROSS_PROFILES";
 
     private final Context mContext = ApplicationProvider.getApplicationContext();
-    private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
     private final PackageManager mPackageManager = mContext.getPackageManager();
     private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
     private final CrossProfileApps mCrossProfileApps = mContext.getSystemService(
@@ -68,10 +66,10 @@
                 WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME));
         shadowOf(mCrossProfileApps).addCrossProfilePackage(
                 CROSS_PROFILE_PACKAGE_NAME);
-        String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
-        shadowOf(mAppOpsManager).setMode(
-                appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
-        shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
+        ShadowPermissionChecker.setResult(
+                CROSS_PROFILE_PACKAGE_NAME,
+                INTERACT_ACROSS_PROFILES_PERMISSION,
+                PermissionChecker.PERMISSION_GRANTED);
 
         assertThat(InteractAcrossProfilesDetails.getPreferenceSummary(
                 mContext, CROSS_PROFILE_PACKAGE_NAME))
@@ -91,11 +89,10 @@
                 WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME));
         shadowOf(mCrossProfileApps).addCrossProfilePackage(
                 CROSS_PROFILE_PACKAGE_NAME);
-        String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
-        shadowOf(mAppOpsManager).setMode(
-                appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_IGNORED);
-        shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
-
+        ShadowPermissionChecker.setResult(
+                CROSS_PROFILE_PACKAGE_NAME,
+                INTERACT_ACROSS_PROFILES_PERMISSION,
+                PermissionChecker.PERMISSION_SOFT_DENIED);
         assertThat(InteractAcrossProfilesDetails.getPreferenceSummary(
                 mContext, CROSS_PROFILE_PACKAGE_NAME))
                 .isEqualTo(mContext.getString(
@@ -114,11 +111,4 @@
                 .isEqualTo(mContext.getString(
                         R.string.interact_across_profiles_summary_not_allowed));
     }
-
-    private PermissionInfo createCrossProfilesPermissionInfo() {
-        PermissionInfo permissionInfo = new PermissionInfo();
-        permissionInfo.name = INTERACT_ACROSS_PROFILES_PERMISSION;
-        permissionInfo.protectionLevel = PermissionInfo.PROTECTION_FLAG_APPOP;
-        return permissionInfo;
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java
index bbbcd82..029fb28 100644
--- a/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/specialaccess/interactacrossprofiles/InteractAcrossProfilesSettingsTest.java
@@ -21,7 +21,6 @@
 import static org.junit.Assert.assertTrue;
 import static org.robolectric.Shadows.shadowOf;
 
-import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.PermissionChecker;
 import android.content.pm.ApplicationInfo;
@@ -51,7 +50,6 @@
     private static final int PERSONAL_PROFILE_ID = 0;
     private static final int WORK_PROFILE_ID = 10;
     private static final int WORK_UID = UserHandle.PER_USER_RANGE * WORK_PROFILE_ID;
-    private static final int PACKAGE_UID = 0;
 
     private static final String PERSONAL_CROSS_PROFILE_PACKAGE = "personalCrossProfilePackage";
     private static final String PERSONAL_NON_CROSS_PROFILE_PACKAGE =
@@ -71,7 +69,6 @@
     private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
     private final CrossProfileApps mCrossProfileApps =
             mContext.getSystemService(CrossProfileApps.class);
-    private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
 
     @Test
     public void collectConfigurableApps_fromPersonal_returnsCombinedPackages() {
@@ -84,8 +81,8 @@
                 PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
         shadowOf(mPackageManager).setInstalledPackagesForUserId(
                 WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
-        installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
-        installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
+        installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
+        installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
 
         List<Pair<ApplicationInfo, UserHandle>> apps =
                 InteractAcrossProfilesSettings.collectConfigurableApps(
@@ -110,8 +107,8 @@
                 PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
         shadowOf(mPackageManager).setInstalledPackagesForUserId(
                 WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
-        installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
-        installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
+        installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
+        installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
 
         List<Pair<ApplicationInfo, UserHandle>> apps =
                 InteractAcrossProfilesSettings.collectConfigurableApps(
@@ -130,7 +127,7 @@
                 PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */);
         shadowOf(mPackageManager).setInstalledPackagesForUserId(
                 PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
-        installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
+        installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
 
         List<Pair<ApplicationInfo, UserHandle>> apps =
                 InteractAcrossProfilesSettings.collectConfigurableApps(
@@ -150,10 +147,9 @@
                 PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
         shadowOf(mPackageManager).setInstalledPackagesForUserId(
                 WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
-        installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
-        installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
+        installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
+        installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
         shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
-        String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
         ShadowPermissionChecker.setResult(
                 PERSONAL_CROSS_PROFILE_PACKAGE,
                 INTERACT_ACROSS_PROFILES_PERMISSION,
@@ -169,7 +165,7 @@
         assertThat(numOfApps).isEqualTo(1);
     }
 
-    private void installCrossProfilePackage(int profileId, String packageName) {
+    private void installCrossProfilePackage(String packageName) {
         PackageInfo personalPackageInfo = shadowOf(mPackageManager).getInternalMutablePackageInfo(
                 packageName);
         personalPackageInfo.requestedPermissions = new String[]{
diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
index cc3b20d..068de34 100644
--- a/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotatePreferenceControllerTest.java
@@ -20,46 +20,65 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.when;
 
+import android.Manifest;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
 import android.os.UserHandle;
 import android.provider.Settings;
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.ResolveInfoBuilder;
+import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowSensorPrivacyManager.class)
 public class SmartAutoRotatePreferenceControllerTest {
 
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
+    private static final String PACKAGE_NAME = "package_name";
     @Mock
     private PackageManager mPackageManager;
+    @Mock
+    private Resources mResources;
+    private Context mContext;
     private ContentResolver mContentResolver;
     private SmartAutoRotatePreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mContext = Mockito.spy(RuntimeEnvironment.application);
         FakeFeatureFactory.setupForTest();
         mContentResolver = RuntimeEnvironment.application.getContentResolver();
+
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mContext.getResources()).thenReturn(mResources);
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
+
+        doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName();
+        doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
+                Manifest.permission.CAMERA, PACKAGE_NAME);
         when(mContext.getString(R.string.auto_rotate_option_off))
                 .thenReturn("Off");
         when(mContext.getString(R.string.auto_rotate_option_on))
@@ -68,8 +87,14 @@
                 .thenReturn("On - Face-based");
 
         disableCameraBasedRotation();
+        final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
+        resolveInfo.serviceInfo = new ServiceInfo();
+        when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo);
 
-        mController = new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate");
+        mController = Mockito.spy(
+                new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate"));
+        when(mController.isCameraLocked()).thenReturn(false);
+        when(mController.isPowerSaveMode()).thenReturn(false);
     }
 
     @Test
@@ -82,33 +107,37 @@
     }
 
     @Test
-    public void updatePreference_settingsIsOff_shouldTurnOffToggle() {
+    public void getSummary_settingsIsOff_returnsOff() {
         disableAutoRotation();
 
         assertThat(mController.getSummary()).isEqualTo("Off");
     }
 
     @Test
-    public void updatePreference_settingsIsOn_shouldTurnOnToggle() {
+    public void getSummary_settingsIsOn_returnsOn() {
         enableAutoRotation();
 
         assertThat(mController.getSummary()).isEqualTo("On");
     }
 
     @Test
-    public void updatePreference_settingsIsCameraBased_shouldTurnOnToggle() {
+    public void getSummary_autoRotateOffSmartAutoRotateOn_returnsOff() {
+        enableCameraBasedRotation();
+        disableAutoRotation();
+
+        assertThat(mController.getSummary()).isEqualTo("Off");
+    }
+
+    @Test
+    public void updatePreference_smartAutoRotateOn_returnsFaceBased() {
         enableCameraBasedRotation();
         enableAutoRotation();
 
         assertThat(mController.getSummary()).isEqualTo("On - Face-based");
-
-        disableAutoRotation();
-
-        assertThat(mController.getSummary()).isEqualTo("Off");
     }
 
     @Test
-    public void updatePreference_settingsIsOff_noSmartAuto_shouldTurnOffToggle() {
+    public void getSummary_noSmartAuto_returnsOff() {
         disableAutoRotation();
         Settings.Secure.putStringForUser(mContentResolver,
                 CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT);
@@ -118,7 +147,7 @@
     }
 
     @Test
-    public void updatePreference_settingsIsOn_noSmartAuto_shouldTurnOnToggle() {
+    public void getSummary_noSmartAuto_returnsOn() {
         enableAutoRotation();
         Settings.Secure.putStringForUser(mContentResolver,
                 CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT);
@@ -127,6 +156,34 @@
     }
 
     @Test
+    public void getSummary_noCameraPermission_returnsOn() {
+        enableAutoRotation();
+        enableCameraBasedRotation();
+        doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
+                Manifest.permission.CAMERA, PACKAGE_NAME);
+
+        assertThat(mController.getSummary()).isEqualTo("On");
+    }
+
+    @Test
+    public void getSummary_cameraDisabled_returnsOn() {
+        enableAutoRotation();
+        enableCameraBasedRotation();
+        when(mController.isCameraLocked()).thenReturn(true);
+
+        assertThat(mController.getSummary()).isEqualTo("On");
+    }
+
+    @Test
+    public void getSummary_powerSaveEnabled_returnsOn() {
+        enableAutoRotation();
+        enableCameraBasedRotation();
+        when(mController.isPowerSaveMode()).thenReturn(true);
+
+        assertThat(mController.getSummary()).isEqualTo("On");
+    }
+
+    @Test
     public void testGetAvailabilityStatus() {
         assertThat(mController.getAvailabilityStatus()).isEqualTo(BasePreferenceController
                 .UNSUPPORTED_ON_DEVICE);
@@ -158,14 +215,14 @@
 
     private void enableAutoRotationPreference() {
         when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
-        when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
+        when(mResources.getBoolean(anyInt())).thenReturn(true);
         Settings.System.putInt(mContentResolver,
                 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0);
     }
 
     private void disableAutoRotationPreference() {
         when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
-        when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
+        when(mResources.getBoolean(anyInt())).thenReturn(true);
         Settings.System.putInt(mContentResolver,
                 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1);
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
index 7894c3f..ef76eee 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartPreferenceControllerTest.java
@@ -35,6 +35,7 @@
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.LocaleList;
 import android.text.format.DateUtils;
 import android.util.Pair;
 
@@ -100,6 +101,8 @@
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
         mContext = spy(RuntimeEnvironment.application);
+        mContext.getResources().getConfiguration().setLocales(
+            new LocaleList(new Locale("en_US")));
         mBatteryChartPreferenceController = createController();
         mBatteryChartPreferenceController.mPrefContext = mContext;
         mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup;
@@ -573,14 +576,12 @@
         // Verifies the title in the preference group.
         verify(mBatteryChartPreferenceController.mAppListPrefGroup)
             .setTitle(captor.capture());
-        assertThat(captor.getValue())
-            .isEqualTo("App usage for 4 pm - 7 am");
+        assertThat(captor.getValue()).isEqualTo("App usage for 4 - 7");
         // Verifies the title in the expandable divider.
         captor = ArgumentCaptor.forClass(String.class);
         verify(mBatteryChartPreferenceController.mExpandDividerPreference)
             .setTitle(captor.capture());
-        assertThat(captor.getValue())
-            .isEqualTo("System usage for 4 pm - 7 am");
+        assertThat(captor.getValue()).isEqualTo("System usage for 4 - 7");
     }
 
     @Test
@@ -716,7 +717,8 @@
     private void setUpBatteryHistoryKeys() {
         mBatteryChartPreferenceController.mBatteryHistoryKeys =
             new long[] {1619196786769L, 0L, 1619247636826L};
-        ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ false);
+        ConvertUtils.utcToLocalTimeHour(
+            mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
         // Simulates the locale in GMT.
         ConvertUtils.sSimpleDateFormatForHour
              .setTimeZone(TimeZone.getTimeZone("GMT"));
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
index 3f94456..ec77f4c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryChartViewTest.java
@@ -27,6 +27,7 @@
 
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.Context;
+import android.os.LocaleList;
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -41,6 +42,7 @@
 
 import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Locale;
 import java.util.TimeZone;
 
 @RunWith(RobolectricTestRunner.class)
@@ -60,6 +62,8 @@
         mFeatureFactory = FakeFeatureFactory.setupForTest();
         mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
         mContext = spy(RuntimeEnvironment.application);
+        mContext.getResources().getConfiguration().setLocales(
+            new LocaleList(new Locale("en_US")));
         mBatteryChartView = new BatteryChartView(mContext);
         doReturn(mockAccessibilityManager).when(mContext)
             .getSystemService(AccessibilityManager.class);
@@ -234,11 +238,11 @@
         final long timestamp = 1619196786769L;
         ConvertUtils.sSimpleDateFormatForHour = null;
         // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ false);
+        ConvertUtils.utcToLocalTimeHour(
+            mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
         ConvertUtils.sSimpleDateFormatForHour
             .setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
-        final String[] expectedTimestamps =
-            new String[] {"9 am", "5 pm", "1 am", "9 am"};
+        final String[] expectedTimestamps = new String[] {"00", "06", "12", "18", "00"};
 
         mBatteryChartView.setLatestTimestamp(timestamp);
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
index e0f8ba7..96f0ec7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
@@ -93,7 +93,7 @@
         when(consumer.getUid()).thenReturn(APP_UID);
         when(consumer.getPackageWithHighestDrain()).thenReturn(highDrainPackage);
         return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
-                consumer, false, packages, packageName);
+                consumer, false, APP_UID, packages, packageName);
     }
 
     private BatteryEntry createAggregateBatteryEntry(int powerComponentId) {
@@ -108,7 +108,7 @@
         UserBatteryConsumer consumer = mock(UserBatteryConsumer.class);
         when(consumer.getUserId()).thenReturn(userId);
         return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
-                consumer, false, null, null);
+                consumer, false, 0, null, null);
     }
 
     @Test
@@ -169,12 +169,12 @@
 
     @Test
     public void getTimeInForegroundMs_app() {
-        final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
-                mockUserManager, mUidBatteryConsumer, false, null, null);
-
         when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
                 .thenReturn(100L);
 
+        final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
+                mockUserManager, mUidBatteryConsumer, false, 0, null, null);
+
         assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L);
     }
 
@@ -188,12 +188,12 @@
 
     @Test
     public void getTimeInBackgroundMs_app() {
-        final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
-                mockUserManager, mUidBatteryConsumer, false, null, null);
-
         when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
                 .thenReturn(100L);
 
+        final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
+                mockUserManager, mUidBatteryConsumer, false, 0, null, null);
+
         assertThat(entry.getTimeInBackgroundMs()).isEqualTo(100L);
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
index 7e1d3e4..0b1a1e3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.os.BatteryManager;
 import android.os.BatteryUsageStats;
+import android.os.LocaleList;
 import android.os.UserHandle;
 
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -325,14 +326,16 @@
         final String expectedZoneId = "America/Los_Angeles";
         ConvertUtils.sSimpleDateFormat = null;
         // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTime(/*timestamp=*/ 0);
+        ConvertUtils.utcToLocalTime(mContext, /*timestamp=*/ 0);
         ConvertUtils.sSimpleDateFormat
             .setTimeZone(TimeZone.getTimeZone(expectedZoneId));
+        mContext.getResources().getConfiguration().setLocales(
+            new LocaleList(new Locale("en_US")));
 
-        assertThat(ConvertUtils.utcToLocalTime(timestamp))
-            .isEqualTo("Apr 23,2021 09:53:06");
+        assertThat(ConvertUtils.utcToLocalTime(mContext, timestamp))
+            .isEqualTo("Apr 24,2021 00:53:06");
         assertThat(ConvertUtils.sZoneId).isNotEqualTo(expectedZoneId);
-        assertThat(ConvertUtils.sLocale).isEqualTo(Locale.getDefault());
+        assertThat(ConvertUtils.sLocale).isEqualTo(new Locale("en_US"));
     }
 
     @Ignore
@@ -340,18 +343,21 @@
     public void testUtcToLocalTimeHour_12HourFormat_returnExpectedResult() {
         ConvertUtils.sZoneIdForHour = null;
         ConvertUtils.sLocaleForHour = null;
-        final long timestamp = 1619196786769L;
+        final long timestamp = 1619000086769L;
         final String expectedZoneId = "America/Los_Angeles";
         ConvertUtils.sSimpleDateFormatForHour = null;
         // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ false);
+        ConvertUtils.utcToLocalTimeHour(
+            mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
         ConvertUtils.sSimpleDateFormatForHour
             .setTimeZone(TimeZone.getTimeZone(expectedZoneId));
+        mContext.getResources().getConfiguration().setLocales(
+            new LocaleList(new Locale("en_US")));
 
         assertThat(ConvertUtils.utcToLocalTimeHour(
-            timestamp, /*is24HourFormat=*/ false)).isEqualTo("9 am");
+            mContext, timestamp, /*is24HourFormat=*/ false)).isEqualTo("6");
         assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId);
-        assertThat(ConvertUtils.sLocaleForHour).isEqualTo(Locale.getDefault());
+        assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US"));
     }
 
     @Ignore
@@ -359,18 +365,39 @@
     public void testUtcToLocalTimeHour_24HourFormat_returnExpectedResult() {
         ConvertUtils.sZoneIdForHour = null;
         ConvertUtils.sLocaleForHour = null;
-        final long timestamp = 1619196786769L;
+        final long timestamp = 1619000086769L;
         final String expectedZoneId = "America/Los_Angeles";
         ConvertUtils.sSimpleDateFormatForHour = null;
         // Invokes the method first to create the SimpleDateFormat.
-        ConvertUtils.utcToLocalTimeHour(/*timestamp=*/ 0, /*is24HourFormat=*/ true);
+        ConvertUtils.utcToLocalTimeHour(
+            mContext, /*timestamp=*/ 0, /*is24HourFormat=*/ false);
         ConvertUtils.sSimpleDateFormatForHour
             .setTimeZone(TimeZone.getTimeZone(expectedZoneId));
+        mContext.getResources().getConfiguration().setLocales(
+            new LocaleList(new Locale("en_US")));
 
         assertThat(ConvertUtils.utcToLocalTimeHour(
-            timestamp, /*is24HourFormat=*/ true)).isEqualTo("09");
+            mContext, timestamp, /*is24HourFormat=*/ true)).isEqualTo("18");
         assertThat(ConvertUtils.sZoneIdForHour).isNotEqualTo(expectedZoneId);
-        assertThat(ConvertUtils.sLocaleForHour).isEqualTo(Locale.getDefault());
+        assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US"));
+    }
+
+    @Test
+    public void getLocale_nullContext_returnDefaultLocale() {
+        assertThat(ConvertUtils.getLocale(/*context=*/ null))
+            .isEqualTo(Locale.getDefault());
+    }
+
+    @Test
+    public void getLocale_nullLocaleList_returnDefaultLocale() {
+        mContext.getResources().getConfiguration().setLocales(null);
+        assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
+    }
+
+    @Test
+    public void getLocale_emptyLocaleList_returnDefaultLocale() {
+        mContext.getResources().getConfiguration().setLocales(new LocaleList());
+        assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
     }
 
     private static BatteryHistEntry createBatteryHistEntry(
diff --git a/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java
new file mode 100644
index 0000000..4fb94f8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/LabeledSeekBarPreferenceTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.gestures;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import androidx.preference.Preference;
+
+import com.android.settings.widget.LabeledSeekBarPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class LabeledSeekBarPreferenceTest {
+
+    private Context mContext;
+    private SeekBar mSeekBar;
+    private LabeledSeekBarPreference mSeekBarPreference;
+
+    @Mock
+    private Preference.OnPreferenceChangeListener mListener;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application;
+        mSeekBarPreference = new LabeledSeekBarPreference(mContext, null);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        final View view =
+                inflater.inflate(mSeekBarPreference.getLayoutResource(),
+                        new LinearLayout(mContext), false);
+        mSeekBar = view.findViewById(com.android.internal.R.id.seekbar);
+    }
+
+    @Test
+    public void seekBarPreferenceOnStopTrackingTouch_callsListener() {
+        mSeekBar.setProgress(2);
+
+        mSeekBarPreference.setOnPreferenceChangeStopListener(mListener);
+        mSeekBarPreference.onStopTrackingTouch(mSeekBar);
+
+        verify(mListener, times(1)).onPreferenceChange(mSeekBarPreference, 2);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
index 0370781..1a7a63c 100644
--- a/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationInjectedServicesPreferenceControllerTest.java
@@ -67,8 +67,6 @@
     @Mock
     private PreferenceCategory mCategoryPrimary;
     @Mock
-    private PreferenceCategory mCategoryManaged;
-    @Mock
     private PreferenceScreen mScreen;
     @Mock
     private AppSettingsInjector mSettingsInjector;
@@ -115,31 +113,6 @@
     }
 
     @Test
-    public void updateState_shouldRemoveAllAndAddInjectedSettings() {
-        final List<Preference> preferences = new ArrayList<>();
-        final Map<Integer, List<Preference>> map = new ArrayMap<>();
-        final Preference pref1 = new Preference(mContext);
-        pref1.setTitle("Title1");
-        final Preference pref2 = new Preference(mContext);
-        pref2.setTitle("Title2");
-        preferences.add(pref1);
-        preferences.add(pref2);
-        map.put(UserHandle.myUserId(), preferences);
-        doReturn(map)
-                .when(mSettingsInjector).getInjectedSettings(any(Context.class), anyInt());
-        when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
-        ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{UserHandle.myUserId()});
-
-        mController.displayPreference(mScreen);
-
-        mController.updateState(mCategoryPrimary);
-
-        verify(mCategoryPrimary).removeAll();
-        verify(mCategoryPrimary).addPreference(pref1);
-        verify(mCategoryPrimary).addPreference(pref2);
-    }
-
-    @Test
     public void workProfileDisallowShareLocationOn_getParentUserLocationServicesOnly() {
         final int fakeWorkProfileId = 123;
         ShadowUserManager.getShadow().setProfileIdsWithDisabled(
@@ -158,7 +131,6 @@
         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
 
         mController.displayPreference(mScreen);
-        mController.updateState(mCategoryPrimary);
         verify(mSettingsInjector).getInjectedSettings(
                 any(Context.class), eq(UserHandle.myUserId()));
     }
@@ -178,7 +150,6 @@
                 enforcingUsers);
 
         mController.displayPreference(mScreen);
-        mController.updateState(mCategoryPrimary);
         verify(mSettingsInjector).getInjectedSettings(
                 any(Context.class), eq(UserHandle.USER_CURRENT));
     }
@@ -216,7 +187,6 @@
         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
 
         mController.displayPreference(mScreen);
-        mController.updateState(mCategoryPrimary);
 
         assertThat(pref.isEnabled()).isFalse();
         assertThat(pref.isDisabledByAdmin()).isTrue();
diff --git a/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java
index a43fa01..de00189 100644
--- a/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/AdjustVolumeRestrictedPreferenceControllerTest.java
@@ -20,20 +20,19 @@
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.os.UserHandle;
 import android.os.UserManager;
 
 import androidx.preference.Preference;
 
 import com.android.settings.accounts.AccountRestrictionHelper;
-import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.RestrictedSeekBarPreference;
+import com.android.settingslib.RestrictedPreference;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -47,10 +46,8 @@
 public class AdjustVolumeRestrictedPreferenceControllerTest {
 
     private static final String KEY = "key";
-    private AccountRestrictionHelper mAccountHelper;
-
     @Mock
-    UserManager mUserManager;
+    private AccountRestrictionHelper mAccountHelper;
 
     private Context mContext;
     private AdjustVolumeRestrictedPreferenceControllerTestable mController;
@@ -59,17 +56,15 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-        mAccountHelper = new AccountRestrictionHelper(mContext);
         mController =
             new AdjustVolumeRestrictedPreferenceControllerTestable(mContext, mAccountHelper, KEY);
     }
 
     @Test
     public void updateState_hasBaseRestriction_shouldDisable() {
-        RestrictedSeekBarPreference preference = mock(RestrictedSeekBarPreference.class);
-        when(RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
-                UserManager.DISALLOW_ADJUST_VOLUME, UserHandle.myUserId())).thenReturn(true);
+        RestrictedPreference preference = mock(RestrictedPreference.class);
+        when(mAccountHelper.hasBaseUserRestriction(
+            eq(UserManager.DISALLOW_ADJUST_VOLUME), anyInt())).thenReturn(true);
 
         mController.updateState(preference);
 
@@ -78,11 +73,13 @@
 
     @Test
     public void updateState_NoBaseRestriction_shouldCheckRestriction() {
-        RestrictedSeekBarPreference preference = spy(new RestrictedSeekBarPreference(mContext));
+        RestrictedPreference preference = spy(new RestrictedPreference(mContext));
 
         when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(null);
-        when(RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
-                UserManager.DISALLOW_ADJUST_VOLUME, UserHandle.myUserId())).thenReturn(false);
+        when(mAccountHelper.hasBaseUserRestriction(
+            eq(UserManager.DISALLOW_ADJUST_VOLUME), anyInt())).thenReturn(false);
+        doCallRealMethod().when(mAccountHelper).enforceRestrictionOnPreference(
+            eq(preference), eq(UserManager.DISALLOW_ADJUST_VOLUME), anyInt());
 
         mController.updateState(preference);
 
diff --git a/tests/robotests/src/com/android/settings/notification/RemoteVolumeGroupControllerTest.java b/tests/robotests/src/com/android/settings/notification/RemoteVolumeGroupControllerTest.java
index d24fe16..8b46374 100644
--- a/tests/robotests/src/com/android/settings/notification/RemoteVolumeGroupControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RemoteVolumeGroupControllerTest.java
@@ -43,8 +43,8 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settings.widget.SeekBarPreference;
 import com.android.settingslib.media.LocalMediaManager;
-import com.android.settingslib.widget.SeekBarPreference;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java
index 15bc598..f0ae7ab 100644
--- a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java
@@ -160,9 +160,9 @@
                 true);
 
         assertThat(mController.getSummary(ccw).toString()).contains(
-                ccw.getParentNotificationChannelGroup().getName());
+                ccw.getNotificationChannelGroup().getName());
         assertThat(mController.getSummary(ccw).toString()).contains(
-                ccw.getParentNotificationChannel().getName());
+                ccw.getNotificationChannel().getName());
     }
 
     @Test
@@ -175,7 +175,7 @@
                 true);
 
         assertThat(mController.getSummary(ccw).toString()).isEqualTo(
-                ccw.getParentNotificationChannel().getName());
+                ccw.getNotificationChannel().getName());
     }
 
     @Test
@@ -207,7 +207,7 @@
                 ccw.getShortcutInfo().getPackage());
         assertThat(extras.getInt(AppInfoBase.ARG_PACKAGE_UID)).isEqualTo(ccw.getUid());
         assertThat(extras.getString(Settings.EXTRA_CHANNEL_ID)).isEqualTo(
-                ccw.getParentNotificationChannel().getId());
+                ccw.getNotificationChannel().getId());
         assertThat(extras.getString(Settings.EXTRA_CONVERSATION_ID)).isEqualTo(
                 ccw.getShortcutInfo().getId());
     }
@@ -230,7 +230,7 @@
             // expected since it tries to launch an activity
         }
         verify(mBackend).createConversationNotificationChannel(
-                si.getPackage(), ccw.getUid(), ccw.getParentNotificationChannel(), si.getId());
+                si.getPackage(), ccw.getUid(), ccw.getNotificationChannel(), si.getId());
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
index cd192ef..d7aa42c 100644
--- a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
@@ -28,6 +28,7 @@
 import android.content.pm.ServiceInfo;
 import android.service.trust.TrustAgentService;
 
+import android.text.TextUtils;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
 
diff --git a/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java
index 6d4a6bb..85ab609 100644
--- a/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java
@@ -45,5 +45,4 @@
     public void getLayoutResource() {
         assertThat(mCardPreference.getLayoutResource()).isEqualTo(R.layout.card_preference_layout);
     }
-
 }
diff --git a/tests/robotests/src/com/android/settings/widget/SeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/SeekBarPreferenceTest.java
new file mode 100644
index 0000000..451b84b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/SeekBarPreferenceTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
+import static android.view.HapticFeedbackConstants.CONTEXT_CLICK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.widget.SeekBar;
+
+import androidx.preference.PreferenceFragmentCompat;
+
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
+
+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;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.androidx.fragment.FragmentController;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
+public class SeekBarPreferenceTest {
+
+    private static final int MAX = 75;
+    private static final int MIN = 5;
+    private static final int PROGRESS = 16;
+    private static final int NEW_PROGRESS = 17;
+
+    private Context mContext;
+    private SeekBarPreference mSeekBarPreference;
+    private SeekBar mSeekBar;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+
+        mSeekBarPreference = spy(new SeekBarPreference(mContext));
+        mSeekBarPreference.setMax(MAX);
+        mSeekBarPreference.setMin(MIN);
+        mSeekBarPreference.setProgress(PROGRESS);
+        mSeekBarPreference.setPersistent(false);
+        mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_NONE);
+
+        mSeekBar = new SeekBar(mContext);
+        mSeekBar.setMax(MAX);
+        mSeekBar.setMin(MIN);
+    }
+
+    @Test
+    public void testSaveAndRestoreInstanceState() {
+        final Parcelable parcelable = mSeekBarPreference.onSaveInstanceState();
+
+        final SeekBarPreference preference = new SeekBarPreference(mContext);
+        preference.onRestoreInstanceState(parcelable);
+
+        assertThat(preference.getMax()).isEqualTo(MAX);
+        assertThat(preference.getMin()).isEqualTo(MIN);
+        assertThat(preference.getProgress()).isEqualTo(PROGRESS);
+    }
+
+    @Test
+    public void isSelectable_disabledByAdmin_returnTrue() {
+        when(mSeekBarPreference.isDisabledByAdmin()).thenReturn(true);
+
+        assertThat(mSeekBarPreference.isSelectable()).isTrue();
+    }
+
+    @Test
+    @Config(qualifiers = "mcc998")
+    public void isSelectable_default_returnFalse() {
+        final PreferenceFragmentCompat fragment = FragmentController.of(new TestFragment(),
+                new Bundle())
+                .create()
+                .start()
+                .resume()
+                .get();
+
+        final SeekBarPreference seekBarPreference = fragment.findPreference("seek_bar");
+
+        assertThat(seekBarPreference.isSelectable()).isFalse();
+    }
+
+    @Test
+    @Config(qualifiers = "mcc999")
+    public void isSelectable_selectableInXml_returnTrue() {
+        final PreferenceFragmentCompat fragment = FragmentController.of(new TestFragment(),
+                new Bundle())
+                .create()
+                .start()
+                .resume()
+                .get();
+
+        final SeekBarPreference seekBarPreference = fragment.findPreference("seek_bar");
+
+        assertThat(seekBarPreference.isSelectable()).isTrue();
+    }
+
+    @Test
+    public void testSetSeekBarStateDescription() {
+        mSeekBarPreference.setSeekBarStateDescription("test");
+
+        verify(mSeekBarPreference).setSeekBarStateDescription("test");
+    }
+
+    @Test
+    public void onProgressChanged_hapticFeedbackModeNone_clockTickFeedbackNotPerformed() {
+        mSeekBar.setProgress(NEW_PROGRESS);
+        when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
+        mSeekBar.performHapticFeedback(CONTEXT_CLICK);
+
+        mSeekBarPreference.onProgressChanged(mSeekBar, NEW_PROGRESS, true);
+
+        assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isNotEqualTo(CLOCK_TICK);
+    }
+
+    @Test
+    public void onProgressChanged_hapticFeedbackModeOnTicks_clockTickFeedbackPerformed() {
+        mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_TICKS);
+        mSeekBar.setProgress(NEW_PROGRESS);
+        when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
+        mSeekBar.performHapticFeedback(CONTEXT_CLICK);
+
+        mSeekBarPreference.onProgressChanged(mSeekBar, NEW_PROGRESS, true);
+
+        assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
+    }
+
+    @Test
+    public void onProgressChanged_hapticFeedbackModeOnEnds_clockTickFeedbackNotPerformed() {
+        mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_ENDS);
+        mSeekBar.setProgress(NEW_PROGRESS);
+        when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
+        mSeekBar.performHapticFeedback(CONTEXT_CLICK);
+
+        mSeekBarPreference.onProgressChanged(mSeekBar, NEW_PROGRESS, true);
+
+        assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isNotEqualTo(CLOCK_TICK);
+    }
+
+    @Test
+    public void onProgressChanged_hapticFeedbackModeOnEndsAndMinValue_clockTickFeedbackPerformed() {
+        mSeekBarPreference.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_ENDS);
+        mSeekBar.setProgress(MIN);
+        when(mSeekBarPreference.callChangeListener(anyInt())).thenReturn(true);
+        mSeekBar.performHapticFeedback(CONTEXT_CLICK);
+
+        mSeekBarPreference.onProgressChanged(mSeekBar, MIN, true);
+
+        assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
+    }
+
+    public static class TestFragment extends PreferenceFragmentCompat {
+        @Override
+        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+            addPreferencesFromResource(com.android.settings.R.xml.seekbar_preference);
+        }
+    }
+}
diff --git a/tests/unit/src/com/android/settings/core/SettingsSliderPreferenceControllerTest.java b/tests/unit/src/com/android/settings/core/SettingsSliderPreferenceControllerTest.java
index 982eb37..846ffd7 100644
--- a/tests/unit/src/com/android/settings/core/SettingsSliderPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/core/SettingsSliderPreferenceControllerTest.java
@@ -23,7 +23,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.settings.slices.SliceData;
-import com.android.settingslib.widget.SeekBarPreference;
+import com.android.settings.widget.SeekBarPreference;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/tests/unit/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java b/tests/unit/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java
deleted file mode 100644
index 9b42951..0000000
--- a/tests/unit/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2020 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.fuelgauge.batterytip;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.provider.Settings;
-import android.text.format.DateUtils;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class BatteryTipPolicyTest {
-
-    private static final String BATTERY_TIP_CONSTANTS_VALUE = "battery_tip_enabled=true"
-            + ",summary_enabled=false"
-            + ",battery_saver_tip_enabled=false"
-            + ",high_usage_enabled=true"
-            + ",high_usage_app_count=5"
-            + ",high_usage_period_ms=2000"
-            + ",high_usage_battery_draining=30"
-            + ",app_restriction_enabled=true"
-            + ",reduced_battery_enabled=true"
-            + ",reduced_battery_percent=30"
-            + ",low_battery_enabled=false"
-            + ",low_battery_hour=10"
-            + ",data_history_retain_day=24"
-            + ",excessive_bg_drain_percentage=25"
-            + ",test_battery_saver_tip=true"
-            + ",test_high_usage_tip=false"
-            + ",test_smart_battery_tip=true"
-            + ",test_low_battery_tip=true"
-            + ",app_restriction_active_hour=6";
-    private Context mContext;
-
-    @Before
-    public void setUp() {
-        mContext = ApplicationProvider.getApplicationContext();
-    }
-
-    @Test
-    public void testInit_usesConfigValues() {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.BATTERY_TIP_CONSTANTS, BATTERY_TIP_CONSTANTS_VALUE);
-
-        final BatteryTipPolicy batteryTipPolicy = new BatteryTipPolicy(mContext);
-
-        assertThat(batteryTipPolicy.batteryTipEnabled).isTrue();
-        assertThat(batteryTipPolicy.summaryEnabled).isFalse();
-        assertThat(batteryTipPolicy.batterySaverTipEnabled).isFalse();
-        assertThat(batteryTipPolicy.highUsageEnabled).isTrue();
-        assertThat(batteryTipPolicy.highUsageAppCount).isEqualTo(5);
-        assertThat(batteryTipPolicy.highUsagePeriodMs).isEqualTo(2000);
-        assertThat(batteryTipPolicy.highUsageBatteryDraining).isEqualTo(30);
-        assertThat(batteryTipPolicy.appRestrictionEnabled).isTrue();
-        assertThat(batteryTipPolicy.appRestrictionActiveHour).isEqualTo(6);
-        assertThat(batteryTipPolicy.reducedBatteryEnabled).isTrue();
-        assertThat(batteryTipPolicy.reducedBatteryPercent).isEqualTo(30);
-        assertThat(batteryTipPolicy.lowBatteryEnabled).isFalse();
-        assertThat(batteryTipPolicy.lowBatteryHour).isEqualTo(10);
-        assertThat(batteryTipPolicy.dataHistoryRetainDay).isEqualTo(24);
-        assertThat(batteryTipPolicy.excessiveBgDrainPercentage).isEqualTo(25);
-        assertThat(batteryTipPolicy.testBatterySaverTip).isTrue();
-        assertThat(batteryTipPolicy.testHighUsageTip).isFalse();
-        assertThat(batteryTipPolicy.testSmartBatteryTip).isTrue();
-        assertThat(batteryTipPolicy.testLowBatteryTip).isTrue();
-    }
-
-    @Test
-    public void testInit_defaultValues() {
-        Settings.Global.putString(mContext.getContentResolver(),
-                Settings.Global.BATTERY_TIP_CONSTANTS, "");
-
-        final BatteryTipPolicy batteryTipPolicy = new BatteryTipPolicy(mContext);
-
-        assertThat(batteryTipPolicy.batteryTipEnabled).isTrue();
-        assertThat(batteryTipPolicy.summaryEnabled).isFalse();
-        assertThat(batteryTipPolicy.batterySaverTipEnabled).isTrue();
-        assertThat(batteryTipPolicy.highUsageEnabled).isTrue();
-        assertThat(batteryTipPolicy.highUsageAppCount).isEqualTo(3);
-        assertThat(batteryTipPolicy.highUsagePeriodMs).isEqualTo(2 * DateUtils.HOUR_IN_MILLIS);
-        assertThat(batteryTipPolicy.highUsageBatteryDraining).isEqualTo(25);
-        assertThat(batteryTipPolicy.appRestrictionEnabled).isTrue();
-        assertThat(batteryTipPolicy.appRestrictionActiveHour).isEqualTo(24);
-        assertThat(batteryTipPolicy.reducedBatteryEnabled).isFalse();
-        assertThat(batteryTipPolicy.reducedBatteryPercent).isEqualTo(50);
-        assertThat(batteryTipPolicy.lowBatteryEnabled).isTrue();
-        assertThat(batteryTipPolicy.lowBatteryHour).isEqualTo(3);
-        assertThat(batteryTipPolicy.dataHistoryRetainDay).isEqualTo(30);
-        assertThat(batteryTipPolicy.excessiveBgDrainPercentage).isEqualTo(10);
-        assertThat(batteryTipPolicy.testBatterySaverTip).isFalse();
-        assertThat(batteryTipPolicy.testHighUsageTip).isFalse();
-        assertThat(batteryTipPolicy.testSmartBatteryTip).isFalse();
-        assertThat(batteryTipPolicy.testLowBatteryTip).isFalse();
-    }
-}
diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
index fb17e34..a96e7cf 100644
--- a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
+++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
@@ -144,6 +144,16 @@
 
     @Test
     @UiThreadTest
+    public void getBroadcastIntent_shouldHaveFlagReceiverForeground() {
+        final PendingIntent pendingIntent = mMockProviderModelSlice.getBroadcastIntent(mContext);
+
+        final int flags = pendingIntent.getIntent().getFlags();
+        assertThat(flags & Intent.FLAG_RECEIVER_FOREGROUND)
+                .isEqualTo(Intent.FLAG_RECEIVER_FOREGROUND);
+    }
+
+    @Test
+    @UiThreadTest
     public void getSlice_noWifiAndHasCarrierNoData_oneCarrier() {
         mWifiList.clear();
         mMockNetworkProviderWorker.updateSelfResults(null);
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
index 0ef44ee..fc18ce7 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
@@ -40,6 +40,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.os.Looper;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -82,6 +83,8 @@
     private static final String KEY = "preference_group";
 
     @Mock
+    private UserManager mUserManager;
+    @Mock
     private SubscriptionManager mSubscriptionManager;
     @Mock
     private ConnectivityManager mConnectivityManager;
@@ -121,10 +124,12 @@
         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
         when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+        when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
         when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
         when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
         when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork))
                 .thenReturn(mNetworkCapabilities);
+        when(mUserManager.isAdminUser()).thenReturn(true);
         when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
 
         mPreferenceManager = new PreferenceManager(mContext);
diff --git a/tests/unit/src/com/android/settings/widget/DefaultIndicatorSeekBarTest.java b/tests/unit/src/com/android/settings/widget/DefaultIndicatorSeekBarTest.java
new file mode 100644
index 0000000..777d984
--- /dev/null
+++ b/tests/unit/src/com/android/settings/widget/DefaultIndicatorSeekBarTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 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.widget;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class DefaultIndicatorSeekBarTest {
+
+    private DefaultIndicatorSeekBar mDefaultIndicatorSeekBar;
+
+    @Before
+    public void setUp() {
+        mDefaultIndicatorSeekBar = new DefaultIndicatorSeekBar(
+                ApplicationProvider.getApplicationContext());
+        mDefaultIndicatorSeekBar.setMax(100);
+    }
+
+    @After
+    public void tearDown() {
+        mDefaultIndicatorSeekBar = null;
+    }
+
+    @Test
+    public void defaultProgress_setSucceeds() {
+        mDefaultIndicatorSeekBar.setDefaultProgress(40);
+        assertEquals(40, mDefaultIndicatorSeekBar.getDefaultProgress());
+    }
+}
diff --git a/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java b/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java
new file mode 100644
index 0000000..a47eade
--- /dev/null
+++ b/tests/unit/src/com/android/settings/widget/GearPreferenceTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 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.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.ResourcesUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unittest for GearPreference */
+@RunWith(AndroidJUnit4.class)
+public class GearPreferenceTest {
+    @Mock
+    private GearPreference.OnGearClickListener mOnGearClickListener;
+
+    private Context mContext = ApplicationProvider.getApplicationContext();
+    private GearPreference mGearPreference;
+    private PreferenceViewHolder mViewHolder;
+    private View mGearView;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mGearPreference =
+                new GearPreference(mContext, null);
+        int layoutId = ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear");
+        PreferenceViewHolder holder =
+                PreferenceViewHolder.createInstanceForTests(
+                        LayoutInflater.from(ApplicationProvider.getApplicationContext())
+                                .inflate(layoutId, null));
+        mViewHolder = spy(holder);
+        mGearView = new View(mContext, null);
+        int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
+        when(mViewHolder.findViewById(gearId)).thenReturn(mGearView);
+    }
+
+    @Test
+    public void onBindViewHolder_gearIsVisible() {
+        mGearPreference.setOnGearClickListener(mOnGearClickListener);
+
+        mGearPreference.onBindViewHolder(mViewHolder);
+
+        assertThat(mGearView.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void onBindViewHolder_gearIsGone() {
+        mGearPreference.setOnGearClickListener(null);
+
+        mGearPreference.onBindViewHolder(mViewHolder);
+
+        assertThat(mGearView.getVisibility()).isEqualTo(View.GONE);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java b/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java
new file mode 100644
index 0000000..44b1d38
--- /dev/null
+++ b/tests/unit/src/com/android/settings/widget/MutableGearPreferenceTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 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.widget;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.widget.ImageView;
+
+import androidx.preference.PreferenceViewHolder;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.ResourcesUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unittest for MutableGearPreference */
+@RunWith(AndroidJUnit4.class)
+public class MutableGearPreferenceTest {
+    @Mock
+    private MutableGearPreference.OnGearClickListener mOnGearClickListener;
+
+    private Context mContext = ApplicationProvider.getApplicationContext();
+    private MutableGearPreference mMutableGearPreference;
+    private PreferenceViewHolder mViewHolder;
+    private ImageView mGearView;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mMutableGearPreference =
+                new MutableGearPreference(mContext, null);
+        int layoutId =
+                ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear");
+        PreferenceViewHolder holder =
+                PreferenceViewHolder.createInstanceForTests(
+                        LayoutInflater.from(ApplicationProvider.getApplicationContext())
+                                .inflate(layoutId, null));
+        mViewHolder = spy(holder);
+        mGearView = spy(new ImageView(mContext, null));
+        int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
+        when(mViewHolder.findViewById(gearId)).thenReturn(mGearView);
+    }
+
+    @Test
+    public void onBindViewHolder_gearChangeAlpha() {
+        mMutableGearPreference.setGearEnabled(false);
+        mMutableGearPreference.setOnGearClickListener(mOnGearClickListener);
+
+        mMutableGearPreference.onBindViewHolder(mViewHolder);
+
+        verify(mGearView).setImageAlpha(anyInt());
+    }
+
+    private static int getDisabledAlphaValue(Context context) {
+        TypedValue value = new TypedValue();
+        context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
+        return (int) (value.getFloat() * 255);
+    }
+}