Merge "Stylus updater in ConnectedDevicesGroupController."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 37c9a7f..5352562 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -126,7 +126,6 @@
     <uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
     <uses-permission android:name="android.permission.START_VIEW_APP_FEATURES" />
     <uses-permission android:name="android.permission.ACCESS_KEYGUARD_QUICK_AFFORDANCES" />
-    <uses-permission android:name="android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS" />
 
     <application
             android:name=".SettingsApplication"
diff --git a/res/drawable/ia_settings_communal.xml b/res/drawable/ia_settings_communal.xml
new file mode 100644
index 0000000..14642c9
--- /dev/null
+++ b/res/drawable/ia_settings_communal.xml
@@ -0,0 +1,24 @@
+<!-- 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"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?android:attr/colorControlNormal">
+    <path android:fillColor="@android:color/white"
+          android:pathData="M24,38Q19,38 15.5,37.325Q12,36.65 12,35.7V34H7.25Q5.95,34 5.05,33.025Q4.15,32.05 4.25,30.75L5.8,12.75Q5.9,11.6 6.75,10.8Q7.6,10 8.75,10H39.25Q40.4,10 41.25,10.8Q42.1,11.6 42.2,12.75L43.75,30.75Q43.85,32.05 42.95,33.025Q42.05,34 40.75,34H36V35.7Q36,36.65 32.5,37.325Q29,38 24,38ZM7.25,31H40.75Q40.75,31 40.75,31Q40.75,31 40.75,31L39.25,13Q39.25,13 39.25,13Q39.25,13 39.25,13H8.75Q8.75,13 8.75,13Q8.75,13 8.75,13L7.25,31Q7.25,31 7.25,31Q7.25,31 7.25,31Z"/>
+</vector>
diff --git a/res/drawable/ic_settings_trackpad.xml b/res/drawable/ic_settings_trackpad.xml
new file mode 100644
index 0000000..9580e02
--- /dev/null
+++ b/res/drawable/ic_settings_trackpad.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"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M5,40Q3.75,40 2.875,39.125Q2,38.25 2,37V11Q2,9.75 2.875,8.875Q3.75,8 5,8H43Q44.25,8 45.125,8.875Q46,9.75 46,11V37Q46,38.25 45.125,39.125Q44.25,40 43,40ZM6.5,11H5Q5,11 5,11Q5,11 5,11V37Q5,37 5,37Q5,37 5,37H6.5ZM9.5,37H38.5V11H9.5ZM41.5,11V37H43Q43,37 43,37Q43,37 43,37V11Q43,11 43,11Q43,11 43,11ZM41.5,11H43Q43,11 43,11Q43,11 43,11Q43,11 43,11Q43,11 43,11H41.5ZM6.5,11H5Q5,11 5,11Q5,11 5,11Q5,11 5,11Q5,11 5,11Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_trackpad_gesture_back.xml b/res/drawable/ic_trackpad_gesture_back.xml
new file mode 100644
index 0000000..b6a80cf
--- /dev/null
+++ b/res/drawable/ic_trackpad_gesture_back.xml
@@ -0,0 +1,26 @@
+<!--
+    Copyright (C) 2019 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:autoMirrored="true"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M20,11H7.83l5.59-5.59L12,4l-8,8l8,8l1.41-1.41L7.83,13H20V11z" />
+</vector>
diff --git a/res/drawable/ic_trackpad_gesture_home.xml b/res/drawable/ic_trackpad_gesture_home.xml
new file mode 100644
index 0000000..f0e7232
--- /dev/null
+++ b/res/drawable/ic_trackpad_gesture_home.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"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M11,39H18.5V26.5H29.5V39H37V19.5L24,9.75L11,19.5ZM8,42V18L24,6L40,18V42H26.5V29.5H21.5V42ZM24,24.35Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_trackpad_gesture_notifications.xml b/res/drawable/ic_trackpad_gesture_notifications.xml
new file mode 100644
index 0000000..37d77d8
--- /dev/null
+++ b/res/drawable/ic_trackpad_gesture_notifications.xml
@@ -0,0 +1,26 @@
+<!--
+    Copyright (C) 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:pathData="M18,17V11C18,7.93 16.37,5.36 13.5,4.68V4C13.5,3.17 12.83,2.5 12,2.5C11.17,2.5 10.5,3.17 10.5,4V4.68C7.64,5.36 6,7.92 6,11V17H4V19H14H14.38H20V17H18ZM16,17H8V11C8,8.52 9.51,6.5 12,6.5C14.49,6.5 16,8.52 16,11V17ZM14,20C14,21.1 13.1,22 12,22C10.9,22 10,21.1 10,20H14Z"
+        android:fillType="evenOdd"
+        android:fillColor="?android:attr/colorPrimary"/>
+</vector>
diff --git a/res/drawable/ic_trackpad_gesture_recent_apps.xml b/res/drawable/ic_trackpad_gesture_recent_apps.xml
new file mode 100644
index 0000000..76ba829
--- /dev/null
+++ b/res/drawable/ic_trackpad_gesture_recent_apps.xml
@@ -0,0 +1,26 @@
+<!--
+    Copyright (C) 2017 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:pathData="M16,6C16,7.1 16.9,8 18,8C19.1,8 20,7.1 20,6C20,4.9 19.1,4 18,4C16.9,4 16,4.9 16,6ZM6,8C7.1,8 8,7.1 8,6C8,4.9 7.1,4 6,4C4.9,4 4,4.9 4,6C4,7.1 4.9,8 6,8ZM12.001,20C13.101,20 14.001,19.1 14.001,18C14.001,16.9 13.101,16 12.001,16C10.901,16 10.001,16.9 10.001,18C10.001,19.1 10.901,20 12.001,20ZM8.001,18C8.001,19.1 7.101,20 6.001,20C4.901,20 4.001,19.1 4.001,18C4.001,16.9 4.901,16 6.001,16C7.101,16 8.001,16.9 8.001,18ZM6.001,14C7.101,14 8.001,13.1 8.001,12C8.001,10.9 7.101,10 6.001,10C4.901,10 4.001,10.9 4.001,12C4.001,13.1 4.901,14 6.001,14ZM14.001,12C14.001,13.1 13.101,14 12.001,14C10.901,14 10.001,13.1 10.001,12C10.001,10.9 10.901,10 12.001,10C13.101,10 14.001,10.9 14.001,12ZM14.001,6C14.001,7.1 13.101,8 12.001,8C10.901,8 10.001,7.1 10.001,6C10.001,4.9 10.901,4 12.001,4C13.101,4 14.001,4.9 14.001,6ZM18,14C19.1,14 20,13.1 20,12C20,10.9 19.1,10 18,10C16.9,10 16,10.9 16,12C16,13.1 16.9,14 18,14ZM20,18C20,19.1 19.1,20 18,20C16.9,20 16,19.1 16,18C16,16.9 16.9,16 18,16C19.1,16 20,16.9 20,18Z"
+        android:fillType="evenOdd"
+        android:fillColor="?android:attr/colorPrimary"/>
+</vector>
diff --git a/res/drawable/ic_trackpad_gesture_switch_apps.xml b/res/drawable/ic_trackpad_gesture_switch_apps.xml
new file mode 100644
index 0000000..3d18d1c
--- /dev/null
+++ b/res/drawable/ic_trackpad_gesture_switch_apps.xml
@@ -0,0 +1,26 @@
+<!--
+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"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?android:attr/colorControlNormal"
+        android:autoMirrored="true">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M15.85,40 L13.75,37.9 19.8,31.85H4V28.85H19.8L13.75,22.8L15.85,20.7L25.5,30.35ZM32.15,27.3 L22.5,17.65 32.15,8 34.25,10.1 28.2,16.15H44V19.15H28.2L34.25,25.2Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_trackpad_pointer_speed.xml b/res/drawable/ic_trackpad_pointer_speed.xml
new file mode 100644
index 0000000..4e9abeb
--- /dev/null
+++ b/res/drawable/ic_trackpad_pointer_speed.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"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M6.05,24.35V21.35H12.35V24.35ZM11.75,35.9 L9.75,33.9 14.15,29.5 16.15,31.5ZM14.15,16.05 L9.75,11.65 11.75,9.65 16.15,14.05ZM37,40.05 L27.6,30.65 25.4,37.45 20.2,19.45 37.8,25 30.9,27.45 40.25,36.8ZM21.85,12.3V6H24.85V12.3ZM32.55,16.05 L30.55,14.05 34.95,9.65 36.95,11.65Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_trackpad_reverse_scrolling.xml b/res/drawable/ic_trackpad_reverse_scrolling.xml
new file mode 100644
index 0000000..a62f904
--- /dev/null
+++ b/res/drawable/ic_trackpad_reverse_scrolling.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"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M16.1,25.5V9.7L10.1,15.7L8,13.6L17.65,3.95L27.3,13.6L25.2,15.7L19.1,9.65V25.5ZM30.35,43.95 L20.7,34.25 22.8,32.2 28.8,38.2V22.4H31.8V38.25L37.9,32.2L40,34.3Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_trackpad_tap_to_click.xml b/res/drawable/ic_trackpad_tap_to_click.xml
new file mode 100644
index 0000000..7db0454
--- /dev/null
+++ b/res/drawable/ic_trackpad_tap_to_click.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"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M23.25,2Q27.8,2 31.025,5.175Q34.25,8.35 34.25,12.9Q34.25,15.5 33.125,17.8Q32,20.1 29.95,21.7H28.25V19.2Q29.7,18.05 30.475,16.4Q31.25,14.75 31.25,12.9Q31.25,9.6 28.9,7.3Q26.55,5 23.25,5Q19.95,5 17.6,7.3Q15.25,9.6 15.25,12.9Q15.25,14.75 16.025,16.4Q16.8,18.05 18.25,19.2V22.8Q15.45,21.35 13.85,18.7Q12.25,16.05 12.25,12.9Q12.25,8.35 15.475,5.175Q18.7,2 23.25,2ZM21.35,44Q20.5,44 19.75,43.675Q19,43.35 18.45,42.8L8.15,32.5L10.95,29.6Q11.65,28.9 12.525,28.525Q13.4,28.15 14.35,28.4L18.25,29.3V13Q18.25,10.9 19.7,9.45Q21.15,8 23.25,8Q25.35,8 26.8,9.45Q28.25,10.9 28.25,13V21.6H29.55Q29.8,21.6 30,21.7Q30.2,21.8 30.45,21.9L37.85,25.5Q39.05,26.05 39.625,27.275Q40.2,28.5 39.95,29.8L38.15,40.7Q37.9,42.15 36.75,43.075Q35.6,44 34.15,44ZM20.95,41H35L37.15,28.55Q37.15,28.55 37.15,28.55Q37.15,28.55 37.15,28.55L28,24H25.25V13Q25.25,12.1 24.7,11.55Q24.15,11 23.25,11Q22.35,11 21.8,11.55Q21.25,12.1 21.25,13V32.95L13.55,31.3L12.4,32.45ZM35,41H20.95H21.25Q21.25,41 21.8,41Q22.35,41 23.25,41Q24.15,41 24.7,41Q25.25,41 25.25,41H28H35Q35,41 35,41Q35,41 35,41Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_trackpad_touch_gestures_inverse.xml b/res/drawable/ic_trackpad_touch_gestures_inverse.xml
new file mode 100644
index 0000000..d663572
--- /dev/null
+++ b/res/drawable/ic_trackpad_touch_gestures_inverse.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"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?android:attr/textColorPrimaryInverse">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M40.15,47 L38.2,43.1 34.3,41.15 38.2,39.3 40.15,35.3 42,39.3 46,41.15 42,43.1ZM28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4ZM23.05,48H30.4L29.75,45H23.05Q22,45 20.975,44.8Q19.95,44.6 19.25,43.9L6.5,30.65L7.85,29.4L19.75,35.85V9.15Q19.75,8.6 20.1,8.25Q20.45,7.9 21,7.9Q21.55,7.9 21.9,8.25Q22.25,8.6 22.25,9.15V24H26V4.25Q26,3.7 26.35,3.35Q26.7,3 27.25,3Q27.8,3 28.15,3.35Q28.5,3.7 28.5,4.25V24H32.25V6.1Q32.25,5.55 32.6,5.2Q32.95,4.85 33.5,4.85Q34.05,4.85 34.4,5.2Q34.75,5.55 34.75,6.1V24H38.5V12.45Q38.5,11.9 38.85,11.55Q39.2,11.2 39.75,11.2Q40.3,11.2 40.65,11.55Q41,11.9 41,12.45V31.4H44V12.45Q44,10.7 42.75,9.45Q41.5,8.2 39.75,8.2Q39.2,8.2 38.675,8.3Q38.15,8.4 37.75,8.75V6.45Q37.75,4.55 36.525,3.2Q35.3,1.85 33.5,1.85Q32.85,1.85 32.25,2.025Q31.65,2.2 31.1,2.6Q30.65,1.4 29.625,0.7Q28.6,0 27.3,0Q25.55,0 24.275,1.25Q23,2.5 23,4.25V5.55Q22.6,5.2 22.075,5.05Q21.55,4.9 21,4.9Q19.25,4.9 18,6.15Q16.75,7.4 16.75,9.15V30.95L8.85,26.5Q8,26.05 7.1,26.325Q6.2,26.6 5.5,27.25L2,30.3L16.85,45.7Q18.05,46.95 19.675,47.475Q21.3,48 23.05,48ZM6.85,14.8 L5.15,11.15 1.5,9.45 5.15,7.75 6.85,4.1 8.55,7.7 12.2,9.6 8.6,11.15Z"/>
+</vector>
diff --git a/res/drawable/ic_trackpad_touch_gestures_normal.xml b/res/drawable/ic_trackpad_touch_gestures_normal.xml
new file mode 100644
index 0000000..34619c8
--- /dev/null
+++ b/res/drawable/ic_trackpad_touch_gestures_normal.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"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="48"
+        android:viewportHeight="48"
+        android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M40.15,47 L38.2,43.1 34.3,41.15 38.2,39.3 40.15,35.3 42,39.3 46,41.15 42,43.1ZM28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4Q28.5,31.4 28.5,31.4ZM23.05,48H30.4L29.75,45H23.05Q22,45 20.975,44.8Q19.95,44.6 19.25,43.9L6.5,30.65L7.85,29.4L19.75,35.85V9.15Q19.75,8.6 20.1,8.25Q20.45,7.9 21,7.9Q21.55,7.9 21.9,8.25Q22.25,8.6 22.25,9.15V24H26V4.25Q26,3.7 26.35,3.35Q26.7,3 27.25,3Q27.8,3 28.15,3.35Q28.5,3.7 28.5,4.25V24H32.25V6.1Q32.25,5.55 32.6,5.2Q32.95,4.85 33.5,4.85Q34.05,4.85 34.4,5.2Q34.75,5.55 34.75,6.1V24H38.5V12.45Q38.5,11.9 38.85,11.55Q39.2,11.2 39.75,11.2Q40.3,11.2 40.65,11.55Q41,11.9 41,12.45V31.4H44V12.45Q44,10.7 42.75,9.45Q41.5,8.2 39.75,8.2Q39.2,8.2 38.675,8.3Q38.15,8.4 37.75,8.75V6.45Q37.75,4.55 36.525,3.2Q35.3,1.85 33.5,1.85Q32.85,1.85 32.25,2.025Q31.65,2.2 31.1,2.6Q30.65,1.4 29.625,0.7Q28.6,0 27.3,0Q25.55,0 24.275,1.25Q23,2.5 23,4.25V5.55Q22.6,5.2 22.075,5.05Q21.55,4.9 21,4.9Q19.25,4.9 18,6.15Q16.75,7.4 16.75,9.15V30.95L8.85,26.5Q8,26.05 7.1,26.325Q6.2,26.6 5.5,27.25L2,30.3L16.85,45.7Q18.05,46.95 19.675,47.475Q21.3,48 23.05,48ZM6.85,14.8 L5.15,11.15 1.5,9.45 5.15,7.75 6.85,4.1 8.55,7.7 12.2,9.6 8.6,11.15Z"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/preference_widget_add_progressbar.xml b/res/layout/preference_widget_add_progressbar.xml
new file mode 100644
index 0000000..95ee09e
--- /dev/null
+++ b/res/layout/preference_widget_add_progressbar.xml
@@ -0,0 +1,41 @@
+<?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.
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:id="@+id/add_clone_layout">
+    <ImageView
+        android:id="@+id/add_preference_widget"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:layout_gravity="center"
+        android:minWidth="@dimen/two_target_min_width"
+        android:paddingStart="?android:attr/listPreferredItemPaddingEnd"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:background="@drawable/ic_add_24dp"
+        android:scaleType="center"
+        android:tint="?android:attr/colorAccent"
+        android:contentDescription="@string/add" />
+
+    <ProgressBar
+        android:id="@+id/progressBar_cyclic"
+        style="?android:attr/progressBarStyleLarge"
+        android:layout_width="24dp"
+        android:layout_height="24dp"
+        android:visibility="gone"/>
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index 970261f..bbacc5c 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -600,6 +600,9 @@
     <!-- Whether the dream setup activity should be enabled as part of setupwizard -->
     <bool name="dream_setup_supported">false</bool>
 
+    <!-- Whether to show communal settings at the top level. -->
+    <bool name="config_show_communal_settings">false</bool>
+
     <!-- Whether to put the apps with system UID into system component bucket or not -->
     <bool name="config_battery_combine_system_components">false</bool>
 
diff --git a/res/values/menu_keys.xml b/res/values/menu_keys.xml
index 2841b69..27e9639 100755
--- a/res/values/menu_keys.xml
+++ b/res/values/menu_keys.xml
@@ -17,6 +17,7 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
     <string name="menu_key_network" translatable="false">top_level_network</string>
+    <string name="menu_key_communal" translatable="false">top_level_communal</string>
     <string name="menu_key_connected_devices" translatable="false">top_level_connected_devices</string>
     <string name="menu_key_apps" translatable="false">top_level_apps</string>
     <string name="menu_key_notifications" translatable="false">top_level_notifications</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1929810..fa1dd36 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2637,6 +2637,12 @@
     <!-- Phone info screen, section titles: -->
     <string name="battery_level_title">Battery level</string>
 
+    <!-- Communal Settings -->
+    <!-- Title of the communal settings under Settings > Communal [CHAR LIMIT=30] -->
+    <string name="communal_settings_title">Communal</string>
+    <!-- Summary of the communal settings under Settings > Communal [CHAR LIMIT=50] -->
+    <string name="communal_settings_summary">Communal settings</string>
+
     <!-- APN Settings -->
     <!-- APN settings screen title -->
     <string name="apn_settings">APNs</string>
@@ -3662,6 +3668,53 @@
     <!-- Title for the 'Virtual keyboards for work' preference. [CHAR LIMIT=45] -->
     <string name="virtual_keyboards_for_work_title">On-screen keyboard for work</string>
 
+    <!-- Title for the button to trigger the 'trackpad settings' page if only connect with a touchpad. [CHAR LIMIT=35] -->
+    <string name="trackpad_settings">Touchpad</string>
+    <!-- Title for the button to trigger the 'trackpad settings' page if connect with a touchpad and a mouse. [CHAR LIMIT=35] -->
+    <string name="trackpad_mouse_settings">Touchpad &amp; mouse</string>
+    <!-- Summary text for the 'trackpad settings' page. [CHAR LIMIT=100] -->
+    <string name="trackpad_settings_summary">Pointer speed, gestures</string>
+
+    <!-- Title text for 'Tap to click'. [CHAR LIMIT=35] -->
+    <string name="trackpad_tap_to_click">Tap to click</string>
+    <!-- Title text for 'Touchpad gestures' [CHAR LIMIT=35] -->
+    <string name="trackpad_touchpad_gesture_title">Touchpad gestures</string>
+    <!-- Summary text for 'Touchpad gestures' [CHAR LIMIT=60] -->
+    <string name="trackpad_touchpad_gesture_summary">Customize individual touchpad navigation gestures</string>
+    <!-- Title text for 'Reverse scrolling' [CHAR LIMIT=35] -->
+    <string name="trackpad_reverse_scrolling_title">Reverse scrolling</string>
+    <!-- Summary text for 'Reverse scrolling' [CHAR LIMIT=60] -->
+    <string name="trackpad_reverse_scrolling_summary">Content moves up when you scroll down</string>
+    <!-- Title text for 'Bottom-right tap' [CHAR LIMIT=35] -->
+    <string name="trackpad_bottom_right_tap_title">Bottom-right tap</string>
+    <!-- Summary text for 'Bottom-right tap' [CHAR LIMIT=60] -->
+    <string name="trackpad_bottom_right_tap_summary">Tap the bottom right corner of the touchpad for more options</string>
+    <!-- Title text for 'Pointer speed'. [CHAR LIMIT=35] -->
+    <string name="trackpad_pointer_speed">Pointer speed</string>
+    <!-- Title for the button to trigger the 'touch gesture' education. [CHAR LIMIT=35] -->
+    <string name="trackpad_touch_gesture">Learn touchpad gestures</string>
+
+    <!-- Title text for 'Go back' [CHAR LIMIT=35] -->
+    <string name="trackpad_go_back_title">Go back</string>
+    <!-- Summary text for 'Go back' [CHAR LIMIT=60] -->
+    <string name="trackpad_go_back_summary">Swipe left or right with three fingers</string>
+    <!-- Title text for 'Go home' [CHAR LIMIT=35] -->
+    <string name="trackpad_go_home_title">Go home</string>
+    <!-- Summary text for 'Go home' [CHAR LIMIT=60] -->
+    <string name="trackpad_go_home_summary">Swipe up with three fingers</string>
+    <!-- Title text for 'Recent apps' [CHAR LIMIT=35] -->
+    <string name="trackpad_recent_apps_title">Recent apps</string>
+    <!-- Summary text for 'Recent apps' [CHAR LIMIT=60] -->
+    <string name="trackpad_recent_apps_summary">Swipe up with three fingers, then hold</string>
+    <!-- Title text for 'Notifications' [CHAR LIMIT=35] -->
+    <string name="trackpad_notifications_title">Notifications</string>
+    <!-- Summary text for 'Notifications' [CHAR LIMIT=60] -->
+    <string name="trackpad_notifications_summary">Swipe down with three fingers</string>
+    <!-- Title text for 'Switch apps' [CHAR LIMIT=35] -->
+    <string name="trackpad_switch_apps_title">Switch apps</string>
+    <!-- Summary text for 'Switch apps' [CHAR LIMIT=60] -->
+    <string name="trackpad_switch_apps_summary">Swipe left or right with four fingers</string>
+
     <!-- Summary text for keyboards when no layout has been selected. [CHAR LIMIT=35] -->
     <string name="default_keyboard_layout">Default</string>
 
@@ -4952,8 +5005,6 @@
     <string name="battery_not_usage_24hr">No usage for past 24 hr</string>
     <!-- Description for no usage time but have battery usage [CHAR LIMIT=120] -->
     <string name="battery_usage_without_time"></string>
-    <!-- Description for other users aggregated battery usage data [CHAR LIMIT=120] -->
-    <string name="battery_usage_other_users">Other users</string>
 
     <!-- Description for battery time left, i.e. 50min Estimated time left. [CHAR LIMIT=80]-->
     <string name="estimated_time_left">Estimated time left</string>
@@ -6473,6 +6524,10 @@
     <!-- Description for introduction of the cloned apps page [CHAR LIMIT=NONE]-->
     <string name="desc_cloned_apps_intro_text">Create a second instance of an app so that you can use two accounts at the same time.</string>
     <string name="cloned_apps_summary"><xliff:g id="cloned_apps_count">%1$s</xliff:g> cloned, <xliff:g id="allowed_apps_count">%2$d</xliff:g> available to clone</string>
+    <!-- Summary text when an app is being cloned [CHAR LIMIT=40] -->
+    <string name="cloned_app_creation_summary">Creating&#8230;</string>
+    <!-- Summary text after an app is cloned [CHAR LIMIT=40] -->
+    <string name="cloned_app_created_summary">Cloned</string>
     <!-- Summary text for system preference title, showing important setting items under system setting [CHAR LIMIT=NONE]-->
     <string name="system_dashboard_summary">Languages, gestures, time, backup</string>
     <!-- Summary text for language preference title, showing important setting items under language setting [CHAR LIMIT=NONE]-->
@@ -9728,12 +9783,8 @@
     <!-- AutoFill strings -->
     <!-- Preference label for choosing auto-fill service. [CHAR LIMIT=60] -->
     <string name="autofill_app">Autofill service</string>
-    <!-- Preference label for choosing auto-fill service. [CHAR LIMIT=60] -->
-    <string name="default_autofill_app">Default autofill service</string>
     <!-- Preference category for showing auto-fill services with saved passwords. [CHAR LIMIT=60] -->
     <string name="autofill_passwords">Passwords</string>
-    <!-- Preference category for showing credman services with saved credentials. [CHAR LIMIT=60] -->
-    <string name="credman_credentials">Password and identity services</string>
     <!-- Summary for passwords settings that shows how many passwords are saved for each autofill
          service. [CHAR LIMIT=NONE] -->
     <plurals name="autofill_passwords_count">
@@ -9745,8 +9796,6 @@
     <string name="autofill_passwords_count_placeholder" translatable="false">\u2014</string>
     <!-- Keywords for the auto-fill feature. [CHAR LIMIT=NONE] -->
     <string name="autofill_keywords">auto, fill, autofill, password</string>
-    <!-- Keywords for the credman feature. [CHAR LIMIT=NONE] -->
-    <string name="credman_keywords">credentials, passkey, password</string>
 
     <!-- Message of the warning dialog for setting the auto-fill app. [CHAR_LIMIT=NONE] -->
     <string name="autofill_confirmation_message">
@@ -9759,21 +9808,6 @@
         ]]>
     </string>
 
-    <!-- Title of the warning dialog for disabling the credential provider. [CHAR_LIMIT=NONE] -->
-    <string name="credman_confirmation_message_title">Turn off %1$s\?</string>
-
-    <!-- Message of the warning dialog for disabling the credential provider. [CHAR_LIMIT=NONE] -->
-    <string name="credman_confirmation_message">Saved info like addresses or payment methods won\'t be filled in when you sign in. To keep your saved info filled in, set a default autofill service.</string>
-
-    <!-- Title of the error dialog when too many credential providers are selected. [CHAR_LIMIT=NONE] -->
-    <string name="credman_error_message_title">Password and identity services limit</string>
-
-    <!-- Message of the error dialog when too many credential providers are selected. [CHAR_LIMIT=NONE] -->
-    <string name="credman_error_message">You can have up to 5 autofill and password services active at the same time. Turn off a service to add more.</string>
-
-    <!-- Positive button to turn off credential manager provider (confirmation). [CHAR LIMIT=60] -->
-    <string name="credman_confirmation_message_positive_button">Turn off</string>
-
     <!-- Preference category for autofill debugging development settings. [CHAR LIMIT=25] -->
     <string name="debug_autofill_category">Autofill</string>
 
@@ -11388,4 +11422,29 @@
     <!-- [CHAR LIMIT=NONE] Title for preference: Transfer eSIM to another device -->
     <string name="transfer_esim_to_another_device_title">Transfer eSIM to another device</string>
 
