Merge "Support ACTION_NOTIFICATION_ASSISTANT_DETAIL_SETTINGS in Enhanced Notifications" into tm-qpr-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index e280b83..1b69a58 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -131,7 +131,8 @@
             android:usesCleartextTraffic="true"
             android:defaultToDeviceProtectedStorage="true"
             android:directBootAware="true"
-            android:appComponentFactory="androidx.core.app.CoreComponentFactory">
+            android:appComponentFactory="androidx.core.app.CoreComponentFactory"
+            android:enableOnBackInvokedCallback="true">
 
         <uses-library android:name="org.apache.http.legacy" />
 
diff --git a/res/drawable/ic_cellular_1_bar.xml b/res/drawable/ic_cellular_1_bar.xml
index 23caacc2..a07e257 100644
--- a/res/drawable/ic_cellular_1_bar.xml
+++ b/res/drawable/ic_cellular_1_bar.xml
@@ -1,5 +1,5 @@
 <!--
-  Copyright (C) 2019 The Android Open Source Project
+  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.
@@ -19,11 +19,11 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24"
-    android:tint="?android:attr/colorControlNormal">
+    android:tint="@color/battery_usage_system_icon_color">
     <path
-        android:fillColor="#000000"
+        android:fillColor="@android:color/white"
         android:pathData="M20,7v13H7L20,7 M22,2L2,22h20V2L22,2z" />
     <path
-        android:fillColor="#000000"
+        android:fillColor="@android:color/white"
         android:pathData="M 11 13 L 2 22 L 11 22 Z" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/res/drawable/ic_power_system.xml b/res/drawable/ic_power_system.xml
index 3b84f59..cdebc0e 100644
--- a/res/drawable/ic_power_system.xml
+++ b/res/drawable/ic_power_system.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2019 The Android Open Source Project
+    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.
@@ -19,8 +19,8 @@
         android:height="24dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:tint="@color/battery_usage_system_icon_color">
     <path
-        android:fillColor="#000000"
+        android:fillColor="@android:color/white"
         android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"/>
 </vector>
diff --git a/res/drawable/ic_settings_aod.xml b/res/drawable/ic_settings_aod.xml
index b238e3a..89affdc 100644
--- a/res/drawable/ic_settings_aod.xml
+++ b/res/drawable/ic_settings_aod.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  Copyright (C) 2018 The Android Open Source Project
+  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.
@@ -19,17 +19,17 @@
         android:height="24dp"
         android:viewportWidth="24"
         android:viewportHeight="24"
-        android:tint="?android:attr/colorControlNormal">
+        android:tint="@color/battery_usage_system_icon_color">
 
     <path
-        android:fillColor="#000000"
-        android:pathData="M17,1.01L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1.01,17,1.01z M17,21H7l0-1h10V21z M17,18H7V6h10V18z M17,4H7V3h10V4z" />
+        android:fillColor="@android:color/white"
+        android:pathData="M17,1.01L7,1C5.9,1,5,1.9,5,3v18c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V3C19,1.9,18.1,1.01,17,1.01z M17,21H7l0-1h10V21z M17,18H7V6h10V18z M17,4H7V3h10V4z"/>
     <path
-        android:fillColor="#000000"
-        android:pathData="M 8 10 H 16 V 11.5 H 8 V 10 Z" />
+        android:fillColor="@android:color/white"
+        android:pathData="M 8 10 H 16 V 11.5 H 8 V 10 Z"/>
     <path
-        android:fillColor="#000000"
-        android:pathData="M 9 13 H 15 V 14.5 H 9 V 13 Z" />
+        android:fillColor="@android:color/white"
+        android:pathData="M 9 13 H 15 V 14.5 H 9 V 13 Z"/>
     <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-</vector>
\ No newline at end of file
+        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z"/>
+</vector>
diff --git a/res/drawable/ic_settings_bluetooth.xml b/res/drawable/ic_settings_bluetooth.xml
new file mode 100644
index 0000000..a8666ac
--- /dev/null
+++ b/res/drawable/ic_settings_bluetooth.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="24.0"
+        android:viewportHeight="24.0"
+        android:tint="@color/battery_usage_system_icon_color">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88z"/>
+</vector>
diff --git a/res/drawable/ic_settings_camera.xml b/res/drawable/ic_settings_camera.xml
index 3c85532..278d295 100644
--- a/res/drawable/ic_settings_camera.xml
+++ b/res/drawable/ic_settings_camera.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     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.
@@ -21,9 +21,9 @@
     android:viewportWidth="48"
     android:viewportHeight="48"
     android:autoMirrored="true"
-    android:tint="?android:attr/colorControlNormal">
+    android:tint="@color/battery_usage_system_icon_color">
 
-    <path android:fillColor="#000000"
+    <path android:fillColor="@android:color/white"
           android:pathData="M18.8 21l9.53-16.51C26.94 4.18 25.49 4 24 4c-4.8 0-9.19 1.69-12.64
                             4.51l7.33 12.69.11-.2zm24.28-3c-1.84-5.85-6.3-10.52-11.99-12.68L23.77
                             18h19.31zm.52 2H28.62l.58 1 9.53 16.5C41.99 33.94 44 29.21 44
diff --git a/res/drawable/ic_settings_display.xml b/res/drawable/ic_settings_display.xml
index 7f0aacd..61d1aeb 100644
--- a/res/drawable/ic_settings_display.xml
+++ b/res/drawable/ic_settings_display.xml
@@ -1,5 +1,5 @@
 <!--
-    Copyright (C) 2016 The Android Open Source Project
+    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.
@@ -18,8 +18,8 @@
         android:height="24.0dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
-        android:tint="?android:attr/colorControlNormal">
+        android:tint="@color/battery_usage_system_icon_color">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="@android:color/white"
         android:pathData="M20,8.69V4h-4.69L12,0.69L8.69,4H4v4.69L0.69,12L4,15.31V20h4.69L12,23.31L15.31,20H20v-4.69L23.31,12L20,8.69zM18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48zM12,17c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5V17z"/>
 </vector>
diff --git a/res/drawable/ic_settings_phone_idle.xml b/res/drawable/ic_settings_phone_idle.xml
index 7bb6c31..fd304e7 100644
--- a/res/drawable/ic_settings_phone_idle.xml
+++ b/res/drawable/ic_settings_phone_idle.xml
@@ -1,5 +1,5 @@
 <!--
-  Copyright (C) 2019 The Android Open Source Project
+  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.
@@ -18,8 +18,8 @@
     android:height="48dp"
     android:viewportWidth="48"
     android:viewportHeight="48"
-    android:tint="?android:attr/colorControlNormal">
-  <path
-      android:pathData="M14,48h4v-4h-4v4zM22,48h4v-4h-4v4zM26,4h-4v20h4L26,4zM33.13,8.87l-2.89,2.89C33.69,13.87 36,17.66 36,22c0,6.63 -5.37,12 -12,12s-12,-5.37 -12,-12c0,-4.34 2.31,-8.13 5.76,-10.24l-2.89,-2.89C10.72,11.76 8,16.56 8,22c0,8.84 7.16,16 16,16s16,-7.16 16,-16c0,-5.44 -2.72,-10.24 -6.87,-13.13zM30,48h4v-4h-4v4z"
-      android:fillColor="#000000"/>
+    android:tint="@color/battery_usage_system_icon_color">
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M14,48h4v-4h-4v4zM22,48h4v-4h-4v4zM26,4h-4v20h4L26,4zM33.13,8.87l-2.89,2.89C33.69,13.87 36,17.66 36,22c0,6.63 -5.37,12 -12,12s-12,-5.37 -12,-12c0,-4.34 2.31,-8.13 5.76,-10.24l-2.89,-2.89C10.72,11.76 8,16.56 8,22c0,8.84 7.16,16 16,16s16,-7.16 16,-16c0,-5.44 -2.72,-10.24 -6.87,-13.13zM30,48h4v-4h-4v4z"/>
 </vector>
