Merge "[Settings] eSIM transfer: MobileNetworkListFragment"
diff --git a/res/drawable/ic_check_24dp.xml b/res/drawable/ic_check_24dp.xml
new file mode 100644
index 0000000..5801e70
--- /dev/null
+++ b/res/drawable/ic_check_24dp.xml
@@ -0,0 +1,25 @@
+<!-- Copyright (C) 2022 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"
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?androidprv:attr/colorAccentPrimaryVariant">
+    <path
+        android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"
+        android:fillColor="@android:color/white"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/accessibility_text_reading_preview.xml b/res/layout/accessibility_text_reading_preview.xml
index 91fb0a0..4b70bb4 100644
--- a/res/layout/accessibility_text_reading_preview.xml
+++ b/res/layout/accessibility_text_reading_preview.xml
@@ -37,7 +37,7 @@
             android:text="@string/screen_zoom_preview_title"
             style="@style/AccessibilityTextReadingPreviewTitle" />
 
-        <androidx.viewpager.widget.ViewPager
+        <com.android.settings.accessibility.TextReadingPreviewPager
             android:id="@+id/preview_pager"
             android:layout_width="match_parent"
             android:layout_height="217dp"
diff --git a/res/layout/accessibility_text_reading_preview_mail_content.xml b/res/layout/accessibility_text_reading_preview_mail_content.xml
index 941535f..e55d389 100644
--- a/res/layout/accessibility_text_reading_preview_mail_content.xml
+++ b/res/layout/accessibility_text_reading_preview_mail_content.xml
@@ -15,35 +15,43 @@
     limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.core.widget.NestedScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
+    android:layout_height="match_parent"
+    android:fillViewport="true"
+    android:importantForAccessibility="noHideDescendants">
 
-    <TextView
-        android:id="@+id/subject"
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="@string/accessibility_text_reading_preview_mail_subject"
-        android:textSize="14sp"
-        android:textAppearance="?android:attr/textAppearanceMedium"
-        android:textColor="?android:attr/textColorPrimary"/>
+        android:orientation="vertical">
 
-    <TextView
-        android:id="@+id/from"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingBottom="16dp"
-        android:paddingTop="11dp"
-        android:textSize="12sp"
-        android:text="@string/accessibility_text_reading_preview_mail_from"
-        android:textColor="?android:attr/textColorSecondary" />
+        <TextView
+            android:id="@+id/subject"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/accessibility_text_reading_preview_mail_subject"
+            android:textSize="14sp"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:textColor="?android:attr/textColorPrimary"/>
 
-    <TextView
-        android:id="@+id/content"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="13sp"
-        android:text="@string/accessibility_text_reading_preview_mail_content"
-        android:textColor="?android:attr/textColorPrimary"/>
-</LinearLayout>
+        <TextView
+            android:id="@+id/from"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingBottom="16dp"
+            android:paddingTop="11dp"
+            android:textSize="12sp"
+            android:text="@string/accessibility_text_reading_preview_mail_from"
+            android:textColor="?android:attr/textColorSecondary"/>
+
+        <TextView
+            android:id="@+id/content"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="13sp"
+            android:text="@string/accessibility_text_reading_preview_mail_content"
+            android:textColor="?android:attr/textColorPrimary"/>
+    </LinearLayout>
+</androidx.core.widget.NestedScrollView>
diff --git a/res/layout/accessibility_text_reading_reset_button_suw.xml b/res/layout/accessibility_text_reading_reset_button_suw.xml
deleted file mode 100644
index 97e12f3..0000000
--- a/res/layout/accessibility_text_reading_reset_button_suw.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright (C) 2022 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:minHeight="?android:attr/listPreferredItemHeight"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:paddingStart="?android:attr/listPreferredItemPaddingStart">
-
-    <Button
-        android:id="@+id/reset_button"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical|start"
-        android:paddingVertical="14dp"
-        android:background="?android:attr/selectableItemBackground"
-        android:textColor="?android:attr/colorAccent"
-        android:textSize="16sp"
-        android:text="@string/accessibility_text_reading_reset_button_title"
-        android:fontFamily="@*android:string/config_bodyFontFamilyMedium" />
-</FrameLayout>
diff --git a/res/layout/dialog_sim_status.xml b/res/layout/dialog_sim_status.xml
index c169e58..4fc7f46 100644
--- a/res/layout/dialog_sim_status.xml
+++ b/res/layout/dialog_sim_status.xml
@@ -17,6 +17,7 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
     <LinearLayout
@@ -168,6 +169,11 @@
             android:layout_height="wrap_content"
             android:textIsSelectable="true"
             android:text="@string/device_info_not_available"/>
+        <ImageView
+            android:id="@+id/esim_id_qrcode"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            tools:ignore="ContentDescription" />
 
         <TextView
             style="@style/device_info_dialog_label"
diff --git a/res/layout/keyboard_layout_picker.xml b/res/layout/keyboard_layout_picker.xml
new file mode 100644
index 0000000..6b163da
--- /dev/null
+++ b/res/layout/keyboard_layout_picker.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:id="@+id/keyboard_layout_picker_container"
+    android:orientation="vertical">
+
+    <FrameLayout
+        android:id="@+id/keyboard_layout_title"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:elevation="1dp"
+        android:background="?android:attr/colorBackground"
+        android:outlineAmbientShadowColor="@android:color/transparent"
+        android:outlineSpotShadowColor="@android:color/transparent"/>
+
+    <FrameLayout
+        android:id="@+id/keyboard_layouts"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="?android:attr/colorBackground"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/preference_check_icon.xml b/res/layout/preference_check_icon.xml
new file mode 100644
index 0000000..5652ac6
--- /dev/null
+++ b/res/layout/preference_check_icon.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/keyboard_check_icon"
+    android:src="@drawable/ic_check_24dp"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_centerVertical="true"
+    android:layout_marginHorizontal="16dp"/>
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 442441d..4d9a001 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1356,8 +1356,8 @@
         <item>1875000</item> <!-- 15Mbps == 1875000/s -->
     </string-array>
 
-    <!-- Array containing help message codes that should not be displayed
-         during fingerprint enrollment. -->
-    <integer-array name="fingerprint_acquired_ignore_list">
-    </integer-array>
+    <!-- An allowlist which packages won't show summary in battery usage screen.
+         [CHAR LIMIT=NONE] -->
+    <string-array name="allowlist_hide_summary_in_battery_usage" translatable="false">
+    </string-array>
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index e7efa6f..c9b5588 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -624,4 +624,11 @@
     <!-- Whether sim related information is visible to the end user. -->
     <bool name="config_show_sim_info">true</bool>
 
+    <!-- In the case of receiving both help and progress message, display progress message. -->
+    <bool name="enrollment_progress_priority_over_help">false</bool>
+    <!-- Prioritize help message by their occurrence -->
+    <bool name="enrollment_prioritize_acquire_messages">false</bool>
+    <!-- Control messages displayed during enrollment -->
+    <bool name="enrollment_message_display_controller_flag">false</bool>
+
 </resources>
diff --git a/res/values/integers.xml b/res/values/integers.xml
index d110de2..530f987 100644
--- a/res/values/integers.xml
+++ b/res/values/integers.xml
@@ -26,4 +26,11 @@
     <integer name="suw_max_faces_enrollable">1</integer>
     <!-- Controls the maximum number of fingerprints enrollable during SUW -->
     <integer name="suw_max_fingerprints_enrollable">1</integer>
+
+    <!-- Minimum display time (in millis) for help messages in fingerprint enrollment. -->
+    <integer name="enrollment_help_minimum_time_display">0</integer>
+    <!-- Minimum display time (in millis) for progress messages in fingerprint enrollment. -->
+    <integer name="enrollment_progress_minimum_time_display">0</integer>
+    <!-- The time (in millis) to wait to collect messages in fingerprint enrollment before displaying it. -->
+    <integer name="enrollment_collect_time">0</integer>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2f2969f..eb8f75b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1312,6 +1312,8 @@
 
     <!-- Title of device details screen [CHAR LIMIT=28]-->
     <string name="device_details_title">Device details</string>
+    <!-- Title for keyboard settings preferences. [CHAR LIMIT=50] -->
+    <string name="bluetooth_device_keyboard_settings_preference_title">Keyboard settings</string>
     <!-- Title of the item to show device MAC address -->
     <string name="bluetooth_device_mac_address">Device\'s Bluetooth address: <xliff:g id="address">%1$s</xliff:g></string>
     <!-- Title of the items to show multuple devices MAC address [CHAR LIMIT=NONE]-->
@@ -2274,6 +2276,12 @@
     <string name="screensaver_settings_summary_dock">While docked</string>
     <!-- Display settings screen, summary fragment for screen saver options, activated never [CHAR LIMIT=35] -->
     <string name="screensaver_settings_summary_never">Never</string>
+    <!-- Display settings screen, summary for screen saver options, screen saver is turned on [CHAR LIMIT=50] -->
+    <string name="screensaver_settings_summary_on">
+        On / <xliff:g id="screen_saver" example="Art gallery">%1$s</xliff:g>
+    </string>
+    <!-- Display settings screen, summary for screen saver options, screen saver is turned off [CHAR LIMIT=20] -->
+    <string name="screensaver_settings_summary_off">Off</string>
     <!-- Dream settings screen, action label, when to dream [CHAR LIMIT=20] -->
     <string name="screensaver_settings_when_to_dream">When to start</string>
     <!-- [CHAR LIMIT=40] Display settings screen, setting option name to change whether the device wakes up when a lift gesture is detected. -->
@@ -3635,8 +3643,8 @@
     <string name="available_virtual_keyboard_category">Available On-screen keyboard</string>
     <!-- Title for the button to trigger the 'Manage keyboards' preference sub-screen, where the user can turn on/off installed virtual keyboards.[CHAR LIMIT=35] -->
     <string name="add_virtual_keyboard">Manage on-screen keyboards</string>
-    <!-- Title for the 'keyboard assistance' preference category. [CHAR LIMIT=35] -->
-    <string name="keyboard_assistance_category">Keyboard assistance</string>
+    <!-- Title for the 'keyboard options' preference category. [CHAR LIMIT=35] -->
+    <string name="keyboard_options_category">Options</string>
     <!-- Title for the 'physical keyboard' settings screen. [CHAR LIMIT=35] -->
     <string name="physical_keyboard_title">Physical keyboard</string>
     <!-- Title for the 'show virtual keyboard' preference switch. [CHAR LIMIT=35] -->
@@ -3646,7 +3654,7 @@
     <!-- Title for the button to trigger the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=35] -->
     <string name="keyboard_shortcuts_helper">Keyboard shortcuts</string>
     <!-- Summary text for the 'keyboard shortcuts helper' dialog. [CHAR LIMIT=100] -->
-    <string name="keyboard_shortcuts_helper_summary">Display available shortcuts</string>
+    <string name="keyboard_shortcuts_helper_summary">Show list of shortcuts</string>
     <!-- Title for the 'Work profile keyboards & tools' preference category inside Languages and inputs'. [CHAR LIMIT=50] -->
     <string name="language_and_input_for_work_category_title">Work profile keyboards &amp; tools</string>
     <!-- Title for the 'Virtual keyboards for work' preference. [CHAR LIMIT=45] -->
@@ -3681,6 +3689,8 @@
     <!-- Keyboard Layout Picker --> <skip />
     <!-- Title for the keyboard layout picker activity. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_picker_title">Keyboard layouts</string>
+    <!-- Category title for the keyboard layout picker activity. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_picker_category_title">Physical keyboard layouts</string>
 
     <!-- User dictionary settings --><skip />
     <!-- User dictionary settings. The title of the list item to go into the Personal dictionary settings screen. [CHAR LIMIT=35] -->
@@ -3736,6 +3746,9 @@
     <!-- Title for built-in keyboard settings -->
     <string name="builtin_keyboard_settings_title">Physical keyboard</string>
 
+    <!-- Title for enabled locales keyboard layout page -->
+    <string name="enabled_locales_keyboard_layout">Layout</string>
+
     <!-- Title for the screen that lets the user choose a gadget to add to the home screen
          (or other screens that can host gadgets).  Note to translators: we're still determining
          the final name for Gadgets/Widgets, so please translate both for now. -->
@@ -6530,7 +6543,11 @@
     <string name="keywords_face_unlock">face, unlock, auth, sign in</string>
     <string name="keywords_biometric_unlock">face, unlock, auth, sign in, fingerprint, biometric</string>
     <string name="keywords_imei_info">imei, meid, min, prl version, imei sv</string>
-    <string name="keywords_sim_status">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid, eid</string>
+    <string name="keywords_sim_status">network, mobile network state, service state, signal strength, mobile network type, roaming</string>
+    <string name="keywords_sim_status_esim">network, mobile network state, service state, signal strength, mobile network type, roaming, eid</string>
+    <string name="keywords_sim_status_iccid">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid</string>
+    <string name="keywords_sim_status_iccid_esim">network, mobile network state, service state, signal strength, mobile network type, roaming, iccid, eid</string>
+    <string name="keywords_esim_eid">eid</string>
     <string name="keywords_model_and_hardware">serial number, hardware version</string>
     <string name="keywords_android_version">android security patch level, baseband version, kernel version</string>
     <!-- Search keywords for dark mode settings [CHAR LIMIT=NONE] -->
@@ -8129,7 +8146,8 @@
     <string name="memtag_reboot_no">Not now</string>
     <!-- [CHAR LIMIT=NONE] Label for Learn More link. -->
     <string name="memtag_learn_more">Learn more about Advanced memory protection.</string>