+    <!-- Background Install Control UI -->
+    <!-- [CHAR LIMIT=NONE] Preference Feature Summary -->
+    <string name="background_install_preference_summary">{count, plural,
+    =1    {# app}
+    other {# apps}
+    }</string>
+
+    <!-- [CHAR LIMIT=NONE] Feature Title -->
+    <string name="background_install_title">Apps installed in the background</string>
+    <!-- [CHAR LIMIT=NONE] Feature summary -->
+    <string name="background_install_summary">Your device manufacturer may install apps on your device in the background, or allow your carrier and other partners to do so.\u000a\u000aAny apps listed here aren\u0027t required for your device to function normally. You can uninstall apps you don\u0027t want. </string>
+    <!-- [CHAR LIMIT=NONE] Group list no entry -->
+    <string name="background_install_feature_list_no_entry">No apps installed in the background</string>
+    <!-- [CHAR LIMIT=NONE] Uninstall app button content description -->
+    <string name="background_install_uninstall_button_description">Uninstall app</string>
+    <!-- [CHAR LIMIT=NONE] Before time period group list title -->
+    <string name="background_install_before">{count, plural,
+    =1    {Apps installed in the last # month}
+    other {Apps installed in the last # months}
+    }</string>
+    <!-- [CHAR LIMIT=NONE] After time period group list title -->
+    <string name="background_install_after">{count, plural,
+    =1    {Apps installed more than # month ago}
+    other {Apps installed more than # months ago}
+    }</string>
 </resources>
diff --git a/res/xml/accessibility_hearing_aids.xml b/res/xml/accessibility_hearing_aids.xml
new file mode 100644
index 0000000..d5d8df6
--- /dev/null
+++ b/res/xml/accessibility_hearing_aids.xml
@@ -0,0 +1,47 @@
+<?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="accessibility_hearing_devices_screen"
+    android:title="@string/accessibility_hearingaid_title">
+
+    <com.android.settingslib.RestrictedPreference
+        android:key="add_bt_devices"
+        android:title="@string/bluetooth_pairing_pref_title"
+        android:icon="@drawable/ic_add_24dp"
+        android:summary="@string/connected_device_add_device_summary"
+        settings:userRestriction="no_config_bluetooth"
+        settings:useAdminDisabledSummary="true" />
+
+    <PreferenceCategory
+        android:key="device_control_category"
+        android:title="@string/accessibility_hearing_device_control">
+
+        <SwitchPreference
+            android:key="hearing_aid_compatibility"
+            android:title="@string/accessibility_hac_mode_title"
+            android:summary="@string/accessibility_hac_mode_summary"
+            settings:searchable="true" />
+
+    </PreferenceCategory>
+
+    <com.android.settings.accessibility.AccessibilityFooterPreference
+        android:key="hearing_device_footer"
+        android:title="@string/accessibility_hearing_device_footer_summary"
+        android:selectable="false"
+        settings:searchable="false" />
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/accounts_dashboard_settings_credman.xml b/res/xml/accounts_dashboard_settings_credman.xml
deleted file mode 100644
index 605d315..0000000
--- a/res/xml/accounts_dashboard_settings_credman.xml
+++ /dev/null
@@ -1,79 +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.
--->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
-    android:key="user_and_account_settings_screen"
-    android:title="@string/account_dashboard_title"
-    settings:keywords="@string/keywords_accounts">
-
-    <PreferenceCategory
-        android:key="default_service_category"
-        android:order="10"
-        android:title="@string/default_autofill_app">
-
-        <com.android.settings.widget.GearPreference
-            android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
-            android:key="default_autofill_main"
-            android:title="@string/default_autofill_app"
-            settings:keywords="@string/autofill_keywords">
-            <extra
-                android:name="for_work"
-                android:value="false" />
-        </com.android.settings.widget.GearPreference>
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:key="credman_category"
-        android:order="20"
-        android:persistent="false"
-        android:title="@string/credman_credentials"
-        settings:controller="com.android.settings.applications.credentials.CredentialManagerPreferenceController"
-        settings:keywords="@string/credman_keywords" />
-
-    <PreferenceCategory
-        android:key="passwords_category"
-        android:order="30"
-        android:persistent="false"
-        settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
-        settings:keywords="@string/autofill_keywords" />
-
-    <PreferenceCategory
-        android:key="dashboard_tile_placeholder"
-        android:order="130"/>
-
-    <SwitchPreference
-        android:key="auto_sync_account_data"
-        android:title="@string/auto_sync_account_title"
-        android:summary="@string/auto_sync_account_summary"
-        android:order="202"
-        settings:allowDividerAbove="true"/>
-
-    <SwitchPreference
-        android:key="auto_sync_work_account_data"
-        android:title="@string/account_settings_menu_auto_sync_work"
-        android:summary="@string/auto_sync_account_summary"
-        settings:forWork="true"
-        android:order="203"/>
-
-    <SwitchPreference
-        android:key="auto_sync_personal_account_data"
-        android:title="@string/account_settings_menu_auto_sync_personal"
-        android:summary="@string/auto_sync_account_summary"
-        android:order="204"/>
-
-</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/accounts_personal_dashboard_settings_credman.xml b/res/xml/accounts_personal_dashboard_settings_credman.xml
deleted file mode 100644
index a5188dd..0000000
--- a/res/xml/accounts_personal_dashboard_settings_credman.xml
+++ /dev/null
@@ -1,73 +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.
-  -->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
-    android:key="user_and_account_settings_screen"
-    android:title="@string/account_dashboard_title"
-    settings:keywords="@string/keywords_accounts">
-
-    <PreferenceCategory
-        android:key="default_service_category"
-        android:order="10"
-        android:title="@string/default_autofill_app">
-
-        <com.android.settings.widget.GearPreference
-            android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
-            android:key="default_autofill_main"
-            android:title="@string/default_autofill_app"
-            settings:keywords="@string/autofill_keywords">
-            <extra
-                android:name="for_work"
-                android:value="false" />
-        </com.android.settings.widget.GearPreference>
-    </PreferenceCategory>
-
-    <PreferenceCategory
-        android:key="credman_category"
-        android:order="20"
-        android:persistent="false"
-        android:title="@string/credman_credentials"
-        settings:controller="com.android.settings.applications.credentials.CredentialManagerPreferenceController"
-        settings:keywords="@string/credman_keywords" />
-
-    <PreferenceCategory
-        android:key="passwords_category"
-        android:order="30"
-        android:persistent="false"
-        settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
-        settings:keywords="@string/autofill_keywords" />
-
-    <PreferenceCategory
-        android:key="dashboard_tile_placeholder"
-        android:order="130"/>
-
-    <SwitchPreference
-        android:key="auto_sync_account_data"
-        android:title="@string/auto_sync_account_title"
-        android:summary="@string/auto_sync_account_summary"
-        android:order="200"
-        settings:allowDividerAbove="true"/>
-
-    <SwitchPreference
-        android:key="auto_sync_personal_account_data"
-        android:title="@string/account_settings_menu_auto_sync_personal"
-        android:summary="@string/auto_sync_account_summary"
-        android:order="210"/>
-
-</PreferenceScreen>
diff --git a/res/xml/accounts_work_dashboard_settings_credman.xml b/res/xml/accounts_work_dashboard_settings_credman.xml
deleted file mode 100644
index f4e8af2..0000000
--- a/res/xml/accounts_work_dashboard_settings_credman.xml
+++ /dev/null
@@ -1,73 +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.
-  -->
-
-<PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
-    android:key="user_and_account_settings_screen"
-    android:title="@string/account_dashboard_title"
-    settings:keywords="@string/keywords_accounts">
-
-    <com.android.settings.widget.WorkOnlyCategory
-        android:key="autofill_work_app_defaults"
-        android:order="30"
-        android:title="@string/default_autofill_app">
-
-        <com.android.settings.widget.GearPreference
-            android:fragment="com.android.settings.applications.defaultapps.DefaultAutofillPicker"
-            android:key="default_autofill_work"
-            android:title="@string/default_autofill_app"
-            settings:searchable="false">
-            <extra
-                android:name="for_work"
-                android:value="true" />
-        </com.android.settings.widget.GearPreference>
-    </com.android.settings.widget.WorkOnlyCategory>
-
-    <PreferenceCategory
-        android:key="credman_category"
-        android:order="20"
-        android:persistent="false"
-        android:title="@string/credman_credentials"
-        settings:controller="com.android.settings.applications.credentials.CredentialManagerPreferenceController"
-        settings:keywords="@string/credman_keywords" />
-
-    <PreferenceCategory
-        android:key="passwords_category"
-        android:order="30"
-        android:persistent="false"
-        settings:controller="com.android.settings.applications.autofill.PasswordsPreferenceController"
-        settings:keywords="@string/autofill_keywords" />
-
-    <PreferenceCategory
-        android:key="dashboard_tile_placeholder"
-        android:order="130"/>
-
-    <SwitchPreference
-        android:key="auto_sync_account_data"
-        android:title="@string/auto_sync_account_title"
-        android:summary="@string/auto_sync_account_summary"
-        android:order="200"
-        settings:allowDividerAbove="true"/>
-
-    <SwitchPreference
-        android:key="auto_sync_work_account_data"
-        android:title="@string/account_settings_menu_auto_sync_work"
-        android:summary="@string/auto_sync_account_summary"
-        android:order="210"/>
-
-</PreferenceScreen>
diff --git a/res/xml/bluetooth_device_details_fragment.xml b/res/xml/bluetooth_device_details_fragment.xml
index c031960..68b234d 100644
--- a/res/xml/bluetooth_device_details_fragment.xml
+++ b/res/xml/bluetooth_device_details_fragment.xml
@@ -71,7 +71,7 @@
         android:key="device_companion_apps"/>
 
     <PreferenceCategory
-        android:key="spatial_audio_group"/>
+        android:key="feature_controls_group"/>
 
     <PreferenceCategory
         android:key="bluetooth_profiles"/>
diff --git a/res/xml/communal_settings.xml b/res/xml/communal_settings.xml
new file mode 100644
index 0000000..1a7938f
--- /dev/null
+++ b/res/xml/communal_settings.xml
@@ -0,0 +1,20 @@
+<?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="communal_preference_screen"
+    android:title="@string/communal_settings_title" />
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 1b5e6c0..ad5236e 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -146,7 +146,8 @@
             android:key="screensaver"
             android:title="@string/screensaver_settings_title"
             android:fragment="com.android.settings.dream.DreamSettings"
-            settings:keywords="@string/keywords_screensaver"/>
+            settings:keywords="@string/keywords_screensaver"
+            settings:controller="com.android.settings.display.ScreenSaverPreferenceController"/>
 
         <SwitchPreference
             android:key="camera_gesture"
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index 3b24203..1f5559f 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -46,6 +46,15 @@
         settings:controller="com.android.settings.inputmethod.KeyboardPreferenceController"/>
 
     <Preference
+        android:key="trackpad_settings"
+        android:title="@string/trackpad_settings"
+        android:summary="@string/trackpad_settings_summary"
+        android:icon="@drawable/ic_settings_trackpad"
+        android:order="-254"
+        android:fragment="com.android.settings.inputmethod.TrackpadSettings"
+        settings:controller="com.android.settings.inputmethod.TrackpadSettingsController"/>
+
+    <Preference
         android:key="gesture_settings"
         android:title="@string/gesture_preference_title"
         android:icon="@drawable/ic_settings_gestures"
diff --git a/res/xml/top_level_settings.xml b/res/xml/top_level_settings.xml
index 5fbc735..8c82b67 100644
--- a/res/xml/top_level_settings.xml
+++ b/res/xml/top_level_settings.xml
@@ -31,6 +31,16 @@
         settings:controller="com.android.settings.network.TopLevelNetworkEntryPreferenceController"/>
 
     <com.android.settings.widget.HomepagePreference
+        android:fragment="com.android.settings.communal.CommunalDashboardFragment"
+        android:icon="@drawable/ia_settings_communal"
+        android:key="top_level_communal"
+        android:order="-145"
+        android:title="@string/communal_settings_title"
+        android:summary="@string/communal_settings_summary"
+        settings:highlightableMenuKey="@string/menu_key_communal"
+        settings:controller="com.android.settings.communal.CommunalPreferenceController"/>
+
+    <com.android.settings.widget.HomepagePreference
         android:fragment="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"
         android:icon="@drawable/ic_devices_other"
         android:key="top_level_connected_devices"
diff --git a/res/xml/trackpad_gesture_settings.xml b/res/xml/trackpad_gesture_settings.xml
new file mode 100644
index 0000000..dfc4199
--- /dev/null
+++ b/res/xml/trackpad_gesture_settings.xml
@@ -0,0 +1,62 @@
+<?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:title="@string/trackpad_touchpad_gesture_title">
+    <SwitchPreference
+        android:key="gesture_go_back"
+        android:title="@string/trackpad_go_back_title"
+        android:summary="@string/trackpad_go_back_summary"
+        android:icon="@drawable/ic_trackpad_gesture_back"
+        android:order="10"/>
+
+    <SwitchPreference
+        android:key="gesture_go_home"
+        android:title="@string/trackpad_go_home_title"
+        android:summary="@string/trackpad_go_home_summary"
+        android:icon="@drawable/ic_trackpad_gesture_home"
+        android:order="20"/>
+
+    <SwitchPreference
+        android:key="gesture_recent_apps"
+        android:title="@string/trackpad_recent_apps_title"
+        android:summary="@string/trackpad_recent_apps_summary"
+        android:icon="@drawable/ic_trackpad_gesture_recent_apps"
+        android:order="30"/>
+
+    <SwitchPreference
+        android:key="gesture_notifications"
+        android:title="@string/trackpad_notifications_title"
+        android:summary="@string/trackpad_notifications_summary"
+        android:icon="@drawable/ic_trackpad_gesture_notifications"
+        android:order="40"/>
+
+    <SwitchPreference
+        android:key="gesture_switch_apps"
+        android:title="@string/trackpad_switch_apps_title"
+        android:summary="@string/trackpad_switch_apps_summary"
+        android:icon="@drawable/ic_trackpad_gesture_switch_apps"
+        android:order="50"/>
+
+    <com.android.settingslib.widget.ButtonPreference
+        android:key="trackpad_touch_gesture_developer_mode"
+        android:title="@string/trackpad_touch_gesture"
+        android:icon="@drawable/ic_trackpad_touch_gestures_inverse"
+        settings:controller="com.android.settings.inputmethod.TouchGesturesButtonPreferenceController"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/trackpad_settings.xml b/res/xml/trackpad_settings.xml
new file mode 100644
index 0000000..6401fb8
--- /dev/null
+++ b/res/xml/trackpad_settings.xml
@@ -0,0 +1,66 @@
+<?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:title="@string/trackpad_settings">
+    <Preference
+        android:key="trackpad_gesture_settings"
+        android:title="@string/trackpad_touchpad_gesture_title"
+        android:summary="@string/trackpad_touchpad_gesture_summary"
+        android:icon="@drawable/ic_trackpad_touch_gestures_normal"
+        android:order="-10"
+        android:fragment="com.android.settings.inputmethod.TrackpadTouchGestureSettings"
+        settings:controller="com.android.settings.inputmethod.TrackpadTouchGestureSettingsController"/>
+
+    <SwitchPreference
+        android:key="trackpad_tap_to_click"
+        android:title="@string/trackpad_tap_to_click"
+        android:icon="@drawable/ic_trackpad_tap_to_click"
+        android:order="10"/>
+
+    <SwitchPreference
+        android:key="trackpad_reverse_scrolling"
+        android:title="@string/trackpad_reverse_scrolling_title"
+        android:summary="@string/trackpad_reverse_scrolling_summary"
+        android:icon="@drawable/ic_trackpad_reverse_scrolling"
+        android:order="20"/>
+
+    <SwitchPreference
+        android:key="trackpad_bottom_right_tap"
+        android:title="@string/trackpad_bottom_right_tap_title"
+        android:summary="@string/trackpad_bottom_right_tap_summary"
+        android:icon="@drawable/ic_trackpad_reverse_scrolling"
+        android:order="30"/>
+
+    <com.android.settings.widget.SeekBarPreference
+        android:key="trackpad_pointer_speed"
+        android:title="@string/trackpad_pointer_speed"
+        android:icon="@drawable/ic_trackpad_pointer_speed"
+        android:order="40"
+        android:selectable="false"
+        android:max="100"
+        android:min="0"
+        android:defaultValue="50"/>
+
+    <com.android.settingslib.widget.ButtonPreference
+        android:key="trackpad_touch_gesture"
+        android:title="@string/trackpad_touch_gesture"
+        android:icon="@drawable/ic_trackpad_touch_gestures_inverse"
+        settings:controller="com.android.settings.inputmethod.TouchGesturesButtonPreferenceController"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 9a62412..97b9aae 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -24,7 +24,6 @@
 import com.android.settings.display.BrightnessLevelPreferenceController;
 import com.android.settings.display.CameraGesturePreferenceController;
 import com.android.settings.display.LiftToWakePreferenceController;
-import com.android.settings.display.ScreenSaverPreferenceController;
 import com.android.settings.display.ShowOperatorNamePreferenceController;
 import com.android.settings.display.TapToWakePreferenceController;
 import com.android.settings.display.ThemePreferenceController;
@@ -76,7 +75,6 @@
         final List<AbstractPreferenceController> controllers = new ArrayList<>();
         controllers.add(new CameraGesturePreferenceController(context));
         controllers.add(new LiftToWakePreferenceController(context));
-        controllers.add(new ScreenSaverPreferenceController(context));
         controllers.add(new TapToWakePreferenceController(context));
         controllers.add(new VrDisplayPreferenceController(context));
         controllers.add(new ShowOperatorNamePreferenceController(context));
diff --git a/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
index 34289dd..cec48bb 100644
--- a/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
+++ b/src/com/android/settings/accessibility/AccessibilityHearingAidPreferenceController.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.accessibility;
 
-import android.app.settings.SettingsEnums;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHapClient;
@@ -29,6 +28,7 @@
 import android.content.IntentFilter;
 import android.os.Bundle;
 import android.text.TextUtils;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
@@ -129,6 +129,11 @@
     public boolean handlePreferenceTreeClick(Preference preference) {
         if (TextUtils.equals(preference.getKey(), getPreferenceKey())) {
             final CachedBluetoothDevice device = getConnectedHearingAidDevice();
+            if (FeatureFlagUtils.isEnabled(mContext,
+                    FeatureFlagUtils.SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE)) {
+                launchHearingAidPage();
+                return true;
+            }
             if (device == null) {
                 launchHearingAidInstructionDialog();
             } else {
@@ -295,7 +300,7 @@
                 .setDestination(BluetoothDeviceDetailsFragment.class.getName())
                 .setArguments(args)
                 .setTitleRes(R.string.device_details_title)
-                .setSourceMetricsCategory(SettingsEnums.ACCESSIBILITY)
+                .setSourceMetricsCategory(getMetricsCategory())
                 .launch();
     }
 
@@ -304,4 +309,11 @@
         HearingAidDialogFragment fragment = HearingAidDialogFragment.newInstance();
         fragment.show(mFragmentManager, HearingAidDialogFragment.class.toString());
     }
+
+    private void launchHearingAidPage() {
+        new SubSettingLauncher(mContext)
+                .setDestination(AccessibilityHearingAidsFragment.class.getName())
+                .setSourceMetricsCategory(getMetricsCategory())
+                .launch();
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
new file mode 100644
index 0000000..03aea31
--- /dev/null
+++ b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
@@ -0,0 +1,68 @@
+/*
+ * 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 static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+/** Accessibility settings for hearing aids. */
+@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
+public class AccessibilityHearingAidsFragment extends RestrictedDashboardFragment {
+
+    private static final String TAG = "AccessibilityHearingAidsFragment";
+
+    public AccessibilityHearingAidsFragment() {
+        super(DISALLOW_CONFIG_BLUETOOTH);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        // TODO(b/237625815): Add shortcutPreference by extending
+        //  AccessibilityShortcutPreferenceFragment
+
+        return super.onCreateView(inflater, container, savedInstanceState);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        // TODO(b/262839191): To be updated settings_enums.proto
+        return 0;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.accessibility_hearing_aids;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.accessibility_hearing_aids);
+}
diff --git a/src/com/android/settings/accessibility/OWNERS b/src/com/android/settings/accessibility/OWNERS
index a0fe42b..ca4b880 100644
--- a/src/com/android/settings/accessibility/OWNERS
+++ b/src/com/android/settings/accessibility/OWNERS
@@ -1,7 +1,6 @@
 # Default reviewers for this and subdirectories.
+danielnorman@google.com
 menghanli@google.com
-pweaver@google.com
-zork@google.com
 
 per-file HapticFeedbackIntensityPreferenceController.java = michaelwr@google.com
 per-file *Vibration* = michaelwr@google.com
diff --git a/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java b/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
index 51a775e..851797e 100644
--- a/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
+++ b/src/com/android/settings/accessibility/PreviewSizeSeekBarController.java
@@ -48,7 +48,9 @@
 
                     final ProgressInteractionListener interactionListener =
                             mInteractionListener.get();
-                    interactionListener.notifyPreferenceChanged();
+                    // Avoid timing issues to update the corresponding preview fail when clicking
+                    // the increase/decrease button.
+                    seekBar.post(interactionListener::notifyPreferenceChanged);
 
                     if (!mSeekByTouch) {
                         interactionListener.onProgressChanged();
diff --git a/src/com/android/settings/accounts/AccountDashboardFragment.java b/src/com/android/settings/accounts/AccountDashboardFragment.java
index 107df94..3e83d6f 100644
--- a/src/com/android/settings/accounts/AccountDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountDashboardFragment.java
@@ -22,13 +22,11 @@
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.pm.UserInfo;
-import android.credentials.CredentialManager;
 import android.os.UserHandle;
 import android.os.UserManager;
 
 import com.android.settings.R;
 import com.android.settings.applications.autofill.PasswordsPreferenceController;
-import com.android.settings.applications.credentials.CredentialManagerPreferenceController;
 import com.android.settings.applications.defaultapps.DefaultAutofillPreferenceController;
 import com.android.settings.applications.defaultapps.DefaultWorkAutofillPreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
@@ -49,6 +47,7 @@
 
     private static final String TAG = "AccountDashboardFrag";
 
+
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.ACCOUNT;
@@ -61,7 +60,7 @@
 
     @Override
     protected int getPreferenceScreenResId() {
-        return getPreferenceLayoutResId();
+        return R.xml.accounts_dashboard_settings;
     }
 
     @Override
@@ -72,12 +71,6 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        if (CredentialManager.isServiceEnabled()) {
-            CredentialManagerPreferenceController cmpp =
-                    use(CredentialManagerPreferenceController.class);
-            cmpp.setParentFragment(this);
-        }
-
         getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
     }
 
@@ -102,13 +95,11 @@
     }
 
     private static void buildAccountPreferenceControllers(
-            Context context,
-            DashboardFragment parent,
-            String[] authorities,
+            Context context, DashboardFragment parent, String[] authorities,
             List<AbstractPreferenceController> controllers) {
         final AccountPreferenceController accountPrefController =
-                new AccountPreferenceController(
-                        context, parent, authorities, ProfileSelectFragment.ProfileType.ALL);
+                new AccountPreferenceController(context, parent, authorities,
+                        ProfileSelectFragment.ProfileType.ALL);
         if (parent != null) {
             parent.getSettingsLifecycle().addObserver(accountPrefController);
         }
@@ -118,14 +109,8 @@
         controllers.add(new AutoSyncWorkDataPreferenceController(context, parent));
     }
 
-    public static int getPreferenceLayoutResId() {
-        return CredentialManager.isServiceEnabled()
-                ? R.xml.accounts_dashboard_settings_credman
-                : R.xml.accounts_dashboard_settings;
-    }
-
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-            new BaseSearchIndexProvider(getPreferenceLayoutResId()) {
+            new BaseSearchIndexProvider(R.xml.accounts_dashboard_settings) {
 
                 @Override
                 public List<AbstractPreferenceController> createPreferenceControllers(
@@ -139,11 +124,11 @@
 
                 @SuppressWarnings("MissingSuperCall") // TODO: Fix me
                 @Override
-                public List<SearchIndexableRaw> getDynamicRawDataToIndex(
-                        Context context, boolean enabled) {
+                public List<SearchIndexableRaw> getDynamicRawDataToIndex(Context context,
+                        boolean enabled) {
                     final List<SearchIndexableRaw> indexRaws = new ArrayList<>();
-                    final UserManager userManager =
-                            (UserManager) context.getSystemService(Context.USER_SERVICE);
+                    final UserManager userManager = (UserManager) context.getSystemService(
+                            Context.USER_SERVICE);
                     final List<UserInfo> profiles = userManager.getProfiles(UserHandle.myUserId());
                     for (final UserInfo userInfo : profiles) {
                         if (userInfo.isManagedProfile()) {
diff --git a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
index e061102..4661c64 100644
--- a/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountPersonalDashboardFragment.java
@@ -22,11 +22,9 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.credentials.CredentialManager;
 
 import com.android.settings.R;
 import com.android.settings.applications.autofill.PasswordsPreferenceController;
-import com.android.settings.applications.credentials.CredentialManagerPreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.users.AutoSyncDataPreferenceController;
@@ -36,7 +34,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
-/** Account Setting page for personal profile. */
+/**
+ * Account Setting page for personal profile.
+ */
 public class AccountPersonalDashboardFragment extends DashboardFragment {
 
     private static final String TAG = "AccountPersonalFrag";
@@ -53,9 +53,6 @@
 
     @Override
     protected int getPreferenceScreenResId() {
-        if (CredentialManager.isServiceEnabled()) {
-            return R.xml.accounts_personal_dashboard_settings_credman;
-        }
         return R.xml.accounts_personal_dashboard_settings;
     }
 
@@ -67,13 +64,6 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-
-        if (CredentialManager.isServiceEnabled()) {
-            CredentialManagerPreferenceController cmpp =
-                    use(CredentialManagerPreferenceController.class);
-            cmpp.setParentFragment(this);
-        }
-
         getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
     }
 
@@ -87,13 +77,11 @@
     }
 
     private static void buildAccountPreferenceControllers(
-            Context context,
-            DashboardFragment parent,
-            String[] authorities,
+            Context context, DashboardFragment parent, String[] authorities,
             List<AbstractPreferenceController> controllers) {
         final AccountPreferenceController accountPrefController =
-                new AccountPreferenceController(
-                        context, parent, authorities, ProfileSelectFragment.ProfileType.PERSONAL);
+                new AccountPreferenceController(context, parent, authorities,
+                        ProfileSelectFragment.ProfileType.PERSONAL);
         if (parent != null) {
             parent.getSettingsLifecycle().addObserver(accountPrefController);
         }
@@ -103,15 +91,15 @@
     }
 
     // TODO: b/141601408. After featureFlag settings_work_profile is launched, unmark this
-    //    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-    //            new BaseSearchIndexProvider(R.xml.accounts_personal_dashboard_settings) {
-    //
-    //                @Override
-    //                public List<AbstractPreferenceController> createPreferenceControllers(
-    //                        Context context) {
-    //                    ..Add autofill here too..
-    //                    return buildPreferenceControllers(
-    //                            context, null /* parent */, null /* authorities*/);
-    //                }
-    //            };
+//    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+//            new BaseSearchIndexProvider(R.xml.accounts_personal_dashboard_settings) {
+//
+//                @Override
+//                public List<AbstractPreferenceController> createPreferenceControllers(
+//                        Context context) {
+//                    ..Add autofill here too..
+//                    return buildPreferenceControllers(
+//                            context, null /* parent */, null /* authorities*/);
+//                }
+//            };
 }
diff --git a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
index 027d1f7..f64e041 100644
--- a/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
+++ b/src/com/android/settings/accounts/AccountWorkProfileDashboardFragment.java
@@ -22,11 +22,9 @@
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
-import android.credentials.CredentialManager;
 
 import com.android.settings.R;
 import com.android.settings.applications.autofill.PasswordsPreferenceController;
-import com.android.settings.applications.credentials.CredentialManagerPreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
 import com.android.settings.users.AutoSyncDataPreferenceController;
@@ -36,7 +34,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
-/** Account Setting page for work profile. */
+/**
+ * Account Setting page for work profile.
+ */
 public class AccountWorkProfileDashboardFragment extends DashboardFragment {
 
     private static final String TAG = "AccountWorkProfileFrag";
@@ -53,9 +53,6 @@
 
     @Override
     protected int getPreferenceScreenResId() {
-        if (CredentialManager.isServiceEnabled()) {
-            return R.xml.accounts_work_dashboard_settings_credman;
-        }
         return R.xml.accounts_work_dashboard_settings;
     }
 
@@ -67,13 +64,6 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-
-        if (CredentialManager.isServiceEnabled()) {
-            CredentialManagerPreferenceController cmpp =
-                    use(CredentialManagerPreferenceController.class);
-            cmpp.setParentFragment(this);
-        }
-
         getSettingsLifecycle().addObserver(use(PasswordsPreferenceController.class));
     }
 
@@ -87,13 +77,11 @@
     }
 
     private static void buildAccountPreferenceControllers(
-            Context context,
-            DashboardFragment parent,
-            String[] authorities,
+            Context context, DashboardFragment parent, String[] authorities,
             List<AbstractPreferenceController> controllers) {
         final AccountPreferenceController accountPrefController =
-                new AccountPreferenceController(
-                        context, parent, authorities, ProfileSelectFragment.ProfileType.WORK);
+                new AccountPreferenceController(context, parent, authorities,
+                        ProfileSelectFragment.ProfileType.WORK);
         if (parent != null) {
             parent.getSettingsLifecycle().addObserver(accountPrefController);
         }
@@ -103,15 +91,15 @@
     }
 
     // TODO: b/141601408. After featureFlag settings_work_profile is launched, unmark this
-    //    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
-    //            new BaseSearchIndexProvider(R.xml.accounts_work_dashboard_settings) {
-    //
-    //                @Override
-    //                public List<AbstractPreferenceController> createPreferenceControllers(
-    //                        Context context) {
-    //                    ..Add autofill here too..
-    //                    return buildPreferenceControllers(
-    //                            context, null /* parent */, null /* authorities*/);
-    //                }
-    //            };
+//    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+//            new BaseSearchIndexProvider(R.xml.accounts_work_dashboard_settings) {
+//
+//                @Override
+//                public List<AbstractPreferenceController> createPreferenceControllers(
+//                        Context context) {
+//                    ..Add autofill here too..
+//                    return buildPreferenceControllers(
+//                            context, null /* parent */, null /* authorities*/);
+//                }
+//            };
 }
diff --git a/src/com/android/settings/applications/AppStateClonedAppsBridge.java b/src/com/android/settings/applications/AppStateClonedAppsBridge.java
index 7feaa3b..3348079 100644
--- a/src/com/android/settings/applications/AppStateClonedAppsBridge.java
+++ b/src/com/android/settings/applications/AppStateClonedAppsBridge.java
@@ -41,6 +41,7 @@
     private final Context mContext;
     private final List<String> mAllowedApps;
     private List<String> mCloneProfileApps = new ArrayList<>();
+    private int mCloneUserId;
 
     public AppStateClonedAppsBridge(Context context, ApplicationsState appState,
             Callback callback) {
@@ -48,17 +49,17 @@
         mContext = context;
         mAllowedApps = Arrays.asList(mContext.getResources()
                 .getStringArray(com.android.internal.R.array.cloneable_apps));
-
-        int cloneUserId = Utils.getCloneUserId(mContext);
-        if (cloneUserId != -1) {
-            mCloneProfileApps = mContext.getPackageManager()
-                    .getInstalledPackagesAsUser(GET_ACTIVITIES,
-                            cloneUserId).stream().map(x -> x.packageName).toList();
-        }
     }
 
     @Override
     protected void loadAllExtraInfo() {
+        mCloneUserId = Utils.getCloneUserId(mContext);
+        if (mCloneUserId != -1) {
+            mCloneProfileApps = mContext.getPackageManager()
+                    .getInstalledPackagesAsUser(GET_ACTIVITIES,
+                            mCloneUserId).stream().map(x -> x.packageName).toList();
+        }
+
         final List<ApplicationsState.AppEntry> allApps = mAppSession.getAllApps();
         for (int i = 0; i < allApps.size(); i++) {
             ApplicationsState.AppEntry app = allApps.get(i);
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
deleted file mode 100644
index 7abe904..0000000
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * 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.applications.credentials;
-
-import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Dialog;
-import android.app.settings.SettingsEnums;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
-import android.credentials.CredentialManager;
-import android.credentials.ListEnabledProvidersException;
-import android.credentials.ListEnabledProvidersResponse;
-import android.credentials.SetEnabledProvidersException;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.OutcomeReceiver;
-import android.os.UserHandle;
-import android.service.credentials.CredentialProviderInfo;
-import android.util.IconDrawableFactory;
-import android.util.Log;
-
-import androidx.appcompat.app.AlertDialog;
-import androidx.core.content.ContextCompat;
-import androidx.fragment.app.DialogFragment;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.core.BasePreferenceController;
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.dashboard.DashboardFragment;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-
-/** Queries available credential manager providers and adds preferences for them. */
-public class CredentialManagerPreferenceController extends BasePreferenceController
-        implements LifecycleObserver {
-    private static final String TAG = "CredentialManagerPreferenceController";
-    private static final int MAX_SELECTABLE_PROVIDERS = 5;
-
-    private final PackageManager mPm;
-    private final IconDrawableFactory mIconFactory;
-    private final List<ServiceInfo> mServices;
-    private final Set<String> mEnabledPackageNames;
-    private final @Nullable CredentialManager mCredentialManager;
-    private final CancellationSignal mCancellationSignal = new CancellationSignal();
-    private final Executor mExecutor;
-
-    private @Nullable DashboardFragment mParentFragment = null;
-
-    public CredentialManagerPreferenceController(Context context, String preferenceKey) {
-        super(context, preferenceKey);
-        mPm = context.getPackageManager();
-        mIconFactory = IconDrawableFactory.newInstance(mContext);
-        mServices = new ArrayList<>();
-        mEnabledPackageNames = new HashSet<>();
-        mExecutor = ContextCompat.getMainExecutor(mContext);
-        mCredentialManager =
-                getCredentialManager(context, preferenceKey.equals("credentials_test"));
-    }
-
-    private @Nullable CredentialManager getCredentialManager(Context context, boolean isTest) {
-        if (isTest) {
-            return null;
-        }
-
-        Object service = context.getSystemService(Context.CREDENTIAL_SERVICE);
-        if (service != null && CredentialManager.isServiceEnabled()) {
-            return (CredentialManager) service;
-        }
-
-        return null;
-    }
-
-    @VisibleForTesting
-    public boolean isConnected() {
-        return mCredentialManager != null;
-    }
-
-    /**
-     * Sets the parent fragment and attaches this controller to the settings lifecycle.
-     *
-     * @param fragment the fragment to use as the parent
-     */
-    public void setParentFragment(DashboardFragment fragment) {
-        mParentFragment = fragment;
-        fragment.getSettingsLifecycle().addObserver(this);
-    }
-
-    @OnLifecycleEvent(ON_CREATE)
-    void onCreate(LifecycleOwner lifecycleOwner) {
-        if (mCredentialManager == null) {
-            return;
-        }
-
-        mCredentialManager.listEnabledProviders(
-                mCancellationSignal,
-                mExecutor,
-                new OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>() {
-                    @Override
-                    public void onResult(ListEnabledProvidersResponse result) {
-                        Set<String> enabledPackages = new HashSet<>();
-                        for (String flattenedComponentName : result.getProviderComponentNames()) {
-                            ComponentName cn =
-                                    ComponentName.unflattenFromString(flattenedComponentName);
-                            if (cn != null) {
-                                enabledPackages.add(cn.getPackageName());
-                            }
-                        }
-
-                        List<ServiceInfo> services = new ArrayList<>();
-                        for (CredentialProviderInfo cpi :
-                                CredentialProviderInfo.getAvailableServices(mContext, getUser())) {
-                            services.add(cpi.getServiceInfo());
-                        }
-
-                        init(lifecycleOwner, services, enabledPackages);
-                    }
-
-                    @Override
-                    public void onError(ListEnabledProvidersException e) {
-                        Log.e(TAG, "listEnabledProviders error: " + e.toString());
-                    }
-                });
-    }
-
-    @VisibleForTesting
-    void init(
-            LifecycleOwner lifecycleOwner,
-            List<ServiceInfo> availableServices,
-            Set<String> enabledPackages) {
-        mServices.clear();
-        mServices.addAll(availableServices);
-
-        mEnabledPackageNames.clear();
-        mEnabledPackageNames.addAll(enabledPackages);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return mServices.isEmpty() ? CONDITIONALLY_UNAVAILABLE : AVAILABLE;
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-
-        PreferenceGroup group = screen.findPreference(getPreferenceKey());
-        Context context = screen.getContext();
-
-        for (ServiceInfo serviceInfo : mServices) {
-            CharSequence title = "";
-            if (serviceInfo.nonLocalizedLabel != null) {
-                title = serviceInfo.loadLabel(mPm);
-            }
-
-            group.addPreference(
-                    addProviderPreference(
-                            context,
-                            title,
-                            mIconFactory.getBadgedIcon(
-                                    serviceInfo, serviceInfo.applicationInfo, getUser()),
-                            serviceInfo.packageName));
-        }
-    }
-
-    /**
-     * Enables the package name as an enabled credential manager provider.
-     *
-     * @param packageName the package name to enable
-     */
-    @VisibleForTesting
-    public boolean togglePackageNameEnabled(String packageName) {
-        if (mEnabledPackageNames.size() >= MAX_SELECTABLE_PROVIDERS) {
-            return false;
-        } else {
-            mEnabledPackageNames.add(packageName);
-            commitEnabledPackages();
-            return true;
-        }
-    }
-
-    /**
-     * Disables the package name as a credential manager provider.
-     *
-     * @param packageName the package name to disable
-     */
-    @VisibleForTesting
-    public void togglePackageNameDisabled(String packageName) {
-        mEnabledPackageNames.remove(packageName);
-        commitEnabledPackages();
-    }
-
-    /** Returns the enabled credential manager provider package names. */
-    @VisibleForTesting
-    public Set<String> getEnabledProviders() {
-        return mEnabledPackageNames;
-    }
-
-    /**
-     * Returns the enabled credential manager provider flattened component names that can be stored
-     * in the setting.
-     */
-    @VisibleForTesting
-    public List<String> getEnabledSettings() {
-        // Get all the component names that match the enabled package names.
-        List<String> enabledServices = new ArrayList<>();
-        for (ServiceInfo service : mServices) {
-            if (mEnabledPackageNames.contains(service.packageName)) {
-                enabledServices.add(service.getComponentName().flattenToString());
-            }
-        }
-
-        return enabledServices;
-    }
-
-    private SwitchPreference addProviderPreference(
-            @NonNull Context prefContext,
-            @NonNull CharSequence title,
-            @Nullable Drawable icon,
-            @NonNull String packageName) {
-        final SwitchPreference pref = new SwitchPreference(prefContext);
-        pref.setTitle(title);
-        pref.setChecked(mEnabledPackageNames.contains(packageName));
-
-        if (icon != null) {
-            pref.setIcon(Utils.getSafeIcon(icon));
-        }
-
-        pref.setOnPreferenceClickListener(
-                p -> {
-                    boolean isChecked = pref.isChecked();
-
-                    if (isChecked) {
-                        // Show the error if too many enabled.
-                        if (!togglePackageNameEnabled(packageName)) {
-                            final DialogFragment fragment = newErrorDialogFragment();
-
-                            if (fragment == null || mParentFragment == null) {
-                                return true;
-                            }
-
-                            fragment.show(
-                                    mParentFragment.getActivity().getSupportFragmentManager(),
-                                    ErrorDialogFragment.TAG);
-
-                            // The user set the check to true so we need to set it back.
-                            pref.setChecked(false);
-                        }
-
-                        return true;
-                    } else {
-                        // Show the confirm disable dialog.
-                        final DialogFragment fragment =
-                                newConfirmationDialogFragment(packageName, title, pref);
-
-                        if (fragment == null || mParentFragment == null) {
-                            return true;
-                        }
-
-                        fragment.show(
-                                mParentFragment.getActivity().getSupportFragmentManager(),
-                                ConfirmationDialogFragment.TAG);
-                    }
-
-                    return true;
-                });
-
-        return pref;
-    }
-
-    private void commitEnabledPackages() {
-        // Commit using the CredMan API.
-        if (mCredentialManager == null) {
-            return;
-        }
-
-        List<String> enabledServices = getEnabledSettings();
-        mCredentialManager.setEnabledProviders(
-                enabledServices,
-                getUser(),
-                mExecutor,
-                new OutcomeReceiver<Void, SetEnabledProvidersException>() {
-                    @Override
-                    public void onResult(Void result) {
-                        Log.i(TAG, "setEnabledProviders success");
-                    }
-
-                    @Override
-                    public void onError(SetEnabledProvidersException e) {
-                        Log.e(TAG, "setEnabledProviders error: " + e.toString());
-                    }
-                });
-    }
-
-    private @Nullable ConfirmationDialogFragment newConfirmationDialogFragment(
-            @NonNull String packageName,
-            @NonNull CharSequence appName,
-            @NonNull SwitchPreference pref) {
-        DialogHost host =
-                new DialogHost() {
-                    @Override
-                    public DashboardFragment getParentFragment() {
-                        return mParentFragment;
-                    }
-
-                    @Override
-                    public void onDialogClick(int whichButton) {
-                        if (whichButton == DialogInterface.BUTTON_POSITIVE) {
-                            // Since the package is now enabled then we
-                            // should remove it from the enabled list.
-                            togglePackageNameDisabled(packageName);
-                        } else if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
-                            // Set the checked back to true because we
-                            // backed out of turning this off.
-                            pref.setChecked(true);
-                        }
-                    }
-                };
-
-        if (host.getParentFragment() == null) {
-            return null;
-        }
-
-        return new ConfirmationDialogFragment(host, packageName, appName);
-    }
-
-    private @Nullable ErrorDialogFragment newErrorDialogFragment() {
-        DialogHost host =
-                new DialogHost() {
-                    @Override
-                    public DashboardFragment getParentFragment() {
-                        return mParentFragment;
-                    }
-
-                    @Override
-                    public void onDialogClick(int whichButton) {}
-                };
-
-        if (host.getParentFragment() == null) {
-            return null;
-        }
-
-        return new ErrorDialogFragment(host);
-    }
-
-    private int getUser() {
-        UserHandle workUser = getWorkProfileUser();
-        return workUser != null ? workUser.getIdentifier() : UserHandle.myUserId();
-    }
-
-    /** Called when the dialog button is clicked. */
-    private interface DialogHost {
-        void onDialogClick(int whichButton);
-
-        DashboardFragment getParentFragment();
-    }
-
-    /** Dialog fragment parent class. */
-    private abstract static class CredentialManagerDialogFragment extends InstrumentedDialogFragment
-            implements DialogInterface.OnClickListener {
-
-        public static final String TAG = "CredentialManagerDialogFragment";
-        public static final String PACKAGE_NAME_KEY = "package_name";
-        public static final String APP_NAME_KEY = "app_name";
-
-        private DialogHost mDialogHost;
-
-        CredentialManagerDialogFragment(DialogHost dialogHost) {
-            super();
-            setTargetFragment(dialogHost.getParentFragment(), 0);
-            mDialogHost = dialogHost;
-        }
-
-        public DialogHost getDialogHost() {
-            return mDialogHost;
-        }
-
-        @Override
-        public int getMetricsCategory() {
-            return SettingsEnums.ACCOUNT;
-        }
-    }
-
-    /** Dialog showing error when too many providers are selected. */
-    private static class ErrorDialogFragment extends CredentialManagerDialogFragment {
-
-        ErrorDialogFragment(DialogHost dialogHost) {
-            super(dialogHost);
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            return new AlertDialog.Builder(getActivity())
-                    .setTitle(getContext().getString(R.string.credman_error_message_title))
-                    .setMessage(getContext().getString(R.string.credman_error_message))
-                    .setPositiveButton(android.R.string.ok, this)
-                    .create();
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {}
-    }
-
-    /**
-     * Confirmation dialog fragment shows a dialog to the user to confirm that they are disabling a
-     * provider.
-     */
-    private static class ConfirmationDialogFragment extends CredentialManagerDialogFragment {
-
-        ConfirmationDialogFragment(
-                DialogHost dialogHost, @NonNull String packageName, @NonNull CharSequence appName) {
-            super(dialogHost);
-
-            final Bundle argument = new Bundle();
-            argument.putString(PACKAGE_NAME_KEY, packageName);
-            argument.putCharSequence(APP_NAME_KEY, appName);
-            setArguments(argument);
-        }
-
-        @Override
-        public Dialog onCreateDialog(Bundle savedInstanceState) {
-            final Bundle bundle = getArguments();
-            final String title =
-                    getContext()
-                            .getString(
-                                    R.string.credman_confirmation_message_title,
-                                    bundle.getCharSequence(
-                                            CredentialManagerDialogFragment.APP_NAME_KEY));
-
-            return new AlertDialog.Builder(getActivity())
-                    .setTitle(title)
-                    .setMessage(getContext().getString(R.string.credman_confirmation_message))
-                    .setPositiveButton(R.string.credman_confirmation_message_positive_button, this)
-                    .setNegativeButton(android.R.string.cancel, this)
-                    .create();
-        }
-
-        @Override
-        public void onClick(DialogInterface dialog, int which) {
-            getDialogHost().onDialogClick(which);
-        }
-    }
-}
diff --git a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
index f3f4b0f..744ac71 100644
--- a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
+++ b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
@@ -16,28 +16,37 @@
 
 package com.android.settings.applications.manageapplications;
 
+import static com.android.settings.applications.manageapplications.ManageApplications.ApplicationsAdapter;
 import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_CLONED_APPS;
+import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NONE;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
+import android.widget.ProgressBar;
 import android.widget.Switch;
 import android.widget.TextView;
 
 import androidx.annotation.StringRes;
 import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.FragmentActivity;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.ApplicationsState.AppEntry;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
 
 public class ApplicationViewHolder extends RecyclerView.ViewHolder {
 
@@ -51,8 +60,8 @@
     final ViewGroup mWidgetContainer;
     @VisibleForTesting
     final Switch mSwitch;
-
-    private static int sListType;
+    final ImageView mAddIcon;
+    final ProgressBar mProgressBar;
 
     private final ImageView mAppIcon;
 
@@ -64,33 +73,23 @@
         mDisabled = itemView.findViewById(R.id.appendix);
         mSwitch = itemView.findViewById(R.id.switchWidget);
         mWidgetContainer = itemView.findViewById(android.R.id.widget_frame);
+        mAddIcon = itemView.findViewById(R.id.add_preference_widget);
+        mProgressBar = itemView.findViewById(R.id.progressBar_cyclic);
     }
 
     static View newView(ViewGroup parent) {
-        return newView(parent, false /* twoTarget */);
+        return newView(parent, false /* twoTarget */, LIST_TYPE_NONE /* listType */);
     }
 
-    static View newView(ViewGroup parent , boolean twoTarget, int listType, Context context) {
-        sListType = listType;
-        return newView(parent, twoTarget);
-    }
-
-    static View newView(ViewGroup parent, boolean twoTarget) {
+    static View newView(ViewGroup parent, boolean twoTarget, int listType) {
         ViewGroup view = (ViewGroup) LayoutInflater.from(parent.getContext())
                 .inflate(R.layout.preference_app, parent, false);
-        final ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame);
+        ViewGroup widgetFrame = view.findViewById(android.R.id.widget_frame);
         if (twoTarget) {
             if (widgetFrame != null) {
-                if (sListType == LIST_TYPE_CLONED_APPS) {
+                if (listType == LIST_TYPE_CLONED_APPS) {
                     LayoutInflater.from(parent.getContext())
-                            .inflate(R.layout.preference_widget_add, widgetFrame, true);
-                    //todo(b/259022623): Invoke the clone backend flow i.e.
-                    // i) upon onclick of add icon, create new clone profile the first time
-                    // and clone an app.
-                    // ii) Show progress bar while app is being cloned
-                    // iii) And upon onClick of trash icon, delete the cloned app instance
-                    // from clone profile.
-                    // iv) Log metrics
+                            .inflate(R.layout.preference_widget_add_progressbar, widgetFrame, true);
                 } else {
                     LayoutInflater.from(parent.getContext())
                             .inflate(R.layout.preference_widget_primary_switch, widgetFrame, true);
@@ -202,4 +201,72 @@
             mSwitch.setEnabled(enabled);
         }
     }
+
+    void updateAppCloneWidget(Context context, View.OnClickListener onClickListener,
+            AppEntry entry) {
+        if (mAddIcon != null) {
+            if (!entry.isCloned) {
+                mAddIcon.setBackground(context.getDrawable(R.drawable.ic_add_24dp));
+            } else {
+                mAddIcon.setBackground(context.getDrawable(R.drawable.ic_trash_can));
+                setSummary(R.string.cloned_app_created_summary);
+            }
+            mAddIcon.setOnClickListener(onClickListener);
+        }
+    }
+
+    View.OnClickListener appCloneOnClickListener(AppEntry entry,
+            ApplicationsAdapter adapter, FragmentActivity manageApplicationsActivity) {
+        Context context = manageApplicationsActivity.getApplicationContext();
+        return new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                CloneBackend cloneBackend = CloneBackend.getInstance(context);
+                final MetricsFeatureProvider metricsFeatureProvider =
+                        FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+
+                String packageName = entry.info.packageName;
+
+                if (mWidgetContainer != null) {
+                    if (!entry.isCloned) {
+                        metricsFeatureProvider.action(context,
+                                SettingsEnums.ACTION_CREATE_CLONE_APP);
+                        mAddIcon.setVisibility(View.INVISIBLE);
+                        mProgressBar.setVisibility(View.VISIBLE);
+                        setSummary(R.string.cloned_app_creation_summary);
+
+                        // todo(b/262352524): To figure out a way to prevent memory leak
+                        //  without making this static.
+                        new AsyncTask<Void, Void, Integer>(){
+
+                            @Override
+                            protected Integer doInBackground(Void... unused) {
+                                return cloneBackend.installCloneApp(packageName);
+                            }
+
+                            @Override
+                            protected void onPostExecute(Integer res) {
+                                mProgressBar.setVisibility(View.INVISIBLE);
+                                mAddIcon.setVisibility(View.VISIBLE);
+
+                                if (res != CloneBackend.SUCCESS) {
+                                    setSummary(null);
+                                    return;
+                                }
+
+                                // Refresh the page to reflect newly created cloned app.
+                                adapter.rebuild();
+                            }
+                        }.execute();
+
+                    } else if (entry.isCloned) {
+                        metricsFeatureProvider.action(context,
+                                SettingsEnums.ACTION_DELETE_CLONE_APP);
+                        cloneBackend.uninstallClonedApp(packageName, /*allUsers*/ false,
+                                manageApplicationsActivity);
+                    }
+                }
+            }
+        };
+    }
 }
diff --git a/src/com/android/settings/applications/manageapplications/CloneBackend.java b/src/com/android/settings/applications/manageapplications/CloneBackend.java
new file mode 100644
index 0000000..3365b51
--- /dev/null
+++ b/src/com/android/settings/applications/manageapplications/CloneBackend.java
@@ -0,0 +1,163 @@
+/*
+ * 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.applications.manageapplications;
+
+import static android.content.pm.PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_URI;
+import static android.content.pm.PackageManager.INSTALL_REASON_USER;
+import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
+
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
+import android.app.IActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.settings.Utils;
+
+import java.util.HashSet;
+
+/**
+ * Handles clone user creation and clone app install/uninstall.
+ */
+public class CloneBackend {
+
+    public static final String TAG = "CloneBackend";
+    public static final int SUCCESS = 0;
+    private static final int ERROR_CREATING_CLONE_USER = 1;
+    private static final int ERROR_STARTING_CLONE_USER = 2;
+    private static final int ERROR_CLONING_PACKAGE = 3;
+    private static CloneBackend sInstance;
+    private Context mContext;
+    private int mCloneUserId;
+
+    private CloneBackend(Context context) {
+        mContext = context;
+        mCloneUserId = Utils.getCloneUserId(context);
+    }
+
+    /**
+     * @param context
+     * @return a CloneBackend object
+     */
+    public static CloneBackend getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new CloneBackend(context);
+        }
+        return sInstance;
+    }
+
+    /**
+     * Starts activity to uninstall cloned app.
+     *
+     * <p> Invokes {@link com.android.packageinstaller.UninstallerActivity} which then displays the
+     * dialog to the user and handles actual uninstall.
+     */
+    void uninstallClonedApp(String packageName, boolean allUsers, FragmentActivity activity) {
+        // Create new intent to launch Uninstaller activity
+        Uri packageUri = Uri.parse("package:" + packageName);
+        Intent uninstallIntent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri);
+        uninstallIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, allUsers);
+        uninstallIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(mCloneUserId));
+        activity.startActivityForResult(uninstallIntent, 0);
+    }
+
+    /**
+     * Installs another instance of given package in clone user.
+     *
+     * <p> Creates clone user if doesn't exist and starts the new user before installing app.
+     * @param packageName
+     * @return error/success code
+     */
+    int installCloneApp(String packageName) {
+        String userName = "cloneUser";
+        UserHandle cloneUserHandle = null;
+        boolean newlyCreated = false;
+
+        // Create clone user if not already exists.
+        if (mCloneUserId == -1) {
+            UserManager um = mContext.getSystemService(UserManager.class);
+            try {
+                cloneUserHandle = um.createProfile(userName, USER_TYPE_PROFILE_CLONE,
+                        new HashSet<>());
+            } catch (Exception e) {
+                if (ManageApplications.DEBUG) {
+                    Log.e("ankita", "Error occurred creating clone user" + e.getMessage());
+                }
+                return ERROR_CREATING_CLONE_USER;
+            }
+
+            if (cloneUserHandle != null) {
+                mCloneUserId = cloneUserHandle.getIdentifier();
+                newlyCreated = true;
+                if (ManageApplications.DEBUG) {
+                    Log.d(TAG, "Created clone user " + mCloneUserId);
+                }
+            } else {
+                mCloneUserId = -1;
+            }
+        }
+
+        if (mCloneUserId > 0) {
+            // If clone user is newly created for the first time, then start this user.
+            if (newlyCreated) {
+                IActivityManager am = ActivityManagerNative.getDefault();
+                try {
+                    am.startUserInBackground(mCloneUserId);
+                } catch (RemoteException e) {
+                    if (ManageApplications.DEBUG) {
+                        Log.e(TAG, "Error starting clone user " + e.getMessage());
+                    }
+                    return ERROR_STARTING_CLONE_USER;
+                }
+            }
+
+            // Install given app in clone user
+            int res = 0;
+            try {
+                res = AppGlobals.getPackageManager().installExistingPackageAsUser(
+                        packageName, mCloneUserId,
+                        INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, INSTALL_REASON_USER, null);
+            } catch (RemoteException e) {
+                if (ManageApplications.DEBUG) {
+                    Log.e(TAG, "Error installing package" + packageName + " in clone user."
+                            + e.getMessage());
+                }
+                return ERROR_CLONING_PACKAGE;
+            }
+
+            if (res == INSTALL_FAILED_INVALID_URI) {
+                if (ManageApplications.DEBUG) {
+                    Log.e(TAG, "Package " + packageName + " doesn't exist.");
+                }
+                return ERROR_CLONING_PACKAGE;
+            }
+        }
+
+        if (ManageApplications.DEBUG) {
+            Log.i(TAG, "Package " + packageName + " cloned successfully.");
+        }
+        return SUCCESS;
+    }
+}
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index ce92459..e6c174c 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -236,6 +236,7 @@
 
     private Menu mOptionsMenu;
 
+    public static final int LIST_TYPE_NONE = -1;
     public static final int LIST_TYPE_MAIN = 0;
     public static final int LIST_TYPE_NOTIFICATION = 1;
     public static final int LIST_TYPE_STORAGE = 3;
@@ -1324,7 +1325,8 @@
                 view = ApplicationViewHolder.newHeader(parent,
                         R.string.desc_app_locale_selection_supported);
             } else if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
-                view = ApplicationViewHolder.newView(parent, true /* twoTarget */);
+                view = ApplicationViewHolder.newView(parent, true /* twoTarget */,
+                        LIST_TYPE_NOTIFICATION);
             } else if (mManageApplications.mListType == LIST_TYPE_CLONED_APPS
                     && viewType == VIEW_TYPE_APP_HEADER) {
                 view = ApplicationViewHolder.newHeader(parent,
@@ -1332,9 +1334,10 @@
             } else if (mManageApplications.mListType == LIST_TYPE_CLONED_APPS
                     && viewType == VIEW_TYPE_TWO_TARGET) {
                 view = ApplicationViewHolder.newView(
-                        parent, true, LIST_TYPE_CLONED_APPS, mContext);
+                        parent, true, LIST_TYPE_CLONED_APPS);
             } else {
-                view = ApplicationViewHolder.newView(parent, false /* twoTarget */);
+                view = ApplicationViewHolder.newView(parent, false /* twoTarget */,
+                        mManageApplications.mListType);
             }
             return new ApplicationViewHolder(view);
         }
@@ -1781,7 +1784,9 @@
                     }
                     break;
                 case LIST_TYPE_CLONED_APPS:
-                    //todo(b/259022623): Attach onClick listener here.
+                    holder.updateAppCloneWidget(mContext,
+                            holder.appCloneOnClickListener(entry, this,
+                                    mManageApplications.getActivity()), entry);
                     break;
             }
         }
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingController.java b/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingController.java
new file mode 100644
index 0000000..509a9b0
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingController.java
@@ -0,0 +1,80 @@
+/*
+ * 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.bluetooth;
+
+import static com.android.settings.bluetooth.BluetoothDeviceDetailsFragment.FEATURE_AUDIO_ROUTING_ORDER;
+
+import android.content.Context;
+import android.util.FeatureFlagUtils;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * The controller of the audio routing in the bluetooth detail settings.
+ */
+public class BluetoothDetailsAudioRoutingController extends BluetoothDetailsController  {
+
+    private static final String KEY_FEATURE_CONTROLS_GROUP = "feature_controls_group";
+    private static final String KEY_AUDIO_ROUTING = "audio_routing";
+
+    public BluetoothDetailsAudioRoutingController(Context context,
+            PreferenceFragmentCompat fragment, CachedBluetoothDevice device, Lifecycle lifecycle) {
+        super(context, fragment, device, lifecycle);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mCachedDevice.isHearingAidDevice() && FeatureFlagUtils.isEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_AUDIO_ROUTING);
+    }
+
+    @Override
+    protected void init(PreferenceScreen screen) {
+        if (!mCachedDevice.isHearingAidDevice()) {
+            return;
+        }
+
+        final PreferenceCategory prefCategory = screen.findPreference(getPreferenceKey());
+        final Preference pref = createAudioRoutingPreference(prefCategory.getContext());
+        pref.setOrder(FEATURE_AUDIO_ROUTING_ORDER);
+        prefCategory.addPreference(pref);
+    }
+
+    @Override
+    protected void refresh() {}
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_FEATURE_CONTROLS_GROUP;
+    }
+
+    private Preference createAudioRoutingPreference(Context context) {
+        final Preference preference = new Preference(context);
+        preference.setKey(KEY_AUDIO_ROUTING);
+        preference.setTitle(context.getString(R.string.bluetooth_audio_routing_title));
+        preference.setSummary(context.getString(R.string.bluetooth_audio_routing_summary));
+
+        return preference;
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsController.java
new file mode 100644
index 0000000..585a5f9
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsController.java
@@ -0,0 +1,81 @@
+/*
+ * 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.bluetooth;
+
+import static com.android.settings.bluetooth.BluetoothDeviceDetailsFragment.FEATURE_HEARING_DEVICE_CONTROLS_ORDER;
+
+import android.content.Context;
+import android.util.FeatureFlagUtils;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * The controller of the hearing device controls in the bluetooth detail settings.
+ */
+public class BluetoothDetailsHearingDeviceControlsController extends BluetoothDetailsController {
+
+    private static final String KEY_FEATURE_CONTROLS_GROUP = "feature_controls_group";
+    private static final String KEY_HEARING_DEVICE_CONTROLS = "hearing_device_controls";
+
+    public BluetoothDetailsHearingDeviceControlsController(Context context,
+            PreferenceFragmentCompat fragment, CachedBluetoothDevice device, Lifecycle lifecycle) {
+        super(context, fragment, device, lifecycle);
+        lifecycle.addObserver(this);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return mCachedDevice.isHearingAidDevice() && FeatureFlagUtils.isEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE);
+    }
+
+    @Override
+    protected void init(PreferenceScreen screen) {
+        if (!mCachedDevice.isHearingAidDevice()) {
+            return;
+        }
+
+        final PreferenceCategory prefCategory = screen.findPreference(getPreferenceKey());
+        final Preference pref = createHearingDeviceControlsPreference(prefCategory.getContext());
+        pref.setOrder(FEATURE_HEARING_DEVICE_CONTROLS_ORDER);
+        prefCategory.addPreference(pref);
+    }
+
+    @Override
+    protected void refresh() {}
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_FEATURE_CONTROLS_GROUP;
+    }
+
+    private Preference createHearingDeviceControlsPreference(Context context) {
+        final Preference preference = new Preference(context);
+        preference.setKey(KEY_HEARING_DEVICE_CONTROLS);
+        preference.setTitle(context.getString(R.string.bluetooth_device_controls_title));
+        preference.setSummary(context.getString(R.string.bluetooth_device_controls_summary));
+
+        return preference;
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
index 29066b8..b5e4c32 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
@@ -16,6 +16,9 @@
 
 package com.android.settings.bluetooth;
 
+import static com.android.settings.bluetooth.BluetoothDeviceDetailsFragment.FEATURE_HEAD_TRACKING_ORDER;
+import static com.android.settings.bluetooth.BluetoothDeviceDetailsFragment.FEATURE_SPATIAL_AUDIO_ORDER;
+
 import android.content.Context;
 import android.media.AudioDeviceAttributes;
 import android.media.AudioDeviceInfo;
@@ -42,7 +45,7 @@
         implements Preference.OnPreferenceClickListener {
 
     private static final String TAG = "BluetoothSpatialAudioController";
-    private static final String KEY_SPATIAL_AUDIO_GROUP = "spatial_audio_group";
+    private static final String KEY_FEATURE_CONTROLS_GROUP = "feature_controls_group";
     private static final String KEY_SPATIAL_AUDIO = "spatial_audio";
     private static final String KEY_HEAD_TRACKING = "head_tracking";
 
@@ -95,13 +98,12 @@
 
     @Override
     public String getPreferenceKey() {
-        return KEY_SPATIAL_AUDIO_GROUP;
+        return KEY_FEATURE_CONTROLS_GROUP;
     }
 
     @Override
     protected void init(PreferenceScreen screen) {
         mProfilesContainer = screen.findPreference(getPreferenceKey());
-        mProfilesContainer.setLayoutResource(R.layout.preference_bluetooth_profile_category);
         refresh();
     }
 
@@ -110,6 +112,7 @@
         SwitchPreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO);
         if (spatialAudioPref == null) {
             spatialAudioPref = createSpatialAudioPreference(mProfilesContainer.getContext());
+            spatialAudioPref.setOrder(FEATURE_SPATIAL_AUDIO_ORDER);
             mProfilesContainer.addPreference(spatialAudioPref);
         }
 
@@ -120,6 +123,7 @@
         SwitchPreference headTrackingPref = mProfilesContainer.findPreference(KEY_HEAD_TRACKING);
         if (headTrackingPref == null) {
             headTrackingPref = createHeadTrackingPreference(mProfilesContainer.getContext());
+            headTrackingPref.setOrder(FEATURE_HEAD_TRACKING_ORDER);
             mProfilesContainer.addPreference(headTrackingPref);
         }
 
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index f68cc40..4cebbef 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -63,6 +63,11 @@
     public static final String KEY_DEVICE_ADDRESS = "device_address";
     private static final String TAG = "BTDeviceDetailsFrg";
 
+    static final int FEATURE_HEARING_DEVICE_CONTROLS_ORDER = 1;
+    static final int FEATURE_AUDIO_ROUTING_ORDER = 2;
+    static final int FEATURE_SPATIAL_AUDIO_ORDER = 3;
+    static final int FEATURE_HEAD_TRACKING_ORDER = 4;
+
     @VisibleForTesting
     static int EDIT_DEVICE_NAME_ITEM_ID = Menu.FIRST;
 
@@ -312,6 +317,10 @@
                     lifecycle));
             controllers.add(new BluetoothDetailsPairOtherController(context, this, mCachedDevice,
                     lifecycle));