diff --git a/res/drawable/ic_settings_voice_calls.xml b/res/drawable/ic_settings_voice_calls.xml
index b455f0a..c8817a8 100644
--- a/res/drawable/ic_settings_voice_calls.xml
+++ b/res/drawable/ic_settings_voice_calls.xml
@@ -1,5 +1,5 @@
 <!--
-  Copyright (C) 2019 The Android Open Source Project
+  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.
@@ -18,8 +18,8 @@
     android:height="48dp"
     android:viewportWidth="48"
     android:viewportHeight="48"
-    android:tint="?android:attr/colorControlNormal">
-  <path
-      android:pathData="M40,31c-2.49,0 -4.89,-0.4 -7.14,-1.14 -0.69,-0.22 -1.48,-0.06 -2.03,0.49l-4.4,4.41c-5.67,-2.88 -10.29,-7.51 -13.18,-13.17l4.4,-4.41c0.55,-0.55 0.71,-1.34 0.49,-2.03C17.4,12.9 17,10.49 17,8c0,-1.11 -0.89,-2 -2,-2L8,6c-1.11,0 -2,0.89 -2,2 0,18.78 15.22,34 34,34 1.11,0 2,-0.89 2,-2v-7c0,-1.11 -0.89,-2 -2,-2zM38,24h4c0,-9.94 -8.06,-18 -18,-18v4c7.73,0 14,6.27 14,14zM30,24h4c0,-5.52 -4.48,-10 -10,-10v4c3.31,0 6,2.69 6,6z"
-      android:fillColor="#000000"/>
+    android:tint="@color/battery_usage_system_icon_color">
+    <path
+      android:fillColor="@android:color/white"
+      android:pathData="M40,31c-2.49,0 -4.89,-0.4 -7.14,-1.14 -0.69,-0.22 -1.48,-0.06 -2.03,0.49l-4.4,4.41c-5.67,-2.88 -10.29,-7.51 -13.18,-13.17l4.4,-4.41c0.55,-0.55 0.71,-1.34 0.49,-2.03C17.4,12.9 17,10.49 17,8c0,-1.11 -0.89,-2 -2,-2L8,6c-1.11,0 -2,0.89 -2,2 0,18.78 15.22,34 34,34 1.11,0 2,-0.89 2,-2v-7c0,-1.11 -0.89,-2 -2,-2zM38,24h4c0,-9.94 -8.06,-18 -18,-18v4c7.73,0 14,6.27 14,14zM30,24h4c0,-5.52 -4.48,-10 -10,-10v4c3.31,0 6,2.69 6,6z"/>
 </vector>
diff --git a/res/drawable/ic_settings_wireless_no_theme.xml b/res/drawable/ic_settings_wireless_no_theme.xml
new file mode 100644
index 0000000..5e18b89a
--- /dev/null
+++ b/res/drawable/ic_settings_wireless_no_theme.xml
@@ -0,0 +1,30 @@
+<!--
+    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="24.0"
+        android:viewportHeight="24.0"
+        android:tint="@color/battery_usage_system_icon_color">
+    <path
+        android:pathData="M1.003,9L3.003,11C7.973,6.03 16.033,6.03 21.003,11L23.003,9C16.933,2.93 7.083,2.93 1.003,9ZM9.003,17L12.003,20L15.003,17C13.353,15.34 10.663,15.34 9.003,17ZM7.005,15L5.005,13C8.875,9.14 15.145,9.14 19.005,13L17.005,15C14.245,12.241 9.765,12.241 7.005,15Z"
+        android:fillType="evenOdd"
+        android:fillColor="@android:color/white"/>
+    <path
+        android:pathData="M0,0H24V24H0V0ZM0,0H24V24H0V0Z"
+        android:fillType="evenOdd"
+        android:fillColor="@android:color/white"/>
+</vector>
diff --git a/res/layout/battery_chart_graph.xml b/res/layout/battery_chart_graph.xml
index b95c660..f116c8e 100644
--- a/res/layout/battery_chart_graph.xml
+++ b/res/layout/battery_chart_graph.xml
@@ -31,25 +31,33 @@
         android:textColor="?android:attr/textColorSecondary"
         android:text="@string/battery_usage_chart_graph_hint_last_full_charge" />
 
-    <com.android.settings.fuelgauge.batteryusage.BatteryChartView
-        android:id="@+id/daily_battery_chart"
+    <LinearLayout
+        android:id="@+id/battery_chart_group"
         android:layout_width="match_parent"
-        android:layout_height="170dp"
-        android:layout_marginBottom="16dp"
-        android:visibility="gone"
-        android:contentDescription="@string/battery_usage_chart"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        settings:textColor="?android:attr/textColorSecondary" />
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:alpha="0">
+        <com.android.settings.fuelgauge.batteryusage.BatteryChartView
+            android:id="@+id/daily_battery_chart"
+            android:layout_width="match_parent"
+            android:layout_height="170dp"
+            android:layout_marginBottom="16dp"
+            android:visibility="gone"
+            android:contentDescription="@string/daily_battery_usage_chart"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            settings:textColor="?android:attr/textColorSecondary" />
 
-    <com.android.settings.fuelgauge.batteryusage.BatteryChartView
-        android:id="@+id/hourly_battery_chart"
-        android:layout_width="match_parent"
-        android:layout_height="170dp"
-        android:layout_marginBottom="16dp"
-        android:visibility="visible"
-        android:contentDescription="@string/battery_usage_chart"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-        settings:textColor="?android:attr/textColorSecondary" />
+        <com.android.settings.fuelgauge.batteryusage.BatteryChartView
+            android:id="@+id/hourly_battery_chart"
+            android:layout_width="match_parent"
+            android:layout_height="170dp"
+            android:layout_marginBottom="16dp"
+            android:visibility="visible"
+            android:contentDescription="@string/hourly_battery_usage_chart"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            settings:textColor="?android:attr/textColorSecondary" />
+    </LinearLayout>
+
     <!-- Use non-scalable text size from text_size_small_material -->
     <TextView
         android:id="@+id/companion_text"
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 4e4ee5d..0017c2c 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -52,5 +52,8 @@
 
     <!-- Material inverse ripple color, useful for inverted backgrounds. -->
     <color name="ripple_material_inverse">@*android:color/ripple_material_light</color>
+
+    <!-- Icon tint color for battery usage system icon -->
+    <color name="battery_usage_system_icon_color">@android:color/white</color>
 </resources>
 
diff --git a/res/values/colors.xml b/res/values/colors.xml
index e818a28..7ca1ab2 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -209,4 +209,7 @@
 
     <!-- Background for multiple user settings page avatars -->
     <color name="user_avatar_color_bg">?androidprv:attr/colorSurface</color>
+
+    <!-- Icon tint color for battery usage system icon -->
+    <color name="battery_usage_system_icon_color">?android:attr/textColorPrimary</color>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 083064f..921cb52 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6790,6 +6790,10 @@
     <string name="battery_usage_screen_footer_empty">Battery usage data will be available after you use your phone for a few hours</string>
     <!-- [CHAR_LIMIT=NONE] Accessibility content description for battery chart view. -->
     <string name="battery_usage_chart">Battery usage chart</string>
+    <!-- [CHAR_LIMIT=NONE] Accessibility content description for daily battery chart view. -->
+    <string name="daily_battery_usage_chart">Daily battery usage chart</string>
+    <!-- [CHAR_LIMIT=NONE] Accessibility content description for hourly battery chart view. -->
+    <string name="hourly_battery_usage_chart">Hourly battery usage chart</string>
     <!-- Process Stats strings -->
     <skip />
 
diff --git a/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java b/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
index dd06b67..62a66cf 100644
--- a/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
+++ b/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
@@ -74,12 +74,12 @@
 
         TextView title = layout.findViewById(com.android.settingslib.R.id.dialog_title);
         TextView subTitle = layout.findViewById(com.android.settingslib.R.id.dialog_subtitle);