-    <!-- [CHAR LIMIT=NONE] Search keywords for Advanced memory protection option. -->
+    <!-- [CHAR LIMIT=NONE] Search keywords for Advanced memory protection option.
+         This is not translatable because it's the technical name for the technology. -->
     <string name="keywords_memtag" translatable="false">MTE, Memory Tagging Extension</string>
 
     <!-- Opening string on the dialog that prompts the user to confirm that they really want to delete their existing work profile. The administration app icon and name appear after the final colon. [CHAR LIMIT=NONE] -->
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index 5cd7c3a..c031960 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -88,6 +88,12 @@
             settings:controller="com.android.settings.accessibility.LiveCaptionPreferenceController"/>
     </PreferenceCategory>
 
+    <Preference
+        android:key="keyboard_settings"
+        android:persistent="false"
+        android:title="@string/bluetooth_device_keyboard_settings_preference_title"
+        settings:controller="com.android.settings.inputmethod.KeyboardSettingsPreferenceController"/>
+
     <com.android.settingslib.widget.FooterPreference
         android:key="device_details_footer"
         android:selectable="false"
diff --git a/res/xml/keyboard_settings.xml b/res/xml/keyboard_settings.xml
index bff1160..9a3ac1a 100644
--- a/res/xml/keyboard_settings.xml
+++ b/res/xml/keyboard_settings.xml
@@ -20,8 +20,7 @@
     xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:title="@string/keyboard_settings">
     <PreferenceCategory
-        android:key="keyboards_category"
-        android:title="@string/keyboard_and_input_methods_category">
+        android:key="keyboards_category">
         <Preference
             android:key="virtual_keyboard_pref"
             android:title="@string/virtual_keyboard_category"
diff --git a/res/xml/keyboard_settings_enabled_locales_list.xml b/res/xml/keyboard_settings_enabled_locales_list.xml
new file mode 100644
index 0000000..06b8d5f
--- /dev/null
+++ b/res/xml/keyboard_settings_enabled_locales_list.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:title="@string/physical_keyboard_title">
+    <PreferenceCategory
+        android:key="enabled_locales_keyboard_layout"
+        android:title="@string/enabled_locales_keyboard_layout">
+    </PreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/new_keyboard_layout_picker_fragment.xml b/res/xml/new_keyboard_layout_picker_fragment.xml
new file mode 100644
index 0000000..0a76984
--- /dev/null
+++ b/res/xml/new_keyboard_layout_picker_fragment.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:key="keyboard_layout_picker_list"
+    settings:controller="com.android.settings.inputmethod.NewKeyboardLayoutPickerController">
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/new_keyboard_layout_picker_title.xml b/res/xml/new_keyboard_layout_picker_title.xml
new file mode 100644
index 0000000..cd03b91
--- /dev/null
+++ b/res/xml/new_keyboard_layout_picker_title.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:key="keyboard_layout_picker_title">
+    <!-- Separate title from new_keyboard_layout_picker_fragment to avoid being moved to the top -->
+    <PreferenceCategory
+        android:key="keyboard_layout_picker_title"
+        android:title="@string/keyboard_layout_picker_category_title">
+    </PreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/physical_keyboard_settings.xml b/res/xml/physical_keyboard_settings.xml
index 96946a9..54a5c65 100644
--- a/res/xml/physical_keyboard_settings.xml
+++ b/res/xml/physical_keyboard_settings.xml
@@ -19,8 +19,8 @@
     <!-- Additional preference screens are inserted here programmatically
          with low order values to set the key map of each attached keyboard. -->
     <PreferenceCategory
-        android:key="keyboard_assistance_category"
-        android:title="@string/keyboard_assistance_category">
+        android:key="keyboard_options_category"
+        android:title="@string/keyboard_options_category">
         <SwitchPreference
             android:key="show_virtual_keyboard_switch"
             android:title="@string/show_ime"
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 23f8fd3..7b1500b 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -43,6 +43,7 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.search.SearchIndexableRaw;
 
@@ -303,6 +304,7 @@
     void updateAllPreferences() {
         updateSystemPreferences();
         updateServicePreferences();
+        updatePreferencesState();
     }
 
     private void registerContentMonitors() {
@@ -478,6 +480,13 @@
         // Do nothing.
     }
 
+    private void updatePreferencesState() {
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        getPreferenceControllers().forEach(controllers::addAll);
+        controllers.forEach(controller -> controller.updateState(
+                findPreference(controller.getPreferenceKey())));
+    }
+
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider(R.xml.accessibility_settings) {
                 @Override
diff --git a/src/com/android/settings/accessibility/ColorAndMotionFragment.java b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
index 7f55053..921aa4e 100644
--- a/src/com/android/settings/accessibility/ColorAndMotionFragment.java
+++ b/src/com/android/settings/accessibility/ColorAndMotionFragment.java
@@ -19,6 +19,7 @@
 import android.app.settings.SettingsEnums;
 import android.hardware.display.ColorDisplayManager;
 import android.os.Bundle;
+import android.os.Handler;
 import android.provider.Settings;
 
 import androidx.preference.Preference;
@@ -28,8 +29,12 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /** Accessibility settings for color and motion. */
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
 public class ColorAndMotionFragment extends DashboardFragment {
@@ -46,18 +51,48 @@
     private Preference mDisplayDaltonizerPreferenceScreen;
     private SwitchPreference mToggleDisableAnimationsPreference;
     private SwitchPreference mToggleLargePointerIconPreference;
+    private AccessibilitySettingsContentObserver mSettingsContentObserver;
+
+    private final List<String> mShortcutFeatureKeys = new ArrayList<>();
 
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.ACCESSIBILITY_COLOR_AND_MOTION;
     }
 
-
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         initializeAllPreferences();
         updateSystemPreferences();
+
+        mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
+        mShortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
+
+        mSettingsContentObserver = new AccessibilitySettingsContentObserver(new Handler());
+        mSettingsContentObserver.registerKeysToObserverCallback(mShortcutFeatureKeys,
+                key -> updatePreferencesState());
+    }
+
+    private void updatePreferencesState() {
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        getPreferenceControllers().forEach(controllers::addAll);
+        controllers.forEach(controller -> controller.updateState(
+                findPreference(controller.getPreferenceKey())));
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        mSettingsContentObserver.register(getContentResolver());
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+
+        mSettingsContentObserver.unregister(getContentResolver());
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java b/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
index 2078112..51a775e 100644
--- a/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
+++ b/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
@@ -25,6 +25,8 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.widget.LabeledSeekBarPreference;
 
+import java.util.Optional;
+
 /**
  * The controller of {@link LabeledSeekBarPreference} that listens to display size and font size
  * settings changes and updates preview size threshold smoothly.
@@ -33,19 +35,24 @@
         TextReadingResetController.ResetStateListener {
     private final PreviewSizeData<? extends Number> mSizeData;
     private boolean mSeekByTouch;
-    private ProgressInteractionListener mInteractionListener;
+    private Optional<ProgressInteractionListener> mInteractionListener = Optional.empty();
     private LabeledSeekBarPreference mSeekBarPreference;
 
     private final SeekBar.OnSeekBarChangeListener mSeekBarChangeListener =
             new SeekBar.OnSeekBarChangeListener() {
                 @Override
                 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-                    mInteractionListener.notifyPreferenceChanged();
-
-                    if (!mSeekByTouch && mInteractionListener != null) {
-                        mInteractionListener.onProgressChanged();
+                    if (mInteractionListener.isEmpty()) {
+                        return;
                     }
 
+                    final ProgressInteractionListener interactionListener =
+                            mInteractionListener.get();
+                    interactionListener.notifyPreferenceChanged();
+
+                    if (!mSeekByTouch) {
+                        interactionListener.onProgressChanged();
+                    }
                 }
 
                 @Override
@@ -57,9 +64,7 @@
                 public void onStopTrackingTouch(SeekBar seekBar) {
                     mSeekByTouch = false;
 
-                    if (mInteractionListener != null) {
-                        mInteractionListener.onEndTrackingTouch();
-                    }
+                    mInteractionListener.ifPresent(ProgressInteractionListener::onEndTrackingTouch);
                 }
             };
 
@@ -70,7 +75,7 @@
     }
 
     void setInteractionListener(ProgressInteractionListener interactionListener) {
-        mInteractionListener = interactionListener;
+        mInteractionListener = Optional.ofNullable(interactionListener);
     }
 
     @Override
@@ -95,6 +100,10 @@
     public void resetState() {
         final int defaultProgress = mSizeData.getValues().indexOf(mSizeData.getDefaultValue());
         mSeekBarPreference.setProgress(defaultProgress);
+
+        // Immediately take the effect of updating the progress to avoid waiting for receiving
+        // the event to delay update.
+        mInteractionListener.ifPresent(ProgressInteractionListener::onProgressChanged);
     }
 
 
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
index d1614ca..22bef28 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
@@ -18,11 +18,11 @@
 
 import static com.android.settings.accessibility.TextReadingResetController.ResetStateListener;
 
+import android.app.Activity;
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.content.Intent;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.Toast;
@@ -44,7 +44,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -55,8 +54,7 @@
 public class TextReadingPreferenceFragment extends DashboardFragment {
     public static final String EXTRA_LAUNCHED_FROM = "launched_from";
     private static final String TAG = "TextReadingPreferenceFragment";
-    private static final String CATEGORY_FOR_ANYTHING_ELSE =
-            "com.android.settings.suggested.category.DISPLAY_SETTINGS";
+    private static final String SETUP_WIZARD_PACKAGE = "setupwizard";
     static final String FONT_SIZE_KEY = "font_size";
     static final String DISPLAY_SIZE_KEY = "display_size";
     static final String BOLD_TEXT_KEY = "toggle_force_bold_text";
@@ -179,10 +177,8 @@
                 new TextReadingResetController(context, RESET_KEY,
                         v -> showDialog(DialogEnums.DIALOG_RESET_SETTINGS));
         resetController.setEntryPoint(mEntryPoint);
+        resetController.setVisible(!WizardManagerHelper.isAnySetupWizard(getIntent()));
         controllers.add(resetController);
-        if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
-            resetController.setSetupWizardStyle();
-        }
 
         return controllers;
     }
@@ -230,6 +226,13 @@
         }
     }
 
+    protected boolean isCallingFromAnythingElseEntryPoint() {
+        final Activity activity = getActivity();
+        final String callingPackage = activity != null ? activity.getCallingPackage() : null;
+
+        return callingPackage != null && callingPackage.contains(SETUP_WIZARD_PACKAGE);
+    }
+
     @VisibleForTesting
     DisplaySizeData createDisplaySizeData(Context context) {
         return new DisplaySizeData(context);
@@ -242,14 +245,7 @@
             return;
         }
 
-        final Intent intent = getIntent();
-        if (intent == null) {
-            mEntryPoint = EntryPoint.UNKNOWN_ENTRY;
-            return;
-        }
-
-        final Set<String> categories = intent.getCategories();
-        mEntryPoint = categories != null && categories.contains(CATEGORY_FOR_ANYTHING_ELSE)
+        mEntryPoint = isCallingFromAnythingElseEntryPoint()
                 ? EntryPoint.SUW_ANYTHING_ELSE : EntryPoint.UNKNOWN_ENTRY;
     }
 
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
index b025cf5..cdbfe5f 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
@@ -16,6 +16,10 @@
 
 package com.android.settings.accessibility;
 
+import static android.app.Activity.RESULT_CANCELED;
+
+import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums.DIALOG_RESET_SETTINGS;
+
 import android.app.settings.SettingsEnums;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -28,9 +32,10 @@
 import com.android.settings.R;
 import com.android.settingslib.Utils;
 
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
 import com.google.android.setupdesign.GlifPreferenceLayout;
 
-
 /**
  * A {@link androidx.preference.PreferenceFragmentCompat} that displays the settings page related
  * to the text and reading option in the SetupWizard.
@@ -48,6 +53,28 @@
         icon.setTintList(Utils.getColorAttr(getContext(), android.R.attr.colorPrimary));
         AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
                 /* description= */ null, icon);
+
+        final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
+        mixin.setSecondaryButton(
+                new FooterButton.Builder(getContext())
+                        .setText(R.string.accessibility_text_reading_reset_button_title)
+                        .setListener(l -> showDialog(DIALOG_RESET_SETTINGS))
+                        .setButtonType(FooterButton.ButtonType.CLEAR)
+                        .setTheme(R.style.SudGlifButton_Secondary)
+                        .build());
+
+        if (isCallingFromAnythingElseEntryPoint()) {
+            mixin.setPrimaryButton(
+                    new FooterButton.Builder(getContext())
+                            .setText(R.string.done)
+                            .setListener(l -> {
+                                setResult(RESULT_CANCELED);
+                                finish();
+                            })
+                            .setButtonType(FooterButton.ButtonType.DONE)
+                            .setTheme(R.style.SudGlifButton_Primary)
+                            .build());
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/accessibility/TextReadingPreviewPager.java b/src/com/android/settings/accessibility/TextReadingPreviewPager.java
new file mode 100644
index 0000000..5d43159
--- /dev/null
+++ b/src/com/android/settings/accessibility/TextReadingPreviewPager.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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 android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.viewpager.widget.ViewPager;
+
+/**
+ * The view pager is used for displaying screen preview with different size configuration changes.
+ */
+public class TextReadingPreviewPager extends ViewPager {
+    public TextReadingPreviewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        final ViewGroup parent = (ViewGroup) getParent();
+        if (parent != null) {
+            // Avoid conflicting with the nested scroll view.
+            parent.requestDisallowInterceptTouchEvent(true);
+        }
+
+        return super.onInterceptTouchEvent(ev);
+    }
+}
diff --git a/src/com/android/settings/accessibility/TextReadingResetController.java b/src/com/android/settings/accessibility/TextReadingResetController.java
index 206090c..325052c 100644
--- a/src/com/android/settings/accessibility/TextReadingResetController.java
+++ b/src/com/android/settings/accessibility/TextReadingResetController.java
@@ -23,7 +23,6 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.accessibility.TextReadingPreferenceFragment.EntryPoint;
-import com.android.settings.accessibility.TextReadingResetPreference.ButtonStyle;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.instrumentation.SettingsStatsLog;
 