+            controllers.add(new BluetoothDetailsHearingDeviceControlsController(context, this,
+                    mCachedDevice, lifecycle));
+            controllers.add(new BluetoothDetailsAudioRoutingController(context, this, mCachedDevice,
+                    lifecycle));
         }
         return controllers;
     }
diff --git a/src/com/android/settings/communal/CommunalDashboardFragment.java b/src/com/android/settings/communal/CommunalDashboardFragment.java
new file mode 100644
index 0000000..64f87b5
--- /dev/null
+++ b/src/com/android/settings/communal/CommunalDashboardFragment.java
@@ -0,0 +1,44 @@
+/*
+ * 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.communal;
+
+import android.app.settings.SettingsEnums;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+
+/**
+ * Dashboard fragment for the top-level Communal settings.
+ */
+public class CommunalDashboardFragment extends DashboardFragment {
+    private static final String TAG = "CommunalFragment";
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.COMMUNAL_MODE_SETTINGS;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.communal_settings;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+}
diff --git a/src/com/android/settings/communal/CommunalPreferenceController.java b/src/com/android/settings/communal/CommunalPreferenceController.java
new file mode 100644
index 0000000..e16dcc3
--- /dev/null
+++ b/src/com/android/settings/communal/CommunalPreferenceController.java
@@ -0,0 +1,37 @@
+/*
+ * 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.communal;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Controls the top-level Communal settings preference.
+ */
+public class CommunalPreferenceController extends BasePreferenceController {
+    public CommunalPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mContext.getResources().getBoolean(R.bool.config_show_communal_settings)
+                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index e7ca698..db23c43 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -124,6 +124,7 @@
 import com.android.settings.inputmethod.NewKeyboardLayoutEnabledLocalesFragment;
 import com.android.settings.inputmethod.PhysicalKeyboardFragment;
 import com.android.settings.inputmethod.SpellCheckersSettings;
+import com.android.settings.inputmethod.TrackpadSettings;
 import com.android.settings.inputmethod.UserDictionaryList;
 import com.android.settings.inputmethod.UserDictionarySettings;
 import com.android.settings.language.LanguageAndInputSettings;
@@ -217,6 +218,7 @@
             LanguageSettings.class.getName(),
             KeyboardSettings.class.getName(),
             NewKeyboardLayoutEnabledLocalesFragment.class.getName(),
+            TrackpadSettings.class.getName(),
             SpellCheckersSettings.class.getName(),
             UserDictionaryList.class.getName(),
             UserDictionarySettings.class.getName(),
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index a2b1454..565a3e0 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -23,6 +23,7 @@
 import com.android.settings.accounts.AccountDashboardFragment;
 import com.android.settings.accounts.AccountDetailDashboardFragment;
 import com.android.settings.applications.AppDashboardFragment;
+import com.android.settings.communal.CommunalDashboardFragment;
 import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.development.DevelopmentSettingsDashboardFragment;
@@ -126,6 +127,8 @@
                 CategoryKey.CATEGORY_BATTERY_SAVER_SETTINGS);
         PARENT_TO_CATEGORY_KEY_MAP.put(SmartBatterySettings.class.getName(),
                 CategoryKey.CATEGORY_SMART_BATTERY_SETTINGS);
+        PARENT_TO_CATEGORY_KEY_MAP.put(CommunalDashboardFragment.class.getName(),
+                CategoryKey.CATEGORY_COMMUNAL_SETTINGS);
 
         CATEGORY_KEY_TO_PARENT_MAP = new ArrayMap<>(PARENT_TO_CATEGORY_KEY_MAP.size());
 
diff --git a/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java b/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java
index b38f13f..b4d2d22 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/DeviceNameWarningDialog.java
@@ -48,7 +48,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return SettingsEnums.DIALOG_ENABLE_DEVELOPMENT_OPTIONS;
+        return SettingsEnums.DIALOG_DEVICENAME_WARNING;
     }
 
     @Override
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
index 691cbd6..22b38d6 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -109,7 +109,9 @@
 
         final ExecutorService executor = (fragment == null) ? null :
                 Executors.newSingleThreadExecutor();
-        final SlotSimStatus slotSimStatus = new SlotSimStatus(context, executor);
+        androidx.lifecycle.Lifecycle lifecycleObject = (fragment == null) ? null :
+                fragment.getLifecycle();
+        final SlotSimStatus slotSimStatus = new SlotSimStatus(context, executor, lifecycleObject);
 
         controllers.add(new IpAddressPreferenceController(context, lifecycle));
         controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
index 16f04df..00819b5 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
@@ -17,12 +17,14 @@
 package com.android.settings.deviceinfo.simstatus;
 
 import android.content.Context;
+import android.os.UserManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
-import android.os.UserManager;
+import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
+import androidx.lifecycle.Observer;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
@@ -40,16 +42,12 @@
 
     private static final String KEY_PREFERENCE_CATEGORY = "device_detail_category";
 
-    private final SubscriptionManager mSubscriptionManager;
-    private final List<Preference> mPreferenceList = new ArrayList<>();
-
     private Fragment mFragment;
     private SlotSimStatus mSlotSimStatus;
+    private Observer mSimChangeObserver;
 
     public SimStatusPreferenceController(Context context, String prefKey) {
         super(context, prefKey);
-
-        mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
     }
 
     /**
@@ -103,26 +101,36 @@
         // Add additional preferences for each sim in the device
         for (int simSlotNumber = 0; simSlotNumber < mSlotSimStatus.size(); simSlotNumber++) {
             final Preference multiSimPreference = createNewPreference(screen.getContext());
-            multiSimPreference.setCopyingEnabled(true);
             multiSimPreference.setOrder(mSlotSimStatus.getPreferenceOrdering(simSlotNumber));
             multiSimPreference.setKey(mSlotSimStatus.getPreferenceKey(simSlotNumber));
             category.addPreference(multiSimPreference);
-            mPreferenceList.add(multiSimPreference);
         }
     }
 
     @Override
     public void updateState(Preference preference) {
-        for (int simSlotNumber = 0; simSlotNumber < mPreferenceList.size(); simSlotNumber++) {
-            final Preference simStatusPreference = mPreferenceList.get(simSlotNumber);
-            simStatusPreference.setTitle(getPreferenceTitle(simSlotNumber /* sim slot */));
-            simStatusPreference.setSummary(getCarrierName(simSlotNumber /* sim slot */));
+        final int simSlot = getSimSlotIndex();
+        if (mSimChangeObserver == null) {
+            mSimChangeObserver = x -> updateStateBySlot(preference, simSlot);
+            mSlotSimStatus.observe(mFragment.getViewLifecycleOwner(), mSimChangeObserver);
         }
+        updateStateBySlot(preference, simSlot);
+    }
+
+    protected void updateStateBySlot(Preference preference, int simSlot) {
+        SubscriptionInfo subInfo = getSubscriptionInfo(simSlot);
+        preference.setEnabled(subInfo != null);
+        preference.setCopyingEnabled(subInfo != null);
+        preference.setTitle(getPreferenceTitle(simSlot));
+        preference.setSummary(getCarrierName(simSlot));
     }
 
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
-        final int simSlot = mPreferenceList.indexOf(preference);
+        if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+            return false;
+        }
+        final int simSlot = getSimSlotIndex();
         if (simSlot == -1) {
             return false;
         }
@@ -138,16 +146,7 @@
     }
 
     private SubscriptionInfo getSubscriptionInfo(int simSlot) {
-        final List<SubscriptionInfo> subscriptionInfoList =
-                mSubscriptionManager.getActiveSubscriptionInfoList();
-        if (subscriptionInfoList != null) {
-            for (SubscriptionInfo info : subscriptionInfoList) {
-                if (info.getSimSlotIndex() == simSlot) {
-                    return info;
-                }
-            }
-        }
-        return null;
+        return (mSlotSimStatus == null) ? null : mSlotSimStatus.getSubscriptionInfo(simSlot);
     }
 
     private CharSequence getCarrierName(int simSlot) {
diff --git a/src/com/android/settings/deviceinfo/simstatus/SlotSimStatus.java b/src/com/android/settings/deviceinfo/simstatus/SlotSimStatus.java
index 033222a..b3aca97 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SlotSimStatus.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SlotSimStatus.java
@@ -17,24 +17,43 @@
 package com.android.settings.deviceinfo.simstatus;
 
 import android.content.Context;
-import android.telephony.TelephonyManager;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+
+import com.android.settings.network.SubscriptionsChangeListener;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Phaser;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * A class for showing a summary of status of sim slots.
  */
-public class SlotSimStatus {
+public class SlotSimStatus extends LiveData<Long>
+        implements DefaultLifecycleObserver,
+        SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
 
     private static final String TAG = "SlotSimStatus";
 
     private final AtomicInteger mNumberOfSlots = new AtomicInteger(0);
+    private final ConcurrentHashMap<Integer, SubscriptionInfo> mSubscriptionMap =
+            new ConcurrentHashMap<Integer, SubscriptionInfo>();
     private final Phaser mBlocker = new Phaser(1);
+    private final AtomicLong mDataVersion = new AtomicLong(0);
+
+    private Context mContext;
     private int mBasePreferenceOrdering;
+    private SubscriptionsChangeListener mSubscriptionsChangeListener;
 
     private static final String KEY_SIM_STATUS = "sim_status";
 
@@ -43,28 +62,71 @@
      * @param context Context
      */
     public SlotSimStatus(Context context) {
-        this(context, null);
+        this(context, null, null);
     }
 
     /**
      * Construct of class.
      * @param context Context
      * @param executor executor for offload to thread
+     * @param lifecycle Lifecycle
      */
-    public SlotSimStatus(Context context, Executor executor) {
+    public SlotSimStatus(Context context, Executor executor, Lifecycle lifecycle) {
+        mContext = context;
         if (executor == null) {
             queryRecords(context);
         } else {
-            executor.execute(() -> queryRecords(context));
+            executor.execute(() -> asyncQueryRecords(context));
+        }
+        if (lifecycle != null) {
+            lifecycle.addObserver(this);
+            mSubscriptionsChangeListener = new SubscriptionsChangeListener(context, this);
+            mSubscriptionsChangeListener.start();
         }
     }
 
     protected void queryRecords(Context context) {
+        queryDetails(context);
+        setValue(mDataVersion.incrementAndGet());
+        mBlocker.arrive();
+    }
+
+    protected void asyncQueryRecords(Context context) {
+        queryDetails(context);
+        postValue(mDataVersion.incrementAndGet());
+        mBlocker.arrive();
+    }
+
+    protected void updateRecords() {
+        queryDetails(mContext);
+        setValue(mDataVersion.incrementAndGet());
+    }
+
+    protected void queryDetails(Context context) {
         TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
         if (telMgr != null) {
             mNumberOfSlots.set(telMgr.getPhoneCount());
         }
-        mBlocker.arrive();
+
+        SubscriptionManager subMgr = context.getSystemService(SubscriptionManager.class);
+        if (subMgr == null) {
+            mSubscriptionMap.clear();
+            return;
+        }
+
+        List<SubscriptionInfo> subInfoList = subMgr.getActiveSubscriptionInfoList();
+        if ((subInfoList == null) || (subInfoList.size() <= 0)) {
+            mSubscriptionMap.clear();
+            Log.d(TAG, "No active SIM.");
+            return;
+        }
+
+        mSubscriptionMap.clear();
+        subInfoList.forEach(subInfo -> {
+            int slotIndex = subInfo.getSimSlotIndex();
+            mSubscriptionMap.put(slotIndex, subInfo);
+        });
+        Log.d(TAG, "Number of active SIM: " + subInfoList.size());
     }
 
     protected void waitForResult() {
@@ -110,6 +172,19 @@
     }
 
     /**
+     * Get subscription based on slot index.
+     * @param slotIndex index of slot (starting from 0)
+     * @return SubscriptionInfo based on index of slot.
+     *         {@code null} means no subscription on slot.
+     */
+    public SubscriptionInfo getSubscriptionInfo(int slotIndex) {
+        if (slotIndex >= size()) {
+            return null;
+        }
+        return mSubscriptionMap.get(slotIndex);
+    }
+
+    /**
      * Get slot index based on Preference key
      * @param prefKey is the preference key
      * @return slot index.
@@ -124,4 +199,28 @@
         }
         return simSlotIndex - 1;
     }
+
+    @Override
+    public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
+        if (airplaneModeEnabled) {
+            /**
+             * Only perform update when airplane mode ON.
+             * Relay on #onSubscriptionsChanged() when airplane mode OFF.
+             */
+            updateRecords();
+        }
+    }
+
+    @Override
+    public void onSubscriptionsChanged() {
+        updateRecords();
+    }
+
+    @Override
+    public void onDestroy(LifecycleOwner lifecycleOwner) {
+        if (mSubscriptionsChangeListener != null) {
+            mSubscriptionsChangeListener.stop();
+        }
+        lifecycleOwner.getLifecycle().removeObserver(this);
+    }
 }