-        title.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
-        subTitle.setText(
-                mContext.getString(R.string.bluetooth_broadcast_dialog_broadcast_message));
 
         Button broadcastBtn = layout.findViewById(com.android.settingslib.R.id.positive_btn);
         if (isBroadcastSupported() && mIsMediaStreaming) {
+            title.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
+            subTitle.setText(
+                    mContext.getString(R.string.bluetooth_broadcast_dialog_broadcast_message));
             broadcastBtn.setVisibility(View.VISIBLE);
             if (TextUtils.isEmpty(mCurrentAppLabel)) {
                 broadcastBtn.setText(mContext.getString(R.string.bluetooth_broadcast_dialog_title));
@@ -92,6 +92,9 @@
                 launchMediaOutputBroadcastDialog();
             });
         } else {
+            title.setText(mContext.getString(R.string.bluetooth_find_broadcast));
+            subTitle.setText(
+                    mContext.getString(R.string.bluetooth_broadcast_dialog_find_message));
             broadcastBtn.setVisibility(View.GONE);
         }
 
diff --git a/src/com/android/settings/datausage/BillingCyclePreference.java b/src/com/android/settings/datausage/BillingCyclePreference.java
index 116ed89..1bd2be8 100644
--- a/src/com/android/settings/datausage/BillingCyclePreference.java
+++ b/src/com/android/settings/datausage/BillingCyclePreference.java
@@ -20,6 +20,7 @@
 import android.net.NetworkTemplate;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
 import android.util.AttributeSet;
 
@@ -78,7 +79,7 @@
         try {
             setEnabled(mServices.mNetworkService.isBandwidthControlEnabled()
                     && mServices.mTelephonyManager.createForSubscriptionId(mSubId)
-                            .isDataEnabledForApn(ApnSetting.TYPE_DEFAULT)
+                            .isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
                     && mServices.mUserManager.isAdminUser());
         } catch (RemoteException e) {
             setEnabled(false);
diff --git a/src/com/android/settings/dream/DreamComplicationPreferenceController.java b/src/com/android/settings/dream/DreamComplicationPreferenceController.java
index d9c4fb3..596fe20 100644
--- a/src/com/android/settings/dream/DreamComplicationPreferenceController.java
+++ b/src/com/android/settings/dream/DreamComplicationPreferenceController.java
@@ -42,14 +42,12 @@
 
     @Override
     public boolean isChecked() {
-        return mBackend.getEnabledComplications().containsAll(mBackend.getSupportedComplications());
+        return mBackend.getComplicationsEnabled();
     }
 
     @Override
     public boolean setChecked(boolean isChecked) {
-        for (int complication : mBackend.getSupportedComplications()) {
-            mBackend.setComplicationEnabled(complication, isChecked);
-        }
+        mBackend.setComplicationsEnabled(isChecked);
         return true;
     }
 
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index ea493a3..95145ba 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -31,7 +31,6 @@
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
-import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.fuelgauge.EstimateKt;
 import com.android.settingslib.utils.AsyncLoaderCompat;
 
@@ -67,16 +66,14 @@
         final BatteryTipPolicy policy = new BatteryTipPolicy(getContext());
         final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(TAG);
         final Context context = getContext();
-        final boolean extraDefend = FeatureFactory.getFactory(context)
-                .getPowerUsageFeatureProvider(context)
-                .isExtraDefend();
 
         tips.add(new LowBatteryDetector(context, policy, batteryInfo).detect());
         tips.add(new HighUsageDetector(context, policy, mBatteryUsageStats, batteryInfo).detect());
         tips.add(new SmartBatteryDetector(
                 context, policy, batteryInfo, context.getContentResolver()).detect());
         tips.add(new EarlyWarningDetector(policy, context).detect());
-        tips.add(new BatteryDefenderDetector(batteryInfo, extraDefend).detect());
+        tips.add(new BatteryDefenderDetector(
+                batteryInfo, context.getApplicationContext()).detect());
         Collections.sort(tips);
         return tips;
     }
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
index 367b2b1..87d4a0b 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetector.java
@@ -16,28 +16,33 @@
 
 package com.android.settings.fuelgauge.batterytip.detectors;
 
+import android.content.Context;
+
 import com.android.settings.fuelgauge.BatteryInfo;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryDefenderTip;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.overlay.FeatureFactory;
 
 /**
  * Detect whether the battery is overheated
  */
 public class BatteryDefenderDetector implements BatteryTipDetector {
     private final BatteryInfo mBatteryInfo;
-    private final boolean mExtraDefend;
+    private final Context mContext;
 
-    public BatteryDefenderDetector(BatteryInfo batteryInfo, boolean extraDefend) {
+    public BatteryDefenderDetector(BatteryInfo batteryInfo, Context context) {
         mBatteryInfo = batteryInfo;
-        mExtraDefend = extraDefend;
+        mContext = context;
     }
 
     @Override
     public BatteryTip detect() {
-        final int state =
-                mBatteryInfo.isOverheated
-                    ? BatteryTip.StateType.NEW
-                    : BatteryTip.StateType.INVISIBLE;
-        return new BatteryDefenderTip(state, mExtraDefend);
+        if (mBatteryInfo.isOverheated) {
+            final boolean extraDefend = FeatureFactory.getFactory(mContext)
+                    .getPowerUsageFeatureProvider(mContext)
+                    .isExtraDefend();
+            return new BatteryDefenderTip(BatteryTip.StateType.NEW, extraDefend);
+        }
+        return new BatteryDefenderTip(BatteryTip.StateType.INVISIBLE);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
index 0a133bb..5c0fc58 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java
@@ -108,7 +108,7 @@
                 });
         cardPreference.setPrimaryButtonVisible(isPluggedIn(context));
 
-        cardPreference.setSecondaryButtonText(context.getString(R.string.see_more));
+        cardPreference.setSecondaryButtonText(context.getString(R.string.learn_more));
         cardPreference.setSecondaryButtonClickListener(unused -> cardPreference.performClick());
         cardPreference.setSecondaryButtonVisible(true);
     }
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index 88bec0d..45ae8c5 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -65,7 +65,10 @@
     private static final String TAG = "BatteryChartPreferenceController";
     private static final String KEY_FOOTER_PREF = "battery_graph_footer";
     private static final String PACKAGE_NAME_NONE = "none";
+    private static final int ENABLED_ICON_ALPHA = 255;
+    private static final int DISABLED_ICON_ALPHA = 255 / 3;
 
+    private static final long FADE_ANIMATION_DURATION = 350L;
     private static final long VALID_USAGE_TIME_DURATION = DateUtils.HOUR_IN_MILLIS * 2;
     private static final long VALID_DIFF_DURATION = DateUtils.MINUTE_IN_MILLIS * 3;
 
@@ -102,6 +105,7 @@
 
     private boolean mIs24HourFormat;
     private boolean mIsFooterPrefAdded = false;
+    private View mBatteryChartViewGroup;
     private PreferenceScreen mPreferenceScreen;
     private FooterPreference mFooterPreference;
     // Daily view model only saves abbreviated day of week texts (e.g. MON). This field saves the
@@ -202,7 +206,7 @@
         mPrefContext = screen.getContext();
         mAppListPrefGroup = screen.findPreference(mPreferenceKey);
         mAppListPrefGroup.setOrderingAsAdded(false);