@@ -31,8 +30,7 @@
  * The controller of the reset button in the text and reading options page.
  */
 class TextReadingResetController extends BasePreferenceController {
-    @ButtonStyle
-    private int mButtonStyle;
+    private boolean mIsVisible;
     private final View.OnClickListener mOnResetClickListener;
 
     @EntryPoint
@@ -67,11 +65,11 @@
             }
         });
 
-        resetPreference.setSetupWizardStyle(mButtonStyle);
+        setVisible(screen, getPreferenceKey(), mIsVisible);
     }
 
-    void setSetupWizardStyle() {
-        mButtonStyle = ButtonStyle.SUW;
+    void setVisible(boolean isVisible) {
+        mIsVisible = isVisible;
     }
 
     /**
diff --git a/src/com/android/settings/accessibility/TextReadingResetPreference.java b/src/com/android/settings/accessibility/TextReadingResetPreference.java
index 64f3834..9518de2 100644
--- a/src/com/android/settings/accessibility/TextReadingResetPreference.java
+++ b/src/com/android/settings/accessibility/TextReadingResetPreference.java
@@ -20,15 +20,11 @@
 import android.util.AttributeSet;
 import android.view.View;
 
-import androidx.annotation.IntDef;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
 /**
  * The preference which is used for resetting the status of all preferences in the display size
  * and text page.
@@ -36,20 +32,10 @@
 public class TextReadingResetPreference extends Preference {
     private View.OnClickListener mOnResetClickListener;
 
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            ButtonStyle.DEFAULT,
-            ButtonStyle.SUW,
-    })
-    @interface ButtonStyle {
-        int DEFAULT = 0;
-        int SUW = 1;
-    }
-
     public TextReadingResetPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
 
-        setSetupWizardStyle(ButtonStyle.DEFAULT);
+        setLayoutResource(R.layout.accessibility_text_reading_reset_button);
     }
 
     @Override
@@ -60,13 +46,6 @@
         view.setOnClickListener(mOnResetClickListener);
     }
 
-    void setSetupWizardStyle(@ButtonStyle int style) {
-        final int layoutResId = (style == ButtonStyle.SUW)
-                ? R.layout.accessibility_text_reading_reset_button_suw
-                : R.layout.accessibility_text_reading_reset_button;
-        setLayoutResource(layoutResId);
-    }
-
     void setOnResetClickListener(View.OnClickListener resetClickListener) {
         mOnResetClickListener = resetClickListener;
     }
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 3ab2f92..5b8cd68 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -352,8 +352,8 @@
 
     @Override
     protected BiometricEnrollSidecar getSidecar() {
-        final FingerprintEnrollSidecar sidecar = new FingerprintEnrollSidecar();
-        sidecar.setEnrollReason(FingerprintManager.ENROLL_ENROLL);
+        final FingerprintEnrollSidecar sidecar = new FingerprintEnrollSidecar(this,
+                FingerprintManager.ENROLL_ENROLL);
         return sidecar;
     }
 
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
index 200b8c5..778ee5c 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
@@ -293,8 +293,8 @@
         mSidecar = (FingerprintEnrollSidecar) getSupportFragmentManager().findFragmentByTag(
                 FingerprintEnrollEnrolling.TAG_SIDECAR);
         if (mSidecar == null) {
-            mSidecar = new FingerprintEnrollSidecar();
-            mSidecar.setEnrollReason(FingerprintManager.ENROLL_FIND_SENSOR);
+            mSidecar = new FingerprintEnrollSidecar(this,
+                    FingerprintManager.ENROLL_FIND_SENSOR);
             getSupportFragmentManager().beginTransaction()
                     .add(mSidecar, FingerprintEnrollEnrolling.TAG_SIDECAR)
                     .commitAllowingStateLoss();
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
index d1e512e..b3b9975 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
@@ -16,19 +16,19 @@
 
 package com.android.settings.biometrics.fingerprint;
 
+import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
+
 import android.app.Activity;
 import android.app.settings.SettingsEnums;
+import android.content.Context;
 import android.hardware.fingerprint.FingerprintManager;
+import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.biometrics.BiometricEnrollSidecar;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
 /**
  * Sidecar fragment to handle the state around fingerprint enrollment.
  */
@@ -37,19 +37,41 @@
 
     private FingerprintUpdater mFingerprintUpdater;
     private @FingerprintManager.EnrollReason int mEnrollReason;
-    private Set<Integer> mHelpIgnore;
+    private final MessageDisplayController mMessageDisplayController;
+    private final boolean mMessageDisplayControllerFlag;
+
+    /**
+     * Create a new FingerprintEnrollSidecar object.
+     * @param context associated context
+     * @param enrollReason reason for enrollment
+     */
+    public FingerprintEnrollSidecar(Context context,
+            @FingerprintManager.EnrollReason int enrollReason) {
+        mEnrollReason = enrollReason;
+
+        int helpMinimumDisplayTime = context.getResources().getInteger(
+                R.integer.enrollment_help_minimum_time_display);
+        int progressMinimumDisplayTime = context.getResources().getInteger(
+                R.integer.enrollment_progress_minimum_time_display);
+        boolean progressPriorityOverHelp = context.getResources().getBoolean(
+                R.bool.enrollment_progress_priority_over_help);
+        boolean prioritizeAcquireMessages = context.getResources().getBoolean(
+                R.bool.enrollment_prioritize_acquire_messages);
+        int collectTime = context.getResources().getInteger(
+                R.integer.enrollment_collect_time);
+        mMessageDisplayControllerFlag = context.getResources().getBoolean(
+                R.bool.enrollment_message_display_controller_flag);
+
+        mMessageDisplayController = new MessageDisplayController(context.getMainThreadHandler(),
+                mEnrollmentCallback, SystemClock.elapsedRealtimeClock(), helpMinimumDisplayTime,
+                progressMinimumDisplayTime, progressPriorityOverHelp, prioritizeAcquireMessages,
+                collectTime);
+    }
 
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         mFingerprintUpdater = new FingerprintUpdater(activity);
-        final int[] ignoreAcquiredInfo = getResources().getIntArray(
-                R.array.fingerprint_acquired_ignore_list);
-        mHelpIgnore = new HashSet<>();
-        for (int acquiredInfo: ignoreAcquiredInfo) {
-            mHelpIgnore.add(acquiredInfo);
-        }
-        mHelpIgnore = Collections.unmodifiableSet(mHelpIgnore);
     }
 
     @Override
@@ -62,8 +84,16 @@
                     getString(R.string.fingerprint_intro_error_unknown));
             return;
         }
-        mFingerprintUpdater.enroll(mToken, mEnrollmentCancel, mUserId, mEnrollmentCallback,
-                mEnrollReason);
+
+        if (mEnrollReason == ENROLL_ENROLL && mMessageDisplayControllerFlag) {
+            //API calls need to be processed for {@link FingerprintEnrollEnrolling}
+            mFingerprintUpdater.enroll(mToken, mEnrollmentCancel, mUserId,
+                    mMessageDisplayController, mEnrollReason);
+        } else {
+            //No processing required for {@link FingerprintEnrollFindSensor}
+            mFingerprintUpdater.enroll(mToken, mEnrollmentCancel, mUserId, mEnrollmentCallback,
+                    mEnrollReason);
+        }
     }
 
     public void setEnrollReason(@FingerprintManager.EnrollReason int enrollReason) {
@@ -80,9 +110,6 @@
 
         @Override
         public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
-            if (mHelpIgnore.contains(helpMsgId)) {
-                return;
-            }
             FingerprintEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);
         }
 