diff --git a/src/com/android/settings/display/ScreenResolutionFragment.java b/src/com/android/settings/display/ScreenResolutionFragment.java
index b42dbe2..665f6b0 100644
--- a/src/com/android/settings/display/ScreenResolutionFragment.java
+++ b/src/com/android/settings/display/ScreenResolutionFragment.java
@@ -28,6 +28,7 @@
 import android.hardware.display.DisplayManager;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Log;
 import android.view.Display;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -36,6 +37,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
+import com.android.settings.core.instrumentation.SettingsStatsLog;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.RadioButtonPickerFragment;
 import com.android.settingslib.display.DisplayDensityUtils;
@@ -167,14 +169,26 @@
         mDisplayObserver.startObserve();
 
         /** For store settings globally. */
-        /** TODO(b/238061217): Moving to an atom with the same string */
+        /** TODO(b/259797244): Remove this once the atom is fully populated. */
         Settings.System.putString(
                 getContext().getContentResolver(),
                 SCREEN_RESOLUTION,
                 mode.getPhysicalWidth() + "x" + mode.getPhysicalHeight());
 
-        /** Apply the resolution change. */
-        mDefaultDisplay.setUserPreferredDisplayMode(mode);
+        try {
+            /** Apply the resolution change. */
+            mDefaultDisplay.setUserPreferredDisplayMode(mode);
+        } catch (Exception e) {
+            Log.e(TAG, "setUserPreferredDisplayMode() failed", e);
+            return;
+        }
+
+        /** Send the atom after resolution changed successfully. */
+        SettingsStatsLog.write(
+                SettingsStatsLog.USER_SELECTED_RESOLUTION,
+                mDefaultDisplay.getUniqueId().hashCode(),
+                mode.getPhysicalWidth(),
+                mode.getPhysicalHeight());
     }
 
     /** Get the key corresponding to the resolution. */
diff --git a/src/com/android/settings/display/ScreenSaverPreferenceController.java b/src/com/android/settings/display/ScreenSaverPreferenceController.java
index d6fef11..db4bc37 100644
--- a/src/com/android/settings/display/ScreenSaverPreferenceController.java
+++ b/src/com/android/settings/display/ScreenSaverPreferenceController.java
@@ -16,47 +16,41 @@
 import android.content.Context;
 import android.os.UserManager;
 
-import androidx.preference.Preference;
-
 import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.PreferenceControllerMixin;
 import com.android.settings.dream.DreamSettings;
-import com.android.settingslib.core.AbstractPreferenceController;
 