-        mAppListPrefGroup.setTitle(mPrefContext.getString(R.string.battery_app_usage));
+        mAppListPrefGroup.setTitle("");
         mFooterPreference = screen.findPreference(KEY_FOOTER_PREF);
         // Removes footer first until usage data is loaded to avoid flashing.
         if (mFooterPreference != null) {
@@ -260,6 +264,8 @@
             final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap) {
         Log.d(TAG, "setBatteryHistoryMap() " + (batteryHistoryMap == null ? "null"
                 : ("size=" + batteryHistoryMap.size())));
+        // Ensure the battery chart group is visible for users.
+        animateBatteryChartViewGroup();
         final BatteryLevelData batteryLevelData =
                 DataProcessor.getBatteryLevelData(mContext, mHandler, batteryHistoryMap,
                         batteryUsageMap -> {
@@ -267,6 +273,11 @@
                             refreshUi();
                         });
         Log.d(TAG, "getBatteryLevelData: " + batteryLevelData);
+        mMetricsFeatureProvider.action(
+                mPrefContext,
+                SettingsEnums.ACTION_BATTERY_HISTORY_LOADED,
+                getTotalHours(batteryLevelData));
+
         if (batteryLevelData == null) {
             mDailyTimestampFullTexts = null;
             mDailyViewModel = null;
@@ -297,8 +308,13 @@
 
     void setBatteryChartView(@NonNull final BatteryChartView dailyChartView,
             @NonNull final BatteryChartView hourlyChartView) {
+        final View parentView = (View) dailyChartView.getParent();
+        if (parentView != null && parentView.getId() == R.id.battery_chart_group) {
+            mBatteryChartViewGroup = (View) dailyChartView.getParent();
+        }
         if (mDailyChartView != dailyChartView || mHourlyChartView != hourlyChartView) {
             mHandler.post(() -> setBatteryChartViewInner(dailyChartView, hourlyChartView));
+            animateBatteryChartViewGroup();
         }
     }
 
@@ -313,7 +329,12 @@
             mDailyChartIndex = trapezoidIndex;
             mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
             refreshUi();
-            // TODO: Change to log daily data.
+            mMetricsFeatureProvider.action(
+                    mPrefContext,
+                    trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
+                            ? SettingsEnums.ACTION_BATTERY_USAGE_DAILY_SHOW_ALL
+                            : SettingsEnums.ACTION_BATTERY_USAGE_DAILY_TIME_SLOT,
+                    mDailyChartIndex);
         });
         mHourlyChartView = hourlyChartView;
         mHourlyChartView.setOnSelectListener(trapezoidIndex -> {
@@ -327,7 +348,8 @@
                     mPrefContext,
                     trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
                             ? SettingsEnums.ACTION_BATTERY_USAGE_SHOW_ALL
-                            : SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT);
+                            : SettingsEnums.ACTION_BATTERY_USAGE_TIME_SLOT,
+                    mHourlyChartIndex);
         });
         refreshUi();
     }
@@ -452,6 +474,7 @@
             if (!isAdded) {
                 mAppListPrefGroup.addPreference(pref);
             }
+            appIcon.setAlpha(pref.isEnabled() ? ENABLED_ICON_ALPHA : DISABLED_ICON_ALPHA);
             prefIndex++;
         }
     }
@@ -601,6 +624,13 @@
         return !DataProcessor.contains(packageName, mNotAllowShowSummaryPackages);
     }
 
+    private void animateBatteryChartViewGroup() {
+        if (mBatteryChartViewGroup != null && mBatteryChartViewGroup.getAlpha() == 0) {
+            mBatteryChartViewGroup.animate().alpha(1f).setDuration(FADE_ANIMATION_DURATION)
+                    .start();
+        }
+    }
+
     private void addFooterPreferenceIfNeeded(boolean containAppItems) {
         if (mIsFooterPrefAdded || mFooterPreference == null) {
             return;
@@ -623,6 +653,16 @@
                 && mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL;
     }
 
+    @VisibleForTesting
+    static int getTotalHours(final BatteryLevelData batteryLevelData) {
+        if (batteryLevelData == null) {
+            return 0;
+        }
+        List<Long> dailyTimestamps = batteryLevelData.getDailyBatteryLevels().getTimestamps();
+        return (int) ((dailyTimestamps.get(dailyTimestamps.size() - 1) - dailyTimestamps.get(0))
+                / DateUtils.HOUR_IN_MILLIS);
+    }
+
     private static List<String> generateTimestampDayOfWeekTexts(@NonNull final Context context,
             @NonNull final List<Long> timestamps, final boolean isAbbreviation) {
         final ArrayList<String> texts = new ArrayList<>();
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
index 24d6dad..ccb2fb7 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
@@ -574,7 +574,7 @@
                 break;
             case BatteryConsumer.POWER_COMPONENT_BLUETOOTH:
                 name = context.getResources().getString(R.string.power_bluetooth);
-                iconId = com.android.internal.R.drawable.ic_settings_bluetooth;
+                iconId = R.drawable.ic_settings_bluetooth;
                 break;
             case BatteryConsumer.POWER_COMPONENT_CAMERA:
                 name = context.getResources().getString(R.string.power_camera);
@@ -598,7 +598,7 @@
                 break;
             case BatteryConsumer.POWER_COMPONENT_WIFI:
                 name = context.getResources().getString(R.string.power_wifi);
-                iconId = R.drawable.ic_settings_wireless;
+                iconId = R.drawable.ic_settings_wireless_no_theme;
                 break;
             case BatteryConsumer.POWER_COMPONENT_IDLE:
             case BatteryConsumer.POWER_COMPONENT_MEMORY:
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java
index 71fd26c..6748223 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistoryPreference.java
@@ -106,12 +106,11 @@
             return;
         }
         if (mIsChartGraphEnabled) {
+            final TextView companionTextView = (TextView) view.findViewById(R.id.companion_text);
             mDailyChartView = (BatteryChartView) view.findViewById(R.id.daily_battery_chart);
-            mDailyChartView.setCompanionTextView(
-                    (TextView) view.findViewById(R.id.companion_text));
+            mDailyChartView.setCompanionTextView(companionTextView);
             mHourlyChartView = (BatteryChartView) view.findViewById(R.id.hourly_battery_chart);
-            mHourlyChartView.setCompanionTextView(
-                    (TextView) view.findViewById(R.id.companion_text));
+            mHourlyChartView.setCompanionTextView(companionTextView);
             if (mChartPreferenceController != null) {
                 mChartPreferenceController.setBatteryChartView(mDailyChartView, mHourlyChartView);
             }
diff --git a/src/com/android/settings/notification/AppBubbleListPreferenceController.java b/src/com/android/settings/notification/AppBubbleListPreferenceController.java
index 6ebb376..bf7fcc0 100644
--- a/src/com/android/settings/notification/AppBubbleListPreferenceController.java
+++ b/src/com/android/settings/notification/AppBubbleListPreferenceController.java
@@ -51,7 +51,7 @@
     private static final String KEY = "bubble_conversations";
 
     public AppBubbleListPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
     }
 
     @Override
@@ -80,25 +80,25 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         // copy rather than inherit super's isAvailable because apps can link to this page
         // as part of onboarding, before they send a valid conversation notification
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mAppRow.banned) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannel != null) {
             if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
                     || NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
-                return CONDITIONALLY_UNAVAILABLE;
+                return false;
             }
         }
         if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_NONE) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        return AVAILABLE;
+        return true;
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java b/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java
index 12b8075..e5afd9d 100644
--- a/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java
+++ b/src/com/android/settings/notification/app/AddToHomeScreenPreferenceController.java
@@ -32,7 +32,7 @@
     private static final String KEY = "add_to_home";
 
     public AddToHomeScreenPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
     }
 
     @Override
@@ -41,11 +41,11 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
-        return mConversationInfo != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return mConversationInfo != null;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/AllowSoundPreferenceController.java b/src/com/android/settings/notification/app/AllowSoundPreferenceController.java
index 99d0873..0664c54 100644
--- a/src/com/android/settings/notification/app/AllowSoundPreferenceController.java
+++ b/src/com/android/settings/notification/app/AllowSoundPreferenceController.java
@@ -40,7 +40,7 @@
     public AllowSoundPreferenceController(Context context,
             NotificationSettings.DependentFieldListener dependentFieldListener,
             NotificationBackend backend) {
-        super(context, backend, KEY_IMPORTANCE);
+        super(context, backend);
         mDependentFieldListener = dependentFieldListener;
     }
 
@@ -50,14 +50,11 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
-        if (mChannel != null && NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return mChannel != null && NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId());
 
     }
 
diff --git a/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java b/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java
index 6c2c0c3..92cd911 100644
--- a/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java
+++ b/src/com/android/settings/notification/app/AppChannelsBypassingDndPreferenceController.java
@@ -64,7 +64,7 @@
     public AppChannelsBypassingDndPreferenceController(
             Context context,
             NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
     }
 
     @Override