diff --git a/src/com/android/settings/biometrics/fingerprint/MessageDisplayController.java b/src/com/android/settings/biometrics/fingerprint/MessageDisplayController.java
new file mode 100644
index 0000000..11f3ee3
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/MessageDisplayController.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Handler;
+
+import java.time.Clock;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+
+/**
+ * Processes message provided from the enrollment callback and filters them based
+ * on the below configurable flags. This is primarily used to reduce the rate
+ * at which messages come through, which in turns eliminates UI flicker.
+ */
+public class MessageDisplayController extends FingerprintManager.EnrollmentCallback {
+
+    private final int mHelpMinimumDisplayTime;
+    private final int mProgressMinimumDisplayTime;
+    private final boolean mProgressPriorityOverHelp;
+    private final boolean mPrioritizeAcquireMessages;
+    private final int mCollectTime;
+    @NonNull
+    private final Deque<HelpMessage> mHelpMessageList;
+    @NonNull
+    private final Deque<ProgressMessage> mProgressMessageList;
+    @NonNull
+    private final Handler mHandler;
+    @NonNull
+    private final Clock mClock;
+    @NonNull
+    private final Runnable mDisplayMessageRunnable;
+
+    @Nullable
+    private ProgressMessage mLastProgressMessageDisplayed;
+    private boolean mMustDisplayProgress;
+    private boolean mWaitingForMessage;
+    @NonNull FingerprintManager.EnrollmentCallback mEnrollmentCallback;
+
+    private abstract static class Message {
+        long mTimeStamp = 0;
+        abstract void display();
+    }
+
+    private class HelpMessage extends Message {
+        private final int mHelpMsgId;
+        private final CharSequence mHelpString;
+
+        HelpMessage(int helpMsgId, CharSequence helpString) {
+            mHelpMsgId = helpMsgId;
+            mHelpString = helpString;
+            mTimeStamp = mClock.millis();
+        }
+
+        @Override
+        void display() {
+            mEnrollmentCallback.onEnrollmentHelp(mHelpMsgId, mHelpString);
+            mHandler.postDelayed(mDisplayMessageRunnable, mHelpMinimumDisplayTime);
+        }
+    }
+
+    private class ProgressMessage extends Message {
+        private final int mRemaining;
+
+        ProgressMessage(int remaining) {
+            mRemaining = remaining;
+            mTimeStamp = mClock.millis();
+        }
+
+        @Override
+        void display() {
+            mEnrollmentCallback.onEnrollmentProgress(mRemaining);
+            mLastProgressMessageDisplayed = this;
+            mHandler.postDelayed(mDisplayMessageRunnable, mProgressMinimumDisplayTime);
+        }
+    }
+
+    /**
+     * Creating a MessageDisplayController object.
+     * @param handler main handler to run message queue
+     * @param enrollmentCallback callback to display messages
+     * @param clock real time system clock
+     * @param helpMinimumDisplayTime the minimum duration (in millis) that
+*        a help message needs to be displayed for
+     * @param progressMinimumDisplayTime the minimum duration (in millis) that
+*        a progress message needs to be displayed for
+     * @param progressPriorityOverHelp if true, then progress message is displayed
+*        when both help and progress message APIs have been called
+     * @param prioritizeAcquireMessages if true, then displays the help message
+*        which has occurred the most after the last display message
+     * @param collectTime the waiting time (in millis) to collect messages when it is idle
+     */
+    public MessageDisplayController(@NonNull Handler handler,
+            FingerprintManager.EnrollmentCallback enrollmentCallback,
+            @NonNull Clock clock, int helpMinimumDisplayTime, int progressMinimumDisplayTime,
+            boolean progressPriorityOverHelp, boolean prioritizeAcquireMessages,
+            int collectTime) {
+        mClock = clock;
+        mWaitingForMessage = false;
+        mHelpMessageList = new ArrayDeque<>();
+        mProgressMessageList = new ArrayDeque<>();
+        mHandler = handler;
+        mEnrollmentCallback = enrollmentCallback;
+
+        mHelpMinimumDisplayTime = helpMinimumDisplayTime;
+        mProgressMinimumDisplayTime = progressMinimumDisplayTime;
+        mProgressPriorityOverHelp = progressPriorityOverHelp;
+        mPrioritizeAcquireMessages = prioritizeAcquireMessages;
+        mCollectTime = collectTime;
+
+        mDisplayMessageRunnable = () -> {
+            long timeStamp = mClock.millis();
+            Message messageToDisplay = getMessageToDisplay(timeStamp);
+
+            if (messageToDisplay != null) {
+                messageToDisplay.display();
+            } else {
+                mWaitingForMessage = true;
+            }
+        };
+
+        mHandler.postDelayed(mDisplayMessageRunnable, 0);
+    }
+
+    /**
+     * Adds help message to the queue to be processed later.
+     *
+     * @param helpMsgId message Id associated with the help message
+     * @param helpString string associated with the help message
+     */
+    @Override
+    public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
+        mHelpMessageList.add(new HelpMessage(helpMsgId, helpString));
+
+        if (mWaitingForMessage) {
+            mWaitingForMessage = false;
+            mHandler.postDelayed(mDisplayMessageRunnable, mCollectTime);
+        }
+    }
+
+    /**
+     * Adds progress change message to the queue to be processed later.
+     *
+     * @param remaining remaining number of steps to complete enrollment
+     */
+    @Override
+    public void onEnrollmentProgress(int remaining) {
+        mProgressMessageList.add(new ProgressMessage(remaining));
+
+        if (mWaitingForMessage) {
+            mWaitingForMessage = false;
+            mHandler.postDelayed(mDisplayMessageRunnable, mCollectTime);
+        }
+    }
+
+    @Override
+    public void onEnrollmentError(int errMsgId, CharSequence errString) {
+        mEnrollmentCallback.onEnrollmentError(errMsgId, errString);
+    }
+
+    private Message getMessageToDisplay(long timeStamp) {
+        ProgressMessage progressMessageToDisplay = getProgressMessageToDisplay(timeStamp);
+        if (mMustDisplayProgress) {
+            mMustDisplayProgress = false;
+            if (progressMessageToDisplay != null) {
+                return progressMessageToDisplay;
+            }
+            if (mLastProgressMessageDisplayed != null) {
+                return mLastProgressMessageDisplayed;
+            }
+        }
+
+        Message helpMessageToDisplay = getHelpMessageToDisplay(timeStamp);
+        if (helpMessageToDisplay != null || progressMessageToDisplay != null) {
+            if (mProgressPriorityOverHelp && progressMessageToDisplay != null) {
+                return progressMessageToDisplay;
+            } else if (helpMessageToDisplay != null) {
+                if (progressMessageToDisplay != null) {
+                    mMustDisplayProgress = true;
+                    mLastProgressMessageDisplayed = progressMessageToDisplay;
+                }
+                return helpMessageToDisplay;
+            } else {
+                return progressMessageToDisplay;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private ProgressMessage getProgressMessageToDisplay(long timeStamp) {
+        ProgressMessage finalProgressMessage = null;
+        while (mProgressMessageList != null && !mProgressMessageList.isEmpty()) {
+            Message message = mProgressMessageList.peekFirst();
+            if (message.mTimeStamp <= timeStamp) {
+                ProgressMessage progressMessage = mProgressMessageList.pollFirst();
+                if (mLastProgressMessageDisplayed != null
+                        && mLastProgressMessageDisplayed.mRemaining == progressMessage.mRemaining) {
+                    continue;
+                }
+                finalProgressMessage = progressMessage;
+            } else {
+                break;
+            }
+        }
+
+        return finalProgressMessage;
+    }
+
+    private HelpMessage getHelpMessageToDisplay(long timeStamp) {
+        HashMap<CharSequence, Integer> messageCount = new HashMap<>();
+        HelpMessage finalHelpMessage = null;
+
+        while (mHelpMessageList != null && !mHelpMessageList.isEmpty()) {
+            Message message = mHelpMessageList.peekFirst();
+            if (message.mTimeStamp <= timeStamp) {
+                finalHelpMessage = mHelpMessageList.pollFirst();
+                CharSequence errString = finalHelpMessage.mHelpString;
+                messageCount.put(errString, messageCount.getOrDefault(errString, 0) + 1);
+            } else {
+                break;
+            }
+        }
+        if (mPrioritizeAcquireMessages) {
+            finalHelpMessage = prioritizeHelpMessageByCount(messageCount);
+        }
+
+        return finalHelpMessage;
+    }
+
+    private HelpMessage prioritizeHelpMessageByCount(HashMap<CharSequence, Integer> messageCount) {
+        int maxCount = 0;
+        CharSequence maxCountMessage = null;
+
+        for (CharSequence key :
+                messageCount.keySet()) {
+            if (maxCount < messageCount.get(key)) {
+                maxCountMessage = key;
+                maxCount = messageCount.get(key);
+            }
+        }
+
+        return maxCountMessage != null ? new HelpMessage(0 /* errMsgId */,
+                maxCountMessage) : null;
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 406ac69..f68cc40 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -47,6 +47,7 @@
 import com.android.settings.connecteddevice.stylus.StylusDevicesController;
 import com.android.settings.core.SettingsUIDeviceConfig;
 import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.inputmethod.KeyboardSettingsPreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.slices.BlockingSlicePrefController;
 import com.android.settings.slices.SlicePreferenceController;
@@ -171,6 +172,7 @@
         }
         use(AdvancedBluetoothDetailsHeaderController.class).init(mCachedDevice);
         use(LeAudioBluetoothDetailsHeaderController.class).init(mCachedDevice, mManager);
+        use(KeyboardSettingsPreferenceController.class).init(mCachedDevice, getActivity());
 
         final BluetoothFeatureProvider featureProvider = FeatureFactory.getFactory(
                 context).getBluetoothFeatureProvider();
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 7904fdb..da81f6e 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -120,6 +120,7 @@
 import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
 import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
 import com.android.settings.inputmethod.KeyboardSettings;
+import com.android.settings.inputmethod.NewKeyboardLayoutEnabledLocalesFragment;
 import com.android.settings.inputmethod.PhysicalKeyboardFragment;
 import com.android.settings.inputmethod.SpellCheckersSettings;
 import com.android.settings.inputmethod.UserDictionaryList;
@@ -214,6 +215,7 @@
             LanguageAndInputSettings.class.getName(),
             LanguageSettings.class.getName(),
             KeyboardSettings.class.getName(),
+            NewKeyboardLayoutEnabledLocalesFragment.class.getName(),
             SpellCheckersSettings.class.getName(),
             UserDictionaryList.class.getName(),
             UserDictionarySettings.class.getName(),
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
index c093472..855cd12 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -22,6 +22,7 @@
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
@@ -72,7 +73,8 @@
 /**
  * Controller for Sim Status information within the About Phone Settings page.
  */
-public class SimStatusDialogController implements LifecycleObserver {
+public class SimStatusDialogController implements LifecycleObserver,
+        DialogInterface.OnShowListener {
 
     private final static String TAG = "SimStatusDialogCtrl";
 
@@ -107,6 +109,8 @@
     @VisibleForTesting
     final static int EID_INFO_VALUE_ID = R.id.esim_id_value;
     @VisibleForTesting
+    final static int EID_INFO_QRCODE_ID = R.id.esim_id_qrcode;
+    @VisibleForTesting
     final static int IMS_REGISTRATION_STATE_LABEL_ID = R.id.ims_reg_state_label;
     @VisibleForTesting
     final static int IMS_REGISTRATION_STATE_VALUE_ID = R.id.ims_reg_state_value;
@@ -158,6 +162,7 @@
 
     private boolean mShowLatestAreaInfo;
     private boolean mIsRegisteredListener = false;
+    private AtomicReference<String> mEid = null;
 
     private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
         @Override
@@ -264,6 +269,19 @@
     }
 
     /**
+     * Callback when dialog end of show().
+     */
+    public void onShow(DialogInterface dialog) {
+        if (mEid != null) {
+            String eidText = mEid.get();
+            if (eidText != null) {
+                // Present QR code after the completion of layout
+                mDialog.setQrCode(EID_INFO_QRCODE_ID, eidText);
+            }
+        }
+    }
+
+    /**
      * Deinitialization works
      */
     public void deinitialize() {
@@ -618,8 +636,8 @@
     @VisibleForTesting
     protected void requestForUpdateEid() {
         ThreadUtils.postOnBackgroundThread(() -> {
-            final AtomicReference<String> eid = getEid(mSlotIndex);
-            ThreadUtils.postOnMainThread(() -> updateEid(eid));
+            mEid = getEid(mSlotIndex);
+            ThreadUtils.postOnMainThread(() -> updateEid(mEid));
         });
     }
 
@@ -663,11 +681,20 @@
 
     @VisibleForTesting
     protected void updateEid(AtomicReference<String> eid) {
+        boolean removeQrCode = true;
         if (eid == null) {
             mDialog.removeSettingFromScreen(EID_INFO_LABEL_ID);
             mDialog.removeSettingFromScreen(EID_INFO_VALUE_ID);
-        } else if (eid.get() != null) {
-            mDialog.setText(EID_INFO_VALUE_ID, eid.get());
+            mDialog.removeSettingFromScreen(EID_INFO_QRCODE_ID);
+        } else {
+            String eidText = eid.get();
+            if (eidText != null) {
+                mDialog.setText(EID_INFO_VALUE_ID, eidText);
+                removeQrCode = (eidText == "");
+            }
+        }
+        if (removeQrCode) {
+            mDialog.removeSettingFromScreen(EID_INFO_QRCODE_ID);
         }
     }
 
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
index 96acd43..3bd9b34 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
@@ -19,11 +19,14 @@
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.os.Bundle;
+import android.graphics.Bitmap;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
+import android.widget.ImageView;
 import android.widget.TextView;
+import android.util.Log;
 
 import androidx.appcompat.app.AlertDialog;
 import androidx.fragment.app.Fragment;
@@ -32,6 +35,7 @@
 import com.android.settings.R;
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settings.deviceinfo.PhoneNumberUtil;
+import com.android.settingslib.qrcode.QrCodeGenerator;
 
 import java.util.Arrays;
 import java.util.stream.IntStream;
@@ -80,6 +84,7 @@
         Dialog dlg = builder.setView(mRootView).create();
         dlg.getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                 WindowManager.LayoutParams.FLAG_SECURE);
+        dlg.setOnShowListener(mController);
 
         return dlg;
     }
@@ -107,6 +112,10 @@
             .sorted().toArray();
 
     public void setText(int viewId, CharSequence text) {
+        setText(viewId, text, true);
+    }
+
+    public void setText(int viewId, CharSequence text, boolean enableCopy) {
         final TextView textView = mRootView.findViewById(viewId);
         if (textView == null) {
             return;
@@ -117,5 +126,21 @@
             text = PhoneNumberUtil.expandByTts(text);
         }
         textView.setText(text);
+        textView.setTextIsSelectable(enableCopy);
+    }
+
+    public void setQrCode(int viewId, String qrcodeText) {
+        ImageView qrCodeView = (ImageView) mRootView.findViewById(viewId);
+
+        Bitmap qrCodeBitmap = null;
+        try {
+            qrCodeBitmap = QrCodeGenerator.encodeQrCode(qrcodeText, qrCodeView.getWidth());
+        } catch (Exception exception) {
+            Log.w(TAG, "Error when presenting QR code in + " + qrCodeView, exception);
+        }
+        if (qrCodeBitmap == null) {
+            return;
+        }
+        qrCodeView.setImageBitmap(qrCodeBitmap);
     }
 }
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
index b75853d..16f04df 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
@@ -31,6 +31,7 @@
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settingslib.Utils;
+import com.android.settingslib.search.SearchIndexableRaw;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -159,4 +160,28 @@
     Preference createNewPreference(Context context) {
         return new Preference(context);
     }
+
+    @Override
+    public void updateDynamicRawDataToIndex(List<SearchIndexableRaw> rawData) {
+        int simSlot = getSimSlotIndex();
+        SubscriptionInfo subInfo = getSubscriptionInfo(simSlot);
+        if (subInfo == null) {
+            /**
+             * Only add to search when SIM is active
+             * (presented in SIM Slot Status as availavle.)
+             */
+            return;
+        }
+
+        /* Have different search keywork when comes to eSIM */
+        int keywordId = subInfo.isEmbedded() ?
+                R.string.keywords_sim_status_esim : R.string.keywords_sim_status;
+
+        SearchIndexableRaw data = new SearchIndexableRaw(mContext);
+        data.key = getPreferenceKey();
+        data.title = getPreferenceTitle(simSlot);
+        data.screenTitle = mContext.getString(R.string.about_settings);
+        data.keywords = mContext.getString(keywordId).toString();
+        rawData.add(data);
+    }
 }
diff --git a/src/com/android/settings/dream/DreamSettings.java b/src/com/android/settings/dream/DreamSettings.java
index 80b321d..acc6973 100644
--- a/src/com/android/settings/dream/DreamSettings.java
+++ b/src/com/android/settings/dream/DreamSettings.java
@@ -138,10 +138,11 @@
 
     @VisibleForTesting
     static CharSequence getSummaryTextFromBackend(DreamBackend backend, Context context) {
-        if (!backend.isEnabled()) {
-            return context.getString(R.string.off);
+        if (backend.isEnabled()) {
+            return context.getString(R.string.screensaver_settings_summary_on,
+                    backend.getActiveDreamName());
         } else {
-            return backend.getActiveDreamName();
+            return context.getString(R.string.screensaver_settings_summary_off);
         }
     }
 
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index b17afa5..71d56ae 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -30,6 +30,11 @@
 public interface PowerUsageFeatureProvider {
 
     /**
+     * Check whether the battery usage button is enabled in the battery page
+     */
+    boolean isBatteryUsageEnabled(Context context);
+
+    /**
      * Check whether location setting is enabled
      */
     boolean isLocationSettingEnabled(String[] packages);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 856f86a..932b35d 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -66,6 +66,11 @@
     }
 
     @Override
+    public boolean isBatteryUsageEnabled(Context context) {
+        return true;
+    }
+
+    @Override
     public boolean isLocationSettingEnabled(String[] packages) {
         return false;
     }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index 0f02d1c..9d2774e 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -18,7 +18,6 @@
 
 import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.utcToLocalTime;
 
-import android.app.settings.SettingsEnums;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
@@ -48,7 +47,6 @@
 import com.android.settings.Utils;
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.fuelgauge.BatteryStatus;
 
 import java.time.Duration;
@@ -84,8 +82,6 @@
             new BatteryHistEntry(new ContentValues());
 
     @VisibleForTesting
-    static final double PERCENTAGE_OF_TOTAL_THRESHOLD = 1f;
-    @VisibleForTesting
     static final int SELECTED_INDEX_ALL = BatteryChartViewModel.SELECTED_INDEX_ALL;
     @VisibleForTesting
     static final String CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER =
@@ -439,16 +435,10 @@
         insertDailyUsageDiffData(hourlyBatteryLevelsPerDay, resultMap);
         // Insert diff data [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL].
         insertAllUsageDiffData(resultMap);
-        // Compute the apps number before purge. Must put before purgeLowPercentageAndFakeData.
-        final int countOfAppBeforePurge = getCountOfApps(resultMap);
-        purgeLowPercentageAndFakeData(context, resultMap);
-        // Compute the apps number after purge. Must put after purgeLowPercentageAndFakeData.
-        final int countOfAppAfterPurge = getCountOfApps(resultMap);
+        purgeFakeAndHiddenPackages(context, resultMap);
         if (!isUsageMapValid(resultMap, hourlyBatteryLevelsPerDay)) {
             return null;
         }
-
-        logAppCountMetrics(context, countOfAppBeforePurge, countOfAppAfterPurge);
         return resultMap;
     }
 
@@ -533,14 +523,7 @@
         allUsageMap.put(SELECTED_INDEX_ALL,
                 generateBatteryDiffData(context, getBatteryHistListFromFromStatsService(context)));
         resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
-
-        // Compute the apps number before purge. Must put before purgeLowPercentageAndFakeData.
-        final int countOfAppBeforePurge = getCountOfApps(resultMap);
-        purgeLowPercentageAndFakeData(context, resultMap);
-        // Compute the apps number after purge. Must put after purgeLowPercentageAndFakeData.
-        final int countOfAppAfterPurge = getCountOfApps(resultMap);
-
-        logAppCountMetrics(context, countOfAppBeforePurge, countOfAppAfterPurge);
+        purgeFakeAndHiddenPackages(context, resultMap);
         return resultMap;
     }
 