-public class ScreenSaverPreferenceController extends AbstractPreferenceController implements
+public class ScreenSaverPreferenceController extends BasePreferenceController implements
         PreferenceControllerMixin {
 
-    private static final String KEY_SCREEN_SAVER = "screensaver";
     private final boolean mDreamsDisabledByAmbientModeSuppression;
 
-    public ScreenSaverPreferenceController(Context context) {
-        super(context);
+    public ScreenSaverPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+
         mDreamsDisabledByAmbientModeSuppression = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
     }
 
     @Override
-    public boolean isAvailable() {
+    public int getAvailabilityStatus() {
         final boolean dreamsSupported = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_dreamsSupported);
         final boolean dreamsOnlyEnabledForDockUser = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_dreamsOnlyEnabledForDockUser);
         // TODO(b/257333623): Allow the Dock User to be non-SystemUser user in HSUM.
-        return dreamsSupported && (!dreamsOnlyEnabledForDockUser || isSystemUser());
+        return (dreamsSupported && (!dreamsOnlyEnabledForDockUser || isSystemUser()))
+                ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
-    public String getPreferenceKey() {
-        return KEY_SCREEN_SAVER;
-    }
-
-    @Override
-    public void updateState(Preference preference) {
+    public CharSequence getSummary() {
         if (mDreamsDisabledByAmbientModeSuppression
                 && AmbientDisplayAlwaysOnPreferenceController.isAodSuppressedByBedtime(mContext)) {
-            preference.setSummary(R.string.screensaver_settings_when_to_dream_bedtime);
+            return mContext.getString(R.string.screensaver_settings_when_to_dream_bedtime);
         } else {
-            preference.setSummary(DreamSettings.getSummaryTextWithDreamName(mContext));
+            return DreamSettings.getSummaryTextWithDreamName(mContext);
         }
     }
 
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 8bf5e16..7b44fd3 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -74,8 +74,6 @@
     public static final int UID_REMOVED_APPS = -4;
     /** Special UID value for data usage by tethering. */
     public static final int UID_TETHERING = -5;
-    /** Special UID for aggregated other users. */
-    public static final long UID_OTHER_USERS = Long.MIN_VALUE;
 
     /** Flag to check if the dock defender mode has been temporarily bypassed */
     public static final String SETTINGS_GLOBAL_DOCK_DEFENDER_BYPASS = "dock_defender_bypass";
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index c2eab57..b048dbc 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -209,7 +209,7 @@
         // Ensure the battery chart group is visible for users.
         animateBatteryChartViewGroup();
         final BatteryLevelData batteryLevelData =
-                DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
+                DataProcessManager.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
                         batteryUsageMap -> {
                             mBatteryUsageMap = batteryUsageMap;
                             refreshUi();
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
index 496200e..893ca4c 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
@@ -129,9 +129,6 @@
 
     /** Gets the app label name for this entry. */
     public String getAppLabel() {
-        if (isOtherUsers()) {
-            return mContext.getString(R.string.battery_usage_other_users);
-        }
         loadLabelAndIcon();
         // Returns default applicationn label if we cannot find it.
         return mAppLabel == null || mAppLabel.length() == 0
@@ -141,9 +138,6 @@
 
     /** Gets the app icon {@link Drawable} for this entry. */
     public Drawable getAppIcon() {
-        if (isOtherUsers()) {
-            return mContext.getDrawable(R.drawable.ic_power_system);
-        }
         loadLabelAndIcon();
         return mAppIcon != null && mAppIcon.getConstantState() != null
                 ? mAppIcon.getConstantState().newDrawable()
@@ -178,9 +172,6 @@
 
     /** Whether the current BatteryDiffEntry is system component or not. */
     public boolean isSystemEntry() {
-        if (isOtherUsers()) {
-            return true;
-        }
         switch (mBatteryHistEntry.mConsumerType) {
             case ConvertUtils.CONSUMER_TYPE_USER_BATTERY:
             case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY:
@@ -200,11 +191,6 @@
         return false;
     }
 
-    private boolean isOtherUsers() {
-        return mBatteryHistEntry.mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY
-                && mBatteryHistEntry.mUid == BatteryUtils.UID_OTHER_USERS;
-    }
-
     void loadLabelAndIcon() {
         if (mIsLoaded) {
             return;
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProvider.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProvider.java
index 4abcdc3..42937e5 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProvider.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProvider.java
@@ -37,6 +37,9 @@
 
 import java.time.Clock;
 import java.time.Duration;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
 
 /** {@link ContentProvider} class to fetch battery usage data. */
 public class BatteryUsageContentProvider extends ContentProvider {
@@ -100,6 +103,8 @@
         switch (sUriMatcher.match(uri)) {
             case BATTERY_STATE_CODE:
                 return getBatteryStates(uri);
+            case APP_USAGE_EVENT_CODE:
+                return getAppUsageEvents(uri);
             case APP_USAGE_LATEST_TIMESTAMP_CODE:
                 return getAppUsageLatestTimestamp(uri);
             default:
@@ -153,8 +158,7 @@
     }
 
     private Cursor getBatteryStates(Uri uri) {
-        final long defaultTimestamp = mClock.millis() - QUERY_DURATION_HOURS.toMillis();
-        final long queryTimestamp = getQueryTimestamp(uri, defaultTimestamp);
+        final long queryTimestamp = getQueryTimestamp(uri);
         return getBatteryStates(uri, queryTimestamp);
     }
 
@@ -171,6 +175,24 @@
         return cursor;
     }
 
+    private Cursor getAppUsageEvents(Uri uri) {
+        final List<Long> queryUserIds = getQueryUserIds(uri);
+        if (queryUserIds == null || queryUserIds.isEmpty()) {
+            return null;
+        }
+        final long queryTimestamp = getQueryTimestamp(uri);
+        final long timestamp = mClock.millis();
+        Cursor cursor = null;
+        try {
+            cursor = mAppUsageEventDao.getAllForUsersAfter(queryUserIds, queryTimestamp);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "query() from:" + uri + " error:" + e);
+        }
+        Log.w(TAG, "query app usage events in " + (mClock.millis() - timestamp) + "/ms");
+        return cursor;
+
+    }
+
     private Cursor getAppUsageLatestTimestamp(Uri uri) {
         final long queryUserId = getQueryUserId(uri);
         if (queryUserId == DatabaseUtils.INVALID_USER_ID) {
@@ -189,6 +211,26 @@
     }
 
     // If URI contains query parameter QUERY_KEY_USERID, use the value directly.
+    // Otherwise, return null.
+    private List<Long> getQueryUserIds(Uri uri) {
+        Log.d(TAG, "getQueryUserIds from uri: " + uri);
+        final String value = uri.getQueryParameter(DatabaseUtils.QUERY_KEY_USERID);
+        if (TextUtils.isEmpty(value)) {
+            Log.w(TAG, "empty query value");
+            return null;
+        }
+        try {
+            return Arrays.asList(value.split(","))
+                    .stream()
+                    .map(s -> Long.parseLong(s.trim()))
+                    .collect(Collectors.toList());
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "invalid query value: " + value, e);
+            return null;
+        }
+    }
+
+    // If URI contains query parameter QUERY_KEY_USERID, use the value directly.
     // Otherwise, return INVALID_USER_ID.
     private long getQueryUserId(Uri uri) {
         Log.d(TAG, "getQueryUserId from uri: " + uri);
@@ -198,8 +240,9 @@
 
     // If URI contains query parameter QUERY_KEY_TIMESTAMP, use the value directly.
     // Otherwise, load the data for QUERY_DURATION_HOURS by default.
-    private long getQueryTimestamp(Uri uri, long defaultTimestamp) {
+    private long getQueryTimestamp(Uri uri) {
         Log.d(TAG, "getQueryTimestamp from uri: " + uri);
+        final long defaultTimestamp = mClock.millis() - QUERY_DURATION_HOURS.toMillis();
         return getQueryValueFromUri(uri, DatabaseUtils.QUERY_KEY_TIMESTAMP, defaultTimestamp);
     }
 
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
index 38879d9..c1b7818 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
@@ -17,7 +17,9 @@
 
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents.Event;
+import android.app.usage.UsageStatsManager;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -25,7 +27,9 @@
 import android.os.BatteryUsageStats;
 import android.os.Build;
 import android.os.LocaleList;
+import android.os.RemoteException;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.util.Base64;
 import android.util.Log;
@@ -167,8 +171,10 @@
     /** Converts to {@link AppUsageEvent} from {@link Event} */
     @Nullable
     public static AppUsageEvent convertToAppUsageEvent(
-            Context context, final Event event, final long userId) {
-        if (event.getPackageName() == null) {
+            Context context, final IUsageStatsManager usageStatsManager, final Event event,
+            final long userId) {
+        final String packageName = event.getPackageName();
+        if (packageName == null) {
             // See b/190609174: Event package names should never be null, but sometimes they are.
             // Note that system events like device shutting down should still come with the android
             // package name.
@@ -182,13 +188,20 @@
         appUsageEventBuilder
                 .setTimestamp(event.getTimeStamp())
                 .setType(getAppUsageEventType(event.getEventType()))
-                .setPackageName(event.getPackageName())
+                .setPackageName(packageName)
                 .setUserId(userId);
 
+        final String taskRootPackageName = getTaskRootPackageName(event);
+        if (taskRootPackageName != null) {
+            appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
+        }
+
+        final String effectivePackageName =
+                getEffectivePackageName(usageStatsManager, packageName, taskRootPackageName);
         try {
             final long uid = context
                     .getPackageManager()
-                    .getPackageUidAsUser(event.getPackageName(), (int) userId);
+                    .getPackageUidAsUser(effectivePackageName, (int) userId);
             appUsageEventBuilder.setUid(uid);
         } catch (PackageManager.NameNotFoundException e) {
             Log.w(TAG, String.format(
@@ -201,14 +214,29 @@
         } catch (NoClassDefFoundError | NoSuchMethodError e) {
             Log.w(TAG, "UsageEvent instance ID API error");
         }
-        String taskRootPackageName = getTaskRootPackageName(event);
-        if (taskRootPackageName != null) {
-            appUsageEventBuilder.setTaskRootPackageName(taskRootPackageName);
-        }
 
         return appUsageEventBuilder.build();
     }
 
+    /** Converts to {@link AppUsageEvent} from {@link Cursor} */
+    public static AppUsageEvent convertToAppUsageEventFromCursor(final Cursor cursor) {
+        final AppUsageEvent.Builder eventBuilder = AppUsageEvent.newBuilder();
+        eventBuilder.setTimestamp(getLongFromCursor(cursor, AppUsageEventEntity.KEY_TIMESTAMP));
+        eventBuilder.setType(
+                AppUsageEventType.forNumber(
+                        getIntegerFromCursor(
+                                cursor, AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE)));
+        eventBuilder.setPackageName(
+                getStringFromCursor(cursor, AppUsageEventEntity.KEY_PACKAGE_NAME));
+        eventBuilder.setInstanceId(
+                getIntegerFromCursor(cursor, AppUsageEventEntity.KEY_INSTANCE_ID));
+        eventBuilder.setTaskRootPackageName(
+                getStringFromCursor(cursor, AppUsageEventEntity.KEY_TASK_ROOT_PACKAGE_NAME));
+        eventBuilder.setUserId(getLongFromCursor(cursor, AppUsageEventEntity.KEY_USER_ID));
+        eventBuilder.setUid(getLongFromCursor(cursor, AppUsageEventEntity.KEY_UID));
+        return eventBuilder.build();
+    }
+
     /** Converts UTC timestamp to human readable local time string. */
     public static String utcToLocalTime(Context context, long timestamp) {
         final Locale locale = getLocale(context);
@@ -249,6 +277,35 @@
     }
 
     /**
+     * Returns the package name the app usage should be attributed to.
+     *
+     * <ul>
+     *   <li>If {@link UsageStatsManager#getUsageSource()} returns {@link
+     *       UsageStatsManager#USAGE_SOURCE_CURRENT_ACTIVITY}, this method will return packageName.
+     *   <li>If {@link UsageStatsManager#getUsageSource()} returns {@link
+     *       UsageStatsManager#USAGE_SOURCE_TASK_ROOT_ACTIVITY}, this method will return
+     *       taskRootPackageName if it exists, or packageName otherwise.
+     * </ul>
+     */
+    @VisibleForTesting
+    static String getEffectivePackageName(
+            final IUsageStatsManager usageStatsManager, final String packageName,
+            final String taskRootPackageName) {
+        int usageSource = getUsageSource(usageStatsManager);
+        switch (usageSource) {
+            case UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+                return !TextUtils.isEmpty(taskRootPackageName)
+                        ? taskRootPackageName
+                        : packageName;
+            case UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY:
+                return packageName;
+            default:
+                Log.e(TAG, "Unexpected usage source: " + usageSource);
+                return packageName;
+        }
+    }
+
+    /**
      * Returns the package name of the task root when this event was reported when {@code event} is
      * one of:
      *
@@ -279,6 +336,20 @@
         }
     }
 
+    /**
+     * Returns what App Usage Observers will consider the source of usage for an activity.
+     *
+     * @see UsageStatsManager#getUsageSource()
+     */
+    private static int getUsageSource(final IUsageStatsManager usageStatsManager) {
+        try {
+            return usageStatsManager.getUsageSource();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to getUsageSource", e);
+            return UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
+        }
+    }
+
     private static AppUsageEventType getAppUsageEventType(final int eventType) {
         switch (eventType) {
             case Event.ACTIVITY_RESUMED:
@@ -331,4 +402,28 @@
 
         return batteryInformationBuilder.build();
     }
+
+    private static int getIntegerFromCursor(final Cursor cursor, final String key) {
+        final int columnIndex = cursor.getColumnIndex(key);
+        if (columnIndex >= 0) {
+            return cursor.getInt(columnIndex);
+        }
+        return 0;
+    }
+
+    private static long getLongFromCursor(final Cursor cursor, final String key) {
+        final int columnIndex = cursor.getColumnIndex(key);
+        if (columnIndex >= 0) {
+            return cursor.getLong(columnIndex);
+        }
+        return 0L;
+    }
+
+    private static String getStringFromCursor(final Cursor cursor, final String key) {
+        final int columnIndex = cursor.getColumnIndex(key);
+        if (columnIndex >= 0) {
+            return cursor.getString(columnIndex);
+        }
+        return "";
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
index 350bbce..dd6b9d9 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessManager.java
@@ -20,14 +20,20 @@
 import android.content.Context;
 import android.os.AsyncTask;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.Utils;
 
 import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -35,7 +41,7 @@
 /**
  * Manages the async tasks to process battery and app usage data.
  *
- * For now, there exist 3 async tasks in this manager:
+ * For now, there exist 4 async tasks in this manager:
  * <ul>
  *  <li>loadCurrentBatteryHistoryMap: load the latest battery history data from battery stats
  *  service.</li>
@@ -43,9 +49,11 @@
  *  from usage stats service.</li>
  *  <li>loadDatabaseAppUsageList: load the necessary app usage data (after last full charge) from
  *  database</li>
+ *  <li>loadAndApplyBatteryMapFromServiceOnly: load all the battery history data (should be after
+ *  last full charge) from battery stats service and apply the callback function directly</li>
  * </ul>
  *
- * The 3 async tasks will be started at the same time.
+ * If there is battery level data, the first 3 async tasks will be started at the same time.
  * <ul>
  *  <li>After loadCurrentAppUsageList and loadDatabaseAppUsageList complete, which means all app
  *  usage data has been loaded, the intermediate usage result will be generated.</li>
@@ -55,6 +63,9 @@
  *  <li>If current user is locked, which means we couldn't get the latest app usage data,
  *  screen-on time will not be shown in the UI and empty screen-on time data will be returned.</li>
  * </ul>
+ *
+ * If there is no battery level data, the 4th async task will be started only and the usage map
+ * callback function will be applied directly to show the app list on the UI.
  */
 public class DataProcessManager {
     private static final String TAG = "DataProcessManager";
@@ -63,43 +74,92 @@
     private final DataProcessor.UsageMapAsyncResponse mCallbackFunction;
 
     private Context mContext;
+    private UserManager mUserManager;
     private List<BatteryLevelData.PeriodBatteryLevelData> mHourlyBatteryLevelsPerDay;
     private Map<Long, Map<String, BatteryHistEntry>> mBatteryHistoryMap;
 
+    // The start timestamp of battery level data. As we don't know when is the full charge cycle
+    // start time when loading app usage data, this value is used as the start time of querying app
+    // usage data.
+    private long mStartTimestampOfLevelData;
+
     private boolean mIsCurrentBatteryHistoryLoaded = false;
     private boolean mIsCurrentAppUsageLoaded = false;
     private boolean mIsDatabaseAppUsageLoaded = false;
     // Used to identify whether screen-on time data should be shown in the UI.
     private boolean mShowScreenOnTime = true;
+    // Used to identify whether battery level data should be shown in the UI.
+    private boolean mShowBatteryLevel = true;
 
     private List<AppUsageEvent> mAppUsageEventList = new ArrayList<>();
 
     /**
-     * Constructor when this exists battery level data.
+     * Constructor when there exists battery level data.
      */
     DataProcessManager(
             Context context,
             Handler handler,
-            final DataProcessor.UsageMapAsyncResponse callbackFunction,
-            final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
-            final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
+            @NonNull final DataProcessor.UsageMapAsyncResponse callbackFunction,
+            @NonNull final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay,
+            @NonNull final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
         mContext = context.getApplicationContext();
         mHandler = handler;
+        mUserManager = mContext.getSystemService(UserManager.class);
         mCallbackFunction = callbackFunction;
         mHourlyBatteryLevelsPerDay = hourlyBatteryLevelsPerDay;
         mBatteryHistoryMap = batteryHistoryMap;
+        mStartTimestampOfLevelData = getStartTimestampOfBatteryLevelData();
+    }
+
+    /**
+     * Constructor when there is no battery level data.
+     */
+    DataProcessManager(
+            Context context,
+            Handler handler,
+            @NonNull final DataProcessor.UsageMapAsyncResponse callbackFunction) {
+        mContext = context.getApplicationContext();
+        mHandler = handler;
+        mUserManager = mContext.getSystemService(UserManager.class);
+        mCallbackFunction = callbackFunction;
+        // When there is no battery level data, don't show screen-on time and battery level chart on
+        // the UI.
+        mShowScreenOnTime = false;
+        mShowBatteryLevel = false;
     }
 
     /**
      * Starts the async tasks to load battery history data and app usage data.
      */
     public void start() {
-        // Load the latest battery history data from the service.
-        loadCurrentBatteryHistoryMap();
-        // Load app usage list from database.
-        loadDatabaseAppUsageList();
-        // Load the latest app usage list from the service.
-        loadCurrentAppUsageList();
+        // If we have battery level data, load the battery history map and app usage simultaneously.
+        if (mShowBatteryLevel) {
+            // Loads the latest battery history data from the service.
+            loadCurrentBatteryHistoryMap();
+            // Loads app usage list from database.
+            loadDatabaseAppUsageList();
+            // Loads the latest app usage list from the service.
+            loadCurrentAppUsageList();
+        } else {
+            // If there is no battery level data, only load the battery history data from service
+            // and show it as the app list directly.
+            loadAndApplyBatteryMapFromServiceOnly();
+        }
+    }
+
+    @VisibleForTesting
+    long getStartTimestampOfBatteryLevelData() {
+        for (int dailyIndex = 0; dailyIndex < mHourlyBatteryLevelsPerDay.size(); dailyIndex++) {
+            if (mHourlyBatteryLevelsPerDay.get(dailyIndex) == null) {
+                continue;
+            }
+            final List<Long> timestamps =
+                    mHourlyBatteryLevelsPerDay.get(dailyIndex).getTimestamps();
+            if (timestamps.size() > 0) {
+                return timestamps.get(0);
+            }
+        }
+        return 0;
     }
 
     @VisibleForTesting
@@ -127,6 +187,11 @@
         return mShowScreenOnTime;
     }
 
+    @VisibleForTesting
+    boolean getShowBatteryLevel() {
+        return mShowBatteryLevel;
+    }
+
     private void loadCurrentBatteryHistoryMap() {
         new AsyncTask<Void, Void, Map<String, BatteryHistEntry>>() {
             @Override
@@ -164,12 +229,17 @@
         new AsyncTask<Void, Void, List<AppUsageEvent>>() {
             @Override
             protected List<AppUsageEvent> doInBackground(Void... voids) {
+                if (!shouldLoadAppUsageData()) {
+                    Log.d(TAG, "not loadCurrentAppUsageList");
+                    return null;
+                }
                 final long startTime = System.currentTimeMillis();
                 // Loads the current battery usage data from the battery stats service.
                 final int currentUserId = getCurrentUserId();
                 final int workProfileUserId = getWorkProfileUserId();
                 final UsageEvents usageEventsForCurrentUser =
-                        DataProcessor.getAppUsageEventsForUser(mContext, currentUserId);
+                        DataProcessor.getAppUsageEventsForUser(
+                                mContext, currentUserId, mStartTimestampOfLevelData);
                 // If fail to load usage events for current user, return null directly and screen-on
                 // time will not be shown in the UI.
                 if (usageEventsForCurrentUser == null) {
@@ -180,7 +250,7 @@
                 if (workProfileUserId != Integer.MIN_VALUE) {
                     usageEventsForWorkProfile =
                             DataProcessor.getAppUsageEventsForUser(
-                                    mContext, workProfileUserId);
+                                    mContext, workProfileUserId, mStartTimestampOfLevelData);
                 } else {
                     Log.d(TAG, "there is no work profile");
                 }
@@ -203,16 +273,8 @@
             @Override
             protected void onPostExecute(
                     final List<AppUsageEvent> currentAppUsageList) {
-                final int currentUserId = getCurrentUserId();
-                final UserManager userManager = mContext.getSystemService(UserManager.class);
-                // If current user is locked, don't show screen-on time data in the UI.
-                // Even if we have data in the database, we won't show screen-on time because we
-                // don't have the latest data.
-                if (userManager == null || !userManager.isUserUnlocked(currentUserId)) {
-                    Log.d(TAG, "current user is locked");
-                    mShowScreenOnTime = false;
-                } else if (currentAppUsageList == null || currentAppUsageList.isEmpty()) {
-                    Log.d(TAG, "usageEventsForWorkProfile is null or empty");
+                if (currentAppUsageList == null || currentAppUsageList.isEmpty()) {
+                    Log.d(TAG, "currentAppUsageList is null or empty");
                 } else {
                     mAppUsageEventList.addAll(currentAppUsageList);
                 }
@@ -223,9 +285,65 @@
     }
 
     private void loadDatabaseAppUsageList() {
-        // TODO: load app usage data from database.
-        mIsDatabaseAppUsageLoaded = true;
-        tryToProcessAppUsageData();
+        new AsyncTask<Void, Void, List<AppUsageEvent>>() {
+            @Override
+            protected List<AppUsageEvent> doInBackground(Void... voids) {
+                if (!shouldLoadAppUsageData()) {
+                    Log.d(TAG, "not loadDatabaseAppUsageList");
+                    return null;
+                }
+                final long startTime = System.currentTimeMillis();
+                // Loads the current battery usage data from the battery stats service.
+                final List<AppUsageEvent> appUsageEventList =
+                        DatabaseUtils.getAppUsageEventForUsers(
+                                mContext, Calendar.getInstance(), getCurrentUserIds(),
+                                mStartTimestampOfLevelData);
+                Log.d(TAG, String.format("execute loadDatabaseAppUsageList size=%d in %d/ms",
+                        appUsageEventList.size(), (System.currentTimeMillis() - startTime)));
+                return appUsageEventList;
+            }
+
+            @Override
+            protected void onPostExecute(
+                    final List<AppUsageEvent> databaseAppUsageList) {
+                if (databaseAppUsageList == null || databaseAppUsageList.isEmpty()) {
+                    Log.d(TAG, "databaseAppUsageList is null or empty");
+                } else {
+                    mAppUsageEventList.addAll(databaseAppUsageList);
+                }
+                mIsDatabaseAppUsageLoaded = true;
+                tryToProcessAppUsageData();
+            }
+        }.execute();
+    }
+
+    private void loadAndApplyBatteryMapFromServiceOnly() {
+        new AsyncTask<Void, Void, Map<Integer, Map<Integer, BatteryDiffData>>>() {
+            @Override
+            protected Map<Integer, Map<Integer, BatteryDiffData>> doInBackground(Void... voids) {
+                final long startTime = System.currentTimeMillis();
+                final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap =
+                        DataProcessor.getBatteryUsageMapFromStatsService(mContext);
+                DataProcessor.loadLabelAndIcon(batteryUsageMap);
+                Log.d(TAG, String.format(
+                        "execute loadAndApplyBatteryMapFromServiceOnly size=%d in %d/ms",
+                        batteryUsageMap.size(), (System.currentTimeMillis() - startTime)));
+                return batteryUsageMap;
+            }
+
+            @Override
+            protected void onPostExecute(
+                    final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap) {
+                // Set the unused variables to null.
+                mContext = null;
+                // Post results back to main thread to refresh UI.
+                if (mHandler != null && mCallbackFunction != null) {
+                    mHandler.post(() -> {
+                        mCallbackFunction.onBatteryUsageMapLoaded(batteryUsageMap);
+                    });
+                }
+            }
+        }.execute();
     }
 
     private void tryToProcessAppUsageData() {
@@ -243,6 +361,8 @@
         if (!mShowScreenOnTime) {
             return;
         }
+        // Sort the appUsageEventList in ascending order based on the timestamp.
+        Collections.sort(mAppUsageEventList, DataProcessor.TIMESTAMP_COMPARATOR);
         // TODO: process app usage data to an intermediate result for further use.
     }
 
@@ -260,6 +380,36 @@
     private void generateFinalDataAndApplyCallback() {
         // TODO: generate the final data including battery usage map and device screen-on time and
         // then apply the callback function.
+        // Set the unused variables to null.
+        mContext = null;
+        mHourlyBatteryLevelsPerDay = null;
+        mBatteryHistoryMap = null;
+    }
+
+    // Whether we should load app usage data from service or database.
+    private boolean shouldLoadAppUsageData() {
+        if (!mShowScreenOnTime) {
+            return false;
+        }
+        final int currentUserId = getCurrentUserId();
+        // If current user is locked, no need to load app usage data from service or database.
+        if (mUserManager == null || !mUserManager.isUserUnlocked(currentUserId)) {
+            Log.d(TAG, "shouldLoadAppUsageData: false, current user is locked");
+            mShowScreenOnTime = false;
+            return false;
+        }
+        return true;
+    }
+
+    // Returns the list of current user id and work profile id if exists.
+    private List<Integer> getCurrentUserIds() {
+        final List<Integer> userIds = new ArrayList<>();
+        userIds.add(getCurrentUserId());
+        final int workProfileUserId = getWorkProfileUserId();
+        if (workProfileUserId != Integer.MIN_VALUE) {
+            userIds.add(workProfileUserId);
+        }
+        return userIds;
     }
 
     private int getCurrentUserId() {
@@ -268,8 +418,50 @@
 
     private int getWorkProfileUserId() {
         final UserHandle userHandle =
-                Utils.getManagedProfile(
-                        mContext.getSystemService(UserManager.class));
+                Utils.getManagedProfile(mUserManager);
         return userHandle != null ? userHandle.getIdentifier() : Integer.MIN_VALUE;
     }
+
+    /**
+     * @return Returns battery level data and start async task to compute battery diff usage data
+     * and load app labels + icons.
+     * Returns null if the input is invalid or not having at least 2 hours data.
+     */
+    @Nullable
+    public static BatteryLevelData getBatteryLevelData(
+            Context context,
+            @Nullable Handler handler,
+            @Nullable final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
+            final DataProcessor.UsageMapAsyncResponse asyncResponseDelegate) {
+        if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
+            Log.d(TAG, "batteryHistoryMap is null in getBatteryLevelData()");
+            new DataProcessManager(context, handler, asyncResponseDelegate).start();
+            return null;
+        }
+        handler = handler != null ? handler : new Handler(Looper.getMainLooper());
+        // Process raw history map data into hourly timestamps.
+        final Map<Long, Map<String, BatteryHistEntry>> processedBatteryHistoryMap =
+                DataProcessor.getHistoryMapWithExpectedTimestamps(context, batteryHistoryMap);
+        // Wrap and processed history map into easy-to-use format for UI rendering.
+        final BatteryLevelData batteryLevelData =
+                DataProcessor.getLevelDataThroughProcessedHistoryMap(
+                        context, processedBatteryHistoryMap);
+        if (batteryLevelData == null) {
+            new DataProcessManager(context, handler, asyncResponseDelegate).start();
+            Log.d(TAG, "getBatteryLevelData() returns null");
+            return null;
+        }
+
+        // TODO: replace the task below with new DataProcessManager(...).start() after
+        // DataProcessManager is completed;
+        // Start the async task to compute diff usage data and load labels and icons.
+        new DataProcessor.ComputeUsageMapAndLoadItemsTask(
+                context,
+                handler,
+                asyncResponseDelegate,
+                batteryLevelData.getHourlyBatteryLevelsPerDay(),
+                processedBatteryHistoryMap).execute();
+
+        return batteryLevelData;
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index bc5c031..c33e0a3 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -32,7 +32,6 @@
 import android.os.BatteryUsageStats;
 import android.os.BatteryUsageStatsQuery;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -100,6 +99,8 @@
 
     public static final String CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER =
             "CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER";
+    public static final Comparator<AppUsageEvent> TIMESTAMP_COMPARATOR =
+            Comparator.comparing(AppUsageEvent::getTimestamp);
 
     /** A callback listener when battery usage loading async task is executed. */
     public interface UsageMapAsyncResponse {
@@ -112,48 +113,6 @@
     }
 
     /**
-     * @return Returns battery level data and start async task to compute battery diff usage data
-     * and load app labels + icons.
-     * Returns null if the input is invalid or not having at least 2 hours data.
-     */
-    @Nullable
-    public static BatteryLevelData getBatteryLevelData(
-            Context context,
-            @Nullable Handler handler,
-            @Nullable final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
-            final UsageMapAsyncResponse asyncResponseDelegate) {
-        if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) {
-            Log.d(TAG, "batteryHistoryMap is null in getBatteryLevelData()");
-            loadBatteryUsageDataFromBatteryStatsService(
-                    context, handler, asyncResponseDelegate);
-            return null;
-        }
-        handler = handler != null ? handler : new Handler(Looper.getMainLooper());
-        // Process raw history map data into hourly timestamps.
-        final Map<Long, Map<String, BatteryHistEntry>> processedBatteryHistoryMap =
-                getHistoryMapWithExpectedTimestamps(context, batteryHistoryMap);
-        // Wrap and processed history map into easy-to-use format for UI rendering.
-        final BatteryLevelData batteryLevelData =
-                getLevelDataThroughProcessedHistoryMap(context, processedBatteryHistoryMap);
-        if (batteryLevelData == null) {
-            loadBatteryUsageDataFromBatteryStatsService(
-                    context, handler, asyncResponseDelegate);
-            Log.d(TAG, "getBatteryLevelData() returns null");
-            return null;
-        }
-
-        // Start the async task to compute diff usage data and load labels and icons.
-        new ComputeUsageMapAndLoadItemsTask(
-                context,
-                handler,
-                asyncResponseDelegate,
-                batteryLevelData.getHourlyBatteryLevelsPerDay(),
-                processedBatteryHistoryMap).execute();
-
-        return batteryLevelData;
-    }
-
-    /**
      * @return Returns battery usage data of different entries.
      * Returns null if the input is invalid or there is no enough data.
      */
@@ -228,7 +187,8 @@
      * Gets the {@link UsageEvents} from system service for the specific user.
      */
     @Nullable
-    public static UsageEvents getAppUsageEventsForUser(Context context, final int userID) {
+    public static UsageEvents getAppUsageEventsForUser(
+            Context context, final int userID, final long startTimestampOfLevelData) {
         final long start = System.currentTimeMillis();
         context = DatabaseUtils.getOwnerContext(context);
         if (context == null) {
@@ -240,8 +200,9 @@
         }
         final long sixDaysAgoTimestamp =
                 DatabaseUtils.getTimestampSixDaysAgo(Calendar.getInstance());
+        final long earliestTimestamp = Math.max(sixDaysAgoTimestamp, startTimestampOfLevelData);
         final UsageEvents events = getAppUsageEventsForUser(
-                context, userManager, userID, sixDaysAgoTimestamp);
+                context, userManager, userID, earliestTimestamp);
         final long elapsedTime = System.currentTimeMillis() - start;
         Log.d(TAG, String.format("getAppUsageEventsForUser() for user %d in %d/ms",
                 userID, elapsedTime));
@@ -295,7 +256,8 @@
                             break;
                         }
                         final AppUsageEvent appUsageEvent =
-                                ConvertUtils.convertToAppUsageEvent(context, event, userId);
+                                ConvertUtils.convertToAppUsageEvent(
+                                        context, sUsageStatsManager, event, userId);
                         if (appUsageEvent != null) {
                             numEventsFetched++;
                             appUsageEventList.add(appUsageEvent);
@@ -357,7 +319,6 @@
      * The keys of processed history map should contain every hour between the start and end
      * timestamp. If there's no data in some key, the value will be the empty hashmap.
      */
-    @VisibleForTesting
     static Map<Long, Map<String, BatteryHistEntry>> getHistoryMapWithExpectedTimestamps(
             Context context,
             final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
@@ -381,7 +342,6 @@
         return resultMap;
     }
 
-    @VisibleForTesting
     @Nullable
     static BatteryLevelData getLevelDataThroughProcessedHistoryMap(
             Context context,
@@ -585,13 +545,13 @@
                 userHandle != null ? userHandle.getIdentifier() : Integer.MIN_VALUE;
         final List<BatteryDiffEntry> appEntries = new ArrayList<>();
         final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
-        double consumePowerFromOtherUsers = 0f;
 
         for (BatteryHistEntry entry : batteryHistEntryList) {
             final boolean isFromOtherUsers = isConsumedFromOtherUsers(
                     currentUserId, workProfileUserId, entry);
+            // Not show other users' battery usage data.
             if (isFromOtherUsers) {
-                consumePowerFromOtherUsers += entry.mConsumePower;
+                continue;
             } else {
                 final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
                         context,
@@ -610,9 +570,6 @@
                 }
             }
         }
-        if (consumePowerFromOtherUsers != 0) {
-            systemEntries.add(createOtherUsersEntry(context, consumePowerFromOtherUsers));
-        }
 
         // If there is no data, return null instead of empty item.
         if (appEntries.isEmpty() && systemEntries.isEmpty()) {
@@ -623,22 +580,43 @@
     }
 
     /**
-     * Starts the async task to load battery diff usage data and load app labels + icons.
+     * @return Returns the overall battery usage data from battery stats service directly.
+     *
+     * The returned value should be always a 2d map and composed by only 1 part:
+     * - [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL]
      */
-    private static void loadBatteryUsageDataFromBatteryStatsService(
-            Context context,
-            @Nullable Handler handler,
-            final UsageMapAsyncResponse asyncResponseDelegate) {
-        new LoadUsageMapFromBatteryStatsServiceTask(
-                context,
-                handler,
-                asyncResponseDelegate).execute();
+    static Map<Integer, Map<Integer, BatteryDiffData>> getBatteryUsageMapFromStatsService(
+            final Context context) {
+        final Map<Integer, Map<Integer, BatteryDiffData>> resultMap = new HashMap<>();
+        final Map<Integer, BatteryDiffData> allUsageMap = new HashMap<>();
+        // Always construct the map whether the value is null or not.
+        allUsageMap.put(SELECTED_INDEX_ALL,
+                generateBatteryDiffData(context, getBatteryHistListFromFromStatsService(context)));
+        resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
+        processBatteryDiffData(context, resultMap);
+        return resultMap;
+    }
+
+    static void loadLabelAndIcon(
+            @Nullable final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap) {
+        if (batteryUsageMap == null) {
+            return;
+        }
+        // Pre-loads each BatteryDiffEntry relative icon and label for all slots.
+        final BatteryDiffData batteryUsageMapForAll =
+                batteryUsageMap.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL);
+        if (batteryUsageMapForAll != null) {
+            batteryUsageMapForAll.getAppDiffEntryList().forEach(
+                    entry -> entry.loadLabelAndIcon());
+            batteryUsageMapForAll.getSystemDiffEntryList().forEach(
+                    entry -> entry.loadLabelAndIcon());
+        }
     }
 
     @Nullable
     private static UsageEvents getAppUsageEventsForUser(
             Context context, final UserManager userManager, final int userID,
-            final long sixDaysAgoTimestamp) {
+            final long earliestTimestamp) {
         final String callingPackage = context.getPackageName();
         final long now = System.currentTimeMillis();
         // When the user is not unlocked, UsageStatsManager will return null, so bypass the
@@ -648,7 +626,7 @@
             return null;
         }
         final long startTime = DatabaseUtils.getAppUsageStartTimestampOfUser(
-                context, userID, sixDaysAgoTimestamp);
+                context, userID, earliestTimestamp);
         return loadAppUsageEventsForUserFromService(
                 sUsageStatsManager, startTime, now, userID, callingPackage);
     }
@@ -671,24 +649,6 @@
         return events;
     }
 
-    /**
-     * @return Returns the overall battery usage data from battery stats service directly.
-     *
-     * The returned value should be always a 2d map and composed by only 1 part:
-     * - [SELECTED_INDEX_ALL][SELECTED_INDEX_ALL]
-     */
-    private static Map<Integer, Map<Integer, BatteryDiffData>> getBatteryUsageMapFromStatsService(
-            final Context context) {
-        final Map<Integer, Map<Integer, BatteryDiffData>> resultMap = new HashMap<>();
-        final Map<Integer, BatteryDiffData> allUsageMap = new HashMap<>();
-        // Always construct the map whether the value is null or not.
-        allUsageMap.put(SELECTED_INDEX_ALL,
-                generateBatteryDiffData(context, getBatteryHistListFromFromStatsService(context)));
-        resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
-        processBatteryDiffData(context, resultMap);
-        return resultMap;
-    }
-
     @Nullable
     private static List<BatteryHistEntry> getBatteryHistListFromFromStatsService(
             final Context context) {
@@ -1082,7 +1042,6 @@
         allBatteryHistEntryKeys.addAll(nextBatteryHistMap.keySet());
         allBatteryHistEntryKeys.addAll(nextTwoBatteryHistMap.keySet());
 
-        double consumePowerFromOtherUsers = 0f;
         // Calculates all packages diff usage data in a specific time slot.
         for (String key : allBatteryHistEntryKeys) {
             final BatteryHistEntry currentEntry =
@@ -1091,6 +1050,20 @@
                     nextBatteryHistMap.getOrDefault(key, EMPTY_BATTERY_HIST_ENTRY);
             final BatteryHistEntry nextTwoEntry =
                     nextTwoBatteryHistMap.getOrDefault(key, EMPTY_BATTERY_HIST_ENTRY);
+
+            final BatteryHistEntry selectedBatteryEntry =
+                    selectBatteryHistEntry(currentEntry, nextEntry, nextTwoEntry);
+            if (selectedBatteryEntry == null) {
+                continue;
+            }
+
+            // Not show other users' battery usage data.
+            final boolean isFromOtherUsers = isConsumedFromOtherUsers(
+                    currentUserId, workProfileUserId, selectedBatteryEntry);
+            if (isFromOtherUsers) {
+                continue;
+            }
+
             // Cumulative values is a specific time slot for a specific app.
             long foregroundUsageTimeInMs =
                     getDiffValue(
@@ -1133,11 +1106,6 @@
                     && consumePower == 0) {
                 continue;
             }
-            final BatteryHistEntry selectedBatteryEntry =
-                    selectBatteryHistEntry(currentEntry, nextEntry, nextTwoEntry);
-            if (selectedBatteryEntry == null) {
-                continue;
-            }
             // Forces refine the cumulative value since it may introduce deviation error since we
             // will apply the interpolation arithmetic.
             final float totalUsageTimeInMs =
@@ -1161,31 +1129,22 @@
                 cachedUsageConsumePower = cachedUsageConsumePower * ratio;
             }
 
-            final boolean isFromOtherUsers = isConsumedFromOtherUsers(
-                    currentUserId, workProfileUserId, selectedBatteryEntry);
-            if (isFromOtherUsers) {
-                consumePowerFromOtherUsers += consumePower;
+            final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
+                    context,
+                    foregroundUsageTimeInMs,
+                    backgroundUsageTimeInMs,
+                    consumePower,
+                    foregroundUsageConsumePower,
+                    foregroundServiceUsageConsumePower,
+                    backgroundUsageConsumePower,
+                    cachedUsageConsumePower,
+                    selectedBatteryEntry);
+            if (currentBatteryDiffEntry.isSystemEntry()) {
+                systemEntries.add(currentBatteryDiffEntry);
             } else {
-                final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
-                        context,
-                        foregroundUsageTimeInMs,
-                        backgroundUsageTimeInMs,
-                        consumePower,
-                        foregroundUsageConsumePower,
-                        foregroundServiceUsageConsumePower,
-                        backgroundUsageConsumePower,
-                        cachedUsageConsumePower,
-                        selectedBatteryEntry);
-                if (currentBatteryDiffEntry.isSystemEntry()) {
-                    systemEntries.add(currentBatteryDiffEntry);
-                } else {
-                    appEntries.add(currentBatteryDiffEntry);
-                }
+                appEntries.add(currentBatteryDiffEntry);
             }
         }
-        if (consumePowerFromOtherUsers != 0) {
-            systemEntries.add(createOtherUsersEntry(context, consumePowerFromOtherUsers));
-        }
 
         // If there is no data, return null instead of empty item.
         if (appEntries.isEmpty() && systemEntries.isEmpty()) {
@@ -1469,22 +1428,6 @@
         return true;
     }
 
-    private static void loadLabelAndIcon(
-            @Nullable final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap) {
-        if (batteryUsageMap == null) {
-            return;
-        }
-        // Pre-loads each BatteryDiffEntry relative icon and label for all slots.
-        final BatteryDiffData batteryUsageMapForAll =
-                batteryUsageMap.get(SELECTED_INDEX_ALL).get(SELECTED_INDEX_ALL);
-        if (batteryUsageMapForAll != null) {
-            batteryUsageMapForAll.getAppDiffEntryList().forEach(
-                    entry -> entry.loadLabelAndIcon());
-            batteryUsageMapForAll.getSystemDiffEntryList().forEach(
-                    entry -> entry.loadLabelAndIcon());
-        }
-    }
-
     private static long getTimestampWithDayDiff(final long timestamp, final int dayDiff) {
         final Calendar calendar = Calendar.getInstance();
         calendar.setTimeInMillis(timestamp);
@@ -1514,27 +1457,6 @@
         return null;
     }
 
-    private static BatteryDiffEntry createOtherUsersEntry(
-            Context context, final double consumePower) {
-        final ContentValues values = new ContentValues();
-        values.put(BatteryHistEntry.KEY_UID, BatteryUtils.UID_OTHER_USERS);
-        values.put(BatteryHistEntry.KEY_USER_ID, BatteryUtils.UID_OTHER_USERS);
-        values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
-        // We will show the percentage for the "other users" item only, the aggregated
-        // running time information is useless for users to identify individual apps.
-        final BatteryDiffEntry batteryDiffEntry = new BatteryDiffEntry(
-                context,
-                /*foregroundUsageTimeInMs=*/ 0,
-                /*backgroundUsageTimeInMs=*/ 0,
-                consumePower,
-                /*foregroundUsageConsumePower=*/ 0,
-                /*foregroundServiceUsageConsumePower=*/ 0,
-                /*backgroundUsageConsumePower=*/ 0,
-                /*cachedUsageConsumePower=*/ 0,
-                new BatteryHistEntry(values));
-        return batteryDiffEntry;
-    }
-
     private static long getCurrentTimeMillis() {
         return sFakeCurrentTimeMillis > 0 ? sFakeCurrentTimeMillis : System.currentTimeMillis();
     }
@@ -1548,7 +1470,7 @@
     }
 
     // Compute diff map and loads all items (icon and label) in the background.
-    private static class ComputeUsageMapAndLoadItemsTask
+    static class ComputeUsageMapAndLoadItemsTask
             extends AsyncTask<Void, Void, Map<Integer, Map<Integer, BatteryDiffData>>> {
 
         Context mApplicationContext;
@@ -1557,7 +1479,7 @@
         private List<BatteryLevelData.PeriodBatteryLevelData> mHourlyBatteryLevelsPerDay;
         private Map<Long, Map<String, BatteryHistEntry>> mBatteryHistoryMap;
 
-        private ComputeUsageMapAndLoadItemsTask(
+        ComputeUsageMapAndLoadItemsTask(
                 Context context,
                 Handler handler,
                 final UsageMapAsyncResponse asyncResponseDelegate,
@@ -1615,35 +1537,4 @@
             }
         }
     }
-
-    // Loads battery usage data from battery stats service directly and loads all items (icon and
-    // label) in the background.
-    private static final class LoadUsageMapFromBatteryStatsServiceTask
-            extends ComputeUsageMapAndLoadItemsTask {
-
-        private LoadUsageMapFromBatteryStatsServiceTask(
-                Context context,
-                Handler handler,
-                final UsageMapAsyncResponse asyncResponseDelegate) {
-            super(context, handler, asyncResponseDelegate, /*hourlyBatteryLevelsPerDay=*/ null,
-                    /*batteryHistoryMap=*/ null);
-        }
-
-        @Override
-        protected Map<Integer, Map<Integer, BatteryDiffData>> doInBackground(Void... voids) {
-            if (mApplicationContext == null
-                    || mHandler == null
-                    || mAsyncResponseDelegate == null) {
-                Log.e(TAG, "invalid input for ComputeUsageMapAndLoadItemsTask()");
-                return null;
-            }
-            final long startTime = System.currentTimeMillis();
-            final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap =
-                    getBatteryUsageMapFromStatsService(mApplicationContext);
-            loadLabelAndIcon(batteryUsageMap);
-            Log.d(TAG, String.format("execute LoadUsageMapFromBatteryStatsServiceTask in %d/ms",
-                    (System.currentTimeMillis() - startTime)));
-            return batteryUsageMap;
-        }
-    }
 }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
index f6b4e03..b52938a 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -46,6 +46,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 /** A utility class to operate battery usage database. */
 public final class DatabaseUtils {
@@ -93,6 +94,8 @@
     @VisibleForTesting
     static Supplier<Cursor> sFakeBatteryStateSupplier;
     @VisibleForTesting
+    static Supplier<Cursor> sFakeAppUsageEventSupplier;
+    @VisibleForTesting
     static Supplier<Cursor> sFakeAppUsageLatestTimestampSupplier;
 
     private DatabaseUtils() {
@@ -125,6 +128,38 @@
         return Math.max(latestTimestamp, earliestTimestamp);
     }
 
+    /** Returns the current user data in app usage event table. */
+    public static List<AppUsageEvent> getAppUsageEventForUsers(
+            Context context,
+            final Calendar calendar,
+            final List<Integer> userIds,
+            final long startTimestampOfLevelData) {
+        final long startTime = System.currentTimeMillis();
+        final long sixDaysAgoTimestamp = getTimestampSixDaysAgo(calendar);
+        final long queryTimestamp = Math.max(startTimestampOfLevelData, sixDaysAgoTimestamp);
+        Log.d(TAG, "sixDayAgoTimestamp: " + sixDaysAgoTimestamp);
+        final String queryUserIdString = userIds.stream()
+                .map(userId -> String.valueOf(userId))
+                .collect(Collectors.joining(","));
+        // Builds the content uri everytime to avoid cache.
+        final Uri appUsageEventUri =
+                new Uri.Builder()
+                        .scheme(ContentResolver.SCHEME_CONTENT)
+                        .authority(AUTHORITY)
+                        .appendPath(APP_USAGE_EVENT_TABLE)
+                        .appendQueryParameter(
+                                QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+                        .appendQueryParameter(QUERY_KEY_USERID, queryUserIdString)
+                        .build();
+
+        final List<AppUsageEvent> appUsageEventList =
+                loadAppUsageEventsFromContentProvider(context, appUsageEventUri);
+        Log.d(TAG, String.format("getAppUsageEventForUser userId=%s size=%d in %d/ms",
+                queryUserIdString, appUsageEventList.size(),
+                (System.currentTimeMillis() - startTime)));
+        return appUsageEventList;
+    }
+
     /** Long: for timestamp and String: for BatteryHistEntry.getKey() */
     public static Map<Long, Map<String, BatteryHistEntry>> getHistoryMapSinceLastFullCharge(
             Context context, Calendar calendar) {
@@ -357,6 +392,32 @@
         }
     }
 
+    private static List<AppUsageEvent> loadAppUsageEventsFromContentProvider(
+            Context context, Uri appUsageEventUri) {
+        final List<AppUsageEvent> appUsageEventList = new ArrayList<>();
+        context = getOwnerContext(context);
+        if (context == null) {
+            return appUsageEventList;
+        }
+        try (Cursor cursor = sFakeAppUsageEventSupplier != null
+                ? sFakeAppUsageEventSupplier.get()
+                : context.getContentResolver().query(appUsageEventUri, null, null, null)) {
+            if (cursor == null || cursor.getCount() == 0) {
+                return appUsageEventList;
+            }
+            // Loads and recovers all AppUsageEvent data from cursor.
+            while (cursor.moveToNext()) {
+                appUsageEventList.add(ConvertUtils.convertToAppUsageEventFromCursor(cursor));
+            }
+            try {
+                cursor.close();
+            } catch (Exception e) {
+                Log.e(TAG, "cursor.close() failed", e);
+            }
+        }
+        return appUsageEventList;
+    }
+
     private static Map<Long, Map<String, BatteryHistEntry>> loadHistoryMapFromContentProvider(
             Context context, Uri batteryStateUri) {
         context = DatabaseUtils.getOwnerContext(context);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java b/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
index 578a1ff..19360f4 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDao.java
@@ -41,6 +41,11 @@
     @Query("SELECT * FROM AppUsageEventEntity WHERE timestamp > :timestamp ORDER BY timestamp DESC")
     List<AppUsageEventEntity> getAllAfter(long timestamp);
 
+    /** Gets the {@link Cursor} of all recorded data after a specific timestamp of the users. */
+    @Query("SELECT * FROM AppUsageEventEntity WHERE timestamp >= :timestamp"
+            + " AND userId IN (:userIds) ORDER BY timestamp ASC")
+    Cursor getAllForUsersAfter(List<Long> userIds, long timestamp);
+
     /** Gets the {@link Cursor} of the latest timestamp of the specific user. */
     @Query("SELECT MAX(timestamp) as timestamp FROM AppUsageEventEntity WHERE userId = :userId")
     Cursor getLatestTimestampOfUser(long userId);
diff --git a/src/com/android/settings/gestures/TapScreenGestureSettings.java b/src/com/android/settings/gestures/TapScreenGestureSettings.java
index bf847f4..98439d6 100644
--- a/src/com/android/settings/gestures/TapScreenGestureSettings.java
+++ b/src/com/android/settings/gestures/TapScreenGestureSettings.java
@@ -16,11 +16,11 @@
 
 package com.android.settings.gestures;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.hardware.display.AmbientDisplayConfiguration;
 
-import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
@@ -49,7 +49,7 @@
 
     @Override
     public int getMetricsCategory() {
-        return MetricsProto.MetricsEvent.SETTINGS_GESTURE_TAP_SCREEN;
+        return SettingsEnums.SETTINGS_GESTURE_TAP_SCREEN;
     }
 
     @Override
diff --git a/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
new file mode 100644
index 0000000..6e54689
--- /dev/null
+++ b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
@@ -0,0 +1,70 @@
+/*
+ * 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.util.FeatureFlagUtils;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.ButtonPreference;
+
+public class TouchGesturesButtonPreferenceController extends BasePreferenceController {
+
+    private static final int ORDER_TOP = 0;
+    private static final int ORDER_BOTTOM = 100;
+    private static final String PREFERENCE_KEY = "trackpad_touch_gesture";
+
+    public TouchGesturesButtonPreferenceController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        ButtonPreference buttonPreference =
+                (ButtonPreference) screen.findPreference(getPreferenceKey());
+        boolean touchGestureDeveloperMode = FeatureFlagUtils
+                .isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE);
+        if (getPreferenceKey().equals(PREFERENCE_KEY)) {
+            if (touchGestureDeveloperMode) {
+                buttonPreference.setOrder(ORDER_TOP);
+            } else {
+                buttonPreference.setOrder(ORDER_BOTTOM);
+            }
+        }
+        buttonPreference.setOnClickListener(v -> {
+            showTouchpadGestureEducation();
+        });
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    private void showTouchpadGestureEducation() {
+        // TODO: Waiting for the education UX design.
+        /* For example:
+        FragmentManager fragmentManager = mParent.getActivity().getSupportFragmentManager();
+        FragmentTransaction transaction = fragmentManager.beginTransaction();
+        TrackpadGestureDialogFragment fragment = new TrackpadGestureDialogFragment();
+        fragment.show(transaction, GESTURE_DIALOG_TAG);
+        */
+    }
+}
diff --git a/src/com/android/settings/inputmethod/TrackpadSettings.java b/src/com/android/settings/inputmethod/TrackpadSettings.java
new file mode 100644
index 0000000..436e3e6
--- /dev/null
+++ b/src/com/android/settings/inputmethod/TrackpadSettings.java
@@ -0,0 +1,59 @@
+/*
+ * 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.util.FeatureFlagUtils;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+
+public class TrackpadSettings extends DashboardFragment {
+
+    private static final String TAG = "TrackpadSettings";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.SETTINGS_KEYBOARDS_TOUCHPAD;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.trackpad_settings;
+    }
+
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.trackpad_settings) {
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return FeatureFlagUtils
+                            .isEnabled(context, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_TRACKPAD);
+                }
+            };
+}
diff --git a/src/com/android/settings/inputmethod/TrackpadSettingsController.java b/src/com/android/settings/inputmethod/TrackpadSettingsController.java
new file mode 100644
index 0000000..41be395
--- /dev/null
+++ b/src/com/android/settings/inputmethod/TrackpadSettingsController.java
@@ -0,0 +1,37 @@
+/*
+ * 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.util.FeatureFlagUtils;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class TrackpadSettingsController extends BasePreferenceController {
+
+    public TrackpadSettingsController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        // TODO: Need to detect if trackpad is connected with device.
+        boolean isFeatureOn = FeatureFlagUtils
+                .isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_TRACKPAD);
+        return isFeatureOn ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/inputmethod/TrackpadTouchGestureSettings.java b/src/com/android/settings/inputmethod/TrackpadTouchGestureSettings.java
new file mode 100644
index 0000000..9884862
--- /dev/null
+++ b/src/com/android/settings/inputmethod/TrackpadTouchGestureSettings.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.app.settings.SettingsEnums;
+import android.content.Context;
+import android.util.FeatureFlagUtils;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+
+public class TrackpadTouchGestureSettings extends DashboardFragment {
+
+    private static final String TAG = "TrackpadTouchGestureSettings";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.SETTINGS_KEYBOARDS_TOUCHPAD_GESTURE;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.trackpad_gesture_settings;
+    }
+
+    public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider(R.xml.trackpad_settings) {
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return FeatureFlagUtils
+                            .isEnabled(
+                                    context,
+                                    FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE);
+                }
+            };
+}
diff --git a/src/com/android/settings/inputmethod/TrackpadTouchGestureSettingsController.java b/src/com/android/settings/inputmethod/TrackpadTouchGestureSettingsController.java
new file mode 100644
index 0000000..8f04aee
--- /dev/null
+++ b/src/com/android/settings/inputmethod/TrackpadTouchGestureSettingsController.java
@@ -0,0 +1,36 @@
+/*
+ * 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.util.FeatureFlagUtils;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class TrackpadTouchGestureSettingsController extends BasePreferenceController {
+
+    public TrackpadTouchGestureSettingsController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        boolean isFeatureOn = FeatureFlagUtils
+                .isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_TRACKPAD_GESTURE);
+        return isFeatureOn ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    }
+}
diff --git a/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java b/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java
new file mode 100644
index 0000000..7dbef0c
--- /dev/null
+++ b/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java
@@ -0,0 +1,44 @@
+/*
+ * 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.network.telephony;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import com.android.settingslib.CustomDialogPreferenceCompat;
+
+/**
+ * This is DialogPreference for supporting connectivity features.
+ */
+public class TelephonyPreferenceDialog extends CustomDialogPreferenceCompat {
+
+    public TelephonyPreferenceDialog(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public TelephonyPreferenceDialog(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public TelephonyPreferenceDialog(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public TelephonyPreferenceDialog(Context context) {
+        super(context);
+    }
+}
diff --git a/src/com/android/settings/sim/CallsSimListDialogFragment.java b/src/com/android/settings/sim/CallsSimListDialogFragment.java
index 58da111..cbee634 100644
--- a/src/com/android/settings/sim/CallsSimListDialogFragment.java
+++ b/src/com/android/settings/sim/CallsSimListDialogFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.sim;
 
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+
 import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.telecom.PhoneAccountHandle;
@@ -51,6 +53,12 @@
             if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
                 continue;
             }
+
+            SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(subId);
+            if (info == null || (info.isEmbedded()
+                    && info.getProfileClass() == PROFILE_CLASS_PROVISIONING)) {
+                continue;
+            }
             result.add(subscriptionManager.getActiveSubscriptionInfo(subId));
         }
         return result;
diff --git a/src/com/android/settings/sim/PreferredSimDialogFragment.java b/src/com/android/settings/sim/PreferredSimDialogFragment.java
index 2bfeafe..50eb993 100644
--- a/src/com/android/settings/sim/PreferredSimDialogFragment.java
+++ b/src/com/android/settings/sim/PreferredSimDialogFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.sim;
 
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+
 import android.app.Activity;
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
@@ -95,7 +97,8 @@
         }
 
         final SubscriptionInfo info = getPreferredSubscription();
-        if (info == null) {
+        if (info == null || (info.isEmbedded()
+                && info.getProfileClass() == PROFILE_CLASS_PROVISIONING)) {
             dismiss();
             return;
         }
diff --git a/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java b/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
index 9fa60ef..b2ca621 100644
--- a/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
+++ b/src/com/android/settings/sim/SelectSpecificDataSimDialogFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.sim;
 
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.DialogInterface;
@@ -113,6 +115,15 @@
             dismiss();
             return;
         }
+
+        if ((newSubInfo.isEmbedded() && newSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING)
+                || (currentDataSubInfo.isEmbedded()
+                && currentDataSubInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING)) {
+            Log.d(TAG, "do not set the provision eSIM");
+            dismiss();
+            return;
+        }
+
         Log.d(TAG, "newSubId: " + newSubInfo.getSubscriptionId()
                 + "currentDataSubID: " + currentDataSubInfo.getSubscriptionId());
         setTargetSubscriptionInfo(newSubInfo);
diff --git a/src/com/android/settings/sim/SimListDialogFragment.java b/src/com/android/settings/sim/SimListDialogFragment.java
index 06b116c..245d31e 100644
--- a/src/com/android/settings/sim/SimListDialogFragment.java
+++ b/src/com/android/settings/sim/SimListDialogFragment.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.sim;
 
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.Context;
@@ -137,6 +139,11 @@
             dismiss();
             return;
         }
+
+        // Remove the provision eSIM from the subscription list.
+        currentSubscriptions.removeIf(info -> info.isEmbedded()
+                && info.getProfileClass() == PROFILE_CLASS_PROVISIONING);
+
         boolean includeAskEveryTime = getArguments().getBoolean(KEY_INCLUDE_ASK_EVERY_TIME);
         boolean isCancelItemShowed = getArguments().getBoolean(KEY_SHOW_CANCEL_ITEM);
         if (includeAskEveryTime || isCancelItemShowed) {
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index bf15ddf..9eab400 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -20,6 +20,7 @@
 import com.android.settings.spa.app.AllAppListPageProvider
 import com.android.settings.spa.app.AppsMainPageProvider
 import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
+import com.android.settings.spa.app.backgroundinstall.BackgroundInstalledAppsPageProvider
 import com.android.settings.spa.app.specialaccess.AlarmsAndRemindersAppListProvider
 import com.android.settings.spa.app.specialaccess.AllFilesAccessAppListProvider
 import com.android.settings.spa.app.specialaccess.DisplayOverOtherAppsAppListProvider
@@ -66,6 +67,7 @@
                 LanguageAndInputPageProvider,
                 AppLanguagesPageProvider,
                 UsageStatsPageProvider,
+                BackgroundInstalledAppsPageProvider,
             ) + togglePermissionAppListTemplate.createPageProviders(),
             rootPages = listOf(
                 SettingsPage.create(HomePageProvider.name),
diff --git a/src/com/android/settings/spa/app/AppsMain.kt b/src/com/android/settings/spa/app/AppsMain.kt
index 4b47278..e9eca1f 100644
--- a/src/com/android/settings/spa/app/AppsMain.kt
+++ b/src/com/android/settings/spa/app/AppsMain.kt
@@ -22,7 +22,9 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.res.stringResource
 import com.android.settings.R
+import com.android.settings.spa.app.backgroundinstall.BackgroundInstalledAppsPageProvider
 import com.android.settings.spa.app.specialaccess.SpecialAppAccessPageProvider
+import com.android.settings.spa.home.HomePageProvider
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPage
@@ -45,6 +47,7 @@
         RegularScaffold(title = getTitle(arguments)) {
             AllAppListPageProvider.buildInjectEntry().build().UiLayout()
             SpecialAppAccessPageProvider.EntryItem()
+            BackgroundInstalledAppsPageProvider.EntryItem()
         }
     }
 
@@ -70,6 +73,7 @@
         return listOf(
             AllAppListPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
             SpecialAppAccessPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
+            BackgroundInstalledAppsPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
         )
     }
 }
diff --git a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
index 3a4d3f6..1f7cc4d 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInfoSettings.kt
@@ -95,7 +95,7 @@
 
         AppSettingsPreference(app)
         AppAllServicesPreference(app)
-        // TODO: notification_settings
+        AppNotificationPreference(app)
         AppPermissionPreference(app)
         AppStoragePreference(app)
         InstantAppDomainsPreference(app)
diff --git a/src/com/android/settings/spa/app/appinfo/AppNotificationPreference.kt b/src/com/android/settings/spa/app/appinfo/AppNotificationPreference.kt
new file mode 100644
index 0000000..e1792a9
--- /dev/null
+++ b/src/com/android/settings/spa/app/appinfo/AppNotificationPreference.kt
@@ -0,0 +1,67 @@
+/*
+* 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.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import com.android.settings.R
+import com.android.settings.applications.appinfo.AppInfoDashboardFragment
+import com.android.settings.notification.app.AppNotificationSettings
+import com.android.settings.spa.notification.AppNotificationRepository
+import com.android.settings.spa.notification.IAppNotificationRepository
+import com.android.settingslib.spa.framework.compose.rememberContext
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
+
+@OptIn(ExperimentalLifecycleComposeApi::class)
+@Composable
+fun AppNotificationPreference(
+    app: ApplicationInfo,
+    repository: IAppNotificationRepository = rememberContext(::AppNotificationRepository),
+) {
+    val context = LocalContext.current
+    val summaryFlow = remember(app) {
+        flow {
+            emit(repository.getNotificationSummary(app))
+        }.flowOn(Dispatchers.IO)
+    }
+    Preference(object : PreferenceModel {
+        override val title = stringResource(R.string.notifications_label)
+        override val summary = summaryFlow.collectAsStateWithLifecycle(
+            initialValue = stringResource(R.string.summary_placeholder)
+        )
+        override val onClick = { navigateToAppNotificationSettings(context, app) }
+    })
+}
+
+private fun navigateToAppNotificationSettings(context: Context, app: ApplicationInfo) {
+    AppInfoDashboardFragment.startAppInfoFragment(
+        AppNotificationSettings::class.java,
+        app,
+        context,
+        AppInfoSettingsProvider.METRICS_CATEGORY,
+    )
+}
\ No newline at end of file
diff --git a/src/com/android/settings/spa/app/backgroundinstall/BackgroundInstalledAppsPageProvider.kt b/src/com/android/settings/spa/app/backgroundinstall/BackgroundInstalledAppsPageProvider.kt
new file mode 100644
index 0000000..9cf9516
--- /dev/null
+++ b/src/com/android/settings/spa/app/backgroundinstall/BackgroundInstalledAppsPageProvider.kt
@@ -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.spa.app.backgroundinstall
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.content.pm.IBackgroundInstallControlService
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.content.pm.ParceledListSlice
+import android.net.Uri
+import android.os.Bundle
+import android.os.ServiceManager
+import android.provider.DeviceConfig
+import android.util.Log
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.Delete
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.produceState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import com.android.settings.R
+import com.android.settings.spa.app.appinfo.AppInfoSettingsProvider
+import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
+import com.android.settingslib.spa.framework.common.SettingsPage
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.framework.compose.rememberContext
+import com.android.settingslib.spa.framework.theme.SettingsDimension
+import com.android.settingslib.spa.framework.util.asyncMap
+import com.android.settingslib.spa.framework.util.formatString
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.ui.SettingsBody
+import com.android.settingslib.spaprivileged.model.app.AppEntry
+import com.android.settingslib.spaprivileged.model.app.AppListModel
+import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.template.app.AppList
+import com.android.settingslib.spaprivileged.template.app.AppListButtonItem
+import com.android.settingslib.spaprivileged.template.app.AppListInput
+import com.android.settingslib.spaprivileged.template.app.AppListItemModel
+import com.android.settingslib.spaprivileged.template.app.AppListPage
+import com.google.common.annotations.VisibleForTesting
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.withContext
+
+private const val KEY_GROUPING_MONTH = "key_grouping_by_month"
+const val DEFAULT_GROUPING_MONTH_VALUE = 6
+const val MONTH_IN_MILLIS = 2629800000L
+const val KEY_BIC_UI_ENABLED = "key_bic_ui_enabled"
+const val BACKGROUND_INSTALL_CONTROL_FLAG = PackageManager.MATCH_ALL.toLong()
+
+object BackgroundInstalledAppsPageProvider : SettingsPageProvider {
+    override val name = "BackgroundInstalledAppsPage"
+    private var backgroundInstallService = IBackgroundInstallControlService.Stub.asInterface(
+        ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE))
+    private var featureIsDisabled = featureIsDisabled()
+
+    @Composable
+    override fun Page(arguments: Bundle?) {
+        if(featureIsDisabled) return
+        BackgroundInstalledAppList()
+    }
+
+    @Composable
+    fun EntryItem() {
+        if(featureIsDisabled) return
+        Preference(object : PreferenceModel {
+            override val title = stringResource(R.string.background_install_title)
+            override val summary = generatePreferenceSummary()
+            override val onClick = navigator(name)
+        })
+    }
+
+    fun buildInjectEntry() = SettingsEntryBuilder
+        .createInject(owner = SettingsPage.create(name))
+        .setSearchDataFn { null }
+        .setUiLayoutFn { EntryItem() }
+
+    private fun featureIsDisabled() = !DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
+        KEY_BIC_UI_ENABLED, false)
+
+    @Composable
+    private fun generatePreferenceSummary(): State<String> {
+        val context = LocalContext.current
+        return produceState(initialValue = stringResource(R.string.summary_placeholder)) {
+            withContext(Dispatchers.IO) {
+                val backgroundInstalledApps =
+                    backgroundInstallService.getBackgroundInstalledPackages(
+                        BACKGROUND_INSTALL_CONTROL_FLAG, context.user.identifier
+                    ).list.size
+                value = context.formatString(
+                    R.string.background_install_preference_summary,
+                    "count" to backgroundInstalledApps
+                )
+            }
+        }
+    }
+
+    @VisibleForTesting
+    fun setDisableFeature(disableFeature : Boolean): BackgroundInstalledAppsPageProvider {
+        featureIsDisabled = disableFeature
+        return this
+    }
+
+    @VisibleForTesting
+    fun setBackgroundInstallControlService(bic: IBackgroundInstallControlService):
+        BackgroundInstalledAppsPageProvider {
+        backgroundInstallService = bic
+        return this
+    }
+}
+
+@Composable
+fun BackgroundInstalledAppList(
+    appList: @Composable AppListInput<BackgroundInstalledAppListWithGroupingAppRecord>.() -> Unit
+    = { AppList() },
+) {
+    AppListPage(
+            title = stringResource(R.string.background_install_title),
+            listModel = rememberContext(::BackgroundInstalledAppsWithGroupingListModel),
+            noItemMessage = stringResource(R.string.background_install_feature_list_no_entry),
+            appList = appList,
+            header = {
+                Box(Modifier.padding(SettingsDimension.itemPadding)) {
+                    SettingsBody(stringResource(R.string.background_install_summary))
+                }
+            }
+    )
+}
+/*
+Based on PackageManagerService design, and it looks like the suggested replacement in the deprecate
+notes suggest that we use PackageInstaller.uninstall which does not guarantee a pop up would open
+and depends on the calling application. Seems like further investigation is needed before we can
+move over to the new API.
+ */
+@Suppress
+@VisibleForTesting
+fun startUninstallActivity(context: Context,
+                                   packageName: String,
+                                   forAllUsers: Boolean = false) {
+    val packageUri = Uri.parse("package:${packageName}")
+    val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
+        putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers)
+    }
+    context.startActivityAsUser(intent, context.user)
+}
+
+data class BackgroundInstalledAppListWithGroupingAppRecord(
+    override val app: ApplicationInfo,
+    val dateOfInstall: Long,
+) : AppRecord
+
+class BackgroundInstalledAppsWithGroupingListModel(private val context: Context)
+    : AppListModel<BackgroundInstalledAppListWithGroupingAppRecord> {
+
+    companion object {
+        private const val tag = "AppListModel<BackgroundInstalledAppListWithGroupingAppRecord>"
+    }
+
+    private var backgroundInstallService = IBackgroundInstallControlService.Stub.asInterface(
+        ServiceManager.getService(Context.BACKGROUND_INSTALL_CONTROL_SERVICE))
+
+    @VisibleForTesting
+    fun setBackgroundInstallControlService(bic: IBackgroundInstallControlService) {
+        backgroundInstallService = bic
+    }
+    @Composable
+    override fun AppListItemModel<BackgroundInstalledAppListWithGroupingAppRecord>.AppItem() {
+        val context = LocalContext.current
+        AppListButtonItem(
+            onClick = AppInfoSettingsProvider.navigator(app = record.app),
+            onButtonClick = { startUninstallActivity(context, record.app.packageName) },
+            buttonIcon = Icons.Outlined.Delete,
+            buttonIconDescription = stringResource(
+                R.string.background_install_uninstall_button_description))
+    }
+
+    override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
+        userIdFlow.combine(appListFlow) { userId, appList ->
+            appList.asyncMap { app ->
+                BackgroundInstalledAppListWithGroupingAppRecord(
+                        app = app,
+                        dateOfInstall = context.packageManager.getPackageInfoAsUser(app.packageName,
+                                PackageManager.PackageInfoFlags.of(0), userId).firstInstallTime
+                )
+            }
+        }
+
+    @Composable
+    override fun getSummary(option: Int, record: BackgroundInstalledAppListWithGroupingAppRecord)
+        = null
+
+    @Suppress
+    override fun filter(
+            userIdFlow: Flow<Int>,
+            option: Int,
+            recordListFlow: Flow<List<BackgroundInstalledAppListWithGroupingAppRecord>>
+    ): Flow<List<BackgroundInstalledAppListWithGroupingAppRecord>> {
+        if(backgroundInstallService == null) {
+            Log.e(tag, "Failed to retrieve Background Install Control Service")
+            return flowOf()
+        }
+        return userIdFlow.combine(recordListFlow) { userId, recordList ->
+            val appList = (backgroundInstallService.getBackgroundInstalledPackages(
+                PackageManager.MATCH_ALL.toLong(), userId) as ParceledListSlice<PackageInfo>).list
+            val appNameList = appList.map { it.packageName }
+            recordList.filter { record -> record.app.packageName in appNameList }
+        }
+    }
+
+    override fun getComparator(
+            option: Int,
+    ): Comparator<AppEntry<BackgroundInstalledAppListWithGroupingAppRecord>> =
+            compareByDescending { it.record.dateOfInstall }
+
+    override fun getGroupTitle(option: Int, record: BackgroundInstalledAppListWithGroupingAppRecord)
+    : String {
+        val groupByMonth = getGroupSeparationByMonth()
+        return when (record.dateOfInstall > System.currentTimeMillis()
+            - (groupByMonth * MONTH_IN_MILLIS)) {
+            true -> context.formatString(R.string.background_install_before, "count" to groupByMonth)
+            else -> context.formatString(R.string.background_install_after, "count" to groupByMonth)
+        }
+    }
+}
+
+private fun getGroupSeparationByMonth(): Int {
+    val month = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SETTINGS_UI, KEY_GROUPING_MONTH)
+    return try {
+        if (month.isNullOrBlank()) {
+            DEFAULT_GROUPING_MONTH_VALUE
+        } else {
+            month.toInt()
+        }
+    } catch (e: Exception) {
+        Log.d(
+            BackgroundInstalledAppsPageProvider.name, "Error parsing list grouping value: " +
+            "${e.message} falling back to default value: $DEFAULT_GROUPING_MONTH_VALUE")
+        DEFAULT_GROUPING_MONTH_VALUE
+    }
+}
diff --git a/src/com/android/settings/spa/notification/AppNotificationRepository.kt b/src/com/android/settings/spa/notification/AppNotificationRepository.kt
index 7ec5d3e..fe8babb 100644
--- a/src/com/android/settings/spa/notification/AppNotificationRepository.kt
+++ b/src/com/android/settings/spa/notification/AppNotificationRepository.kt
@@ -31,8 +31,10 @@
 import android.os.ServiceManager
 import android.util.Log
 import com.android.settings.R
+import com.android.settingslib.spa.framework.util.formatString
 import com.android.settingslib.spaprivileged.model.app.IPackageManagers
 import com.android.settingslib.spaprivileged.model.app.PackageManagers
+import com.android.settingslib.spaprivileged.model.app.userId
 import java.util.concurrent.TimeUnit
 import kotlin.math.max
 import kotlin.math.roundToInt
@@ -50,6 +52,11 @@
     var sentCount: Int = 0,
 )
 
+interface IAppNotificationRepository {
+    /** Gets the notification summary for the given application. */
+    fun getNotificationSummary(app: ApplicationInfo): String
+}
+
 class AppNotificationRepository(
     private val context: Context,
     private val packageManagers: IPackageManagers = PackageManagers,
@@ -59,7 +66,7 @@
     private val notificationManager: INotificationManager = INotificationManager.Stub.asInterface(
         ServiceManager.getService(Context.NOTIFICATION_SERVICE)
     ),
-) {
+) : IAppNotificationRepository {
     fun getAggregatedUsageEvents(userIdFlow: Flow<Int>): Flow<Map<String, NotificationSentState>> =
         userIdFlow.map { userId ->
             val aggregatedStats = mutableMapOf<String, NotificationSentState>()
@@ -115,6 +122,58 @@
         }
     }
 
+    override fun getNotificationSummary(app: ApplicationInfo): String {
+        if (!isEnabled(app)) return context.getString(R.string.off)
+        val channelCount = getChannelCount(app)
+        if (channelCount == 0) {
+            return calculateFrequencySummary(getSentCount(app))
+        }
+        val blockedChannelCount = getBlockedChannelCount(app)
+        if (channelCount == blockedChannelCount) return context.getString(R.string.off)
+        val frequencySummary = calculateFrequencySummary(getSentCount(app))
+        if (blockedChannelCount == 0) return frequencySummary
+        return context.getString(
+            R.string.notifications_enabled_with_info,
+            frequencySummary,
+            context.formatString(
+                R.string.notifications_categories_off, "count" to blockedChannelCount
+            )
+        )
+    }
+
+    private fun getSentCount(app: ApplicationInfo): Int {
+        var sentCount = 0
+        queryEventsForPackageForUser(app).forEachNotificationEvent { sentCount++ }
+        return sentCount
+    }
+
+    private fun queryEventsForPackageForUser(app: ApplicationInfo): UsageEvents? {
+        val now = System.currentTimeMillis()
+        val startTime = now - TimeUnit.DAYS.toMillis(DAYS_TO_CHECK)
+        return try {
+            usageStatsManager.queryEventsForPackageForUser(
+                startTime, now, app.userId, app.packageName, context.packageName
+            )
+        } catch (e: RemoteException) {
+            Log.e(TAG, "Failed IUsageStatsManager.queryEventsForPackageForUser(): ", e)
+            null
+        }
+    }
+
+    private fun getChannelCount(app: ApplicationInfo): Int = try {
+        notificationManager.getNumNotificationChannelsForPackage(app.packageName, app.uid, false)
+    } catch (e: Exception) {
+        Log.w(TAG, "Error calling INotificationManager", e)
+        0
+    }
+
+    private fun getBlockedChannelCount(app: ApplicationInfo): Int = try {
+        notificationManager.getBlockedChannelCount(app.packageName, app.uid)
+    } catch (e: Exception) {
+        Log.w(TAG, "Error calling INotificationManager", e)
+        0
+    }
+
     fun calculateFrequencySummary(sentCount: Int): String {
         val dailyFrequency = (sentCount.toFloat() / DAYS_TO_CHECK).roundToInt()
         return if (dailyFrequency > 0) {
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 44b41d0..7728b3e 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -127,7 +127,12 @@
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
+        if (preference != null && preference.getKey() != null) {
+            mMetricsFeatureProvider.logSettingsTileClick(preference.getKey(), getMetricsCategory());
+        }
         if (preference == mRemoveUserPref) {
+            mMetricsFeatureProvider.action(getActivity(),
+                    UserMetricsUtils.getRemoveUserMetricCategory(mUserInfo));
             if (canDeleteUser()) {
                 if (mUserInfo.isGuest()) {
                     showDialog(DIALOG_CONFIRM_RESET_GUEST);
@@ -137,6 +142,8 @@
                 return true;
             }
         } else if (preference == mSwitchUserPref) {
+            mMetricsFeatureProvider.action(getActivity(),
+                    UserMetricsUtils.getSwitchUserMetricCategory(mUserInfo));
             if (canSwitchUserNow()) {
                 if (shouldShowSetupPromptDialog()) {
                     showDialog(DIALOG_SETUP_USER);
@@ -164,9 +171,13 @@
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if (preference == mPhonePref) {
             if (Boolean.TRUE.equals(newValue)) {
+                mMetricsFeatureProvider.action(getActivity(),
+                        SettingsEnums.ACTION_ENABLE_USER_CALL);
                 showDialog(DIALOG_CONFIRM_ENABLE_CALLING_AND_SMS);
                 return false;
             }
+            mMetricsFeatureProvider.action(getActivity(),
+                    SettingsEnums.ACTION_DISABLE_USER_CALL);
             enableCallsAndSms(false);
         }
         return true;
@@ -364,9 +375,6 @@
     void switchUser() {
         Trace.beginSection("UserDetailSettings.switchUser");
         try {
-            if (mUserInfo.isGuest()) {
-                mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_SWITCH_TO_GUEST);
-            }
             if (mUserCaps.mIsGuest && mUserCaps.mIsEphemeral) {
                 int guestUserId = UserHandle.myUserId();
                 // Using markGuestForDeletion allows us to create a new guest before this one is
diff --git a/src/com/android/settings/users/UserMetricsUtils.java b/src/com/android/settings/users/UserMetricsUtils.java
new file mode 100644
index 0000000..bcbc01b
--- /dev/null
+++ b/src/com/android/settings/users/UserMetricsUtils.java
@@ -0,0 +1,56 @@
+/*
+ * 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.users;
+
+import android.app.settings.SettingsEnums;
+import android.content.pm.UserInfo;
+
+/**
+ * Utils class for metrics to avoid user characteristics checks in code
+ */
+public class UserMetricsUtils {
+
+    /**
+     * Returns relevant remove SettingsEnum key depending on UserInfo
+     * @param userInfo information about user
+     * @return list of RestrictionEntry objects with user-visible text.
+     */
+    public static int getRemoveUserMetricCategory(UserInfo userInfo) {
+        if (userInfo.isGuest()) {
+            return  SettingsEnums.ACTION_REMOVE_GUEST_USER;
+        }
+        if (userInfo.isRestricted()) {
+            return SettingsEnums.ACTION_REMOVE_RESTRICTED_USER;
+        }
+        return SettingsEnums.ACTION_REMOVE_USER;
+    }
+
+    /**
+     * Returns relevant switch user SettingsEnum key depending on UserInfo
+     * @param userInfo information about user
+     * @return SettingsEnums.
+     */
+    public static int getSwitchUserMetricCategory(UserInfo userInfo) {
+        if (userInfo.isGuest()) {
+            return  SettingsEnums.ACTION_SWITCH_TO_GUEST;
+        }
+        if (userInfo.isRestricted()) {
+            return SettingsEnums.ACTION_SWITCH_TO_RESTRICTED_USER;
+        }
+        return SettingsEnums.ACTION_SWITCH_TO_USER;
+    }
+}
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index ac2b26b..da6339b 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -1568,6 +1568,7 @@
 
     @Override
     public boolean onPreferenceClick(Preference pref) {
+        mMetricsFeatureProvider.logSettingsTileClick(pref.getKey(), getMetricsCategory());
         if (isCurrentUserGuest()) {
             if (mGuestResetPreference != null && pref == mGuestResetPreference) {
                 showDialog(DIALOG_CONFIRM_RESET_AND_RESTART_GUEST);
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityHearingAidsFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityHearingAidsFragmentTest.java
new file mode 100644
index 0000000..10cf4e1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityHearingAidsFragmentTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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 static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.testutils.XmlTestUtils;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+/** Tests for {@link AccessibilityHearingAidsFragment}. */
+@RunWith(RobolectricTestRunner.class)
+public class AccessibilityHearingAidsFragmentTest {
+
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+
+    @Test
+    public void getNonIndexableKeys_existInXmlLayout() {
+        final List<String> niks = AccessibilityHearingAidsFragment.SEARCH_INDEX_DATA_PROVIDER
+                .getNonIndexableKeys(mContext);
+        final List<String> keys =
+                XmlTestUtils.getKeysFromPreferenceXml(mContext, R.xml.accessibility_hearing_aids);
+
+        assertThat(keys).containsAtLeastElementsIn(niks);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
index 31e0782..52ccb37 100644
--- a/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/PreviewSizeSeekBarControllerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.widget.SeekBar;
 
 import androidx.preference.PreferenceScreen;
 import androidx.test.core.app.ApplicationProvider;
@@ -111,4 +112,15 @@
 
         verify(mInteractionListener).onProgressChanged();
     }
+
+    @Test
+    public void onProgressChanged_verifyNotifyPreferenceChanged() {
+        mSeekBarController.displayPreference(mPreferenceScreen);
+
+        mSeekBarPreference.setProgress(mSeekBarPreference.getMax());
+        mSeekBarPreference.onProgressChanged(new SeekBar(mContext), /* progress= */
+                0, /* fromUser= */ false);
+
+        verify(mInteractionListener).notifyPreferenceChanged();
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
index be01a8a..1311fe2 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.applications.manageapplications;
 
+import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NONE;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
@@ -117,7 +119,8 @@
 
     @Test
     public void twoTouchTarget() {
-        mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true);
+        mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true,
+                LIST_TYPE_NONE);
         mHolder = new ApplicationViewHolder(mView);
         assertThat(mHolder.mSwitch).isNotNull();
         assertThat(mHolder.mWidgetContainer.getChildCount()).isEqualTo(1);
@@ -126,7 +129,8 @@
     @Test
     public void updateSwitch() {
         final CountDownLatch latch = new CountDownLatch(1);
-        mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true);
+        mView = ApplicationViewHolder.newView(new FrameLayout(mContext), true,
+                LIST_TYPE_NONE);
         mHolder = new ApplicationViewHolder(mView);
         mHolder.updateSwitch((buttonView, isChecked) -> latch.countDown(), true, true);
 
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingControllerTest.java
new file mode 100644
index 0000000..92174f3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingControllerTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.util.FeatureFlagUtils;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link BluetoothDetailsAudioRoutingController}. */
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothDetailsAudioRoutingControllerTest extends
+        BluetoothDetailsControllerTestBase {
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
+    private BluetoothDetailsAudioRoutingController mController;
+
+    @Override
+    public void setUp() {
+        super.setUp();
+
+        mController = new BluetoothDetailsAudioRoutingController(mContext, mFragment, mCachedDevice,
+                mLifecycle);
+        mController.init(mScreen);
+    }
+
+    @Test
+    public void isAvailable_isHearingAidDevice_available() {
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_AUDIO_ROUTING, true);
+        when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_isNotHearingAidDevice_notAvailable() {
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_AUDIO_ROUTING, true);
+        when(mCachedDevice.isHearingAidDevice()).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsControllerTest.java
new file mode 100644
index 0000000..7590d61
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHearingDeviceControlsControllerTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.util.FeatureFlagUtils;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link BluetoothDetailsHearingDeviceControlsController}. */
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothDetailsHearingDeviceControlsControllerTest extends
+        BluetoothDetailsControllerTestBase {
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
+    private BluetoothDetailsHearingDeviceControlsController mController;
+
+    @Override
+    public void setUp() {
+        super.setUp();
+
+        mController = new BluetoothDetailsHearingDeviceControlsController(mContext, mFragment,
+                mCachedDevice, mLifecycle);
+    }
+
+    @Test
+    public void isAvailable_isHearingAidDevice_available() {
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, true);
+        when(mCachedDevice.isHearingAidDevice()).thenReturn(true);
+
+        assertThat(mController.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_isNotHearingAidDevice_notAvailable() {
+        FeatureFlagUtils.setEnabled(mContext,
+                FeatureFlagUtils.SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, true);
+        when(mCachedDevice.isHearingAidDevice()).thenReturn(false);
+
+        assertThat(mController.isAvailable()).isFalse();
+    }
+}
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 eea07fe..5cfe404 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
@@ -34,6 +34,8 @@
 
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.Observer;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
@@ -46,6 +48,7 @@
 import java.util.List;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
@@ -125,7 +128,7 @@
     @Test
     public void displayPreference_multiSim_shouldAddSecondPreference() {
         when(mTelephonyManager.getPhoneCount()).thenReturn(2);
-        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        SlotSimStatus slotSimStatus = new TestSlotSimStatus(mContext);
         mController.init(mFragment, slotSimStatus);
 
         mController.displayPreference(mScreen);
@@ -133,10 +136,11 @@
         verify(mCategory).addPreference(mSecondSimPreference);
     }
 
+    @Ignore
     @Test
     public void updateState_singleSim_shouldSetSingleSimTitleAndSummary() {
         when(mTelephonyManager.getPhoneCount()).thenReturn(1);
-        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        SlotSimStatus slotSimStatus = new TestSlotSimStatus(mContext);
         mController.init(mFragment, slotSimStatus);
         mController.displayPreference(mScreen);
 
@@ -146,10 +150,11 @@
         verify(mFirstSimPreference).setSummary(anyString());
     }
 
+    @Ignore
     @Test
     public void updateState_multiSim_shouldSetMultiSimTitleAndSummary() {
         when(mTelephonyManager.getPhoneCount()).thenReturn(2);
-        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        SlotSimStatus slotSimStatus = new TestSlotSimStatus(mContext);
         mController.init(mFragment, slotSimStatus);
         mController.displayPreference(mScreen);
 
@@ -163,12 +168,13 @@
         verify(mSecondSimPreference).setSummary(anyString());
     }
 
+    @Ignore
     @Test
     public void handlePreferenceTreeClick_shouldStartDialogFragment() {
         when(mFragment.getChildFragmentManager()).thenReturn(
                 mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS));
         when(mTelephonyManager.getPhoneCount()).thenReturn(2);
-        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        SlotSimStatus slotSimStatus = new TestSlotSimStatus(mContext);
         mController.init(mFragment, slotSimStatus);
         mController.displayPreference(mScreen);
 
@@ -180,7 +186,7 @@
     @Test
     public void updateDynamicRawDataToIndex_notAddToSearch_emptySimSlot() {
         doReturn(null).when(mSubscriptionManager).getActiveSubscriptionInfoList();
-        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        SlotSimStatus slotSimStatus = new TestSlotSimStatus(mContext);
         List<SearchIndexableRaw> rawData = new ArrayList<SearchIndexableRaw>();
 
         mController.init(mFragment, slotSimStatus);
@@ -191,10 +197,11 @@
 
     @Test
     public void updateDynamicRawDataToIndex_addToSearch_simInSimSlot() {
+        when(mTelephonyManager.getPhoneCount()).thenReturn(1);
         doReturn(false).when(mSubscriptionInfo).isEmbedded();
         doReturn(List.of(mSubscriptionInfo)).when(mSubscriptionManager)
                 .getActiveSubscriptionInfoList();
-        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        SlotSimStatus slotSimStatus = new TestSlotSimStatus(mContext);
         List<SearchIndexableRaw> rawData = new ArrayList<SearchIndexableRaw>();
 
         mController.init(mFragment, slotSimStatus);
@@ -203,23 +210,16 @@
         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);
     }
+
+    private class TestSlotSimStatus extends SlotSimStatus {
+        public TestSlotSimStatus(Context context) {
+            super(context);
+        }
+
+        public void observe(LifecycleOwner owner, Observer observer) {}
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
index 57963aa..839cae2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -371,8 +371,8 @@
     @Test
     public void getTotalHours_getExpectedResult() {
         Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = createBatteryHistoryMap(60);
-        BatteryLevelData batteryLevelData = DataProcessor.getBatteryLevelData(mContext, null,
-                batteryHistoryMap, null);
+        BatteryLevelData batteryLevelData =
+                DataProcessManager.getBatteryLevelData(mContext, null, batteryHistoryMap, null);
 
         final int totalHour = BatteryChartPreferenceController.getTotalHours(batteryLevelData);
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
index f8bcbc8..cb2f5c8 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
@@ -464,19 +464,6 @@
         assertThat(entry.getPackageName()).isEqualTo(expectedPackageName);
     }
 
-    @Test
-    public void getAppLabel_withOtherUsersUid_returnExpectedLabel() {
-        final ContentValues values = getContentValuesWithType(
-                ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
-        values.put(BatteryHistEntry.KEY_UID, BatteryUtils.UID_OTHER_USERS);
-
-        final BatteryDiffEntry batteryDiffEntry = createBatteryDiffEntry(
-                /*consumePower=*/ 0, new BatteryHistEntry(values));
-
-        assertThat(batteryDiffEntry.getAppLabel())
-                .isEqualTo(mContext.getString(R.string.battery_usage_other_users));
-    }
-
     private BatteryDiffEntry createBatteryDiffEntry(
             int consumerType, long uid, boolean isHidden) {
         final ContentValues values = getContentValuesWithType(consumerType);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
index b43727d..e5547c5 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
@@ -43,13 +43,18 @@
 import org.robolectric.Shadows;
 
 import java.time.Duration;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /** Tests for {@link BatteryUsageContentProvider}. */
 @RunWith(RobolectricTestRunner.class)
 public final class BatteryUsageContentProviderTest {
     private static final Uri VALID_BATTERY_STATE_CONTENT_URI = DatabaseUtils.BATTERY_CONTENT_URI;
+    private static final long TIMESTAMP1 = System.currentTimeMillis();
+    private static final long TIMESTAMP2 = System.currentTimeMillis() + 2;
+    private static final long TIMESTAMP3 = System.currentTimeMillis() + 4;
     private static final String PACKAGE_NAME1 = "com.android.settings1";
     private static final String PACKAGE_NAME2 = "com.android.settings2";
     private static final String PACKAGE_NAME3 = "com.android.settings3";
@@ -181,28 +186,48 @@
     }
 
     @Test
+    public void query_appUsageEvent_returnsExpectedResult() {
+        insertAppUsageEvent();
+
+        final List<Long> userIds1 = new ArrayList<>();
+        final long notExistingUserId = 3;
+        userIds1.add(USER_ID1);
+        userIds1.add(USER_ID2);
+        userIds1.add(notExistingUserId);
+        final Cursor cursor1 = getCursorOfAppUsage(userIds1, TIMESTAMP1);
+        assertThat(cursor1.getCount()).isEqualTo(3);
+        // Verifies the queried first battery state.
+        cursor1.moveToFirst();
+        assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME1);
+        // Verifies the queried second battery state.
+        cursor1.moveToNext();
+        assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME2);
+        // Verifies the queried third battery state.
+        cursor1.moveToNext();
+        assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
+
+        final List<Long> userIds2 = new ArrayList<>();
+        userIds2.add(USER_ID1);
+        final Cursor cursor2 = getCursorOfAppUsage(userIds2, TIMESTAMP3);
+        assertThat(cursor2.getCount()).isEqualTo(1);
+        // Verifies the queried first battery state.
+        cursor2.moveToFirst();
+        assertThat(cursor2.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
+    }
+
+    @Test
     public void query_appUsageTimestamp_returnsExpectedResult() throws Exception {
-        mProvider.onCreate();
-        final long timestamp1 = System.currentTimeMillis();
-        final long timestamp2 = timestamp1 + 2;
-        final long timestamp3 = timestamp1 + 4;
-        // Inserts some valid testing data.
-        BatteryTestUtils.insertDataToAppUsageEventTable(
-                mContext, USER_ID1, timestamp1, PACKAGE_NAME1);
-        BatteryTestUtils.insertDataToAppUsageEventTable(
-                mContext, USER_ID2, timestamp2, PACKAGE_NAME2);
-        BatteryTestUtils.insertDataToAppUsageEventTable(
-                mContext, USER_ID1, timestamp3, PACKAGE_NAME3);
+        insertAppUsageEvent();
 
         final Cursor cursor1 = getCursorOfLatestTimestamp(USER_ID1);
         assertThat(cursor1.getCount()).isEqualTo(1);
         cursor1.moveToFirst();
-        assertThat(cursor1.getLong(0)).isEqualTo(timestamp3);
+        assertThat(cursor1.getLong(0)).isEqualTo(TIMESTAMP3);
 
         final Cursor cursor2 = getCursorOfLatestTimestamp(USER_ID2);
         assertThat(cursor2.getCount()).isEqualTo(1);
         cursor2.moveToFirst();
-        assertThat(cursor2.getLong(0)).isEqualTo(timestamp2);
+        assertThat(cursor2.getLong(0)).isEqualTo(TIMESTAMP2);
 
         final long notExistingUserId = 3;
         final Cursor cursor3 = getCursorOfLatestTimestamp(notExistingUserId);
@@ -383,6 +408,17 @@
         return cursor;
     }
 
+    private void insertAppUsageEvent() {
+        mProvider.onCreate();
+        // Inserts some valid testing data.
+        BatteryTestUtils.insertDataToAppUsageEventTable(
+                mContext, USER_ID1, TIMESTAMP1, PACKAGE_NAME1);
+        BatteryTestUtils.insertDataToAppUsageEventTable(
+                mContext, USER_ID2, TIMESTAMP2, PACKAGE_NAME2);
+        BatteryTestUtils.insertDataToAppUsageEventTable(
+                mContext, USER_ID1, TIMESTAMP3, PACKAGE_NAME3);
+    }
+
     private Cursor getCursorOfLatestTimestamp(final long userId) {
         final Uri appUsageLatestTimestampQueryContentUri =
                 new Uri.Builder()
@@ -394,10 +430,28 @@
                         .build();
 
         return mProvider.query(
-                        appUsageLatestTimestampQueryContentUri,
-                        /*strings=*/ null,
-                        /*s=*/ null,
-                        /*strings1=*/ null,
-                        /*s1=*/ null);
+                appUsageLatestTimestampQueryContentUri,
+                /*strings=*/ null,
+                /*s=*/ null,
+                /*strings1=*/ null,
+                /*s1=*/ null);
+    }
+
+    private Cursor getCursorOfAppUsage(final List<Long> userIds, final long queryTimestamp) {
+        final String queryUserIdString = userIds.stream()
+                .map(userId -> String.valueOf(userId))
+                .collect(Collectors.joining(","));
+        final Uri appUsageEventUri =
+                new Uri.Builder()
+                        .scheme(ContentResolver.SCHEME_CONTENT)
+                        .authority(DatabaseUtils.AUTHORITY)
+                        .appendPath(DatabaseUtils.APP_USAGE_EVENT_TABLE)
+                        .appendQueryParameter(
+                                DatabaseUtils.QUERY_KEY_TIMESTAMP, Long.toString(queryTimestamp))
+                        .appendQueryParameter(DatabaseUtils.QUERY_KEY_USERID, queryUserIdString)
+                        .build();
+
+        return mProvider.query(
+                appUsageEventUri, /*strings=*/ null, /*s=*/ null, /*strings1=*/ null, /*s1=*/ null);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index 42cd7ef..fe1bff6 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -15,6 +15,9 @@
  */
 package com.android.settings.fuelgauge.batteryusage;
 
+import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
+import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -22,14 +25,17 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageEvents.Event;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.database.MatrixCursor;
 import android.os.BatteryManager;
 import android.os.BatteryUsageStats;
 import android.os.LocaleList;
+import android.os.RemoteException;
 import android.os.UserHandle;
 
 import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
@@ -55,6 +61,8 @@
     @Mock
     private BatteryUsageStats mBatteryUsageStats;
     @Mock
+    private IUsageStatsManager mUsageStatsManager;
+    @Mock
     private BatteryEntry mMockBatteryEntry;
 
     @Before
@@ -277,7 +285,7 @@
 
         final long userId = 2;
         final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
-                mContext, event, userId);
+                mContext, mUsageStatsManager, event, userId);
         assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
         assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.ACTIVITY_RESUMED);
         assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
@@ -298,7 +306,7 @@
 
         final long userId = 1;
         final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
-                mContext, event, userId);
+                mContext, mUsageStatsManager, event, userId);
         assertThat(appUsageEvent.getTimestamp()).isEqualTo(101L);
         assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
         assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
@@ -314,7 +322,7 @@
         event.mPackage = null;
 
         final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
-                mContext, event, /*userId=*/ 0);
+                mContext, mUsageStatsManager, event, /*userId=*/ 0);
 
         assertThat(appUsageEvent).isNull();
     }
@@ -330,12 +338,74 @@
 
         final long userId = 1;
         final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEvent(
-                mContext, event, userId);
+                mContext, mUsageStatsManager, event, userId);
 
         assertThat(appUsageEvent).isNull();
     }
 
     @Test
+    public void convertToAppUsageEventFromCursor_returnExpectedResult() {
+        final MatrixCursor cursor = new MatrixCursor(
+                new String[]{
+                        AppUsageEventEntity.KEY_UID,
+                        AppUsageEventEntity.KEY_USER_ID,
+                        AppUsageEventEntity.KEY_PACKAGE_NAME,
+                        AppUsageEventEntity.KEY_TIMESTAMP,
+                        AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE,
+                        AppUsageEventEntity.KEY_TASK_ROOT_PACKAGE_NAME,
+                        AppUsageEventEntity.KEY_INSTANCE_ID});
+        cursor.addRow(
+                new Object[]{
+                        101L,
+                        1001L,
+                        "com.android.settings1",
+                        10001L,
+                        AppUsageEventType.DEVICE_SHUTDOWN.getNumber(),
+                        "com.android.settings2",
+                        100001L});
+        cursor.moveToFirst();
+
+        final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEventFromCursor(cursor);
+
+        assertThat(appUsageEvent.getUid()).isEqualTo(101L);
+        assertThat(appUsageEvent.getUserId()).isEqualTo(1001L);
+        assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
+        assertThat(appUsageEvent.getTimestamp()).isEqualTo(10001L);
+        assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
+        assertThat(appUsageEvent.getTaskRootPackageName()).isEqualTo("com.android.settings2");
+        assertThat(appUsageEvent.getInstanceId()).isEqualTo(100001L);
+    }
+
+    @Test
+    public void convertToAppUsageEventFromCursor_emptyInstanceIdAndRootName_returnExpectedResult() {
+        final MatrixCursor cursor = new MatrixCursor(
+                new String[]{
+                        AppUsageEventEntity.KEY_UID,
+                        AppUsageEventEntity.KEY_USER_ID,
+                        AppUsageEventEntity.KEY_PACKAGE_NAME,
+                        AppUsageEventEntity.KEY_TIMESTAMP,
+                        AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE});
+        cursor.addRow(
+                new Object[]{
+                        101L,
+                        1001L,
+                        "com.android.settings1",
+                        10001L,
+                        AppUsageEventType.DEVICE_SHUTDOWN.getNumber()});
+        cursor.moveToFirst();
+
+        final AppUsageEvent appUsageEvent = ConvertUtils.convertToAppUsageEventFromCursor(cursor);
+
+        assertThat(appUsageEvent.getUid()).isEqualTo(101L);
+        assertThat(appUsageEvent.getUserId()).isEqualTo(1001L);
+        assertThat(appUsageEvent.getPackageName()).isEqualTo("com.android.settings1");
+        assertThat(appUsageEvent.getTimestamp()).isEqualTo(10001L);
+        assertThat(appUsageEvent.getType()).isEqualTo(AppUsageEventType.DEVICE_SHUTDOWN);
+        assertThat(appUsageEvent.getTaskRootPackageName()).isEqualTo("");
+        assertThat(appUsageEvent.getInstanceId()).isEqualTo(0);
+    }
+
+    @Test
     public void getLocale_nullContext_returnDefaultLocale() {
         assertThat(ConvertUtils.getLocale(/*context=*/ null))
                 .isEqualTo(Locale.getDefault());
@@ -352,4 +422,53 @@
         mContext.getResources().getConfiguration().setLocales(new LocaleList());
         assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
     }
+
+    @Test
+    public void getEffectivePackageName_currentActivity_returnPackageName() throws RemoteException {
+        when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_CURRENT_ACTIVITY);
+        final String packageName = "com.android.settings1";
+        final String taskRootPackageName = "com.android.settings2";
+
+        assertThat(ConvertUtils.getEffectivePackageName(
+                mUsageStatsManager, packageName, taskRootPackageName))
+                .isEqualTo(packageName);
+    }
+
+    @Test
+    public void getEffectivePackageName_usageSourceThrowException_returnPackageName()
+            throws RemoteException {
+        when(mUsageStatsManager.getUsageSource()).thenThrow(new RemoteException());
+        final String packageName = "com.android.settings1";
+        final String taskRootPackageName = "com.android.settings2";
+
+        assertThat(ConvertUtils.getEffectivePackageName(
+                mUsageStatsManager, packageName, taskRootPackageName))
+                .isEqualTo(packageName);
+    }
+
+    @Test
+    public void getEffectivePackageName_rootActivity_returnTaskRootPackageName()
+            throws RemoteException {
+        when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+        final String packageName = "com.android.settings1";
+        final String taskRootPackageName = "com.android.settings2";
+
+        assertThat(ConvertUtils.getEffectivePackageName(
+                mUsageStatsManager, packageName, taskRootPackageName))
+                .isEqualTo(taskRootPackageName);
+    }
+
+    @Test
+    public void getEffectivePackageName_nullOrEmptyTaskRoot_returnPackageName()
+            throws RemoteException {
+        when(mUsageStatsManager.getUsageSource()).thenReturn(USAGE_SOURCE_TASK_ROOT_ACTIVITY);
+        final String packageName = "com.android.settings1";
+
+        assertThat(ConvertUtils.getEffectivePackageName(
+                mUsageStatsManager, packageName, /*taskRootPackageName=*/ null))
+                .isEqualTo(packageName);
+        assertThat(ConvertUtils.getEffectivePackageName(
+                mUsageStatsManager, packageName, /*taskRootPackageName=*/ ""))
+                .isEqualTo(packageName);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
index a3578cb..ee37469 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessManagerTest.java
@@ -21,15 +21,23 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
+import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
+import android.database.MatrixCursor;
+import android.os.BatteryManager;
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.text.format.DateUtils;
+
+import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -40,10 +48,14 @@
 import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @RunWith(RobolectricTestRunner.class)
 public final class DataProcessManagerTest {
+    private static final String FAKE_ENTRY_KEY = "fake_entry_key";
+
     private Context mContext;
     private DataProcessManager mDataProcessManager;
 
@@ -51,6 +63,8 @@
     private IUsageStatsManager mUsageStatsManager;
     @Mock
     private UserManager mUserManager;
+    @Mock
+    private Intent mIntent;
 
     @Before
     public void setUp() {
@@ -62,14 +76,45 @@
         doReturn(mUserManager)
                 .when(mContext)
                 .getSystemService(UserManager.class);
+        doReturn(mIntent).when(mContext).registerReceiver(any(), any());
+        doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
+        doReturn(66).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_LEVEL), anyInt());
 
         mDataProcessManager = new DataProcessManager(
                 mContext, /*handler=*/ null,  /*callbackFunction=*/ null,
-                /*hourlyBatteryLevelsPerDay=*/ null, /*batteryHistoryMap=*/ null);
+                /*hourlyBatteryLevelsPerDay=*/ new ArrayList<>(), /*batteryHistoryMap=*/ null);
     }
 
     @Test
-    public void start_loadExpectedCurrentAppUsageData() throws RemoteException {
+    public void constructor_noLevelData() {
+        final DataProcessManager dataProcessManager =
+                new DataProcessManager(mContext, /*handler=*/ null, /*callbackFunction=*/ null);
+        assertThat(dataProcessManager.getShowScreenOnTime()).isFalse();
+        assertThat(dataProcessManager.getShowBatteryLevel()).isFalse();
+    }
+
+    @Test
+    public void start_loadEmptyDatabaseAppUsageData() {
+        final MatrixCursor cursor = new MatrixCursor(
+                new String[]{
+                        AppUsageEventEntity.KEY_UID,
+                        AppUsageEventEntity.KEY_PACKAGE_NAME,
+                        AppUsageEventEntity.KEY_TIMESTAMP});
+        DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+        doReturn(true).when(mUserManager).isUserUnlocked(anyInt());
+
+        mDataProcessManager.start();
+
+        assertThat(mDataProcessManager.getIsCurrentAppUsageLoaded()).isTrue();
+        assertThat(mDataProcessManager.getIsDatabaseAppUsageLoaded()).isTrue();
+        assertThat(mDataProcessManager.getIsCurrentBatteryHistoryLoaded()).isTrue();
+        assertThat(mDataProcessManager.getShowScreenOnTime()).isTrue();
+        assertThat(mDataProcessManager.getAppUsageEventList()).isEmpty();
+    }
+
+    @Test
+    public void start_loadExpectedAppUsageData() throws RemoteException {
+        // Fake current usage data.
         final UsageEvents.Event event1 =
                 getUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, /*timestamp=*/ 1);
         final UsageEvents.Event event2 =
@@ -82,6 +127,22 @@
                 .queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
         doReturn(true).when(mUserManager).isUserUnlocked(anyInt());
 
+        // Fake database usage data.
+        final MatrixCursor cursor = new MatrixCursor(
+                new String[]{
+                        AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE,
+                        AppUsageEventEntity.KEY_TIMESTAMP});
+        // Adds fake data into the cursor.
+        cursor.addRow(new Object[] {
+                AppUsageEventType.ACTIVITY_RESUMED.getNumber(), /*timestamp=*/ 3});
+        cursor.addRow(new Object[] {
+                AppUsageEventType.ACTIVITY_RESUMED.getNumber(), /*timestamp=*/ 4});
+        cursor.addRow(new Object[] {
+                AppUsageEventType.ACTIVITY_STOPPED.getNumber(), /*timestamp=*/ 5});
+        cursor.addRow(new Object[] {
+                AppUsageEventType.ACTIVITY_STOPPED.getNumber(), /*timestamp=*/ 6});
+        DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+
         mDataProcessManager.start();
 
         assertThat(mDataProcessManager.getIsCurrentAppUsageLoaded()).isTrue();
@@ -89,11 +150,19 @@
         assertThat(mDataProcessManager.getIsCurrentBatteryHistoryLoaded()).isTrue();
         assertThat(mDataProcessManager.getShowScreenOnTime()).isTrue();
         final List<AppUsageEvent> appUsageEventList = mDataProcessManager.getAppUsageEventList();
-        assertThat(appUsageEventList.size()).isEqualTo(2);
+        assertThat(appUsageEventList.size()).isEqualTo(6);
         assertAppUsageEvent(
                 appUsageEventList.get(0), AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1);
         assertAppUsageEvent(
                 appUsageEventList.get(1), AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 2);
+        assertAppUsageEvent(
+                appUsageEventList.get(2), AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 3);
+        assertAppUsageEvent(
+                appUsageEventList.get(3), AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 4);
+        assertAppUsageEvent(
+                appUsageEventList.get(4), AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 5);
+        assertAppUsageEvent(
+                appUsageEventList.get(5), AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 6);
     }
 
     @Test
@@ -106,6 +175,14 @@
                 .when(mUsageStatsManager)
                 .queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
         doReturn(false).when(mUserManager).isUserUnlocked(anyInt());
+        final MatrixCursor cursor = new MatrixCursor(
+                new String[]{
+                        AppUsageEventEntity.KEY_UID,
+                        AppUsageEventEntity.KEY_PACKAGE_NAME,
+                        AppUsageEventEntity.KEY_TIMESTAMP});
+        // Adds fake data into the cursor.
+        cursor.addRow(new Object[] {101L, "app name1", 1001L});
+        DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
 
         mDataProcessManager.start();
 
@@ -113,6 +190,102 @@
         assertThat(mDataProcessManager.getShowScreenOnTime()).isFalse();
     }
 
+    @Test
+    public void getStartTimestampOfBatteryLevelData_returnExpectedResult() {
+        final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
+                new ArrayList<>();
+        final List<Long> timestamps = new ArrayList<>();
+        timestamps.add(101L);
+        timestamps.add(1001L);
+        final List<Integer> levels = new ArrayList<>();
+        levels.add(1);
+        levels.add(2);
+        hourlyBatteryLevelsPerDay.add(null);
+        hourlyBatteryLevelsPerDay.add(
+                new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
+
+        final DataProcessManager dataProcessManager = new DataProcessManager(
+                mContext, /*handler=*/ null,  /*callbackFunction=*/ null,
+                hourlyBatteryLevelsPerDay, /*batteryHistoryMap=*/ null);
+
+        assertThat(dataProcessManager.getStartTimestampOfBatteryLevelData()).isEqualTo(101);
+    }
+
+    @Test
+    public void getStartTimestampOfBatteryLevelData_emptyLevels_returnZero() {
+        final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
+                new ArrayList<>();
+        hourlyBatteryLevelsPerDay.add(null);
+        hourlyBatteryLevelsPerDay.add(
+                new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
+
+        final DataProcessManager dataProcessManager = new DataProcessManager(
+                mContext, /*handler=*/ null,  /*callbackFunction=*/ null,
+                hourlyBatteryLevelsPerDay, /*batteryHistoryMap=*/ null);
+
+        assertThat(dataProcessManager.getStartTimestampOfBatteryLevelData()).isEqualTo(0);
+    }
+
+    @Test
+    public void getBatteryLevelData_emptyHistoryMap_returnNull() {
+        assertThat(DataProcessManager.getBatteryLevelData(
+                mContext,
+                /*handler=*/ null,
+                /*batteryHistoryMap=*/ null,
+                /*asyncResponseDelegate=*/ null))
+                .isNull();
+        assertThat(DataProcessManager.getBatteryLevelData(
+                mContext, /*handler=*/ null, new HashMap<>(), /*asyncResponseDelegate=*/ null))
+                .isNull();
+    }
+
+    @Test
+    public void getBatteryLevelData_notEnoughData_returnNull() {
+        // The timestamps and the current time are within half hour before an even hour.
+        final long[] timestamps = {
+                DateUtils.HOUR_IN_MILLIS * 2 - 300L,
+                DateUtils.HOUR_IN_MILLIS * 2 - 200L,
+                DateUtils.HOUR_IN_MILLIS * 2 - 100L};
+        final int[] levels = {100, 99, 98};
+        final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
+                createHistoryMap(timestamps, levels);
+        DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
+
+        assertThat(DataProcessManager.getBatteryLevelData(
+                mContext, /*handler=*/ null, batteryHistoryMap, /*asyncResponseDelegate=*/ null))
+                .isNull();
+    }
+
+    @Test
+    public void getBatteryLevelData_returnExpectedResult() {
+        // Timezone GMT+8: 2022-01-01 00:00:00, 2022-01-01 01:00:00
+        final long[] timestamps = {1640966400000L, 1640970000000L};
+        final int[] levels = {100, 99};
+        final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
+                createHistoryMap(timestamps, levels);
+        DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
+
+        final BatteryLevelData resultData =
+                DataProcessManager.getBatteryLevelData(
+                        mContext,
+                        /*handler=*/ null,
+                        batteryHistoryMap,
+                        /*asyncResponseDelegate=*/ null);
+
+        final List<Long> expectedDailyTimestamps = List.of(
+                1640966400000L,  // 2022-01-01 00:00:00
+                1640973600000L); // 2022-01-01 02:00:00
+        final List<Integer> expectedDailyLevels = List.of(100, 66);
+        final List<List<Long>> expectedHourlyTimestamps = List.of(expectedDailyTimestamps);
+        final List<List<Integer>> expectedHourlyLevels = List.of(expectedDailyLevels);
+        verifyExpectedBatteryLevelData(
+                resultData,
+                expectedDailyTimestamps,
+                expectedDailyLevels,
+                expectedHourlyTimestamps,
+                expectedHourlyLevels);
+    }
+
     private UsageEvents getUsageEvents(final List<UsageEvents.Event> events) {
         UsageEvents usageEvents = new UsageEvents(events, new String[] {"package"});
         Parcel parcel = Parcel.obtain();
@@ -131,9 +304,77 @@
         return event;
     }
 
+    private static Map<Long, Map<String, BatteryHistEntry>> createHistoryMap(
+            final long[] timestamps, final int[] levels) {
+        final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
+        for (int index = 0; index < timestamps.length; index++) {
+            final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
+            final ContentValues values = getContentValuesWithBatteryLevel(levels[index]);
+            final BatteryHistEntry entry = new BatteryHistEntry(values);
+            entryMap.put(FAKE_ENTRY_KEY, entry);
+            batteryHistoryMap.put(timestamps[index], entryMap);
+        }
+        return batteryHistoryMap;
+    }
+
+    private static ContentValues getContentValuesWithBatteryLevel(final int level) {
+        final ContentValues values = new ContentValues();
+        final DeviceBatteryState deviceBatteryState =
+                DeviceBatteryState
+                        .newBuilder()
+                        .setBatteryLevel(level)
+                        .build();
+        final BatteryInformation batteryInformation =
+                BatteryInformation
+                        .newBuilder()
+                        .setDeviceBatteryState(deviceBatteryState)
+                        .build();
+        values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
+                ConvertUtils.convertBatteryInformationToString(batteryInformation));
+        return values;
+    }
+
     private void assertAppUsageEvent(
             final AppUsageEvent event, final AppUsageEventType eventType, final long timestamp) {
         assertThat(event.getType()).isEqualTo(eventType);
         assertThat(event.getTimestamp()).isEqualTo(timestamp);
     }
+
+    private static void verifyExpectedBatteryLevelData(
+            final BatteryLevelData resultData,
+            final List<Long> expectedDailyTimestamps,
+            final List<Integer> expectedDailyLevels,
+            final List<List<Long>> expectedHourlyTimestamps,
+            final List<List<Integer>> expectedHourlyLevels) {
+        final BatteryLevelData.PeriodBatteryLevelData dailyResultData =
+                resultData.getDailyBatteryLevels();
+        final List<BatteryLevelData.PeriodBatteryLevelData> hourlyResultData =
+                resultData.getHourlyBatteryLevelsPerDay();
+        verifyExpectedDailyBatteryLevelData(
+                dailyResultData, expectedDailyTimestamps, expectedDailyLevels);
+        verifyExpectedHourlyBatteryLevelData(
+                hourlyResultData, expectedHourlyTimestamps, expectedHourlyLevels);
+    }
+
+    private static void verifyExpectedDailyBatteryLevelData(
+            final BatteryLevelData.PeriodBatteryLevelData dailyResultData,
+            final List<Long> expectedDailyTimestamps,
+            final List<Integer> expectedDailyLevels) {
+        assertThat(dailyResultData.getTimestamps()).isEqualTo(expectedDailyTimestamps);
+        assertThat(dailyResultData.getLevels()).isEqualTo(expectedDailyLevels);
+    }
+
+    private static void verifyExpectedHourlyBatteryLevelData(
+            final List<BatteryLevelData.PeriodBatteryLevelData> hourlyResultData,
+            final List<List<Long>> expectedHourlyTimestamps,
+            final List<List<Integer>> expectedHourlyLevels) {
+        final int expectedHourlySize = expectedHourlyTimestamps.size();
+        assertThat(hourlyResultData).hasSize(expectedHourlySize);
+        for (int dailyIndex = 0; dailyIndex < expectedHourlySize; dailyIndex++) {
+            assertThat(hourlyResultData.get(dailyIndex).getTimestamps())
+                    .isEqualTo(expectedHourlyTimestamps.get(dailyIndex));
+            assertThat(hourlyResultData.get(dailyIndex).getLevels())
+                    .isEqualTo(expectedHourlyLevels.get(dailyIndex));
+        }
+    }
 }
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 f0412df..aab3cb3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -41,7 +41,6 @@
 import android.os.UserManager;
 import android.text.format.DateUtils;
 
-import com.android.settings.fuelgauge.BatteryUtils;
 import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
 import com.android.settings.testutils.FakeFeatureFactory;
 
@@ -100,66 +99,6 @@
     }
 
     @Test
-    public void getBatteryLevelData_emptyHistoryMap_returnNull() {
-        assertThat(DataProcessor.getBatteryLevelData(
-                mContext,
-                /*handler=*/ null,
-                /*batteryHistoryMap=*/ null,
-                /*asyncResponseDelegate=*/ null))
-                .isNull();
-        assertThat(DataProcessor.getBatteryLevelData(
-                mContext, /*handler=*/ null, new HashMap<>(), /*asyncResponseDelegate=*/ null))
-                .isNull();
-    }
-
-    @Test
-    public void getBatteryLevelData_notEnoughData_returnNull() {
-        // The timestamps and the current time are within half hour before an even hour.
-        final long[] timestamps = {
-                DateUtils.HOUR_IN_MILLIS * 2 - 300L,
-                DateUtils.HOUR_IN_MILLIS * 2 - 200L,
-                DateUtils.HOUR_IN_MILLIS * 2 - 100L};
-        final int[] levels = {100, 99, 98};
-        final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
-                createHistoryMap(timestamps, levels);
-        DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
-
-        assertThat(DataProcessor.getBatteryLevelData(
-                mContext, /*handler=*/ null, batteryHistoryMap, /*asyncResponseDelegate=*/ null))
-                .isNull();
-    }
-
-    @Test
-    public void getBatteryLevelData_returnExpectedResult() {
-        // Timezone GMT+8: 2022-01-01 00:00:00, 2022-01-01 01:00:00
-        final long[] timestamps = {1640966400000L, 1640970000000L};
-        final int[] levels = {100, 99};
-        final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
-                createHistoryMap(timestamps, levels);
-        DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
-
-        final BatteryLevelData resultData =
-                DataProcessor.getBatteryLevelData(
-                        mContext,
-                        /*handler=*/ null,
-                        batteryHistoryMap,
-                        /*asyncResponseDelegate=*/ null);
-
-        final List<Long> expectedDailyTimestamps = List.of(
-                1640966400000L,  // 2022-01-01 00:00:00
-                1640973600000L); // 2022-01-01 02:00:00
-        final List<Integer> expectedDailyLevels = List.of(100, 66);
-        final List<List<Long>> expectedHourlyTimestamps = List.of(expectedDailyTimestamps);
-        final List<List<Integer>> expectedHourlyLevels = List.of(expectedDailyLevels);
-        verifyExpectedBatteryLevelData(
-                resultData,
-                expectedDailyTimestamps,
-                expectedDailyLevels,
-                expectedHourlyTimestamps,
-                expectedHourlyLevels);
-    }
-
-    @Test
     public void getAppUsageEvents_returnExpectedResult() throws RemoteException {
         UserInfo userInfo = new UserInfo(/*id=*/ 0, "user_0", /*flags=*/ 0);
         final List<UserInfo> userInfoList = new ArrayList<>();
@@ -213,7 +152,7 @@
                 .when(mUsageStatsManager)
                 .queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
 
-        assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId))
+        assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0))
                 .isEqualTo(mUsageEvents1);
     }
 
@@ -223,7 +162,7 @@
         // Test locked user.
         doReturn(false).when(mUserManager).isUserUnlocked(userId);
 
-        assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId)).isNull();
+        assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0)).isNull();
     }
 
     @Test