@@ -110,8 +110,8 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        return mAppRow != null;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/AppConversationListPreferenceController.java b/src/com/android/settings/notification/app/AppConversationListPreferenceController.java
index e7b2378..dd44a13 100644
--- a/src/com/android/settings/notification/app/AppConversationListPreferenceController.java
+++ b/src/com/android/settings/notification/app/AppConversationListPreferenceController.java
@@ -49,12 +49,7 @@
     protected PreferenceCategory mPreference;
 
     public AppConversationListPreferenceController(Context context, NotificationBackend backend) {
-        this(context, backend, KEY);
-    }
-
-    public AppConversationListPreferenceController(Context context, NotificationBackend backend,
-            String key) {
-        super(context, backend, key);
+        super(context, backend);
     }
 
     @Override
@@ -63,24 +58,21 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mAppRow.banned) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannel != null) {
             if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
                     || NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
-                return CONDITIONALLY_UNAVAILABLE;
+                return false;
             }
         }
-        if (mBackend.hasSentValidMsg(mAppRow.pkg, mAppRow.uid) || mBackend.isInInvalidMsgState(
-                mAppRow.pkg, mAppRow.uid)) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return mBackend.hasSentValidMsg(mAppRow.pkg, mAppRow.uid) || mBackend.isInInvalidMsgState(
+                mAppRow.pkg, mAppRow.uid);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/AppLinkPreferenceController.java b/src/com/android/settings/notification/app/AppLinkPreferenceController.java
index ecf9670..043ae69 100644
--- a/src/com/android/settings/notification/app/AppLinkPreferenceController.java
+++ b/src/com/android/settings/notification/app/AppLinkPreferenceController.java
@@ -32,7 +32,7 @@
     private static final String KEY_APP_LINK = "app_link";
 
     public AppLinkPreferenceController(Context context) {
-        super(context, null, KEY_APP_LINK);
+        super(context, null);
     }
 
     @Override
@@ -41,11 +41,11 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
-        return mAppRow.settingsIntent != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return mAppRow.settingsIntent != null;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/BadgePreferenceController.java b/src/com/android/settings/notification/app/BadgePreferenceController.java
index f94dfb5..108fa1d 100644
--- a/src/com/android/settings/notification/app/BadgePreferenceController.java
+++ b/src/com/android/settings/notification/app/BadgePreferenceController.java
@@ -38,7 +38,7 @@
 
     public BadgePreferenceController(Context context,
             NotificationBackend backend) {
-        super(context, backend, KEY_BADGE);
+        super(context, backend);
     }
 
     @Override
@@ -47,29 +47,25 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mAppRow == null && mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (Settings.Secure.getInt(mContext.getContentResolver(),
                 NOTIFICATION_BADGING, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannel != null) {
             if (isDefaultChannel()) {
-                return AVAILABLE;
+                return true;
             } else {
-                return mAppRow == null
-                        ? CONDITIONALLY_UNAVAILABLE
-                        : mAppRow.showBadge
-                                ? AVAILABLE
-                                : CONDITIONALLY_UNAVAILABLE;
+                return mAppRow == null ? false : mAppRow.showBadge;
             }
         }
-        return AVAILABLE;
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/BlockPreferenceController.java b/src/com/android/settings/notification/app/BlockPreferenceController.java
index ea3eaeb..f4e2132 100644
--- a/src/com/android/settings/notification/app/BlockPreferenceController.java
+++ b/src/com/android/settings/notification/app/BlockPreferenceController.java
@@ -42,7 +42,7 @@
     public BlockPreferenceController(Context context,
             NotificationSettings.DependentFieldListener dependentFieldListener,
             NotificationBackend backend) {
-        super(context, backend, KEY_BLOCK);
+        super(context, backend);
         mDependentFieldListener = dependentFieldListener;
     }
 
@@ -52,14 +52,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mPreferenceFilter != null && !isIncludedInFilter()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        return AVAILABLE;
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java b/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java
index da67afe..ad3a10c 100644
--- a/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java
+++ b/src/com/android/settings/notification/app/BubbleCategoryPreferenceController.java
@@ -32,15 +32,15 @@
     static final int ON = 1;
 
     public BubbleCategoryPreferenceController(Context context) {
-        super(context, null, KEY);
+        super(context, null);
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
-        return areBubblesEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return areBubblesEnabled();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java b/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java
index ed1c9b5..0b9529b 100644
--- a/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java
+++ b/src/com/android/settings/notification/app/BubbleLinkPreferenceController.java
@@ -32,15 +32,15 @@
     static final int ON = 1;
 
     public BubbleLinkPreferenceController(Context context) {
-        super(context, null, KEY);
+        super(context, null);
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
-        return areBubblesEnabled() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return areBubblesEnabled();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/BubblePreferenceController.java b/src/com/android/settings/notification/app/BubblePreferenceController.java
index 516a45e..351b463 100644
--- a/src/com/android/settings/notification/app/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/app/BubblePreferenceController.java
@@ -56,7 +56,7 @@
     public BubblePreferenceController(Context context, @Nullable FragmentManager fragmentManager,
             NotificationBackend backend, boolean isAppPage,
             @Nullable NotificationSettings.DependentFieldListener listener) {
-        super(context, backend, KEY);
+        super(context, backend);
         mFragmentManager = fragmentManager;
         mIsAppPage = isAppPage;
         mListener = listener;
@@ -68,24 +68,21 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (!mIsAppPage && !isEnabled()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannel != null) {
             if (isDefaultChannel()) {
-                return AVAILABLE;
+                return true;
             } else {
-                if (mAppRow != null &&  mAppRow.bubblePreference != BUBBLE_PREFERENCE_NONE) {
-                    return AVAILABLE;
-                }
-                return CONDITIONALLY_UNAVAILABLE;
+                return mAppRow != null &&  mAppRow.bubblePreference != BUBBLE_PREFERENCE_NONE;
             }
         }
-        return AVAILABLE;
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
index abbe89e..51370b1 100644
--- a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
+++ b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
@@ -42,31 +42,28 @@
     static final int ON = 1;
 
     public BubbleSummaryPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannel != null) {
             if (!isGloballyEnabled()) {
-                return CONDITIONALLY_UNAVAILABLE;
+                return false;
             }
             if (isDefaultChannel()) {
-                return AVAILABLE;
+                return true;
             } else {
-                return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+                return mAppRow != null;
             }
         }
-        if (isGloballyEnabled() && mBackend.hasSentValidBubble(mAppRow.pkg, mAppRow.uid)) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return isGloballyEnabled() && mBackend.hasSentValidBubble(mAppRow.pkg, mAppRow.uid);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/ChannelListPreferenceController.java b/src/com/android/settings/notification/app/ChannelListPreferenceController.java
index 8d07911..8db3b21 100644
--- a/src/com/android/settings/notification/app/ChannelListPreferenceController.java
+++ b/src/com/android/settings/notification/app/ChannelListPreferenceController.java
@@ -28,7 +28,6 @@
 import android.os.Bundle;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.util.Slog;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -40,19 +39,16 @@
 import com.android.settings.R;
 import com.android.settings.Utils;
 import com.android.settings.applications.AppInfoBase;
-import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.notification.NotificationBackend;
 import com.android.settingslib.PrimarySwitchPreference;
 import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
-public class ChannelListPreferenceController extends NotificationPreferenceController
-        implements BasePreferenceController.UiBlocker {
+public class ChannelListPreferenceController extends NotificationPreferenceController {
 
     private static final String KEY = "channels";
     private static final String KEY_GENERAL_CATEGORY = "categories";
@@ -63,7 +59,7 @@
     private PreferenceCategory mPreference;
 
     public ChannelListPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
     }
 
     @Override
@@ -72,20 +68,20 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mAppRow.banned) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannel != null) {
             if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
                     || NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
-                return CONDITIONALLY_UNAVAILABLE;
+                return false;
             }
         }
-        return AVAILABLE;
+        return true;
     }
 
     @Override