@@ -1122,7 +1105,7 @@
     }
 
     // Removes low percentage data and fake usage data, which will be zero value.
-    private static void purgeLowPercentageAndFakeData(
+    private static void purgeFakeAndHiddenPackages(
             final Context context,
             final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
         final Set<CharSequence> backgroundUsageTimeHideList =
@@ -1139,17 +1122,17 @@
                 if (diffEntryLists == null) {
                     return;
                 }
-                purgeLowPercentageAndFakeData(
+                purgeFakeAndHiddenPackages(
                         diffEntryLists.getAppDiffEntryList(), backgroundUsageTimeHideList,
                         notAllowShowEntryPackages);
-                purgeLowPercentageAndFakeData(
+                purgeFakeAndHiddenPackages(
                         diffEntryLists.getSystemDiffEntryList(), backgroundUsageTimeHideList,
                         notAllowShowEntryPackages);
             });
         });
     }
 
-    private static void purgeLowPercentageAndFakeData(
+    private static void purgeFakeAndHiddenPackages(
             final List<BatteryDiffEntry> entries,
             final Set<CharSequence> backgroundUsageTimeHideList,
             final CharSequence[] notAllowShowEntryPackages) {
@@ -1157,8 +1140,7 @@
         while (iterator.hasNext()) {
             final BatteryDiffEntry entry = iterator.next();
             final String packageName = entry.getPackageName();
-            if (entry.getPercentOfTotal() < PERCENTAGE_OF_TOTAL_THRESHOLD
-                    || ConvertUtils.FAKE_PACKAGE_NAME.equals(packageName)
+            if (ConvertUtils.FAKE_PACKAGE_NAME.equals(packageName)
                     || contains(packageName, notAllowShowEntryPackages)) {
                 iterator.remove();
             }
@@ -1353,15 +1335,6 @@
         return calendar.getTimeInMillis();
     }
 
-    private static int getCountOfApps(final Map<Integer, Map<Integer, BatteryDiffData>> resultMap) {
-        final BatteryDiffData diffDataList =
-                resultMap.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL);
-        return diffDataList == null
-                ? 0
-                : diffDataList.getAppDiffEntryList().size()
-                        + diffDataList.getSystemDiffEntryList().size();
-    }
-
     private static boolean contains(String target, Set<CharSequence> packageNames) {
         if (target != null && packageNames != null) {
             for (CharSequence packageName : packageNames) {
@@ -1417,21 +1390,6 @@
         return sFakeCurrentTimeMillis > 0 ? sFakeCurrentTimeMillis : System.currentTimeMillis();
     }
 
-    private static void logAppCountMetrics(
-            Context context, final int countOfAppBeforePurge, final int countOfAppAfterPurge) {
-        context = context.getApplicationContext();
-        final MetricsFeatureProvider metricsFeatureProvider =
-                FeatureFactory.getFactory(context).getMetricsFeatureProvider();
-        metricsFeatureProvider.action(
-                context,
-                SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
-                countOfAppAfterPurge);
-        metricsFeatureProvider.action(
-                context,
-                SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
-                countOfAppBeforePurge - countOfAppAfterPurge);
-    }
-
     /**
      * @return Returns whether the target is in the CharSequence array.
      */
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreference.java
index 5a4f672..4ab1f42 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreference.java
@@ -36,6 +36,8 @@
  */
 public class PowerGaugePreference extends AppPreference {
 
+    private static final double PERCENTAGE_TO_SHOW_THRESHOLD = 1f;
+
     private BatteryEntry mInfo;
     private BatteryDiffEntry mBatteryDiffEntry;
     private CharSequence mContentDescription;
@@ -75,7 +77,8 @@
 
     /** Sets the percent of total. */
     public void setPercent(double percentOfTotal) {
-        mProgress = Utils.formatPercentage(percentOfTotal, true);
+        mProgress = percentOfTotal < PERCENTAGE_TO_SHOW_THRESHOLD
+                ? "-" : Utils.formatPercentage(percentOfTotal, true);
         notifyChanged();
     }
 
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
index f266492..dea2431 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageSummary.java
@@ -255,6 +255,8 @@
     void initPreference() {
         mBatteryUsagePreference = findPreference(KEY_BATTERY_USAGE);
         mBatteryUsagePreference.setSummary(getString(R.string.advanced_battery_preference_summary));
+        mBatteryUsagePreference.setVisible(
+                mPowerFeatureProvider.isBatteryUsageEnabled(getContext()));
 
         mHelpPreference = findPreference(KEY_BATTERY_ERROR);
         mHelpPreference.setVisible(false);
diff --git a/src/com/android/settings/homepage/TopLevelHighlightMixin.java b/src/com/android/settings/homepage/TopLevelHighlightMixin.java
index f361ed6..d9e646f 100644
--- a/src/com/android/settings/homepage/TopLevelHighlightMixin.java
+++ b/src/com/android/settings/homepage/TopLevelHighlightMixin.java
@@ -116,9 +116,14 @@
         }
 
         Log.d(TAG, "onCreateAdapter, pref key: " + mCurrentKey);
+
+        // Remove the animator to avoid a RecyclerView crash.
+        RecyclerView recyclerView = topLevelSettings.getListView();
+        recyclerView.setItemAnimator(null);
+
         mTopLevelAdapter = new HighlightableTopLevelPreferenceAdapter(
                 (SettingsHomepageActivity) topLevelSettings.getActivity(), preferenceScreen,
-                topLevelSettings.getListView(), mCurrentKey, scrollNeeded);
+                recyclerView, mCurrentKey, scrollNeeded);
         return mTopLevelAdapter;
     }
 
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
index 4ac52bc..c6a0d75 100644
--- a/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
@@ -154,6 +154,7 @@
             final SwitchPreference pref = new SwitchPreference(mScreen.getContext());
             pref.setTitle(layout.getLabel());
             pref.setSummary(layout.getCollection());
+            // TODO: Waiting for new API to use a prefix with special number to setKey
             pref.setKey(layout.getDescriptor());
             mScreen.addPreference(pref);
             mPreferenceMap.put(pref, layout);
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPreference.java b/src/com/android/settings/inputmethod/KeyboardLayoutPreference.java
new file mode 100644
index 0000000..f9f858b
--- /dev/null
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutPreference.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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.inputmethod;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.ImageView;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+
+public class KeyboardLayoutPreference extends Preference {
+
+    private ImageView mCheckIcon;
+    private boolean mIsMark;
+
+    public KeyboardLayoutPreference(Context context, String layoutName, boolean defaultMark) {
+        super(context);
+        setWidgetLayoutResource(R.layout.preference_check_icon);
+        setTitle(layoutName);
+        mIsMark = defaultMark;
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        mCheckIcon = (ImageView) holder.findViewById(R.id.keyboard_check_icon);
+        setCheckMark(mIsMark);
+    }
+
+    public void setCheckMark(boolean isMark) {
+        if (mCheckIcon != null) {
+            mCheckIcon.setVisibility(isMark ? View.VISIBLE : View.INVISIBLE);
+            mIsMark = isMark;
+        }
+    }
+}
diff --git a/src/com/android/settings/inputmethod/KeyboardPreferenceController.java b/src/com/android/settings/inputmethod/KeyboardPreferenceController.java
index 75351b1..adabec5 100644
--- a/src/com/android/settings/inputmethod/KeyboardPreferenceController.java
+++ b/src/com/android/settings/inputmethod/KeyboardPreferenceController.java
@@ -78,9 +78,9 @@
 
     @Override
     public int getAvailabilityStatus() {
-        boolean isFeatureOn = FeatureFlagUtils
-                .isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
-        return isFeatureOn ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)
+                ? AVAILABLE
+                : CONDITIONALLY_UNAVAILABLE;
     }
 
     private void updateSummary() {
diff --git a/src/com/android/settings/inputmethod/KeyboardSettingsPreferenceController.java b/src/com/android/settings/inputmethod/KeyboardSettingsPreferenceController.java
new file mode 100644
index 0000000..3b86c3f
--- /dev/null
+++ b/src/com/android/settings/inputmethod/KeyboardSettingsPreferenceController.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2022 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.inputmethod;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.util.FeatureFlagUtils;
+
+import androidx.annotation.NonNull;
+import androidx.preference.Preference;
+
+import com.android.settings.Settings.PhysicalKeyboardActivity;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.inputmethod.PhysicalKeyboardFragment.HardKeyboardDeviceInfo;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+import java.util.List;
+
+public class KeyboardSettingsPreferenceController extends BasePreferenceController {
+
+    private Context mContext;
+    private CachedBluetoothDevice mCachedDevice;
+    private Activity mActivity;
+
+    public KeyboardSettingsPreferenceController(Context context, String key) {
+        super(context, key);
+        mContext = context;
+    }
+
+    public void init(@NonNull CachedBluetoothDevice cachedDevice, @NonNull Activity activity) {
+        mCachedDevice = cachedDevice;
+        mActivity = activity;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        final Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
+        intent.setClass(mContext, PhysicalKeyboardActivity.class);
+        intent.putExtra(PhysicalKeyboardFragment.EXTRA_BT_ADDRESS, mCachedDevice.getAddress());
+        mActivity.startActivityForResult(intent, 0);
+        return true;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        final List<HardKeyboardDeviceInfo> newHardKeyboards =
+                PhysicalKeyboardFragment.getHardKeyboards(mContext);
+        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)
+                && !newHardKeyboards.isEmpty()) {
+            for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
+                if (mCachedDevice.getAddress() != null
+                        && hardKeyboardDeviceInfo.mBluetoothAddress != null
+                        && mCachedDevice.getAddress().equals(
+                                hardKeyboardDeviceInfo.mBluetoothAddress)) {
+                    return AVAILABLE;
+                }
+            }
+        }
+        return CONDITIONALLY_UNAVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
new file mode 100644
index 0000000..5c0f88f
--- /dev/null
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2022 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.inputmethod;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.hardware.input.InputDeviceIdentifier;
+import android.hardware.input.InputManager;
+import android.os.Bundle;
+import android.view.InputDevice;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.DashboardFragment;
+
+public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
+        implements InputManager.InputDeviceListener {
+
+    private static final String TAG = "NewKeyboardLayoutEnabledLocalesFragment";
+    private static final String PREF_KEY_ENABLED_LOCALES = "enabled_locales_keyboard_layout";
+
+    static final String EXTRA_KEYBOARD_DEVICE_NAME = "extra_keyboard_device_name";
+
+    private InputManager mIm;
+    private InputDeviceIdentifier mInputDeviceIdentifier;
+    private int mInputDeviceId;
+    private Context mContext;
+
+    @Override
+    public void onActivityCreated(final Bundle icicle) {
+        super.onActivityCreated(icicle);
+
+        Bundle arguments = getArguments();
+        final String title = arguments.getString(EXTRA_KEYBOARD_DEVICE_NAME);
+        mInputDeviceIdentifier = arguments.getParcelable(
+                KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER);
+        getActivity().setTitle(title);
+        final PreferenceCategory category = findPreference(PREF_KEY_ENABLED_LOCALES);
+
+        // TODO(b/252816846): Need APIs to get the available keyboards from Inputmanager.
+        // For example: InputMethodManager.getEnabledInputMethodLocales()
+        //              InputManager.getKeyboardLayoutForLocale()
+        // Hardcode the default value for demo purpose
+        String[] keyboardLanguages = {"English (US)", "German (Germany)", "Spanish (Spain)"};
+        String[] keyboardLayouts = {"English (US)", "German", "Spanish"};
+        for (int i = 0; i < keyboardLanguages.length; i++) {
+            final Preference pref = new Preference(mContext);
+            String key = "keyboard_language_label_" + String.valueOf(i);
+            String keyboardLanguageTitle = keyboardLanguages[i];
+            String keyboardLanguageSummary = keyboardLayouts[i];
+            // TODO: Waiting for new API to use a prefix with special number to setKey
+            pref.setKey(key);
+            pref.setTitle(keyboardLanguageTitle);
+            pref.setSummary(keyboardLanguageSummary);
+            pref.setOnPreferenceClickListener(
+                    preference -> {
+                        showKeyboardLayoutPicker(
+                                keyboardLanguageTitle,
+                                keyboardLanguageSummary,
+                                mInputDeviceIdentifier);
+                        return true;
+                    });
+            category.addPreference(pref);
+        }
+    }
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+        // Do nothing.
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+            getActivity().finish();
+        }
+    }
+
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+            // TODO(b/252816846): Need APIs to update the available keyboards.
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mContext = getContext();
+        mIm = mContext.getSystemService(InputManager.class);
+        mInputDeviceId = -1;
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        mIm.registerInputDeviceListener(this, null);
+        final InputDevice inputDevice =
+                mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
+        if (inputDevice == null) {
+            getActivity().finish();
+            return;
+        }
+        mInputDeviceId = inputDevice.getId();
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        mIm.unregisterInputDeviceListener(this);
+        mInputDeviceId = -1;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        // TODO(b/252816846): Need APIs to get the available keyboards from Inputmanager.
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.SETTINGS_KEYBOARDS_ENABLED_LOCALES;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.keyboard_settings_enabled_locales_list;
+    }
+
+    private void showKeyboardLayoutPicker(String language, String layout,
+            InputDeviceIdentifier inputDeviceIdentifier) {
+        Bundle arguments = new Bundle();
+        arguments.putParcelable(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
+                inputDeviceIdentifier);
+        arguments.putString(NewKeyboardLayoutPickerFragment.EXTRA_TITLE, language);
+        arguments.putString(NewKeyboardLayoutPickerFragment.EXTRA_KEYBOARD_LAYOUT, layout);
+        new SubSettingLauncher(mContext)
+                .setSourceMetricsCategory(getMetricsCategory())
+                .setDestination(NewKeyboardLayoutPickerFragment.class.getName())
+                .setArguments(arguments)
+                .launch();
+    }
+}
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java
new file mode 100644
index 0000000..dc94306
--- /dev/null
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerContent.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 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.inputmethod;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.hardware.input.InputDeviceIdentifier;
+import android.os.Bundle;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+
+public class NewKeyboardLayoutPickerContent extends DashboardFragment {
+
+    private static final String TAG = "KeyboardLayoutPicker";
+
+    static final String EXTRA_TITLE = "keyboard_layout_picker_title";
+    static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
+
+    /**
+     * Intent extra: The input device descriptor of the keyboard whose keyboard
+     * layout is to be changed.
+     */
+    public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+
+        Bundle arguments = getArguments();
+        final String title = arguments.getString(EXTRA_TITLE);
+        final String layout = arguments.getString(EXTRA_KEYBOARD_LAYOUT);
+        final InputDeviceIdentifier inputDeviceIdentifier =
+                arguments.getParcelable(EXTRA_INPUT_DEVICE_IDENTIFIER);
+
+        if (inputDeviceIdentifier == null) {
+            getActivity().finish();
+        }
+        getActivity().setTitle(title);
+        use(NewKeyboardLayoutPickerController.class).initialize(this /*parent*/,
+                inputDeviceIdentifier, layout);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        // TODO: add new SettingsEnums SETTINGS_KEYBOARDS_LAYOUT_PICKER_CONTENT
+        return SettingsEnums.SETTINGS_KEYBOARDS_LAYOUT_PICKER;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    protected int getPreferenceScreenResId() {
+        return R.xml.new_keyboard_layout_picker_fragment;
+    }
+}
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java
new file mode 100644
index 0000000..4a598d5
--- /dev/null
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerController.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2022 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.inputmethod;
+
+import android.content.Context;
+import android.hardware.input.InputDeviceIdentifier;
+import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardLayout;
+import android.view.InputDevice;
+
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class NewKeyboardLayoutPickerController extends BasePreferenceController implements
+        InputManager.InputDeviceListener, LifecycleObserver, OnStart, OnStop {
+    private final InputManager mIm;
+    private final Map<KeyboardLayoutPreference, KeyboardLayout> mPreferenceMap;
+
+    private Fragment mParent;
+    private int mInputDeviceId;
+    private InputDeviceIdentifier mInputDeviceIdentifier;
+    private KeyboardLayout[] mKeyboardLayouts;
+    private PreferenceScreen mScreen;
+    private String mPreviousSelection;
+    private String mLayout;
+
+    public NewKeyboardLayoutPickerController(Context context, String key) {
+        super(context, key);
+        mIm = context.getSystemService(InputManager.class);
+        mInputDeviceId = -1;
+        mPreferenceMap = new HashMap<>();
+    }
+
+    public void initialize(Fragment parent, InputDeviceIdentifier inputDeviceIdentifier,
+            String layout) {
+        mLayout = layout;
+        mParent = parent;
+        mInputDeviceIdentifier = inputDeviceIdentifier;
+        mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
+        Arrays.sort(mKeyboardLayouts);
+    }
+
+    @Override
+    public void onStart() {
+        mIm.registerInputDeviceListener(this, null);
+        final InputDevice inputDevice =
+                mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
+        if (inputDevice == null) {
+            mParent.getActivity().finish();
+            return;
+        }
+        mInputDeviceId = inputDevice.getId();
+    }
+
+    @Override
+    public void onStop() {
+        mIm.unregisterInputDeviceListener(this);
+        mInputDeviceId = -1;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        mScreen = screen;
+        createPreferenceHierarchy();
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+
+        if (!(preference instanceof KeyboardLayoutPreference)) {
+            return false;
+        }
+
+        final KeyboardLayoutPreference pref = (KeyboardLayoutPreference) preference;
+        // TODO(b/259530132): Need APIs to update the available keyboards for input device.
+        // For example:
+        // inputManager.setCurrentKeyboardLayoutForInputDevice(
+        //            InputDevice..., Userid..., ImeSubType ..., String keyboardLayoutDescriptor)
+        if (mPreviousSelection != null && !mPreviousSelection.equals(preference.getKey())) {
+            KeyboardLayoutPreference preSelectedPref = mScreen.findPreference(mPreviousSelection);
+            pref.setCheckMark(true);
+            preSelectedPref.setCheckMark(false);
+        }
+        mPreviousSelection = preference.getKey();
+        return true;
+    }
+
+    @Override
+    public void onInputDeviceAdded(int deviceId) {
+        // Do nothing.
+    }
+
+    @Override
+    public void onInputDeviceRemoved(int deviceId) {
+        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+            mParent.getActivity().finish();
+        }
+    }
+
+    @Override
+    public void onInputDeviceChanged(int deviceId) {
+        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+            updateCheckedState();
+        }
+    }
+
+    private void updateCheckedState() {
+        // TODO(b/259530132): Need API to update the keyboard language layout list.
+    }
+
+    private void createPreferenceHierarchy() {
+        for (KeyboardLayout layout : mKeyboardLayouts) {
+            final KeyboardLayoutPreference pref;
+            if (mLayout.equals(layout.getLabel())) {
+                pref = new KeyboardLayoutPreference(mScreen.getContext(), layout.getLabel(), true);
+                mPreviousSelection = layout.getLabel();
+            } else {
+                pref = new KeyboardLayoutPreference(mScreen.getContext(), layout.getLabel(), false);
+            }
+            // TODO: Waiting for new API to use a prefix with special number to setKey
+            pref.setKey(layout.getLabel());
+            mScreen.addPreference(pref);
+            mPreferenceMap.put(pref, layout);
+        }
+    }
+}
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerFragment.java
new file mode 100644
index 0000000..c2f41a2
--- /dev/null
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerFragment.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 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.inputmethod;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.fragment.app.Fragment;
+
+import com.android.settings.R;
+
+public class NewKeyboardLayoutPickerFragment extends Fragment {
+
+    static final String EXTRA_TITLE = "keyboard_layout_picker_title";
+    static final String EXTRA_KEYBOARD_LAYOUT = "keyboard_layout";
+
+    /**
+     * Intent extra: The input device descriptor of the keyboard whose keyboard
+     * layout is to be changed.
+     */
+    public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
+
+    private ViewGroup mFragmentView;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+
+        mFragmentView = (ViewGroup) inflater.inflate(
+                R.layout.keyboard_layout_picker, container, false);
+        getActivity().getSupportFragmentManager()
+                .beginTransaction()
+                .replace(R.id.keyboard_layout_title, new NewKeyboardLayoutPickerTitle())
+                .commit();
+
+        NewKeyboardLayoutPickerContent fragment = new NewKeyboardLayoutPickerContent();
+        fragment.setArguments(getArguments());
+        getActivity().getSupportFragmentManager()
+                .beginTransaction()
+                .replace(R.id.keyboard_layouts, fragment)
+                .commit();
+
+        return mFragmentView;
+    }
+}
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerTitle.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerTitle.java
new file mode 100644
index 0000000..abcad27
--- /dev/null
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutPickerTitle.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 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.inputmethod;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+
+public class NewKeyboardLayoutPickerTitle extends SettingsPreferenceFragment {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.new_keyboard_layout_picker_title);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        // TODO: add new SettingsEnums SETTINGS_KEYBOARDS_LAYOUT_PICKER_TITLE
+        return SettingsEnums.SETTINGS_KEYBOARDS_LAYOUT_PICKER;
+    }
+
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.new_keyboard_layout_picker_title) {
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return false;
+                }
+            };
+}
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index d7a208c..38ea840 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -33,6 +33,7 @@
 import android.provider.SearchIndexableResource;
 import android.provider.Settings.Secure;
 import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
 import android.view.InputDevice;
 
 import androidx.preference.Preference;