@@ -233,7 +172,7 @@
         doReturn(null)
                 .when(mUsageStatsManager).queryEventsForUser(anyLong(), anyLong(), anyInt(), any());
 
-        assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId)).isNull();
+        assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0)).isNull();
     }
 
     @Test public void generateAppUsageEventListFromUsageEvents_returnExpectedResult() {
@@ -647,6 +586,7 @@
     public void getBatteryUsageMap_emptyHistoryMap_returnNull() {
         final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
                 new ArrayList<>();
+
         hourlyBatteryLevelsPerDay.add(
                 new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
 
@@ -933,13 +873,7 @@
                 /*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
                 /*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
                 /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 10);
-        assertBatteryDiffEntry(
-                resultDiffData.getSystemDiffEntryList().get(0), BatteryUtils.UID_OTHER_USERS,
-                /*uid=*/ BatteryUtils.UID_OTHER_USERS, ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
-                /*consumePercentage=*/ 100.0,
-                /*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
-                /*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
-                /*foregroundUsageTimeInMs=*/ 0, /*backgroundUsageTimeInMs=*/ 0);
+        assertThat(resultDiffData.getSystemDiffEntryList()).isEmpty();
         assertThat(resultMap.get(0).get(0)).isNotNull();
         assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
index a04baa0..7d04e85 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtilsTest.java
@@ -277,6 +277,62 @@
     }
 
     @Test
+    public void getAppUsageEventForUsers_emptyCursorContent_returnEmptyMap() {
+        final MatrixCursor cursor = new MatrixCursor(
+                new String[]{
+                        AppUsageEventEntity.KEY_UID,
+                        AppUsageEventEntity.KEY_USER_ID,
+                        AppUsageEventEntity.KEY_PACKAGE_NAME,
+                        AppUsageEventEntity.KEY_TIMESTAMP,
+                        AppUsageEventEntity.KEY_APP_USAGE_EVENT_TYPE});
+        DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+
+        assertThat(DatabaseUtils.getAppUsageEventForUsers(
+                mContext,
+                /*calendar=*/ null,
+                /*userIds=*/ new ArrayList<>(),
+                /*startTimestampOfLevelData=*/ 0)).isEmpty();
+    }
+
+    @Test
+    public void getAppUsageEventForUsers_nullCursor_returnEmptyMap() {
+        DatabaseUtils.sFakeAppUsageEventSupplier = () -> null;
+        assertThat(DatabaseUtils.getAppUsageEventForUsers(
+                mContext,
+                /*calendar=*/ null,
+                /*userIds=*/ new ArrayList<>(),
+                /*startTimestampOfLevelData=*/ 0)).isEmpty();
+    }
+
+    @Test
+    public void getAppUsageEventForUsers_returnExpectedMap() {
+        final Long timestamp1 = 1001L;
+        final Long timestamp2 = 1002L;
+        final MatrixCursor cursor = new MatrixCursor(
+                new String[]{
+                        AppUsageEventEntity.KEY_UID,
+                        AppUsageEventEntity.KEY_PACKAGE_NAME,
+                        AppUsageEventEntity.KEY_TIMESTAMP});
+        // Adds fake data into the cursor.
+        cursor.addRow(new Object[] {101L, "app name1", timestamp1});
+        cursor.addRow(new Object[] {101L, "app name2", timestamp2});
+        cursor.addRow(new Object[] {101L, "app name3", timestamp2});
+        cursor.addRow(new Object[] {101L, "app name4", timestamp2});
+        DatabaseUtils.sFakeAppUsageEventSupplier = () -> cursor;
+
+        final List<AppUsageEvent> appUsageEventList = DatabaseUtils.getAppUsageEventForUsers(
+                mContext,
+                /*calendar=*/ null,
+                /*userIds=*/ new ArrayList<>(),
+                /*startTimestampOfLevelData=*/ 0);
+
+        assertThat(appUsageEventList.get(0).getPackageName()).isEqualTo("app name1");
+        assertThat(appUsageEventList.get(1).getPackageName()).isEqualTo("app name2");
+        assertThat(appUsageEventList.get(2).getPackageName()).isEqualTo("app name3");
+        assertThat(appUsageEventList.get(3).getPackageName()).isEqualTo("app name4");
+    }
+
+    @Test
     public void getHistoryMapSinceLastFullCharge_emptyCursorContent_returnEmptyMap() {
         final MatrixCursor cursor = new MatrixCursor(
                 new String[] {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDaoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDaoTest.java
index ade585f..4883d4f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDaoTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/AppUsageEventDaoTest.java
@@ -31,11 +31,13 @@
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /** Tests for {@link AppUsageEventDao}. */
 @RunWith(RobolectricTestRunner.class)
 public final class AppUsageEventDaoTest {
+    private static final int CURSOR_COLUMN_SIZE = 8;
     private static final long TIMESTAMP1 = System.currentTimeMillis();
     private static final long TIMESTAMP2 = System.currentTimeMillis() + 2;
     private static final long TIMESTAMP3 = System.currentTimeMillis() + 4;
@@ -78,6 +80,36 @@
     }
 
     @Test
+    public void appUsageEventDao_getAllForUsersAfter() {
+        final List<Long> userIds1 = new ArrayList<>();
+        final long notExistingUserId = 3;
+        userIds1.add(USER_ID1);
+        userIds1.add(USER_ID2);
+        userIds1.add(notExistingUserId);
+        final Cursor cursor1 = mAppUsageEventDao.getAllForUsersAfter(userIds1, TIMESTAMP1);
+        assertThat(cursor1.getCount()).isEqualTo(3);
+        assertThat(cursor1.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
+        // Verifies the queried first battery state.
+        cursor1.moveToFirst();
+        assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME1);
+        // Verifies the queried second battery state.
+        cursor1.moveToNext();
+        assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME2);
+        // Verifies the queried third battery state.
+        cursor1.moveToNext();
+        assertThat(cursor1.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
+
+        final List<Long> userIds2 = new ArrayList<>();
+        userIds2.add(USER_ID1);
+        final Cursor cursor2 = mAppUsageEventDao.getAllForUsersAfter(userIds2, TIMESTAMP3);
+        assertThat(cursor2.getCount()).isEqualTo(1);
+        assertThat(cursor2.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
+        // Verifies the queried first battery state.
+        cursor2.moveToFirst();
+        assertThat(cursor2.getString(5 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
+    }
+
+    @Test
     public void appUsageEventDao_getLatestTimestampOfUser() throws Exception {
         final Cursor cursor1 = mAppUsageEventDao.getLatestTimestampOfUser(USER_ID1);
         assertThat(cursor1.getCount()).isEqualTo(1);
diff --git a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
index ff57ebc..14ca76f 100644
--- a/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/users/UserDetailsSettingsTest.java
@@ -91,6 +91,7 @@
     private static final String KEY_APP_COPYING = "app_copying";
 
     private static final int DIALOG_CONFIRM_REMOVE = 1;
+    private static final int DIALOG_CONFIRM_RESET_GUEST = 4;
 
     @Mock
     private TelephonyManager mTelephonyManager;
@@ -469,8 +470,24 @@
         mFragment.onPreferenceClick(mSwitchUserPref);
 
         verify(mFragment).switchUser();
-        verify(mMetricsFeatureProvider, never()).action(any(),
-                eq(SettingsEnums.ACTION_SWITCH_TO_GUEST));
+        verify(mMetricsFeatureProvider).action(any(),
+                eq(SettingsEnums.ACTION_SWITCH_TO_USER));
+    }
+
+    @Test
+    public void onPreferenceClick_switchToRestrictedClicked_canSwitch_shouldSwitch() {
+        setupSelectedRestrictedUser();
+        mUserManager.setSwitchabilityStatus(SWITCHABILITY_STATUS_OK);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+        mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
+        mFragment.mUserInfo = mUserInfo;
+
+        mFragment.onPreferenceClick(mSwitchUserPref);
+
+        verify(mFragment).switchUser();
+        verify(mMetricsFeatureProvider).action(any(),
+                eq(SettingsEnums.ACTION_SWITCH_TO_RESTRICTED_USER));
     }
 
     @Test
@@ -503,6 +520,41 @@
     }
 
     @Test
+    public void onPreferenceClick_removeGuestClicked_canDelete_shouldShowDialog() {
+        setupSelectedGuest();
+        mFragment.mUserInfo = mUserInfo;
+        mUserManager.setIsAdminUser(true);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+        mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
+        doNothing().when(mFragment).showDialog(anyInt());
+
+        mFragment.onPreferenceClick(mRemoveUserPref);
+
+        verify(mMetricsFeatureProvider).action(any(), eq(SettingsEnums.ACTION_REMOVE_GUEST_USER));
+        verify(mFragment).canDeleteUser();
+        verify(mFragment).showDialog(DIALOG_CONFIRM_RESET_GUEST);
+    }
+
+    @Test
+    public void onPreferenceClick_removeRestrictedClicked_canDelete_shouldShowDialog() {
+        setupSelectedRestrictedUser();
+        mFragment.mUserInfo = mUserInfo;
+        mUserManager.setIsAdminUser(true);
+        mFragment.mSwitchUserPref = mSwitchUserPref;
+        mFragment.mRemoveUserPref = mRemoveUserPref;
+        mFragment.mAppAndContentAccessPref = mAppAndContentAccessPref;
+        doNothing().when(mFragment).showDialog(anyInt());
+
+        mFragment.onPreferenceClick(mRemoveUserPref);
+
+        verify(mMetricsFeatureProvider)
+                .action(any(), eq(SettingsEnums.ACTION_REMOVE_RESTRICTED_USER));
+        verify(mFragment).canDeleteUser();
+        verify(mFragment).showDialog(DIALOG_CONFIRM_REMOVE);
+    }
+
+    @Test
     public void onPreferenceClick_removeClicked_canDelete_shouldShowDialog() {
         setupSelectedUser();
         mFragment.mUserInfo = mUserInfo;
@@ -514,6 +566,7 @@
 
         mFragment.onPreferenceClick(mRemoveUserPref);
 
+        verify(mMetricsFeatureProvider).action(any(), eq(SettingsEnums.ACTION_REMOVE_USER));
         verify(mFragment).canDeleteUser();
         verify(mFragment).showDialog(DIALOG_CONFIRM_REMOVE);
     }
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppNotificationPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppNotificationPreferenceTest.kt
new file mode 100644
index 0000000..c54d35f
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppNotificationPreferenceTest.kt
@@ -0,0 +1,122 @@
+/*
+ * 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.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.onRoot
+import androidx.compose.ui.test.performClick
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.settings.R
+import com.android.settings.applications.appinfo.AppInfoDashboardFragment
+import com.android.settings.notification.app.AppNotificationSettings
+import com.android.settings.spa.notification.IAppNotificationRepository
+import com.android.settingslib.spa.testutils.delay
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoSession
+import org.mockito.Spy
+import org.mockito.quality.Strictness
+
+@RunWith(AndroidJUnit4::class)
+class AppNotificationPreferenceTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    private lateinit var mockSession: MockitoSession
+
+    @Spy
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    private val repository = object : IAppNotificationRepository {
+        override fun getNotificationSummary(app: ApplicationInfo) = SUMMARY
+    }
+
+    @Before
+    fun setUp() {
+        mockSession = ExtendedMockito.mockitoSession()
+            .initMocks(this)
+            .mockStatic(AppInfoDashboardFragment::class.java)
+            .strictness(Strictness.LENIENT)
+            .startMocking()
+    }
+
+    @After
+    fun tearDown() {
+        mockSession.finishMocking()
+    }
+
+    @Test
+    fun title_displayed() {
+        setContent()
+
+        composeTestRule.onNodeWithText(context.getString(R.string.notifications_label))
+            .assertIsDisplayed()
+    }
+
+    @Test
+    fun summary_displayed() {
+        setContent()
+
+        composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
+    }
+
+    @Test
+    fun onClick_startActivity() {
+        setContent()
+
+        composeTestRule.onRoot().performClick()
+        composeTestRule.delay()
+
+        ExtendedMockito.verify {
+            AppInfoDashboardFragment.startAppInfoFragment(
+                AppNotificationSettings::class.java,
+                APP,
+                context,
+                AppInfoSettingsProvider.METRICS_CATEGORY,
+            )
+        }
+    }
+
+    private fun setContent() {
+        composeTestRule.setContent {
+            CompositionLocalProvider(LocalContext provides context) {
+                AppNotificationPreference(app = APP, repository = repository)
+            }
+        }
+    }
+
+    private companion object {
+        const val PACKAGE_NAME = "package.name"
+        const val UID = 123
+        val APP = ApplicationInfo().apply {
+            packageName = PACKAGE_NAME
+            uid = UID
+        }
+        const val SUMMARY = "Summary"
+    }
+}
\ No newline at end of file
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/backgroundinstall/BackgroundInstalledAppsPageProviderTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/backgroundinstall/BackgroundInstalledAppsPageProviderTest.kt
new file mode 100644
index 0000000..8e1757f
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/spa/app/backgroundinstall/BackgroundInstalledAppsPageProviderTest.kt
@@ -0,0 +1,319 @@
+/*
+ * 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.spa.app.backgroundinstall
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.content.pm.IBackgroundInstallControlService
+import android.content.pm.PackageInfo
+import android.content.pm.PackageManager
+import android.content.pm.ParceledListSlice
+import android.net.Uri
+import android.os.UserHandle
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.testutils.FakeNavControllerWrapper
+import com.android.settingslib.spa.testutils.any
+import com.android.settingslib.spaprivileged.template.app.AppListItemModel
+import com.google.common.truth.Truth
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+
+@RunWith(AndroidJUnit4::class)
+class BackgroundInstalledAppsPageProviderTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val mockito: MockitoRule = MockitoJUnit.rule()
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Mock
+    private lateinit var mockContext: Context
+
+    @Mock
+    private lateinit var mockPackageManager: PackageManager
+
+    @Mock
+    private lateinit var mockBackgroundInstallControlService: IBackgroundInstallControlService
+
+    private var packageInfoFlagsCaptor =
+        ArgumentCaptor.forClass(PackageManager.PackageInfoFlags::class.java)
+
+    private var intentCaptor =
+        ArgumentCaptor.forClass(Intent::class.java)
+
+    private val fakeNavControllerWrapper = FakeNavControllerWrapper()
+
+    @Before
+    fun setup() {
+        Mockito.`when`(mockContext.packageManager).thenReturn(mockPackageManager)
+    }
+    @Test
+    fun allAppListPageProvider_name() {
+        Truth.assertThat(BackgroundInstalledAppsPageProvider.name)
+            .isEqualTo(EXPECTED_PROVIDER_NAME)
+    }
+
+    @Test
+    fun injectEntry_title() {
+        Mockito.`when`(mockBackgroundInstallControlService
+            .getBackgroundInstalledPackages(any(Long::class.java), any(Int::class.java)))
+            .thenReturn(ParceledListSlice(listOf()))
+        setInjectEntry(false)
+
+        composeTestRule.onNodeWithText(
+            context.getString(R.string.background_install_title)).assertIsDisplayed()
+    }
+
+    @Test
+    fun injectEntry_title_disabled() {
+        setInjectEntry(true)
+
+        composeTestRule.onNodeWithText(
+            context.getString(R.string.background_install_title)).assertDoesNotExist()
+    }
+
+    @Test
+    fun injectEntry_summary() {
+        Mockito.`when`(mockBackgroundInstallControlService
+            .getBackgroundInstalledPackages(any(Long::class.java), any(Int::class.java)))
+            .thenReturn(ParceledListSlice(listOf()))
+        setInjectEntry(false)
+
+        composeTestRule.onNodeWithText("0 apps").assertIsDisplayed()
+    }
+
+    @Test
+    fun injectEntry_summary_disabled() {
+        setInjectEntry(true)
+
+        composeTestRule.onNodeWithText("0 apps").assertDoesNotExist()
+    }
+
+    @Test
+    fun injectEntry_onClick_navigate() {
+        Mockito.`when`(mockBackgroundInstallControlService
+            .getBackgroundInstalledPackages(any(Long::class.java), any(Int::class.java)))
+            .thenReturn(ParceledListSlice(listOf()))
+        setInjectEntry(false)
+
+        composeTestRule.onNodeWithText(
+            context.getString(R.string.background_install_title)).performClick()
+
+        Truth.assertThat(fakeNavControllerWrapper.navigateCalledWith)
+            .isEqualTo(EXPECTED_PROVIDER_NAME)
+    }
+
+    private fun setInjectEntry(disableFeature: Boolean = false) {
+        composeTestRule.setContent {
+            fakeNavControllerWrapper.Wrapper {
+                BackgroundInstalledAppsPageProvider
+                    .setBackgroundInstallControlService(mockBackgroundInstallControlService)
+                    .setDisableFeature(disableFeature)
+                    .buildInjectEntry().build().UiLayout()
+            }
+        }
+    }
+
+    @Test
+    fun title_displayed() {
+        composeTestRule.setContent {
+            BackgroundInstalledAppList()
+        }
+
+        composeTestRule.onNodeWithText(
+            context.getString(R.string.background_install_title)).assertIsDisplayed()
+    }
+
+    @Test
+    fun item_labelDisplayed() {
+        setItemContent()
+
+        composeTestRule.onNodeWithText(TEST_LABEL).assertIsDisplayed()
+    }
+
+    @Test
+    fun item_onClick_navigate() {
+        setItemContent()
+
+        composeTestRule.onNodeWithText(TEST_LABEL).performClick()
+
+        Truth.assertThat(fakeNavControllerWrapper.navigateCalledWith)
+            .isEqualTo("AppInfoSettings/package.name/0")
+    }
+
+    @Suppress
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun startUninstallActivity_success() = runTest {
+        val expectedPackageUri = Uri.parse("package:package.name")
+        val mockUserHandle = UserHandle(0)
+        Mockito.`when`(mockContext.user).thenReturn(mockUserHandle)
+        Mockito.`when`(mockContext.startActivityAsUser(
+            intentCaptor.capture(),
+            eq(mockUserHandle)
+        )).then {  }
+
+        startUninstallActivity(mockContext, TEST_PACKAGE_NAME)
+
+        Truth.assertThat(intentCaptor.value.action).isEqualTo(Intent.ACTION_UNINSTALL_PACKAGE)
+        Truth.assertThat(intentCaptor.value.data).isEqualTo(expectedPackageUri)
+        Truth.assertThat(intentCaptor.value.extras?.getBoolean(Intent.EXTRA_UNINSTALL_ALL_USERS))
+            .isEqualTo(false)
+    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun backgroundInstalledAppsWithGroupingListModel_getGroupTitleOne() = runTest {
+        val listModel = BackgroundInstalledAppsWithGroupingListModel(context)
+
+        val actualGroupTitle = listModel
+            .getGroupTitle(0,
+                BackgroundInstalledAppListWithGroupingAppRecord(
+                    APP,
+                    System.currentTimeMillis()
+                ))
+
+        Truth.assertThat(actualGroupTitle).isEqualTo("Apps installed in the last 6 months")
+    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun backgroundInstalledAppsWithGroupingListModel_getGroupTitleTwo() = runTest {
+        val listModel = BackgroundInstalledAppsWithGroupingListModel(context)
+
+        val actualGroupTitle = listModel
+            .getGroupTitle(0,
+                BackgroundInstalledAppListWithGroupingAppRecord(
+                APP,
+                    0L
+        ))
+
+        Truth.assertThat(actualGroupTitle).isEqualTo("Apps installed more than 6 months ago")
+    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun backgroundInstalledAppsWithGroupingListModel_transform() = runTest {
+        val listModel = BackgroundInstalledAppsWithGroupingListModel(mockContext)
+        Mockito.`when`(mockPackageManager.getPackageInfoAsUser(
+            eq(TEST_PACKAGE_NAME),
+            packageInfoFlagsCaptor.capture(),
+            eq(TEST_USER_ID))
+        )
+            .thenReturn(PACKAGE_INFO)
+        val recordListFlow = listModel.transform(flowOf(TEST_USER_ID), flowOf(listOf(APP)))
+
+        val recordList = recordListFlow.first()
+
+        Truth.assertThat(recordList).hasSize(1)
+        Truth.assertThat(recordList[0].app).isSameInstanceAs(APP)
+        Truth.assertThat(packageInfoFlagsCaptor.value.value).isEqualTo(EXPECTED_PACKAGE_INFO_FLAG)
+    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun backgroundInstalledAppsWithGroupingListModel_filter() = runTest {
+        val listModel = BackgroundInstalledAppsWithGroupingListModel(mockContext)
+        listModel.setBackgroundInstallControlService(mockBackgroundInstallControlService)
+        Mockito.`when`(mockBackgroundInstallControlService.getBackgroundInstalledPackages(
+            PackageManager.MATCH_ALL.toLong(),
+            TEST_USER_ID
+        )).thenReturn(ParceledListSlice(listOf(PACKAGE_INFO)))
+
+        val recordListFlow = listModel.filter(
+            flowOf(TEST_USER_ID),
+            0,
+            flowOf(listOf(APP_RECORD_WITH_PACKAGE_MATCH, APP_RECORD_WITHOUT_PACKAGE_MATCH))
+        )
+
+
+        val recordList = recordListFlow.first()
+        Truth.assertThat(recordList).hasSize(1)
+        Truth.assertThat(recordList[0]).isSameInstanceAs(APP_RECORD_WITH_PACKAGE_MATCH)
+    }
+
+    private fun setItemContent() {
+        composeTestRule.setContent {
+            BackgroundInstalledAppList {
+                fakeNavControllerWrapper.Wrapper {
+                    with(BackgroundInstalledAppsWithGroupingListModel(context)) {
+                        AppListItemModel(
+                            record = BackgroundInstalledAppListWithGroupingAppRecord(
+                                app = APP,
+                                dateOfInstall = TEST_FIRST_INSTALL_TIME),
+                            label = TEST_LABEL,
+                            summary = stateOf(TEST_SUMMARY),
+                        ).AppItem()
+                    }
+                }
+            }
+        }
+    }
+
+    private companion object {
+        private const val TEST_USER_ID = 0
+        private const val TEST_PACKAGE_NAME = "package.name"
+        private const val TEST_NO_MATCH_PACKAGE_NAME = "no.match"
+        private const val TEST_LABEL = "Label"
+        private const val TEST_SUMMARY = "Summary"
+        private const val TEST_FIRST_INSTALL_TIME = 0L
+        private const val EXPECTED_PROVIDER_NAME = "BackgroundInstalledAppsPage"
+        private const val EXPECTED_PACKAGE_INFO_FLAG = 0L
+
+        val APP = ApplicationInfo().apply {
+            packageName = TEST_PACKAGE_NAME
+        }
+        val APP_NO_RECORD = ApplicationInfo().apply {
+            packageName = TEST_NO_MATCH_PACKAGE_NAME
+        }
+        val APP_RECORD_WITH_PACKAGE_MATCH = BackgroundInstalledAppListWithGroupingAppRecord(
+            APP,
+            TEST_FIRST_INSTALL_TIME
+        )
+        val APP_RECORD_WITHOUT_PACKAGE_MATCH = BackgroundInstalledAppListWithGroupingAppRecord(
+            APP_NO_RECORD,
+            TEST_FIRST_INSTALL_TIME
+        )
+        val PACKAGE_INFO = PackageInfo().apply {
+            packageName = TEST_PACKAGE_NAME
+            applicationInfo = APP
+            firstInstallTime = TEST_FIRST_INSTALL_TIME
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/spa_unit/src/com/android/settings/spa/notification/AppNotificationRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/spa/notification/AppNotificationRepositoryTest.kt
index 7a5bc9f..a1d8d3f 100644
--- a/tests/spa_unit/src/com/android/settings/spa/notification/AppNotificationRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/notification/AppNotificationRepositoryTest.kt
@@ -29,8 +29,10 @@
 import android.os.Build
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
 import com.android.settingslib.spa.testutils.any
 import com.android.settingslib.spaprivileged.model.app.IPackageManagers
+import com.android.settingslib.spaprivileged.model.app.userId
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.first
@@ -89,6 +91,39 @@
         return channel
     }
 
+    private fun mockIsEnabled(app: ApplicationInfo, enabled: Boolean) {
+        whenever(notificationManager.areNotificationsEnabledForPackage(app.packageName, app.uid))
+            .thenReturn(enabled)
+    }
+
+    private fun mockChannelCount(app: ApplicationInfo, count: Int) {
+        whenever(
+            notificationManager.getNumNotificationChannelsForPackage(
+                app.packageName,
+                app.uid,
+                false,
+            )
+        ).thenReturn(count)
+    }
+
+    private fun mockBlockedChannelCount(app: ApplicationInfo, count: Int) {
+        whenever(notificationManager.getBlockedChannelCount(app.packageName, app.uid))
+            .thenReturn(count)
+    }
+
+    private fun mockSentCount(app: ApplicationInfo, sentCount: Int) {
+        val events = (1..sentCount).map {
+            UsageEvents.Event().apply {
+                mEventType = UsageEvents.Event.NOTIFICATION_INTERRUPTION
+            }
+        }
+        whenever(
+            usageStatsManager.queryEventsForPackageForUser(
+                any(), any(), eq(app.userId), eq(app.packageName), any()
+            )
+        ).thenReturn(UsageEvents(events, arrayOf()))
+    }
+
     @Test
     fun getAggregatedUsageEvents() = runTest {
         val events = listOf(
@@ -120,8 +155,7 @@
 
     @Test
     fun isEnabled() {
-        whenever(notificationManager.areNotificationsEnabledForPackage(APP.packageName, APP.uid))
-            .thenReturn(true)
+        mockIsEnabled(app = APP, enabled = true)
 
         val isEnabled = repository.isEnabled(APP)
 
@@ -212,6 +246,61 @@
     }
 
     @Test
+    fun getNotificationSummary_notEnabled() {
+        mockIsEnabled(app = APP, enabled = false)
+
+        val summary = repository.getNotificationSummary(APP)
+
+        assertThat(summary).isEqualTo(context.getString(R.string.off))
+    }
+
+    @Test
+    fun getNotificationSummary_noChannel() {
+        mockIsEnabled(app = APP, enabled = true)
+        mockChannelCount(app = APP, count = 0)
+        mockSentCount(app = APP, sentCount = 1)
+
+        val summary = repository.getNotificationSummary(APP)
+
+        assertThat(summary).isEqualTo("About 1 notification per week")
+    }
+
+    @Test
+    fun getNotificationSummary_allChannelsBlocked() {
+        mockIsEnabled(app = APP, enabled = true)
+        mockChannelCount(app = APP, count = 2)
+        mockBlockedChannelCount(app = APP, count = 2)
+
+        val summary = repository.getNotificationSummary(APP)
+
+        assertThat(summary).isEqualTo(context.getString(R.string.off))
+    }
+
+    @Test
+    fun getNotificationSummary_noChannelBlocked() {
+        mockIsEnabled(app = APP, enabled = true)
+        mockChannelCount(app = APP, count = 2)
+        mockSentCount(app = APP, sentCount = 2)
+        mockBlockedChannelCount(app = APP, count = 0)
+
+        val summary = repository.getNotificationSummary(APP)
+
+        assertThat(summary).isEqualTo("About 2 notifications per week")
+    }
+
+    @Test
+    fun getNotificationSummary_someChannelsBlocked() {
+        mockIsEnabled(app = APP, enabled = true)
+        mockChannelCount(app = APP, count = 2)
+        mockSentCount(app = APP, sentCount = 3)
+        mockBlockedChannelCount(app = APP, count = 1)
+
+        val summary = repository.getNotificationSummary(APP)
+
+        assertThat(summary).isEqualTo("About 3 notifications per week / 1 category turned off")
+    }
+
+    @Test
     fun calculateFrequencySummary_daily() {
         val summary = repository.calculateFrequencySummary(4)
 
diff --git a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
deleted file mode 100644
index 5848326..0000000
--- a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.applications.credentials;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ServiceInfo;
-import android.os.Looper;
-
-import androidx.lifecycle.Lifecycle;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.google.android.collect.Lists;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-@RunWith(AndroidJUnit4.class)
-public class CredentialManagerPreferenceControllerTest {
-
-    private Context mContext;
-    private PreferenceScreen mScreen;
-    private PreferenceCategory mCredentialsPreferenceCategory;
-
-    @Before
-    public void setUp() {
-        mContext = spy(ApplicationProvider.getApplicationContext());
-        if (Looper.myLooper() == null) {
-            Looper.prepare(); // needed to create the preference screen
-        }
-        mScreen = new PreferenceManager(mContext).createPreferenceScreen(mContext);
-        mCredentialsPreferenceCategory = new PreferenceCategory(mContext);
-        mCredentialsPreferenceCategory.setKey("credentials_test");
-        mScreen.addPreference(mCredentialsPreferenceCategory);
-    }
-
-    @Test
-    // Tests that getAvailabilityStatus() does not throw an exception if it's called before the
-    // Controller is initialized (this can happen during indexing).
-    public void getAvailabilityStatus_withoutInit_returnsUnavailable() {
-        CredentialManagerPreferenceController controller =
-                new CredentialManagerPreferenceController(
-                        mContext, mCredentialsPreferenceCategory.getKey());
-        assertThat(controller.isConnected()).isFalse();
-        assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_noServices_returnsUnavailable() {
-        CredentialManagerPreferenceController controller =
-                createControllerWithServices(Collections.emptyList());
-        assertThat(controller.isConnected()).isFalse();
-        assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_withServices_returnsAvailable() {
-        CredentialManagerPreferenceController controller =
-                createControllerWithServices(Lists.newArrayList(createServiceInfo()));
-        assertThat(controller.isConnected()).isFalse();
-        assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
-    }
-
-    @Test
-    public void displayPreference_noServices_noPreferencesAdded() {
-        CredentialManagerPreferenceController controller =
-                createControllerWithServices(Collections.emptyList());
-        controller.displayPreference(mScreen);
-        assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(0);
-    }
-
-    @Test
-    public void displayPreference_withServices_preferencesAdded() {
-        CredentialManagerPreferenceController controller =
-                createControllerWithServices(Lists.newArrayList(createServiceInfo()));
-        controller.displayPreference(mScreen);
-        assertThat(controller.isConnected()).isFalse();
-        assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(1);
-    }
-
-    @Test
-    public void getAvailabilityStatus_handlesToggleAndSave() {
-        CredentialManagerPreferenceController controller =
-                createControllerWithServices(
-                        Lists.newArrayList(
-                                createServiceInfo("com.android.provider1", "ClassA"),
-                                createServiceInfo("com.android.provider1", "ClassB"),
-                                createServiceInfo("com.android.provider2", "ClassA"),
-                                createServiceInfo("com.android.provider3", "ClassA"),
-                                createServiceInfo("com.android.provider4", "ClassA"),
-                                createServiceInfo("com.android.provider5", "ClassA"),
-                                createServiceInfo("com.android.provider6", "ClassA")));
-        assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
-        assertThat(controller.isConnected()).isFalse();
-
-        // Ensure that we stay under 5 providers.
-        assertThat(controller.togglePackageNameEnabled("com.android.provider1")).isTrue();
-        assertThat(controller.togglePackageNameEnabled("com.android.provider2")).isTrue();
-        assertThat(controller.togglePackageNameEnabled("com.android.provider3")).isTrue();
-        assertThat(controller.togglePackageNameEnabled("com.android.provider4")).isTrue();
-        assertThat(controller.togglePackageNameEnabled("com.android.provider5")).isTrue();
-        assertThat(controller.togglePackageNameEnabled("com.android.provider6")).isFalse();
-
-        // Check that they are all actually registered.
-        Set<String> enabledProviders = controller.getEnabledProviders();
-        assertThat(enabledProviders.size()).isEqualTo(5);
-        assertThat(enabledProviders.contains("com.android.provider1")).isTrue();
-        assertThat(enabledProviders.contains("com.android.provider2")).isTrue();
-        assertThat(enabledProviders.contains("com.android.provider3")).isTrue();
-        assertThat(enabledProviders.contains("com.android.provider4")).isTrue();
-        assertThat(enabledProviders.contains("com.android.provider5")).isTrue();
-        assertThat(enabledProviders.contains("com.android.provider6")).isFalse();
-
-        // Check that the settings string has the right component names.
-        List<String> enabledServices = controller.getEnabledSettings();
-        assertThat(enabledServices.size()).isEqualTo(6);
-        assertThat(enabledServices.contains("com.android.provider1/ClassA")).isTrue();
-        assertThat(enabledServices.contains("com.android.provider1/ClassB")).isTrue();
-        assertThat(enabledServices.contains("com.android.provider2/ClassA")).isTrue();
-        assertThat(enabledServices.contains("com.android.provider3/ClassA")).isTrue();
-        assertThat(enabledServices.contains("com.android.provider4/ClassA")).isTrue();
-        assertThat(enabledServices.contains("com.android.provider5/ClassA")).isTrue();
-        assertThat(enabledServices.contains("com.android.provider6/ClassA")).isFalse();
-
-        // Toggle the provider disabled.
-        controller.togglePackageNameDisabled("com.android.provider2");
-
-        // Check that the provider was removed from the list of providers.
-        Set<String> currentlyEnabledProviders = controller.getEnabledProviders();
-        assertThat(currentlyEnabledProviders.size()).isEqualTo(4);
-        assertThat(currentlyEnabledProviders.contains("com.android.provider1")).isTrue();
-        assertThat(currentlyEnabledProviders.contains("com.android.provider2")).isFalse();
-        assertThat(currentlyEnabledProviders.contains("com.android.provider3")).isTrue();
-        assertThat(currentlyEnabledProviders.contains("com.android.provider4")).isTrue();
-        assertThat(currentlyEnabledProviders.contains("com.android.provider5")).isTrue();
-        assertThat(currentlyEnabledProviders.contains("com.android.provider6")).isFalse();
-
-        // Check that the provider was removed from the list of services stored in the setting.
-        List<String> currentlyEnabledServices = controller.getEnabledSettings();
-        assertThat(currentlyEnabledServices.size()).isEqualTo(5);
-        assertThat(currentlyEnabledServices.contains("com.android.provider1/ClassA")).isTrue();
-        assertThat(currentlyEnabledServices.contains("com.android.provider1/ClassB")).isTrue();
-        assertThat(currentlyEnabledServices.contains("com.android.provider3/ClassA")).isTrue();
-        assertThat(currentlyEnabledServices.contains("com.android.provider4/ClassA")).isTrue();
-        assertThat(currentlyEnabledServices.contains("com.android.provider5/ClassA")).isTrue();
-        assertThat(currentlyEnabledServices.contains("com.android.provider6/ClassA")).isFalse();
-    }
-
-    private CredentialManagerPreferenceController createControllerWithServices(
-            List<ServiceInfo> availableServices) {
-        CredentialManagerPreferenceController controller =
-                new CredentialManagerPreferenceController(
-                        mContext, mCredentialsPreferenceCategory.getKey());
-        controller.init(() -> mock(Lifecycle.class), availableServices, new HashSet<>());
-        return controller;
-    }
-
-    private ServiceInfo createServiceInfo() {
-        return createServiceInfo("com.android.provider", "CredManProvider");
-    }
-
-    private ServiceInfo createServiceInfo(String packageName, String className) {
-        ServiceInfo si = new ServiceInfo();
-        si.packageName = packageName;
-        si.name = className;
-        si.nonLocalizedLabel = "test";
-
-        si.applicationInfo = new ApplicationInfo();
-        si.applicationInfo.packageName = packageName;
-        si.applicationInfo.nonLocalizedLabel = "test";
-
-        return si;
-    }
-}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index 5f02b04..bff9d41 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -41,6 +41,7 @@
 import com.android.settings.testutils.ResourcesUtils;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -102,6 +103,7 @@
     }
 
     @Test
+    @Ignore
     public void getAvailabilityStatus_isNotVoiceCapable_shouldBeUNSUPPORTED_ON_DEVICE() {
         when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
 
@@ -121,6 +123,7 @@
     }
 
     @Test
+    @Ignore
     public void updateState_singleSim_shouldUpdateTitleAndPhoneNumber() {
         final String phoneNumber = "1111111111";
         doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
@@ -134,6 +137,7 @@
     }
 
     @Test
+    @Ignore
     public void updateState_multiSim_shouldUpdateTitleAndPhoneNumberOfMultiplePreferences() {
         final String phoneNumber = "1111111111";
         doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
@@ -151,6 +155,7 @@
     }
 
     @Test
+    @Ignore
     public void getSummary_cannotGetActiveSubscriptionInfo_shouldShowUnknown() {
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
 
@@ -162,6 +167,7 @@
     }
 
     @Test
+    @Ignore
     public void getSummary_getEmptySubscriptionInfo_shouldShowUnknown() {
         List<SubscriptionInfo> infos = new ArrayList<>();
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(infos);
diff --git a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SlotSimStatusTest.java b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SlotSimStatusTest.java
index 4c17d15..3136af7 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SlotSimStatusTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SlotSimStatusTest.java
@@ -23,8 +23,13 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.os.Bundle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 
+import androidx.lifecycle.Lifecycle;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
@@ -36,15 +41,27 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
 import java.util.concurrent.Executor;
 
 @RunWith(AndroidJUnit4.class)
 public class SlotSimStatusTest {
 
+    private static final int SUB_ID_1 = 3;
+    private static final int SUB_ID_2 = 8;
+
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
     @Mock
     private TelephonyManager mTelephonyManager;
     @Mock
+    private SubscriptionInfo mSubscriptionInfo1;
+    @Mock
+    private SubscriptionInfo mSubscriptionInfo2;
+    @Mock
     private Executor mExecutor;
+    @Mock
+    private Lifecycle mLifecycle;
     @Captor
     private ArgumentCaptor<Runnable> mRunnableCaptor;
 
@@ -56,13 +73,20 @@
 
         mContext = spy(ApplicationProvider.getApplicationContext());
         mockService(Context.TELEPHONY_SERVICE, TelephonyManager.class, mTelephonyManager);
+        mockService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,
+                mSubscriptionManager);
     }
 
     @Test
     public void size_returnNumberOfPhone_whenQuery() {
         doReturn(2).when(mTelephonyManager).getPhoneCount();
 
-        SlotSimStatus target = new SlotSimStatus(mContext);
+        SlotSimStatus target = new SlotSimStatus(mContext, null, null) {
+            @Override
+            protected void postValue(Long value) {}
+            @Override
+            protected void setValue(Long value) {}
+        };
 
         assertEquals(new Integer(target.size()), new Integer(2));
     }
@@ -71,7 +95,12 @@
     public void size_returnNumberOfPhone_whenQueryInBackgroundThread() {
         doReturn(2).when(mTelephonyManager).getPhoneCount();
 
-        SlotSimStatus target = new SlotSimStatus(mContext, mExecutor);
+        SlotSimStatus target = new SlotSimStatus(mContext, mExecutor, mLifecycle) {
+            @Override
+            protected void postValue(Long value) {}
+            @Override
+            protected void setValue(Long value) {}
+        };
 
         verify(mExecutor).execute(mRunnableCaptor.capture());
         mRunnableCaptor.getValue().run();
@@ -83,7 +112,12 @@
     public void getPreferenceOrdering_returnOrdering_whenQuery() {
         doReturn(2).when(mTelephonyManager).getPhoneCount();
 
-        SlotSimStatus target = new SlotSimStatus(mContext);
+        SlotSimStatus target = new SlotSimStatus(mContext, null, null) {
+            @Override
+            protected void postValue(Long value) {}
+            @Override
+            protected void setValue(Long value) {}
+        };
         target.setBasePreferenceOrdering(30);
 
         assertEquals(new Integer(target.getPreferenceOrdering(1)), new Integer(32));
@@ -93,10 +127,36 @@
     public void getPreferenceKey_returnKey_whenQuery() {
         doReturn(2).when(mTelephonyManager).getPhoneCount();
 
-        SlotSimStatus target = new SlotSimStatus(mContext);
+        SlotSimStatus target = new SlotSimStatus(mContext, null, null) {
+            @Override
+            protected void postValue(Long value) {}
+            @Override
+            protected void setValue(Long value) {}
+        };
         target.setBasePreferenceOrdering(50);
 
-        assertEquals(target.getPreferenceKey(1), "sim_status52");
+        assertEquals(target.getPreferenceKey(1), "sim_status2");
+    }
+
+    @Test
+    public void getSubscriptionInfo_returnSubscriptionInfo_whenActive() {
+        doReturn(SUB_ID_1).when(mSubscriptionInfo1).getSubscriptionId();
+        doReturn(0).when(mSubscriptionInfo1).getSimSlotIndex();
+        doReturn(SUB_ID_2).when(mSubscriptionInfo2).getSubscriptionId();
+        doReturn(1).when(mSubscriptionInfo2).getSimSlotIndex();
+
+        doReturn(List.of(mSubscriptionInfo1, mSubscriptionInfo2))
+                .when(mSubscriptionManager).getActiveSubscriptionInfoList();
+        doReturn(2).when(mTelephonyManager).getPhoneCount();
+
+        SlotSimStatus target = new SlotSimStatus(mContext, null, null) {
+            @Override
+            protected void postValue(Long value) {}
+            @Override
+            protected void setValue(Long value) {}
+        };
+
+        assertEquals(target.getSubscriptionInfo(1), mSubscriptionInfo2);
     }
 
     private <T> void mockService(String serviceName, Class<T> serviceClass, T service) {
diff --git a/tests/unit/src/com/android/settings/display/ScreenSaverPreferenceControllerTest.java b/tests/unit/src/com/android/settings/display/ScreenSaverPreferenceControllerTest.java
index 484138e..180ea90 100644
--- a/tests/unit/src/com/android/settings/display/ScreenSaverPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/display/ScreenSaverPreferenceControllerTest.java
@@ -45,11 +45,13 @@
 
     private ScreenSaverPreferenceController mController;
 
+    private final String mPrefKey = "test_screensaver";
+
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
 
-        mController = new ScreenSaverPreferenceController(mContext);
+        mController = new ScreenSaverPreferenceController(mContext, mPrefKey);
 
         when(mContext.getResources()).thenReturn(mResources);
         when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
diff --git a/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
index 8beeffb..cd9d2a3 100644
--- a/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/InternetPreferenceControllerTest.java
@@ -56,6 +56,7 @@
 import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -177,6 +178,7 @@
                 any(Handler.class));
     }
 
+    @Ignore
     @Test
     @UiThreadTest
     public void onPause_shouldUnregisterCallback() {
diff --git a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java
index 3fe6882..a527822 100644
--- a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java
+++ b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java
@@ -42,6 +42,7 @@
 import com.android.settingslib.utils.HandlerInjector;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -241,6 +242,7 @@
         verify(mRecoveryWorker).triggerRestart();
     }
 
+    @Ignore
     @Test
     public void checkRecovering_isRecovering_showResetting() {
         when(mRecoveryWorker.isRecovering()).thenReturn(true);
@@ -250,6 +252,7 @@
         verify(mResettingPreference).setVisible(true);
     }
 
+    @Ignore
     @Test
     public void checkRecovering_isNotRecovering_doNotShowResetting() {
         when(mRecoveryWorker.isRecovering()).thenReturn(false);
diff --git a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
index 345631c..553fefd 100644
--- a/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
+++ b/tests/unit/src/com/android/settings/network/ProviderModelSliceTest.java
@@ -66,6 +66,7 @@
 import com.android.wifitrackerlib.WifiPickerTracker;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -462,6 +463,7 @@
         }
     }
 
+    @Ignore
     @Test
     @UiThreadTest
     public void onNotifyChange_FirstTimeDisableToggleState_showDialog() {
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
index 63dca7e..e06e0a5 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -459,6 +459,7 @@
     }
 
     @Test
+    @Ignore
     public void isSimHardwareVisible_configAsVisible_returnTrue() {
         when(mContext.getResources()).thenReturn(mResources);
         when(mResources.getBoolean(R.bool.config_show_sim_info))
diff --git a/tests/unit/src/com/android/settings/wifi/RequestToggleWiFiActivityTest.java b/tests/unit/src/com/android/settings/wifi/RequestToggleWiFiActivityTest.java
index 0e3dd40..8810386 100644
--- a/tests/unit/src/com/android/settings/wifi/RequestToggleWiFiActivityTest.java
+++ b/tests/unit/src/com/android/settings/wifi/RequestToggleWiFiActivityTest.java
@@ -34,6 +34,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -76,6 +77,7 @@
     }
 
     @Test
+    @Ignore
     public void getAppLabel_nullPackageName_returnNull() {
         fakeCallingPackage(null);
 
@@ -83,6 +85,7 @@
     }
 
     @Test
+    @Ignore
     public void getAppLabel_settingsPackageName_returnNotNull() {
         fakeCallingPackage("com.android.settings");