@@ -95,17 +91,24 @@
 
     @Override
     public void updateState(Preference preference) {
-            mPreference = (PreferenceCategory) preference;
-            // Load channel settings
-            ThreadUtils.postOnBackgroundThread(() -> {
+        mPreference = (PreferenceCategory) preference;
+        // Load channel settings
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... unused) {
                 mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList();
                 Collections.sort(mChannelGroupList, CHANNEL_GROUP_COMPARATOR);
-                ThreadUtils.getUiThreadHandler().getLooper().prepare();
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Void unused) {
+                if (mContext == null) {
+                    return;
+                }
                 updateFullList(mPreference, mChannelGroupList);
-                ThreadUtils.postOnMainThread(() -> {
-                    showPreferences();
-                });
-            });
+            }
+        }.execute();
     }
 
     /**
@@ -141,12 +144,6 @@
         }
     }
 
-    private void showPreferences() {
-        if (mUiBlockListener != null) {
-           mUiBlockListener.onBlockerWorkFinished(this);
-        }
-    }
-
     /**
      * Looks for the category for the given group's key at the expected index, if that doesn't
      * match, it checks all groups, and if it can't find that group anywhere, it creates it.
diff --git a/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java b/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java
index ba7ca35..02f639c 100644
--- a/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationDemotePreferenceController.java
@@ -37,7 +37,7 @@
     public ConversationDemotePreferenceController(Context context,
             SettingsPreferenceFragment hostFragment,
             NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
         mHostFragment = hostFragment;
     }
 
@@ -47,17 +47,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mAppRow == null || mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        if (!TextUtils.isEmpty(mChannel.getConversationId()) && !mChannel.isDemoted()) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return !TextUtils.isEmpty(mChannel.getConversationId()) && !mChannel.isDemoted();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java b/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java
index 56de88b..f99a56a 100644
--- a/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationHeaderPreferenceController.java
@@ -45,7 +45,7 @@
     private boolean mStarted = false;
 
     public ConversationHeaderPreferenceController(Context context, DashboardFragment fragment) {
-        super(context, null, PREF_KEY_APP_HEADER);
+        super(context, null);
         mFragment = fragment;
     }
 
@@ -55,8 +55,8 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        return mAppRow != null;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
index 46bc3c0..ae16928 100644
--- a/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
@@ -34,7 +34,7 @@
 
     public ConversationPriorityPreferenceController(Context context,
             NotificationBackend backend, NotificationSettings.DependentFieldListener listener) {
-        super(context, backend, KEY);
+        super(context, backend);
         mDependentFieldListener = listener;
     }
 
@@ -44,14 +44,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mAppRow == null || mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        return AVAILABLE;
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java b/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java
index a5ef569..24c3d2f 100644
--- a/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationPromotePreferenceController.java
@@ -37,7 +37,7 @@
     public ConversationPromotePreferenceController(Context context,
             SettingsPreferenceFragment hostFragment,
             NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
         mHostFragment = hostFragment;
     }
 
@@ -47,17 +47,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mAppRow == null || mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        if (!TextUtils.isEmpty(mChannel.getConversationId()) && mChannel.isDemoted()) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return !TextUtils.isEmpty(mChannel.getConversationId()) && mChannel.isDemoted();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java b/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java
index cd160df..77a692f 100644
--- a/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java
+++ b/src/com/android/settings/notification/app/DeletedChannelsPreferenceController.java
@@ -30,7 +30,7 @@
     private static final String  KEY_DELETED = "deleted";
 
     public DeletedChannelsPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY_DELETED);
+        super(context, backend);
     }
 
     @Override
@@ -39,19 +39,16 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         // only visible on app screen
         if (mChannel != null || hasValidGroup()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
 
-        if (mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid) > 0) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid) > 0;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/DescriptionPreferenceController.java b/src/com/android/settings/notification/app/DescriptionPreferenceController.java
index 413a876..0a5bb2f 100644
--- a/src/com/android/settings/notification/app/DescriptionPreferenceController.java
+++ b/src/com/android/settings/notification/app/DescriptionPreferenceController.java
@@ -29,7 +29,7 @@
     private static final String KEY_DESC = "desc";
 
     public DescriptionPreferenceController(Context context) {
-        super(context, null, KEY_DESC);
+        super(context, null);
     }
 
     @Override
@@ -38,20 +38,20 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mChannel == null && !hasValidGroup()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannel != null && !TextUtils.isEmpty(mChannel.getDescription())) {
-            return AVAILABLE;
+            return true;
         }
         if (hasValidGroup() && !TextUtils.isEmpty(mChannelGroup.getDescription())) {
-            return AVAILABLE;
+            return true;
         }
-        return CONDITIONALLY_UNAVAILABLE;
+        return false;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/DndPreferenceController.java b/src/com/android/settings/notification/app/DndPreferenceController.java
index 811eeb4..b65928a 100644
--- a/src/com/android/settings/notification/app/DndPreferenceController.java
+++ b/src/com/android/settings/notification/app/DndPreferenceController.java
@@ -31,7 +31,7 @@
     private static final String KEY_BYPASS_DND = "bypass_dnd";
 
     public DndPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY_BYPASS_DND);
+        super(context, backend);
     }
 
     @Override
@@ -40,11 +40,11 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE || mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable() || mChannel == null) {
+            return false;
         }
-        return AVAILABLE;
+        return true;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/HeaderPreferenceController.java b/src/com/android/settings/notification/app/HeaderPreferenceController.java
index c4b0e59..7379d55 100644
--- a/src/com/android/settings/notification/app/HeaderPreferenceController.java
+++ b/src/com/android/settings/notification/app/HeaderPreferenceController.java
@@ -45,7 +45,7 @@
     private boolean mStarted = false;
 
     public HeaderPreferenceController(Context context, DashboardFragment fragment) {
-        super(context, null, PREF_KEY_APP_HEADER);
+        super(context, null);
         mFragment = fragment;
     }
 
@@ -55,8 +55,8 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        return mAppRow != null ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        return mAppRow != null;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/HighImportancePreferenceController.java b/src/com/android/settings/notification/app/HighImportancePreferenceController.java
index 98dc8a7..d60668b 100644
--- a/src/com/android/settings/notification/app/HighImportancePreferenceController.java
+++ b/src/com/android/settings/notification/app/HighImportancePreferenceController.java
@@ -37,7 +37,7 @@
     public HighImportancePreferenceController(Context context,
             NotificationSettings.DependentFieldListener dependentFieldListener,
             NotificationBackend backend) {
-        super(context, backend, KEY_IMPORTANCE);
+        super(context, backend);
         mDependentFieldListener = dependentFieldListener;
     }
 
@@ -47,19 +47,17 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (isDefaultChannel()) {
-           return CONDITIONALLY_UNAVAILABLE;
+           return false;
         }
-        return mChannel.getImportance() >= IMPORTANCE_DEFAULT
-                ? AVAILABLE
-                : CONDITIONALLY_UNAVAILABLE;
+        return mChannel.getImportance() >= IMPORTANCE_DEFAULT;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/ImportancePreferenceController.java b/src/com/android/settings/notification/app/ImportancePreferenceController.java
index 31ddac3..3c32ca4 100644
--- a/src/com/android/settings/notification/app/ImportancePreferenceController.java
+++ b/src/com/android/settings/notification/app/ImportancePreferenceController.java
@@ -38,7 +38,7 @@
     public ImportancePreferenceController(Context context,
             NotificationSettings.DependentFieldListener dependentFieldListener,
             NotificationBackend backend) {
-        super(context, backend, KEY_IMPORTANCE);
+        super(context, backend);
         mDependentFieldListener = dependentFieldListener;
     }
 
@@ -48,14 +48,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        return !isDefaultChannel() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return !isDefaultChannel();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java b/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java
index bb2c58b..b937e80 100644
--- a/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java
+++ b/src/com/android/settings/notification/app/InvalidConversationInfoPreferenceController.java
@@ -31,7 +31,7 @@
 
     public InvalidConversationInfoPreferenceController(Context context,
             NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
     }
 
     @Override
@@ -40,19 +40,17 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mAppRow.banned) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mPreferenceFilter != null && !isIncludedInFilter()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid)
-                ? AVAILABLE
-                : CONDITIONALLY_UNAVAILABLE;
+        return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java b/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java
index 219ccbc..5c502dc 100644
--- a/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java
+++ b/src/com/android/settings/notification/app/InvalidConversationPreferenceController.java
@@ -31,7 +31,7 @@
     private static final String KEY = "invalid_conversation_switch";
 
     public InvalidConversationPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY);
+        super(context, backend);
     }
 
     @Override
@@ -40,19 +40,17 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mAppRow.banned) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mPreferenceFilter != null && !isIncludedInFilter()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid)
-                ? AVAILABLE
-                : CONDITIONALLY_UNAVAILABLE;
+        return mBackend.isInInvalidMsgState(mAppRow.pkg, mAppRow.uid);
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/LightsPreferenceController.java b/src/com/android/settings/notification/app/LightsPreferenceController.java
index f7f9244..d096922 100644
--- a/src/com/android/settings/notification/app/LightsPreferenceController.java
+++ b/src/com/android/settings/notification/app/LightsPreferenceController.java
@@ -33,7 +33,7 @@
     private static final String KEY_LIGHTS = "lights";
 
     public LightsPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY_LIGHTS);
+        super(context, backend);
     }
 
     @Override
@@ -42,18 +42,16 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        if (checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && canPulseLight()
-                && !isDefaultChannel()) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
+                && canPulseLight()
+                && !isDefaultChannel();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/MinImportancePreferenceController.java b/src/com/android/settings/notification/app/MinImportancePreferenceController.java
index b2c0862..f825763 100644
--- a/src/com/android/settings/notification/app/MinImportancePreferenceController.java
+++ b/src/com/android/settings/notification/app/MinImportancePreferenceController.java
@@ -37,7 +37,7 @@
     public MinImportancePreferenceController(Context context,
             NotificationSettings.DependentFieldListener dependentFieldListener,
             NotificationBackend backend) {
-        super(context, backend, KEY_IMPORTANCE);
+        super(context, backend);
         mDependentFieldListener = dependentFieldListener;
     }
 
@@ -47,17 +47,17 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (isDefaultChannel()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        return mChannel.getImportance() <= IMPORTANCE_LOW ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return mChannel.getImportance() <= IMPORTANCE_LOW;
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/NotificationPreferenceController.java b/src/com/android/settings/notification/app/NotificationPreferenceController.java
index 271a83d..fb19d9d 100644
--- a/src/com/android/settings/notification/app/NotificationPreferenceController.java
+++ b/src/com/android/settings/notification/app/NotificationPreferenceController.java
@@ -17,24 +17,26 @@
 package com.android.settings.notification.app;
 
 import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.os.UserHandle.USER_SYSTEM;
 
 import android.annotation.Nullable;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Drawable;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.Log;
-import android.util.Slog;
 
 import androidx.preference.Preference;
 
-import com.android.settings.core.BasePreferenceController;
 import com.android.settings.notification.NotificationBackend;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.core.AbstractPreferenceController;
 
 import java.util.Comparator;
 import java.util.List;
@@ -44,7 +46,7 @@
  * Parent class for preferences appearing on notification setting pages at the app,
  * notification channel group, or notification channel level.
  */