@@ -45,6 +46,7 @@
 import com.android.settings.R;
 import com.android.settings.Settings;
 import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.utils.ThreadUtils;
@@ -52,7 +54,9 @@
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 @SearchIndexable
@@ -60,7 +64,7 @@
         implements InputManager.InputDeviceListener,
         KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener {
 
-    private static final String KEYBOARD_ASSISTANCE_CATEGORY = "keyboard_assistance_category";
+    private static final String KEYBOARD_OPTIONS_CATEGORY = "keyboard_options_category";
     private static final String SHOW_VIRTUAL_KEYBOARD_SWITCH = "show_virtual_keyboard_switch";
     private static final String KEYBOARD_SHORTCUTS_HELPER = "keyboard_shortcuts_helper";
 
@@ -74,17 +78,25 @@
     private SwitchPreference mShowVirtualKeyboardSwitch;
 
     private Intent mIntentWaitingForResult;
+    private boolean mIsNewKeyboardSettings;
+
+    static final String EXTRA_BT_ADDRESS = "extra_bt_address";
+    private String mBluetoothAddress;
 
     @Override
     public void onCreatePreferences(Bundle bundle, String s) {
         Activity activity = Preconditions.checkNotNull(getActivity());
+        mBluetoothAddress = activity.getIntent().getStringExtra(EXTRA_BT_ADDRESS);
         addPreferencesFromResource(R.xml.physical_keyboard_settings);
         mIm = Preconditions.checkNotNull(activity.getSystemService(InputManager.class));
         mKeyboardAssistanceCategory = Preconditions.checkNotNull(
-                (PreferenceCategory) findPreference(KEYBOARD_ASSISTANCE_CATEGORY));
+                (PreferenceCategory) findPreference(KEYBOARD_OPTIONS_CATEGORY));
         mShowVirtualKeyboardSwitch = Preconditions.checkNotNull(
                 (SwitchPreference) mKeyboardAssistanceCategory.findPreference(
                         SHOW_VIRTUAL_KEYBOARD_SWITCH));
+        mIsNewKeyboardSettings = FeatureFlagUtils.isEnabled(
+                getContext(), FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI);
+        // TODO(b/247080921): Support shortcuts list & modifier keys
     }
 
     @Override