-public abstract class NotificationPreferenceController extends BasePreferenceController {
+public abstract class NotificationPreferenceController extends AbstractPreferenceController {
     private static final String TAG = "ChannelPrefContr";
     @Nullable
     protected NotificationChannel mChannel;
@@ -69,11 +71,8 @@
     boolean overrideCanBlockValue;
     boolean overrideCanConfigureValue;
 
-    boolean mLoadedChannelState;
-
-    public NotificationPreferenceController(Context context, NotificationBackend backend,
-            String key) {
-        super(context, key);
+    public NotificationPreferenceController(Context context, NotificationBackend backend) {
+        super(context);
         mContext = context;
         mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
         mBackend = backend;
@@ -82,30 +81,28 @@
     }
 
     /**
-     * Returns available if field's parent object is not blocked.
+     * Returns true if field's parent object is not blocked.
      */
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mAppRow.banned) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mChannelGroup != null) {
             if (mChannelGroup.isBlocked()) {
-                return CONDITIONALLY_UNAVAILABLE;
+                return false;
             }
         }
         if (mChannel != null) {
             if (mPreferenceFilter != null && !isIncludedInFilter()) {
-                return CONDITIONALLY_UNAVAILABLE;
+                return false;
             }
-            if(mChannel.getImportance() == IMPORTANCE_NONE) {
-                return CONDITIONALLY_UNAVAILABLE;
-            }
+            return mChannel.getImportance() != IMPORTANCE_NONE;
         }
-        return AVAILABLE;
+        return true;
     }
 
     protected void onResume(NotificationBackend.AppRow appRow,
diff --git a/src/com/android/settings/notification/app/NotificationSettings.java b/src/com/android/settings/notification/app/NotificationSettings.java
index 5750167..192a0ee 100644
--- a/src/com/android/settings/notification/app/NotificationSettings.java
+++ b/src/com/android/settings/notification/app/NotificationSettings.java
@@ -41,7 +41,6 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
-import android.util.Slog;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
@@ -130,52 +129,15 @@
             }
         }
 
-        mUserId = UserHandle.getUserId(mUid);
         mPkgInfo = findPackageInfo(mPkg, mUid);
-    }
 
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        if (mIntent == null && mArgs == null) {
-            toastAndFinish("no intent");
-            return;
-        }
-
-        if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
-            toastAndFinish("Missing package or uid or packageinfo");
-            return;
-        }
-
-        startListeningToPackageRemove();
-    }
-
-    @Override
-    public void onDestroy() {
-        stopListeningToPackageRemove();
-        super.onDestroy();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
-            toastAndFinish("Missing package or uid or packageinfo");
-            return;
-        }
-        mPkgInfo = findPackageInfo(mPkg, mUid);
         if (mPkgInfo != null) {
+            mUserId = UserHandle.getUserId(mUid);
             mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended(
                     mContext, mPkg, mUserId);
 
-            loadAppRow();
-            if (mAppRow == null) {
-                toastAndFinish("Can't load package");
-                return;
-            }
             loadChannel();
-            loadConversation();
+            loadAppRow();
             loadChannelGroup();
             loadPreferencesFilter();
             collectConfigActivities();
@@ -195,6 +157,55 @@
         }
     }
 
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (mIntent == null && mArgs == null) {
+            Log.w(TAG, "No intent");
+            toastAndFinish();
+            return;
+        }
+
+        if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
+            Log.w(TAG, "Missing package or uid or packageinfo");
+            toastAndFinish();
+            return;
+        }
+
+        startListeningToPackageRemove();
+    }
+
+    @Override
+    public void onDestroy() {
+        stopListeningToPackageRemove();
+        super.onDestroy();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null || mAppRow == null) {
+            Log.w(TAG, "Missing package or uid or packageinfo");
+            finish();
+            return;
+        }
+        // Reload app, channel, etc onResume in case they've changed. A little wasteful if we've
+        // just done onAttach but better than making every preference controller reload all
+        // the data
+        loadAppRow();
+        if (mAppRow == null) {
+            Log.w(TAG, "Can't load package");
+            finish();
+            return;
+        }
+        loadChannel();
+        loadConversation();
+        loadChannelGroup();
+        loadPreferencesFilter();
+        collectConfigActivities();
+    }
+
     protected void animatePanel() {
         if (mPreferenceFilter != null) {
             mLayoutView = getActivity().findViewById(R.id.main_content);
@@ -296,8 +307,7 @@
         }
     }
 
-    protected void toastAndFinish(String msg) {
-        Log.w(TAG, msg);
+    protected void toastAndFinish() {
         Toast.makeText(mContext, R.string.app_not_found_dlg_text, Toast.LENGTH_SHORT).show();
         getActivity().finish();
     }
diff --git a/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java b/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
index 46625c3..0c7cd23 100644
--- a/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
+++ b/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
@@ -30,7 +30,7 @@
     private static final String KEY_BLOCKED_DESC = "block_desc";
 
     public NotificationsOffPreferenceController(Context context) {
-        super(context, null, KEY_BLOCKED_DESC);
+        super(context, null);
     }
 
     @Override
@@ -39,20 +39,16 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
+    public boolean isAvailable() {
         if (mAppRow == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         if (mPreferenceFilter != null && !isIncludedInFilter()) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
         // Available only when other controllers are unavailable - this UI replaces the UI that
         // would give more detailed notification controls.
-        if (super.getAvailabilityStatus() == AVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
-        } else {
-            return AVAILABLE;
-        }
+        return !super.isAvailable();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/SoundPreferenceController.java b/src/com/android/settings/notification/app/SoundPreferenceController.java
index 335b442..b23b4fc 100644
--- a/src/com/android/settings/notification/app/SoundPreferenceController.java
+++ b/src/com/android/settings/notification/app/SoundPreferenceController.java
@@ -47,7 +47,7 @@
     public SoundPreferenceController(Context context, SettingsPreferenceFragment hostFragment,
             NotificationSettings.DependentFieldListener dependentFieldListener,
             NotificationBackend backend) {
-        super(context, backend, KEY_SOUND);
+        super(context, backend);
         mFragment = hostFragment;
         mListener = dependentFieldListener;
     }
@@ -58,17 +58,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        if (checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel()) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+        return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/VibrationPreferenceController.java b/src/com/android/settings/notification/app/VibrationPreferenceController.java
index f91999f..34d1a54 100644
--- a/src/com/android/settings/notification/app/VibrationPreferenceController.java
+++ b/src/com/android/settings/notification/app/VibrationPreferenceController.java
@@ -34,7 +34,7 @@
     private final Vibrator mVibrator;
 
     public VibrationPreferenceController(Context context, NotificationBackend backend) {
-        super(context, backend, KEY_VIBRATE);
+        super(context, backend);
         mVibrator = context.getSystemService(Vibrator.class);
     }
 
@@ -44,15 +44,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE || mChannel == null) {
-            return CONDITIONALLY_UNAVAILABLE;
-        }
-        if (checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && !isDefaultChannel()
-                && mVibrator != null && mVibrator.hasVibrator()) {
-            return AVAILABLE;
-        }
-        return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable() || mChannel == null) {
+            return false;
+       }
+        return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
+                && !isDefaultChannel()
+                && mVibrator != null
+                && mVibrator.hasVibrator();
     }
 
     @Override
diff --git a/src/com/android/settings/notification/app/VisibilityPreferenceController.java b/src/com/android/settings/notification/app/VisibilityPreferenceController.java
index 3f33267..a2a1d76 100644
--- a/src/com/android/settings/notification/app/VisibilityPreferenceController.java
+++ b/src/com/android/settings/notification/app/VisibilityPreferenceController.java
@@ -48,7 +48,7 @@
 
     public VisibilityPreferenceController(Context context, LockPatternUtils utils,
             NotificationBackend backend) {
-        super(context, backend, KEY_VISIBILITY_OVERRIDE);
+        super(context, backend);
         mLockPatternUtils = utils;
     }
 
@@ -58,18 +58,14 @@
     }
 
     @Override
-    public int getAvailabilityStatus() {
-        if (super.getAvailabilityStatus() == CONDITIONALLY_UNAVAILABLE) {
-            return CONDITIONALLY_UNAVAILABLE;
+    public boolean isAvailable() {
+        if (!super.isAvailable()) {
+            return false;
         }
         if (mChannel == null || mAppRow.banned) {
-            return CONDITIONALLY_UNAVAILABLE;
+            return false;
         }
-        if (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure()) {
-            return AVAILABLE;
-        }
-
-        return CONDITIONALLY_UNAVAILABLE;
+        return checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure();
     }
 
     @Override
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java
index 3309f59..90e7ad7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryDefenderDetectorTest.java
@@ -18,6 +18,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import androidx.test.core.app.ApplicationProvider;
+
 import com.android.settings.fuelgauge.BatteryInfo;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 
@@ -42,7 +44,7 @@
         mBatteryInfo.discharging = false;
 
         mBatteryDefenderDetector = new BatteryDefenderDetector(
-            mBatteryInfo, /* extraDefend= */ false);
+            mBatteryInfo, ApplicationProvider.getApplicationContext());
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java
index c1ec7c6..6bd6b26 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTipTest.java
@@ -125,7 +125,7 @@
 
     @Test
     public void updatePreference_shouldSetSecondaryButtonText() {
-        String expected = mContext.getString(R.string.see_more);
+        String expected = mContext.getString(R.string.learn_more);
 
         mBatteryDefenderTip.updatePreference(mCardPreference);
 
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 016287e..1eead82 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -630,6 +630,18 @@
                 .isFalse();
     }
 
+    @Test
+    public void getTotalHours_getExpectedResult() {
+        Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = createBatteryHistoryMap(60);
+        BatteryLevelData batteryLevelData = DataProcessor.getBatteryLevelData(mContext, null,
+                batteryHistoryMap, null);
+
+        final int totalHour = BatteryChartPreferenceController.getTotalHours(batteryLevelData);
+
+        // Only calculate the even hours.
+        assertThat(totalHour).isEqualTo(58);
+    }
+
     private static Long generateTimestamp(int index) {
         // "2021-04-23 07:00:00 UTC" + index hours
         return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java
index 5ca3aca..ffc6d9a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java
@@ -307,7 +307,7 @@
                 R.drawable.ic_settings_aod);
         assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
                 R.string.power_bluetooth,
-                com.android.internal.R.drawable.ic_settings_bluetooth);
+                R.drawable.ic_settings_bluetooth);
         assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_CAMERA,
                 R.string.power_camera,
                 R.drawable.ic_settings_camera);
@@ -325,7 +325,7 @@
                 R.drawable.ic_settings_display);
         assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_WIFI,
                 R.string.power_wifi,
-                R.drawable.ic_settings_wireless);
+                R.drawable.ic_settings_wireless_no_theme);
         assertNameAndIcon(BatteryConsumer.POWER_COMPONENT_IDLE,
                 R.string.power_idle,
                 R.drawable.ic_settings_phone_idle);
diff --git a/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java
index bf529e6..b2f1673 100644
--- a/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/NotificationPreferenceControllerTest.java
@@ -426,7 +426,7 @@
     private final class TestPreferenceController extends NotificationPreferenceController {
 
         private TestPreferenceController(Context context, NotificationBackend backend) {
-            super(context, backend, "key");
+            super(context, backend);
         }
 
         @Override
diff --git a/tests/unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.java b/tests/unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.java
new file mode 100644
index 0000000..f74768f
--- /dev/null
+++ b/tests/unit/src/com/android/settings/datausage/BillingCyclePreferenceTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.datausage;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.telephony.TelephonyManager;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class BillingCyclePreferenceTest {
+
+    private Context mContext;
+    private BillingCyclePreference mPreference;
+    private TemplatePreference.NetworkServices mServices;
+    @Mock
+    private INetworkManagementService mNetManageSerice;
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private UserManager mUserManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+
+        mServices = new TemplatePreference.NetworkServices();
+        mServices.mNetworkService = mNetManageSerice;
+        mServices.mTelephonyManager = mTelephonyManager;
+        mServices.mUserManager = mUserManager;
+
+        doReturn(mTelephonyManager).when(mTelephonyManager)
+                .createForSubscriptionId(anyInt());
+
+        mPreference = spy(new BillingCyclePreference(mContext, null /* attrs */));
+        mPreference.setTemplate(null, 0, mServices);
+    }
+
+    @Test
+    public void testPreferenceUpdate_onMobileDataEnabledChange_accessDataEnabledApi() {
+        try {
+            doReturn(true).when(mNetManageSerice).isBandwidthControlEnabled();
+        } catch (RemoteException exception) {}
+        doReturn(true).when(mUserManager).isAdminUser();
+        mPreference.onMobileDataEnabledChange();
+
+        verify(mTelephonyManager)
+                .isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER);
+    }
+}
\ No newline at end of file