@@ -164,17 +176,55 @@
         preferenceScreen.addPreference(category);
 
         for (HardKeyboardDeviceInfo hardKeyboardDeviceInfo : newHardKeyboards) {
+
+            // if user go into this page from Connected devices entry, we should distinguish the
+            // user-selected keyboard from all enabled keyboards.
+            if (mBluetoothAddress != null
+                    && !mBluetoothAddress.equals(hardKeyboardDeviceInfo.mBluetoothAddress)) {
+                continue;
+            }
+
             // TODO(yukawa): Consider using com.android.settings.widget.GearPreference
             final Preference pref = new Preference(getPrefContext());
             pref.setTitle(hardKeyboardDeviceInfo.mDeviceName);
-            pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
-            pref.setOnPreferenceClickListener(preference -> {
-                showKeyboardLayoutDialog(hardKeyboardDeviceInfo.mDeviceIdentifier);
-                return true;
-            });
+            if (mIsNewKeyboardSettings) {
+                // TODO(b/252816846): Need InputMethodManager to provide the enabled locales.
+                // Hardcode Languages for demo until inputMethodManager provides the latest API.
+                // For example: InputMethodManager.getEnabledInputMethodLocales();
+                String[] keyboardLanguages =
+                        {"English (US)", "German (Germany)", "Spanish (Spain)"};
+                String[] keyboardLayouts = {"English (US)", "German", "Spanish"};
+                Map<String, String> keyboardMap = new HashMap<>();
+                for (int i = 0; i < keyboardLanguages.length; i++) {
+                    keyboardMap.put(keyboardLanguages[i], keyboardLayouts[i]);
+                }
+                if (!keyboardMap.isEmpty()) {
+                    String summary = keyboardMap.get(keyboardLanguages[0]);
+                    StringBuilder result = new StringBuilder(summary);
+                    for (int i = 1; i < keyboardLanguages.length; i++) {
+                        result.append(", ").append(keyboardMap.get(keyboardLanguages[i]));
+                    }
+                    pref.setSummary(result.toString());
+                } else {
+                    pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
+                }
+                pref.setOnPreferenceClickListener(
+                        preference -> {
+                            showEnabledLocalesKeyboardLayoutList(
+                                    hardKeyboardDeviceInfo.mDeviceName,
+                                    hardKeyboardDeviceInfo.mDeviceIdentifier);
+                            return true;
+                        });
+            } else {
+                pref.setSummary(hardKeyboardDeviceInfo.mLayoutLabel);
+                pref.setOnPreferenceClickListener(
+                        preference -> {
+                            showKeyboardLayoutDialog(hardKeyboardDeviceInfo.mDeviceIdentifier);
+                            return true;
+                        });
+            }
             category.addPreference(pref);
         }
-
         mKeyboardAssistanceCategory.setOrder(1);
         preferenceScreen.addPreference(mKeyboardAssistanceCategory);
         updateShowVirtualKeyboardSwitch();
@@ -187,6 +237,21 @@
         fragment.show(getActivity().getSupportFragmentManager(), "keyboardLayout");
     }
 
+    private void showEnabledLocalesKeyboardLayoutList(String keyboardName,
+            InputDeviceIdentifier inputDeviceIdentifier) {
+        // TODO(b/252816846: Need to get enabled locales.
+        Bundle arguments = new Bundle();
+        arguments.putParcelable(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_IDENTIFIER,
+                inputDeviceIdentifier);
+        arguments.putString(NewKeyboardLayoutEnabledLocalesFragment.EXTRA_KEYBOARD_DEVICE_NAME,
+                keyboardName);
+        new SubSettingLauncher(getContext())
+                .setSourceMetricsCategory(getMetricsCategory())
+                .setDestination(NewKeyboardLayoutEnabledLocalesFragment.class.getName())
+                .setArguments(arguments)
+                .launch();
+    }
+
     private void registerShowVirtualKeyboardSettingsObserver() {
         unregisterShowVirtualKeyboardSettingsObserver();
         getActivity().getContentResolver().registerContentObserver(
@@ -277,7 +342,10 @@
                 continue;
             }
             keyboards.add(new HardKeyboardDeviceInfo(
-                    device.getName(), device.getIdentifier(), getLayoutLabel(device, context, im)));
+                    device.getName(),
+                    device.getIdentifier(),
+                    getLayoutLabel(device, context, im),
+                    device.getBluetoothAddress()));
         }
 
         // We intentionally don't reuse Comparator because Collator may not be thread-safe.
@@ -304,14 +372,18 @@
         public final InputDeviceIdentifier mDeviceIdentifier;
         @NonNull
         public final String mLayoutLabel;
+        @Nullable
+        public final String mBluetoothAddress;
 
         public HardKeyboardDeviceInfo(
                 @Nullable String deviceName,
                 @NonNull InputDeviceIdentifier deviceIdentifier,
-                @NonNull String layoutLabel) {
+                @NonNull String layoutLabel,
+                @Nullable String bluetoothAddress) {
             mDeviceName = TextUtils.emptyIfNull(deviceName);
             mDeviceIdentifier = deviceIdentifier;
             mLayoutLabel = layoutLabel;
+            mBluetoothAddress = bluetoothAddress;
         }
 
         @Override
@@ -331,6 +403,9 @@
             if (!TextUtils.equals(mLayoutLabel, that.mLayoutLabel)) {
                 return false;
             }
+            if (!TextUtils.equals(mBluetoothAddress, that.mBluetoothAddress)) {
+                return false;
+            }
 
             return true;
         }
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index a9010ac..68d8beb 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -96,7 +96,7 @@
      * @return true if Settings cannot modify the config due to lockDown.
      */
     public static boolean isNetworkLockedDown(Context context, WifiConfiguration config) {
-        if (config == null) {
+        if (context == null || config == null) {
             return false;
         }
 
diff --git a/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
index fae61d6..31e0782 100644
--- a/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
@@ -54,6 +54,9 @@
     @Mock
     private PreferenceScreen mPreferenceScreen;
 
+    @Mock
+    private PreviewSizeSeekBarController.ProgressInteractionListener mInteractionListener;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -65,6 +68,8 @@
 
         mSeekBarPreference = spy(new LabeledSeekBarPreference(mContext, /* attrs= */ null));
         when(mPreferenceScreen.findPreference(anyString())).thenReturn(mSeekBarPreference);
+
+        mSeekBarController.setInteractionListener(mInteractionListener);
     }
 
     @Test
@@ -98,4 +103,12 @@
 
         assertThat(mSeekBarPreference.getProgress()).isEqualTo(defaultProgress);
     }
+
+    @Test
+    public void resetState_verifyOnProgressChanged() {
+        mSeekBarController.displayPreference(mPreferenceScreen);
+        mSeekBarController.resetState();
+
+        verify(mInteractionListener).onProgressChanged();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
index 4813c80..7df24f1 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
@@ -20,6 +20,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -27,11 +28,13 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 
+import androidx.fragment.app.FragmentActivity;
 import androidx.test.core.app.ApplicationProvider;
 
 import com.android.settings.R;
 import com.android.settingslib.widget.LayoutPreference;
 
+import com.google.android.setupcompat.template.FooterBarMixin;
 import com.google.android.setupdesign.GlifPreferenceLayout;
 
 import org.junit.Before;
@@ -50,8 +53,16 @@
 
     @Rule
     public final MockitoRule mMockito = MockitoJUnit.rule();
+
     @Mock
     private GlifPreferenceLayout mGlifLayoutView;
+
+    @Mock
+    private FooterBarMixin mFooterBarMixin;
+
+    @Mock
+    private FragmentActivity mActivity;
+
     @Spy
     private final Context mContext = ApplicationProvider.getApplicationContext();
     private TextReadingPreferenceFragmentForSetupWizard mFragment;
@@ -61,13 +72,14 @@
         mFragment = spy(new TextReadingPreferenceFragmentForSetupWizard());
         final LayoutPreference resetPreference =
                 new LayoutPreference(mContext, R.layout.accessibility_text_reading_reset_button);
+        doReturn(mContext).when(mFragment).getContext();
         doReturn(resetPreference).when(mFragment).findPreference(RESET_KEY);
+        doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
     }
 
     @Test
     public void setHeaderText_onViewCreated_verifyAction() {
         final String title = "title";
-        doReturn(mContext).when(mFragment).getContext();
         doReturn(title).when(mContext).getString(
                 R.string.accessibility_text_reading_options_title);
 
@@ -86,4 +98,21 @@
     public void getHelpResource_shouldNotHaveHelpResource() {
         assertThat(mFragment.getHelpResource()).isEqualTo(0);
     }
+
+    @Test
+    public void onViewCreated_verifySetSecondaryButton() {
+        mFragment.onViewCreated(mGlifLayoutView, null);
+
+        verify(mFooterBarMixin).setSecondaryButton(any());
+    }
+
+    @Test
+    public void onViewCreated_verifySetPrimaryButton() {
+        doReturn(mActivity).when(mFragment).getActivity();
+        doReturn("setupwizard").when(mActivity).getCallingPackage();
+
+        mFragment.onViewCreated(mGlifLayoutView, null);
+
+        verify(mFooterBarMixin).setPrimaryButton(any());
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingResetControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingResetControllerTest.java
index 231c9ca..d5b138a 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingResetControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingResetControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.accessibility;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -70,4 +72,20 @@
 
         verify(mResetPreference).setOnResetClickListener(any(View.OnClickListener.class));
     }
+
+    @Test
+    public void setVisibleAsFalse_preferenceInvisible() {
+        mResetController.setVisible(false);
+        mResetController.displayPreference(mPreferenceScreen);
+
+        assertThat(mResetPreference.isVisible()).isFalse();
+    }
+
+    @Test
+    public void setVisibleAsTrue_preferenceVisible() {
+        mResetController.setVisible(true);
+        mResetController.displayPreference(mPreferenceScreen);
+
+        assertThat(mResetPreference.isVisible()).isTrue();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index f9d4445..596f3b2 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -18,7 +18,6 @@
 
 import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
 import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
-import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UNKNOWN;
 
 import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.KEY_STATE_PREVIOUS_ROTATION;
 import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_NO_ANIMATION;
@@ -31,7 +30,6 @@
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -52,9 +50,6 @@
 import android.os.Vibrator;
 import android.view.Display;
 import android.view.Surface;
-import android.widget.TextView;
-
-import androidx.annotation.Nullable;
 
 import com.android.settings.R;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -106,42 +101,6 @@
     }
 
     @Test
-    public void fingerprintEnrollHelp_shouldShowHelpText() {
-        initializeActivityFor(TYPE_UNKNOWN);
-        TestFingerprintEnrollSidecar sidecar = new TestFingerprintEnrollSidecar();
-        Resources resources = mock(Resources.class);
-        doReturn(resources).when(mContext).getResources();
-        when(resources.getIntArray(R.array.fingerprint_acquired_ignore_list))
-                .thenReturn(new int[]{3});
-
-        sidecar.setListener(mActivity);
-        sidecar.onAttach(mActivity);
-        sidecar.mEnrollmentCallback.onEnrollmentHelp(5,
-                "Help message should be displayed.");
-
-        TextView errorText = mActivity.findViewById(R.id.error_text);
-        assertThat(errorText.getText()).isEqualTo("Help message should be displayed.");
-    }
-
-    @Test
-    public void fingerprintEnrollHelp_shouldNotShowHelpText() {
-        initializeActivityFor(TYPE_UNKNOWN);
-        TestFingerprintEnrollSidecar sidecar = new TestFingerprintEnrollSidecar();
-        Resources resources = mock(Resources.class);
-        doReturn(resources).when(mContext).getResources();
-        when(resources.getIntArray(R.array.fingerprint_acquired_ignore_list))
-                .thenReturn(new int[]{3});
-
-        sidecar.setListener(mActivity);
-        sidecar.onAttach(mActivity);
-        sidecar.mEnrollmentCallback.onEnrollmentHelp(3,
-                "Help message should not be displayed.");
-
-        TextView errorText = mActivity.findViewById(R.id.error_text);
-        assertThat(errorText.getText()).isEqualTo("");
-    }
-
-    @Test
     public void fingerprintUdfpsEnrollSuccessProgress_shouldNotVibrate() {
         initializeActivityFor(TYPE_UDFPS_OPTICAL);
 
@@ -389,12 +348,4 @@
 
         return callbackCaptor.getValue();
     }
-
-    private class TestFingerprintEnrollSidecar extends FingerprintEnrollSidecar {
-        @Nullable
-        @Override
-        public Context getContext() {
-            return mContext;
-        }
-    }
 }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/MessageDisplayControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/MessageDisplayControllerTest.java
new file mode 100644
index 0000000..0fa0918
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/MessageDisplayControllerTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Handler;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowLooper;
+
+import java.time.Clock;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(RobolectricTestRunner.class)
+public class MessageDisplayControllerTest {
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
+    private static final long START_TIME = 0L;
+    private static final int HELP_ID = 0;
+    private static final String HELP_MESSAGE = "Default Help Message";
+    private static final int REMAINING = 5;
+    private static final int HELP_MINIMUM_DISPLAY_TIME = 300;
+    private static final int PROGRESS_MINIMUM_DISPLAY_TIME = 250;
+    private static final int COLLECT_TIME = 100;
+
+    private MessageDisplayController mMessageDisplayController;
+    @Mock
+    private FingerprintManager.EnrollmentCallback mEnrollmentCallback;
+    @Mock
+    private Clock mClock;
+
+    @Before
+    public void setup() {
+        mMessageDisplayController = new MessageDisplayController(new Handler(), mEnrollmentCallback,
+                mClock,
+                HELP_MINIMUM_DISPLAY_TIME,   /* progressPriorityOverHelp */
+                PROGRESS_MINIMUM_DISPLAY_TIME,   /* prioritizeAcquireMessages */
+                false, false, COLLECT_TIME);
+    }
+
+    private void setMessageDisplayController(boolean progressPriorityOverHelp,
+            boolean prioritizeAcquireMessages) {
+        mMessageDisplayController = new MessageDisplayController(new Handler(), mEnrollmentCallback,
+                mClock, HELP_MINIMUM_DISPLAY_TIME, PROGRESS_MINIMUM_DISPLAY_TIME,
+                progressPriorityOverHelp, prioritizeAcquireMessages, COLLECT_TIME);
+    }
+
+    @Test
+    public void showsHelpMessageAfterCollectTime() {
+        when(mClock.millis()).thenReturn(START_TIME);
+
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        verifyNoMoreInteractions(mEnrollmentCallback);
+    }
+
+    @Test
+    public void showsProgressMessageAfterCollectTime() {
+        when(mClock.millis()).thenReturn(START_TIME);
+
+        mMessageDisplayController.onEnrollmentProgress(REMAINING);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentProgress(REMAINING);
+        verifyNoMoreInteractions(mEnrollmentCallback);
+    }
+
+    @Test
+    public void helpDisplayedForMinimumDisplayTime() {
+        when(mClock.millis()).thenReturn(START_TIME);
+
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+
+        mMessageDisplayController.onEnrollmentProgress(REMAINING);
+
+        verifyNoMoreInteractions(mEnrollmentCallback);
+
+        when(mClock.millis()).thenReturn((long) (HELP_MINIMUM_DISPLAY_TIME + COLLECT_TIME));
+        ShadowLooper.idleMainLooper(HELP_MINIMUM_DISPLAY_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentProgress(REMAINING);
+    }
+
+    @Test
+    public void progressDisplayedForMinimumDisplayTime() {
+        when(mClock.millis()).thenReturn(START_TIME);
+
+        mMessageDisplayController.onEnrollmentProgress(REMAINING);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentProgress(REMAINING);
+
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+
+        verifyNoMoreInteractions(mEnrollmentCallback);
+
+        when(mClock.millis()).thenReturn((long) (COLLECT_TIME + PROGRESS_MINIMUM_DISPLAY_TIME));
+        ShadowLooper.idleMainLooper(PROGRESS_MINIMUM_DISPLAY_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+    }
+
+    @Test
+    public void prioritizeHelpMessage_thenShowProgress() {
+        when(mClock.millis()).thenReturn(START_TIME);
+
+        mMessageDisplayController.onEnrollmentProgress(REMAINING);
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        verifyNoMoreInteractions(mEnrollmentCallback);
+
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) (COLLECT_TIME + HELP_MINIMUM_DISPLAY_TIME));
+        ShadowLooper.idleMainLooper(HELP_MINIMUM_DISPLAY_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentProgress(REMAINING);
+    }
+
+    @Test
+    public void prioritizeProgressOverHelp() {
+        when(mClock.millis()).thenReturn(START_TIME);
+        setMessageDisplayController(true /* progressPriorityOverHelp */,
+                false /* prioritizeAcquireMessages */);
+
+        mMessageDisplayController.onEnrollmentProgress(REMAINING);
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentProgress(REMAINING);
+        verifyNoMoreInteractions(mEnrollmentCallback);
+    }
+
+    @Test
+    public void prioritizeHelpMessageByCount() {
+        String newHelpMessage = "New message";
+        when(mClock.millis()).thenReturn(START_TIME);
+        setMessageDisplayController(false /* progressPriorityOverHelp */,
+                true /* prioritizeAcquireMessages */);
+
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, newHelpMessage);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        verifyNoMoreInteractions(mEnrollmentCallback);
+    }
+
+    @Test
+    public void ignoreSameProgress() {
+        int progressChange = REMAINING - 1;
+        when(mClock.millis()).thenReturn(START_TIME);
+        setMessageDisplayController(true /* progressPriorityOverHelp */,
+                false /* prioritizeAcquireMessages */);
+
+        mMessageDisplayController.onEnrollmentProgress(REMAINING);
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) COLLECT_TIME);
+        ShadowLooper.idleMainLooper(COLLECT_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentProgress(REMAINING);
+        verifyNoMoreInteractions(mEnrollmentCallback);
+
+        mMessageDisplayController.onEnrollmentProgress(REMAINING);
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) (COLLECT_TIME + PROGRESS_MINIMUM_DISPLAY_TIME));
+        ShadowLooper.idleMainLooper(PROGRESS_MINIMUM_DISPLAY_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+
+        mMessageDisplayController.onEnrollmentProgress(progressChange);
+        mMessageDisplayController.onEnrollmentHelp(HELP_ID, HELP_MESSAGE);
+        when(mClock.millis()).thenReturn((long) (COLLECT_TIME + PROGRESS_MINIMUM_DISPLAY_TIME
+                + HELP_MINIMUM_DISPLAY_TIME));
+        ShadowLooper.idleMainLooper(HELP_MINIMUM_DISPLAY_TIME, TimeUnit.MILLISECONDS);
+
+        verify(mEnrollmentCallback).onEnrollmentProgress(progressChange);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
index 9d4956d..eea07fe 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.deviceinfo.simstatus;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -26,6 +28,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.UserManager;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
@@ -37,6 +40,7 @@
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.search.SearchIndexableRaw;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -62,6 +66,10 @@
     @Mock
     private PreferenceScreen mScreen;
     @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo;
+    @Mock
     private TelephonyManager mTelephonyManager;
     @Mock
     private UserManager mUserManager;
@@ -85,6 +93,8 @@
         when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
 
         mockService(Context.TELEPHONY_SERVICE, TelephonyManager.class, mTelephonyManager);
+        mockService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
+                mSubscriptionManager);
 
         mockService(Context.USER_SERVICE, UserManager.class, mUserManager);
         final List<Preference> preferencePool = new ArrayList<Preference>();
@@ -96,6 +106,10 @@
             public Preference createNewPreference(Context context) {
                 return preferencePool.remove(0);
             }
+            @Override
+            public int getSimSlotIndex() {
+                return 0;
+            }
         });
         doReturn(BasePreferenceController.AVAILABLE).when(mController).getAvailabilityStatus();
         when(mScreen.getContext()).thenReturn(mContext);
@@ -163,6 +177,47 @@
         verify(mFragment).getChildFragmentManager();
     }
 
+    @Test
+    public void updateDynamicRawDataToIndex_notAddToSearch_emptySimSlot() {
+        doReturn(null).when(mSubscriptionManager).getActiveSubscriptionInfoList();
+        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        List<SearchIndexableRaw> rawData = new ArrayList<SearchIndexableRaw>();
+
+        mController.init(mFragment, slotSimStatus);
+        mController.updateDynamicRawDataToIndex(rawData);
+
+        assertThat(rawData.size()).isEqualTo(0);
+    }
+
+    @Test
+    public void updateDynamicRawDataToIndex_addToSearch_simInSimSlot() {
+        doReturn(false).when(mSubscriptionInfo).isEmbedded();
+        doReturn(List.of(mSubscriptionInfo)).when(mSubscriptionManager)
+                .getActiveSubscriptionInfoList();
+        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        List<SearchIndexableRaw> rawData = new ArrayList<SearchIndexableRaw>();
+
+        mController.init(mFragment, slotSimStatus);
+        mController.updateDynamicRawDataToIndex(rawData);
+
+        assertThat(rawData.size()).isEqualTo(1);
+    }
+
+    @Test
+    public void updateDynamicRawDataToIndex_addEsimToSearch_esimInSimSlot() {
+        doReturn(true).when(mSubscriptionInfo).isEmbedded();
+        doReturn(List.of(mSubscriptionInfo)).when(mSubscriptionManager)
+                .getActiveSubscriptionInfoList();
+        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        List<SearchIndexableRaw> rawData = new ArrayList<SearchIndexableRaw>();
+
+        mController.init(mFragment, slotSimStatus);
+        mController.updateDynamicRawDataToIndex(rawData);
+
+        assertThat(rawData.size()).isEqualTo(1);
+        assertThat(rawData.get(0).keywords.contains("eid")).isTrue();
+    }
+
     private <T> void mockService(String serviceName, Class<T> serviceClass, T service) {
         when(mContext.getSystemServiceName(serviceClass)).thenReturn(serviceName);
         when(mContext.getSystemService(serviceName)).thenReturn(service);
diff --git a/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java b/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java
index e9e8072..4fceb17 100644
--- a/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -104,23 +106,28 @@
 
     @Test
     public void summaryText_whenDreamsAreOff() {
-        DreamBackend mockBackend = mock(DreamBackend.class);
-        Context mockContext = mock(Context.class);
+        final String fakeSummaryOff = "test dream off";
+        final DreamBackend mockBackend = mock(DreamBackend.class);
+        final Context mockContext = mock(Context.class);
         when(mockBackend.isEnabled()).thenReturn(false);
+        when(mockContext.getString(R.string.screensaver_settings_summary_off)).thenReturn(
+                fakeSummaryOff);
 
-        assertThat(DreamSettings.getSummaryTextFromBackend(mockBackend, mockContext))
-                .isEqualTo(mockContext.getString(R.string.off));
+        assertThat(DreamSettings.getSummaryTextFromBackend(mockBackend, mockContext)).isEqualTo(
+                fakeSummaryOff);
     }
 
     @Test
     public void summaryTest_WhenDreamsAreOn() {
         final String fakeName = "test_name";
-        DreamBackend mockBackend = mock(DreamBackend.class);
-        Context mockContext = mock(Context.class);
+        final DreamBackend mockBackend = mock(DreamBackend.class);
+        final Context mockContext = mock(Context.class);
         when(mockBackend.isEnabled()).thenReturn(true);
         when(mockBackend.getActiveDreamName()).thenReturn(fakeName);
+        when(mockContext.getString(eq(R.string.screensaver_settings_summary_on), anyString()))
+                .thenAnswer(i -> i.getArgument(1) + " test dream is on");
 
-        assertThat(DreamSettings.getSummaryTextFromBackend(mockBackend, mockContext))
-                .isEqualTo(fakeName);
+        assertThat(DreamSettings.getSummaryTextFromBackend(mockBackend, mockContext)).isEqualTo(
+                fakeName + " test dream is on");
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
index 648685a..ab61abc 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -63,6 +63,11 @@
     }
 
     @Test
+    public void testIsBatteryUsageEnabled_returnFalse() {
+        assertThat(mPowerFeatureProvider.isBatteryUsageEnabled(mContext)).isTrue();
+    }
+
+    @Test
     public void testIsTypeSystem_uidRoot_returnTrue() {
         assertThat(mPowerFeatureProvider.isTypeSystem(Process.ROOT_UID, null)).isTrue();
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index 5b69e7c..210a21b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -22,12 +22,9 @@
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
-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.app.settings.SettingsEnums;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
@@ -39,7 +36,6 @@
 import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -65,7 +61,6 @@
     private Context mContext;
 
     private FakeFeatureFactory mFeatureFactory;
-    private MetricsFeatureProvider mMetricsFeatureProvider;
     private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
 
     @Mock private Intent mIntent;
@@ -83,7 +78,6 @@
 
         mContext = spy(RuntimeEnvironment.application);
         mFeatureFactory = FakeFeatureFactory.setupForTest();
-        mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
         mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
 
         doReturn(mIntent).when(mContext).registerReceiver(any(), any());
@@ -102,10 +96,6 @@
         assertThat(DataProcessor.getBatteryLevelData(
                 mContext, /*handler=*/ null, new HashMap<>(), /*asyncResponseDelegate=*/ null))
                 .isNull();
-        verify(mMetricsFeatureProvider, never())
-                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT);
-        verify(mMetricsFeatureProvider, never())
-                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT);
     }
 
     @Test
@@ -123,10 +113,6 @@
         assertThat(DataProcessor.getBatteryLevelData(
                 mContext, /*handler=*/ null, batteryHistoryMap, /*asyncResponseDelegate=*/ null))
                 .isNull();
-        verify(mMetricsFeatureProvider, never())
-                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT);
-        verify(mMetricsFeatureProvider, never())
-                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT);
     }
 
     @Test
@@ -541,10 +527,6 @@
 
         assertThat(DataProcessor.getBatteryUsageMap(
                 mContext, hourlyBatteryLevelsPerDay, new HashMap<>())).isNull();
-        verify(mMetricsFeatureProvider, never())
-                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT);
-        verify(mMetricsFeatureProvider, never())
-                .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT);
     }
 
     @Test
@@ -713,14 +695,6 @@
                 /*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
                 /*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
                 /*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
-                        3);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
-                        0);
     }
 
     @Test
@@ -843,14 +817,6 @@
                 /*foregroundUsageTimeInMs=*/ 0, /*backgroundUsageTimeInMs=*/ 0);
         assertThat(resultMap.get(0).get(0)).isNotNull();
         assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
-                        2);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
-                        0);
     }
 
     @Test
@@ -929,14 +895,6 @@
                 .isEqualTo(entry.mCachedUsageConsumePower * ratio);
         assertThat(resultMap.get(0).get(0)).isNotNull();
         assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
-                        1);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
-                        0);
     }
 
     @Test
@@ -1028,14 +986,6 @@
                 /*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
                 /*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
                 /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 20);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
-                        1);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
-                        1);
     }
 
     @Test
@@ -1125,14 +1075,6 @@
         assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(20);
         resultEntry = resultDiffData.getAppDiffEntryList().get(1);
         assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(0);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
-                        2);
-        verify(mMetricsFeatureProvider)
-                .action(mContext.getApplicationContext(),
-                        SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
-                        0);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreferenceTest.java
index 5d599fe..e9573f1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/PowerGaugePreferenceTest.java
@@ -104,4 +104,18 @@
         assertThat(mPreferenceViewHolder.findViewById(android.R.id.title).getContentDescription())
                 .isEqualTo(CONTENT_DESCRIPTION);
     }
+
+    @Test
+    public void setPercent_greaterThanThreshold_showNumber() {
+        mPowerGaugePreference.setPercent(99.5);
+
+        assertThat(mPowerGaugePreference.getPercent()).isEqualTo("100%");
+    }
+
+    @Test
+    public void setPercent_lessThanThreshold_showBar() {
+        mPowerGaugePreference.setPercent(0.95);
+
+        assertThat(mPowerGaugePreference.getPercent()).isEqualTo("-");
+    }
 }