Merge "Fix b/243746796 Crash when mouse hangs over an empty battery chart"
diff --git a/res/layout/locale_drag_cell.xml b/res/layout/locale_drag_cell.xml
index 7b932f3..47bf70a 100644
--- a/res/layout/locale_drag_cell.xml
+++ b/res/layout/locale_drag_cell.xml
@@ -56,6 +56,17 @@
         android:layout_toStartOf="@+id/dragHandle"
         android:layout_below="@id/label"/>
 
+    <TextView
+        android:id="@+id/default_locale"
+        style="@style/LanguageCheckboxAndLabel"
+        android:layout_marginTop="-28dp"
+        android:paddingStart="56dp"
+        android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+        android:textColor="?android:textColorSecondary"
+        android:text="@string/desc_current_default_language"
+        android:layout_toStartOf="@+id/dragHandle"
+        android:layout_below="@id/label"/>
+
     <ImageView
         android:id="@+id/dragHandle"
         android:layout_width="wrap_content"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2aae74a..ea0253a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -401,6 +401,12 @@
     <!-- Title for the locale picker activity. [CHAR LIMIT=30]-->
     <string name="language_picker_title">Languages</string>
 
+    <!-- Title for category of the locale picker . [CHAR LIMIT=50]-->
+    <string name="language_picker_category_title">Preferred language order</string>
+
+    <!-- Description for indication of current system default language. [CHAR LIMIT=50]-->
+    <string name="desc_current_default_language">System language</string>
+
     <!-- Menu item in the locale menu. Will remove the selected locales. [CHAR LIMIT=30] -->
     <string name="locale_remove_menu">Remove</string>
 
@@ -414,13 +420,13 @@
     <string name="locale_picker_category_title">Preferred Language</string>
 
     <!-- Title for the Apps' locale menu entry [CHAR LIMIT=50]-->
-    <string name="app_locales_picker_menu_title">App Languages</string>
+    <string name="app_locales_picker_menu_title">App languages</string>
 
     <!-- Summary for the app's locale picker activity. [CHAR LIMIT=50]-->
     <string name="app_locale_picker_summary">Set the language for each app</string>
 
     <!-- Title for the App's locale picker activity. [CHAR LIMIT=50]-->
-    <string name="app_locale_picker_title">App Language</string>
+    <string name="app_locale_picker_title">App language</string>
 
     <!-- Category for the suggested app's locales. [CHAR LIMIT=50]-->
     <string name="suggested_app_locales_title">Suggested languages</string>
@@ -443,6 +449,18 @@
     <!-- Description for introduction of the locale selection supported of app list [CHAR LIMIT=NONE]-->
     <string name="desc_app_locale_selection_supported">Only apps that support language selection are shown here.</string>
 
+    <!-- Description for the introduction to language picker activity. [CHAR LIMIT=NONE]-->
+    <string name="desc_introduction_of_language_picker">Your system, apps, and websites use the first supported language from your preferred languages.</string>
+
+    <!-- Description for the notice of language picker. [CHAR LIMIT=NONE]-->
+    <string name="desc_notice_of_language_picker">To select a language for each app, go to app language settings.</string>
+
+    <!-- Title for locale helper page [CHAR LIMIT=NONE] -->
+    <string name="desc_locale_helper_footer_general">Learn more about languages</string>
+
+    <!-- Link for Locale helper page. [CHAR LIMIT=NONE]-->
+    <string name="link_locale_picker_footer_learn_more" translatable="false">https://support.google.com/android?p=per_language_app_settings</string>
+
     <!-- The title of the confirmation dialog shown when the user selects one / several languages and tries to remove them [CHAR LIMIT=60] -->
     <plurals name="dlg_remove_locales_title">
         <item quantity="one">Remove selected language?</item>
@@ -458,7 +476,7 @@
     <string name="dlg_remove_locales_error_message">Keep at least one preferred language</string>
 
     <!-- This text shows in the language picker when the system is not translated into that languages [CHAR LIMIT=80] -->
-    <string name="locale_not_translated">May not be available in some apps</string>
+    <string name="locale_not_translated">Not available as system language</string>
 
     <!-- Label for an accessibility action that moves a language up in the ordered language list [CHAR LIMIT=20] -->
     <string name="action_drag_label_move_up">Move up</string>
@@ -1870,6 +1888,21 @@
     <!-- Nfc developer settings: The description of the setting. -->
     <string name="nfc_stack_debuglog_summary">Increase NFC stack logging level</string>
 
+    <!-- Nfc developer settings: The title of the setting to enable nfc verbose vendor log. [CHAR LIMIT=60] -->
+    <string name="nfc_verbose_vendor_log_title">NFC verbose vendor debug log</string>
+    <!-- Nfc developer settings: The description of the setting to enable nfc verbose vendor log. [CHAR_LIMIT=NONE] -->
+    <string name="nfc_verbose_vendor_log_summary">Include additional device-specific vendor logs in bugreports, which may contain private information. </string>
+    <!-- Nfc developer settings: The title of the setting to enable full nfc snoop log. [CHAR LIMIT=60] -->
+    <string name="nfc_snoop_log_title">NFC NCI unfiltered snoop log</string>
+    <!-- Nfc developer settings: The description of the setting to enable full nfc snoop log. [CHAR_LIMIT=NONE] -->
+    <string name="nfc_snoop_log_summary">Capture detail NFC packets, which may contain private information. </string>
+    <!-- Nfc developer settings: The title of the popup dialog. [CHAR_LIMIT=60] -->
+    <string name="nfc_reboot_dialog_title">Restart Device?</string>
+    <!-- Nfc developer settings: The content of the popup dialog. [CHAR_LIMIT=NONE] -->
+    <string name="nfc_reboot_dialog_message">Detail NFC logging is intended for development purposes only. Additional NFC data is included in bug reports, which may contain private information. Restart your device to change this setting. </string>
+    <!-- Nfc developer settings: The confirm button of the popup dialog. [CHAR_LIMIT=60] -->
+    <string name="nfc_reboot_dialog_confirm">Restart</string>
+
     <!-- Wifi Display settings. The title of the screen. [CHAR LIMIT=40] -->
     <string name="wifi_display_settings_title">Cast</string>
     <!-- Wifi Display settings. The keywords of the setting. [CHAR LIMIT=NONE] -->
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 19c1209..a0640f5 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -402,6 +402,16 @@
             android:title="@string/nfc_stack_debuglog_title"
             android:summary="@string/nfc_stack_debuglog_summary" />
 
+        <SwitchPreference
+            android:key="nfc_verbose_vendor_log"
+            android:title="@string/nfc_verbose_vendor_log_title"
+            android:summary="@string/nfc_verbose_vendor_log_summary" />
+
+        <SwitchPreference
+            android:key="nfc_snoop_log"
+            android:title="@string/nfc_snoop_log_title"
+            android:summary="@string/nfc_snoop_log_summary"/>
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/res/xml/languages.xml b/res/xml/languages.xml
new file mode 100644
index 0000000..0f45540
--- /dev/null
+++ b/res/xml/languages.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<PreferenceScreen
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    android:title="@string/language_settings">
+
+    <com.android.settingslib.widget.TopIntroPreference
+        android:title="@string/desc_introduction_of_language_picker"
+        android:persistent="false"
+        android:selectable="false"/>
+
+    <PreferenceCategory
+        android:title="@string/language_picker_category_title">
+        <com.android.settingslib.widget.LayoutPreference
+            android:key="languages_picker"
+            android:layout="@layout/locale_order_list" />
+    </PreferenceCategory>
+
+    <com.android.settingslib.widget.FooterPreference
+        android:key="footer_languages_picker"
+        android:title="@string/desc_notice_of_language_picker"
+        android:persistent="false"
+        android:selectable="false"
+        settings:controller="com.android.settings.localepicker.LocaleHelperPreferenceController"/>
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java
index cb5ca75..12a9886 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java
@@ -52,11 +52,17 @@
      */
     private void hidePreferenceSettingComponents() {
         // Intro
-        mTopIntroPreference.setVisible(false);
+        if (mTopIntroPreference != null) {
+            mTopIntroPreference.setVisible(false);
+        }
         // Setting of magnification type
-        mSettingsPreference.setVisible(false);
+        if (mSettingsPreference != null) {
+            mSettingsPreference.setVisible(false);
+        }
         // Setting of following typing
-        mFollowingTypingSwitchPreference.setVisible(false);
+        if (mFollowingTypingSwitchPreference != null) {
+            mFollowingTypingSwitchPreference.setVisible(false);
+        }
     }
 
     @Override
diff --git a/src/com/android/settings/applications/AppLocaleUtil.java b/src/com/android/settings/applications/AppLocaleUtil.java
index 8c3671e..79406f0 100644
--- a/src/com/android/settings/applications/AppLocaleUtil.java
+++ b/src/com/android/settings/applications/AppLocaleUtil.java
@@ -100,8 +100,8 @@
      */
     public static boolean isAppLocaleSupported(Context context, String packageName) {
         LocaleList localeList = getPackageLocales(context, packageName);
-        if (localeList != null && localeList.size() > 0) {
-            return true;
+        if (localeList != null) {
+            return localeList.size() > 0;
         }
 
         if (FeatureFlagUtils.isEnabled(
diff --git a/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java b/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java
index f406d87..6bf94a6 100644
--- a/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppLocalePreferenceController.java
@@ -22,7 +22,6 @@
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.text.TextUtils;
-import android.util.FeatureFlagUtils;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
@@ -51,9 +50,7 @@
 
     @Override
     public int getAvailabilityStatus() {
-        boolean isFeatureOn = FeatureFlagUtils
-                .isEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION);
-        return isFeatureOn && canDisplayLocaleUi() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+        return canDisplayLocaleUi() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
     @Override
diff --git a/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceController.java b/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceController.java
deleted file mode 100644
index aa12b62..0000000
--- a/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceController.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.appinfo;
-
-import android.content.Context;
-import android.util.FeatureFlagUtils;
-
-import com.android.settings.core.BasePreferenceController;
-
-/**
- * A controller to update current locale information of application
- * and a entry to launch {@link ManageApplications}.
- * TODO(209775925) After feature release, this class may be removed.
- */
-public class ManageAppLocalePreferenceController extends BasePreferenceController {
-    public ManageAppLocalePreferenceController(Context context, String key) {
-        super(context, key);
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        return FeatureFlagUtils
-                .isEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION)
-                ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
-    }
-}
diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java
index 7256511..1ae5dae 100644
--- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java
@@ -77,7 +77,7 @@
 
         @NonNull
         public AlertDialog.Builder onCreateDialogBuilder() {
-            return new AlertDialog.Builder(getContext())
+            return new AlertDialog.Builder(getActivity(), R.style.GlifV2ThemeAlertDialog)
                     .setTitle(R.string.setup_fingerprint_enroll_skip_title)
                     .setPositiveButton(R.string.skip_anyway_button_label, this)
                     .setNegativeButton(R.string.go_back_button_label, this)
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index d92fb7f..210d011 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -81,7 +81,8 @@
         implements OnMainSwitchChangeListener, OemUnlockDialogHost, AdbDialogHost,
         AdbClearKeysDialogHost, LogPersistDialogHost,
         BluetoothRebootDialog.OnRebootDialogListener,
-        AbstractBluetoothPreferenceController.Callback {
+        AbstractBluetoothPreferenceController.Callback,
+        NfcRebootDialog.OnNfcRebootDialogConfirmedListener {
 
     private static final String TAG = "DevSettingsDashboard";
 
@@ -299,10 +300,19 @@
                 final BluetoothLeAudioHwOffloadPreferenceController leAudioController =
                         getDevelopmentOptionsController(
                                 BluetoothLeAudioHwOffloadPreferenceController.class);
+                final NfcSnoopLogPreferenceController nfcSnoopLogController =
+                        getDevelopmentOptionsController(
+                                NfcSnoopLogPreferenceController.class);
+                final NfcVerboseVendorLogPreferenceController nfcVerboseLogController =
+                        getDevelopmentOptionsController(
+                                NfcVerboseVendorLogPreferenceController.class);
                 // If hardware offload isn't default value, we must reboot after disable
                 // developer options. Show a dialog for the user to confirm.
                 if ((a2dpController == null || a2dpController.isDefaultValue())
-                        && (leAudioController == null || leAudioController.isDefaultValue())) {
+                        && (leAudioController == null || leAudioController.isDefaultValue())
+                        && (nfcSnoopLogController == null || nfcSnoopLogController.isDefaultValue())
+                        && (nfcVerboseLogController == null
+                        || nfcVerboseLogController.isDefaultValue())) {
                     disableDeveloperOptions();
                 } else {
                     DisableDevSettingsDialogFragment.show(this /* host */);
@@ -396,6 +406,28 @@
     }
 
     @Override
+    public void onNfcRebootDialogConfirmed() {
+        final NfcSnoopLogPreferenceController controller =
+                getDevelopmentOptionsController(NfcSnoopLogPreferenceController.class);
+        controller.onNfcRebootDialogConfirmed();
+
+        final NfcVerboseVendorLogPreferenceController vendorLogController =
+                getDevelopmentOptionsController(NfcVerboseVendorLogPreferenceController.class);
+        vendorLogController.onNfcRebootDialogConfirmed();
+    }
+
+    @Override
+    public void onNfcRebootDialogCanceled() {
+        final NfcSnoopLogPreferenceController controller =
+                getDevelopmentOptionsController(NfcSnoopLogPreferenceController.class);
+        controller.onNfcRebootDialogCanceled();
+
+        final NfcVerboseVendorLogPreferenceController vendorLogController =
+                getDevelopmentOptionsController(NfcVerboseVendorLogPreferenceController.class);
+        vendorLogController.onNfcRebootDialogCanceled();
+    }
+
+    @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         boolean handledResult = false;
         for (AbstractPreferenceController controller : mPreferenceControllers) {
@@ -555,6 +587,8 @@
         controllers.add(new BluetoothLeAudioHwOffloadPreferenceController(context, fragment));
         controllers.add(new BluetoothMaxConnectedAudioDevicesPreferenceController(context));
         controllers.add(new NfcStackDebugLogPreferenceController(context));
+        controllers.add(new NfcSnoopLogPreferenceController(context, fragment));
+        controllers.add(new NfcVerboseVendorLogPreferenceController(context, fragment));
         controllers.add(new ShowTapsPreferenceController(context));
         controllers.add(new PointerLocationPreferenceController(context));
         controllers.add(new ShowSurfaceUpdatesPreferenceController(context));
diff --git a/src/com/android/settings/development/NfcRebootDialog.java b/src/com/android/settings/development/NfcRebootDialog.java
new file mode 100644
index 0000000..7d9890e
--- /dev/null
+++ b/src/com/android/settings/development/NfcRebootDialog.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 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.development;
+
+import android.app.Dialog;
+import android.app.settings.SettingsEnums;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.PowerManager;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentManager;
+
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+/**
+ * The NFC log type switch should reboot the device to take effect,
+ * the dialog is to ask the user to reboot the device.
+ */
+public class NfcRebootDialog extends InstrumentedDialogFragment
+        implements DialogInterface.OnClickListener {
+
+    public static final String TAG = "NfcRebootDialog";
+
+    /**
+     * The function to show the Dialog.
+     */
+    public static void show(DevelopmentSettingsDashboardFragment host) {
+        final FragmentManager manager = host.getActivity().getSupportFragmentManager();
+        if (manager.findFragmentByTag(TAG) == null) {
+            final NfcRebootDialog dialog = new NfcRebootDialog();
+            dialog.setTargetFragment(host, 0 /* requestCode */);
+            dialog.show(manager, TAG);
+        }
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.DIALOG_NFC_ENABLE_DETAIL_LOG;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        return new AlertDialog.Builder(getActivity())
+                .setMessage(R.string.nfc_reboot_dialog_message)
+                .setTitle(R.string.nfc_reboot_dialog_title)
+                .setPositiveButton(
+                        R.string.nfc_reboot_dialog_confirm, this)
+                .setNegativeButton(
+                        android.R.string.cancel, this)
+                .create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        final OnNfcRebootDialogConfirmedListener host =
+                (OnNfcRebootDialogConfirmedListener) getTargetFragment();
+        if (host == null) {
+            return;
+        }
+        if (which == DialogInterface.BUTTON_POSITIVE) {
+            host.onNfcRebootDialogConfirmed();
+            PowerManager pm = getContext().getSystemService(PowerManager.class);
+            pm.reboot(null);
+        } else {
+            host.onNfcRebootDialogCanceled();
+        }
+    }
+
+    /**
+     * Interface for EnableAdbWarningDialog callbacks.
+     */
+    public interface OnNfcRebootDialogConfirmedListener {
+        /**
+         * Called when the user presses enable on the warning dialog.
+         */
+        void onNfcRebootDialogConfirmed();
+
+        /**
+         * Called when the user presses cancel on the warning dialog.
+         */
+        void onNfcRebootDialogCanceled();
+    }
+}
diff --git a/src/com/android/settings/development/NfcSnoopLogPreferenceController.java b/src/com/android/settings/development/NfcSnoopLogPreferenceController.java
new file mode 100644
index 0000000..10cfee0
--- /dev/null
+++ b/src/com/android/settings/development/NfcSnoopLogPreferenceController.java
@@ -0,0 +1,129 @@
+/*
+ * 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.development;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+/**
+ * Preference controller to control NFCSNOOP data payload
+ */
+public class NfcSnoopLogPreferenceController extends
+        DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener {
+    private static final String TAG = "NfcSnoopLog";
+    private static final String NFC_NFCSNOOP_LOG_KEY =
+            "nfc_snoop_log";
+    @VisibleForTesting
+    static final String NFC_NFCSNOOP_LOG_MODE_PROPERTY =
+            "persist.nfc.nfcsnooplogmode";
+    @VisibleForTesting
+    static final String NFCSNOOP_MODE_FILTERED = "filtered";
+    @VisibleForTesting
+    static final String NFCSNOOP_MODE_FULL = "full";
+
+    @VisibleForTesting
+    boolean mChanged = false;
+
+    private final DevelopmentSettingsDashboardFragment mFragment;
+
+    public NfcSnoopLogPreferenceController(Context context,
+            DevelopmentSettingsDashboardFragment fragment) {
+        super(context);
+        mFragment = fragment;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return NFC_NFCSNOOP_LOG_KEY;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        NfcRebootDialog.show(mFragment);
+        mChanged = true;
+        return false;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        try {
+            final String currentValue = SystemProperties.get(NFC_NFCSNOOP_LOG_MODE_PROPERTY);
+            ((SwitchPreference) mPreference).setChecked(currentValue.equals(NFCSNOOP_MODE_FULL));
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to get nfc system property: " + e.getMessage());
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        try {
+            SystemProperties.set(NFC_NFCSNOOP_LOG_MODE_PROPERTY, NFCSNOOP_MODE_FILTERED);
+            ((SwitchPreference) mPreference).setChecked(false);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to set nfc system property: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Check whether the current setting is the default value or not.
+     */
+    public boolean isDefaultValue() {
+        try {
+            final String currentValue = SystemProperties.get(NFC_NFCSNOOP_LOG_MODE_PROPERTY);
+            return !currentValue.equals(NFCSNOOP_MODE_FULL);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to get nfc system property: " + e.getMessage());
+        }
+        return true;
+    }
+
+    /**
+     * Called when the NfcRebootDialog confirm is clicked.
+     */
+    public void onNfcRebootDialogConfirmed() {
+        if (!mChanged) {
+            return;
+        }
+        try {
+            final String currentValue =
+                    SystemProperties.get(NFC_NFCSNOOP_LOG_MODE_PROPERTY, NFCSNOOP_MODE_FILTERED);
+            if (currentValue.equals(NFCSNOOP_MODE_FILTERED)) {
+                SystemProperties.set(NFC_NFCSNOOP_LOG_MODE_PROPERTY, NFCSNOOP_MODE_FULL);
+            } else {
+                SystemProperties.set(NFC_NFCSNOOP_LOG_MODE_PROPERTY, NFCSNOOP_MODE_FILTERED);
+            }
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to set nfc system property: " + e.getMessage());
+        }
+
+    }
+
+    /**
+     * Called when the NfcRebootDialog cancel is clicked.
+     */
+    public void onNfcRebootDialogCanceled() {
+        mChanged = false;
+    }
+}
diff --git a/src/com/android/settings/development/NfcVerboseVendorLogPreferenceController.java b/src/com/android/settings/development/NfcVerboseVendorLogPreferenceController.java
new file mode 100644
index 0000000..8b3cab0
--- /dev/null
+++ b/src/com/android/settings/development/NfcVerboseVendorLogPreferenceController.java
@@ -0,0 +1,130 @@
+/*
+ * 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.development;
+
+import android.content.Context;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+/**
+ * Preference controller to control NFC vendor verbose logging enable and disable
+ */
+public class NfcVerboseVendorLogPreferenceController
+        extends DeveloperOptionsPreferenceController
+        implements Preference.OnPreferenceChangeListener {
+    private static final String TAG = "NfcVerboseVendorLog";
+    private static final String NFC_VERBOSE_VENDOR_LOG_KEY = "nfc_verbose_vendor_log";
+    @VisibleForTesting
+    static final String NFC_VERBOSE_VENDOR_LOG_PROPERTY =
+            "persist.nfc.verbosevendorlog";
+    @VisibleForTesting
+    static final String VERBOSE_VENDOR_LOG_ENABLED = "enabled";
+    @VisibleForTesting
+    static final String VERBOSE_VENDOR_LOG_DISABLED = "disabled";
+
+    @VisibleForTesting
+    boolean mChanged = false;
+
+    private final DevelopmentSettingsDashboardFragment mFragment;
+
+    public NfcVerboseVendorLogPreferenceController(Context context,
+            DevelopmentSettingsDashboardFragment fragment) {
+        super(context);
+        mFragment = fragment;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return NFC_VERBOSE_VENDOR_LOG_KEY;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        NfcRebootDialog.show(mFragment);
+        mChanged = true;
+        return false;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        try {
+            final String currentValue = SystemProperties.get(NFC_VERBOSE_VENDOR_LOG_PROPERTY);
+            ((SwitchPreference) mPreference)
+                    .setChecked(currentValue.equals(VERBOSE_VENDOR_LOG_ENABLED));
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to get nfc system property: " + e.getMessage());
+        }
+    }
+
+    @Override
+    protected void onDeveloperOptionsSwitchDisabled() {
+        super.onDeveloperOptionsSwitchDisabled();
+        try {
+            SystemProperties.set(NFC_VERBOSE_VENDOR_LOG_PROPERTY, VERBOSE_VENDOR_LOG_DISABLED);
+            ((SwitchPreference) mPreference).setChecked(false);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to set nfc system property: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Check whether the current setting is the default value or not.
+     */
+    public boolean isDefaultValue() {
+        try {
+            final String currentValue = SystemProperties.get(NFC_VERBOSE_VENDOR_LOG_PROPERTY);
+            return !currentValue.equals(VERBOSE_VENDOR_LOG_ENABLED);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to get nfc system property: " + e.getMessage());
+        }
+        return true;
+    }
+
+    /**
+     * Called when the NfcRebootDialog confirm is clicked.
+     */
+    public void onNfcRebootDialogConfirmed() {
+        if (!mChanged) {
+            return;
+        }
+        try {
+            final String currentValue = SystemProperties
+                    .get(NFC_VERBOSE_VENDOR_LOG_PROPERTY, VERBOSE_VENDOR_LOG_DISABLED);
+            if (currentValue.equals(VERBOSE_VENDOR_LOG_DISABLED)) {
+                SystemProperties.set(NFC_VERBOSE_VENDOR_LOG_PROPERTY, VERBOSE_VENDOR_LOG_ENABLED);
+            } else {
+                SystemProperties.set(NFC_VERBOSE_VENDOR_LOG_PROPERTY, VERBOSE_VENDOR_LOG_DISABLED);
+            }
+            updateState(mPreference);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Fail to set nfc system property: " + e.getMessage());
+        }
+    }
+
+    /**
+     * Called when the NfcRebootDialog cancel is clicked.
+     */
+    public void onNfcRebootDialogCanceled() {
+        mChanged = 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 45ae8c5..f3fec8e 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -697,12 +697,13 @@
 
         final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageData =
                 DataProcessor.getBatteryUsageData(context, batteryHistoryMap);
-        return batteryUsageData == null
-                ? null
-                : batteryUsageData
-                        .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
-                        .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
-                        .getAppDiffEntryList();
+        if (batteryUsageData == null) {
+            return null;
+        }
+        BatteryDiffData allBatteryDiffData = batteryUsageData.get(
+                BatteryChartViewModel.SELECTED_INDEX_ALL).get(
+                BatteryChartViewModel.SELECTED_INDEX_ALL);
+        return allBatteryDiffData == null ? null : allBatteryDiffData.getAppDiffEntryList();
     }
 
     /** Used for {@link AppBatteryPreferenceController}. */
diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
index ab9110d..b3c2e30 100644
--- a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
+++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
@@ -43,7 +43,6 @@
 import java.util.List;
 import java.util.Locale;
 
-
 class LocaleDragAndDropAdapter
         extends RecyclerView.Adapter<LocaleDragAndDropAdapter.CustomViewHolder> {
 
@@ -154,8 +153,10 @@
         final LocaleDragCell dragCell = holder.getLocaleDragCell();
         final String label = feedItem.getFullNameNative();
         final String description = feedItem.getFullNameInUiLanguage();
+
         dragCell.setLabelAndDescription(label, description);
         dragCell.setLocalized(feedItem.isTranslated());
+        dragCell.setCurrentDefault(feedItem.getLocale().equals(Locale.getDefault()));
         dragCell.setMiniLabel(mNumberFormatter.format(i + 1));
         dragCell.setShowCheckbox(mRemoveMode);
         dragCell.setShowMiniLabel(!mRemoveMode);
diff --git a/src/com/android/settings/localepicker/LocaleDragCell.java b/src/com/android/settings/localepicker/LocaleDragCell.java
index ea86189..2f4cfef 100644
--- a/src/com/android/settings/localepicker/LocaleDragCell.java
+++ b/src/com/android/settings/localepicker/LocaleDragCell.java
@@ -33,6 +33,7 @@
     private CheckBox mCheckbox;
     private TextView mMiniLabel;
     private TextView mLocalized;
+    private TextView mCurrentDefault;
     private ImageView mDragHandle;
 
     public LocaleDragCell(Context context, AttributeSet attrs) {
@@ -44,6 +45,7 @@
         super.onFinishInflate();
         mLabel = (TextView) findViewById(R.id.label);
         mLocalized = (TextView) findViewById(R.id.l10nWarn);
+        mCurrentDefault = (TextView) findViewById(R.id.default_locale);
         mMiniLabel = (TextView) findViewById(R.id.miniLabel);
         mCheckbox = (CheckBox) findViewById(R.id.checkbox);
         mDragHandle = (ImageView) findViewById(R.id.dragHandle);
@@ -100,6 +102,14 @@
         invalidate();
     }
 
+    /**
+     * Indicate current locale is system default.
+     */
+    public void setCurrentDefault(boolean isCurrentDefault) {
+        mCurrentDefault.setVisibility(isCurrentDefault ? VISIBLE : GONE);
+        invalidate();
+    }
+
     public ImageView getDragHandle() {
         return mDragHandle;
     }
diff --git a/src/com/android/settings/localepicker/LocaleHelperPreferenceController.java b/src/com/android/settings/localepicker/LocaleHelperPreferenceController.java
new file mode 100644
index 0000000..05c7401
--- /dev/null
+++ b/src/com/android/settings/localepicker/LocaleHelperPreferenceController.java
@@ -0,0 +1,74 @@
+/*
+ * 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.localepicker;
+
+import android.content.Context;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.HelpUtils;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+
+/**
+ * A controller to update current locale information of application.
+ */
+public class LocaleHelperPreferenceController extends AbstractPreferenceController {
+    private static final String TAG = LocaleHelperPreferenceController.class.getSimpleName();
+
+    private static final String KEY_FOOTER_LANGUAGE_PICKER = "footer_languages_picker";
+
+    public LocaleHelperPreferenceController(Context context) {
+        super(context);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_FOOTER_LANGUAGE_PICKER;
+    }
+
+    @Override
+    public void displayPreference(PreferenceScreen screen) {
+        super.displayPreference(screen);
+        FooterPreference footerPreference = screen.findPreference(getPreferenceKey());
+        updateFooterPreference(footerPreference);
+    }
+
+    @VisibleForTesting
+    void updateFooterPreference(FooterPreference footerPreference) {
+        if (footerPreference != null) {
+            footerPreference.setLearnMoreAction(v -> openLocaleLearnMoreLink());
+            footerPreference.setLearnMoreText(mContext.getString(
+                    R.string.desc_locale_helper_footer_general));
+        }
+    }
+
+    private void openLocaleLearnMoreLink() {
+        mContext.startActivity(
+                HelpUtils.getHelpIntent(
+                        mContext,
+                        mContext.getString(R.string.link_locale_picker_footer_learn_more),
+                        /*backupContext=*/""));
+    }
+}
diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java
index eac2dd1..9db3468 100644
--- a/src/com/android/settings/localepicker/LocaleListEditor.java
+++ b/src/com/android/settings/localepicker/LocaleListEditor.java
@@ -36,6 +36,7 @@
 
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.app.AlertDialog;
+import androidx.preference.PreferenceScreen;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.internal.app.LocalePicker;
@@ -46,6 +47,7 @@
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.search.SearchIndexable;
 import com.android.settingslib.search.SearchIndexableRaw;
+import com.android.settingslib.widget.LayoutPreference;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -64,6 +66,7 @@
     private static final int REQUEST_LOCALE_PICKER = 0;
 
     private static final String INDEX_KEY_ADD_LANGUAGE = "add_language";
+    private static final String KEY_LANGUAGES_PICKER = "languages_picker";
 
     private LocaleDragAndDropAdapter mAdapter;
     private Menu mMenu;
@@ -72,6 +75,9 @@
     private boolean mShowingRemoveDialog;
     private boolean mIsUiRestricted;
 
+    private LayoutPreference mLocalePickerPreference;
+    private LocaleHelperPreferenceController mLocaleHelperPreferenceController;
+
     public LocaleListEditor() {
         super(DISALLOW_CONFIG_LOCALE);
     }
@@ -86,6 +92,14 @@
         super.onCreate(savedInstanceState);
         setHasOptionsMenu(true);
 
+        addPreferencesFromResource(R.xml.languages);
+        final Activity activity = getActivity();
+        activity.setTitle(R.string.language_picker_title);
+        mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(activity);
+        final PreferenceScreen screen = getPreferenceScreen();
+        mLocalePickerPreference = screen.findPreference(KEY_LANGUAGES_PICKER);
+        mLocaleHelperPreferenceController.displayPreference(screen);
+
         LocaleStore.fillCache(this.getContext());
         final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList();
         mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList);
@@ -93,11 +107,8 @@
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstState) {
-        final View result = super.onCreateView(inflater, container, savedInstState);
-        final View myLayout = inflater.inflate(R.layout.locale_order_list, (ViewGroup) result);
-
-        configureDragAndDrop(myLayout);
-        return result;
+        configureDragAndDrop(mLocalePickerPreference);
+        return super.onCreateView(inflater, container, savedInstState);
     }
 
     @Override
@@ -287,8 +298,8 @@
         return result;
     }
 
-    private void configureDragAndDrop(View view) {
-        final RecyclerView list = view.findViewById(R.id.dragList);
+    private void configureDragAndDrop(LayoutPreference layout) {
+        final RecyclerView list = layout.findViewById(R.id.dragList);
         final LocaleLinearLayoutManager llm = new LocaleLinearLayoutManager(getContext(), mAdapter);
         llm.setAutoMeasureEnabled(true);
         list.setLayoutManager(llm);
@@ -297,7 +308,7 @@
         mAdapter.setRecyclerView(list);
         list.setAdapter(mAdapter);
 
-        mAddLanguage = view.findViewById(R.id.add_language);
+        mAddLanguage = layout.findViewById(R.id.add_language);
         mAddLanguage.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
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/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
index a198d86..54a7fb1 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
@@ -22,7 +22,6 @@
 
 import android.content.Intent;
 import android.hardware.fingerprint.FingerprintManager;
-import android.widget.Button;
 
 import androidx.appcompat.app.AlertDialog;
 
@@ -66,6 +65,23 @@
 
     @Test
     public void fingerprintEnroll_showsAlert_whenClickingSkip() {
+        final AlertDialog alertDialog = setupAlertDialog();
+        final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(
+                alertDialog);
+        final int titleRes = R.string.setup_fingerprint_enroll_skip_title;
+
+        assertThat(application.getString(titleRes)).isEqualTo(shadowAlertDialog.getTitle());
+    }
+
+    @Test
+    public void fingerprintEnroll_showsAlert_setSudTheme() {
+        final AlertDialog alertDialog = setupAlertDialog();
+
+        assertThat(alertDialog.getContext().getThemeResId()).isEqualTo(
+                R.style.GlifV2ThemeAlertDialog);
+    }
+
+    private AlertDialog setupAlertDialog() {
         final Intent intent = new Intent()
                 // Set the challenge token so the confirm screen will not be shown
                 .putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, new byte[0]);
@@ -80,9 +96,6 @@
         final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
         assertThat(alertDialog).isNotNull();
 
-        final ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(
-                alertDialog);
-        final int titleRes = R.string.setup_fingerprint_enroll_skip_title;
-        assertThat(application.getString(titleRes)).isEqualTo(shadowAlertDialog.getTitle());
+        return alertDialog;
     }
 }
diff --git a/tests/robotests/src/com/android/settings/development/NfcSnoopLogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/NfcSnoopLogPreferenceControllerTest.java
new file mode 100644
index 0000000..4ea5475
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/NfcSnoopLogPreferenceControllerTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.development;
+
+import static com.android.settings.development.NfcSnoopLogPreferenceController
+        .NFCSNOOP_MODE_FILTERED;
+import static com.android.settings.development.NfcSnoopLogPreferenceController
+        .NFCSNOOP_MODE_FULL;
+import static com.android.settings.development.NfcSnoopLogPreferenceController
+        .NFC_NFCSNOOP_LOG_MODE_PROPERTY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class NfcSnoopLogPreferenceControllerTest {
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+    @Mock
+    private DevelopmentSettingsDashboardFragment mFragment;
+
+    private Context mContext;
+    private SwitchPreference mPreference;
+    private NfcSnoopLogPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mPreference = new SwitchPreference(mContext);
+        mController = spy(new NfcSnoopLogPreferenceController(mContext, mFragment));
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void onNfcRebootDialogConfirmed_nfcSnoopLogDisabled_shouldChangeProperty() {
+        SystemProperties.set(NFC_NFCSNOOP_LOG_MODE_PROPERTY, NFCSNOOP_MODE_FILTERED);
+        mController.mChanged = true;
+
+        mController.onNfcRebootDialogConfirmed();
+
+        final String currentValue = SystemProperties.get(NFC_NFCSNOOP_LOG_MODE_PROPERTY);
+        assertThat(currentValue.equals(NFCSNOOP_MODE_FULL)).isTrue();
+    }
+
+    @Test
+    public void onNfcRebootDialogConfirmed_nfcSnoopLogEnabled_shouldChangeProperty() {
+        SystemProperties.set(NFC_NFCSNOOP_LOG_MODE_PROPERTY, NFCSNOOP_MODE_FULL);
+        mController.mChanged = true;
+
+        mController.onNfcRebootDialogConfirmed();
+
+        final String currentValue = SystemProperties.get(NFC_NFCSNOOP_LOG_MODE_PROPERTY);
+        assertThat(currentValue.equals(NFCSNOOP_MODE_FILTERED)).isTrue();
+    }
+
+    @Test
+    public void onNfcRebootDialogCanceled_shouldNotChangeProperty() {
+        SystemProperties.set(NFC_NFCSNOOP_LOG_MODE_PROPERTY, NFCSNOOP_MODE_FILTERED);
+        mController.mChanged = true;
+
+        mController.onNfcRebootDialogCanceled();
+
+        final String currentValue = SystemProperties.get(NFC_NFCSNOOP_LOG_MODE_PROPERTY);
+        assertThat(currentValue.equals(NFCSNOOP_MODE_FILTERED)).isTrue();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/NfcVerboseVendorLogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/NfcVerboseVendorLogPreferenceControllerTest.java
new file mode 100644
index 0000000..49ddd30
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/NfcVerboseVendorLogPreferenceControllerTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.development;
+
+import static com.android.settings.development.NfcVerboseVendorLogPreferenceController
+        .NFC_VERBOSE_VENDOR_LOG_PROPERTY;
+import static com.android.settings.development.NfcVerboseVendorLogPreferenceController
+        .VERBOSE_VENDOR_LOG_DISABLED;
+import static com.android.settings.development.NfcVerboseVendorLogPreferenceController
+        .VERBOSE_VENDOR_LOG_ENABLED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class NfcVerboseVendorLogPreferenceControllerTest {
+    @Mock
+    private PreferenceScreen mPreferenceScreen;
+    @Mock
+    private DevelopmentSettingsDashboardFragment mFragment;
+
+    private Context mContext;
+    private SwitchPreference mPreference;
+    private NfcVerboseVendorLogPreferenceController mController;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mPreference = new SwitchPreference(mContext);
+        mController = spy(new NfcVerboseVendorLogPreferenceController(mContext, mFragment));
+        when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+            .thenReturn(mPreference);
+        mController.displayPreference(mPreferenceScreen);
+    }
+
+    @Test
+    public void onNfcRebootDialogConfirmed_nfcVendorLogDisabled_shouldChangeProperty() {
+        SystemProperties.set(NFC_VERBOSE_VENDOR_LOG_PROPERTY, VERBOSE_VENDOR_LOG_DISABLED);
+        mController.mChanged = true;
+
+        mController.onNfcRebootDialogConfirmed();
+
+        final String currentValue = SystemProperties.get(NFC_VERBOSE_VENDOR_LOG_PROPERTY);
+        assertThat(currentValue.equals(VERBOSE_VENDOR_LOG_ENABLED)).isTrue();
+    }
+
+    @Test
+    public void onNfcRebootDialogConfirmed_nfcVendorLogEnabled_shouldChangeProperty() {
+        SystemProperties.set(NFC_VERBOSE_VENDOR_LOG_PROPERTY, VERBOSE_VENDOR_LOG_ENABLED);
+        mController.mChanged = true;
+
+        mController.onNfcRebootDialogConfirmed();
+
+        final String currentValue = SystemProperties.get(NFC_VERBOSE_VENDOR_LOG_PROPERTY);
+        assertThat(currentValue.equals(VERBOSE_VENDOR_LOG_DISABLED)).isTrue();
+    }
+
+    @Test
+    public void onNfcRebootDialogCanceled_shouldNotChangeProperty() {
+        SystemProperties.set(NFC_VERBOSE_VENDOR_LOG_PROPERTY, VERBOSE_VENDOR_LOG_DISABLED);
+        mController.mChanged = true;
+
+        mController.onNfcRebootDialogCanceled();
+
+        final String currentValue = SystemProperties.get(NFC_VERBOSE_VENDOR_LOG_PROPERTY);
+        assertThat(currentValue.equals(VERBOSE_VENDOR_LOG_DISABLED)).isTrue();
+    }
+}
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/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/applications/appinfo/AppLocalePreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/appinfo/AppLocalePreferenceControllerTest.java
index 526b6cc..805041c 100644
--- a/tests/unit/src/com/android/settings/applications/appinfo/AppLocalePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/appinfo/AppLocalePreferenceControllerTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Context;
-import android.util.FeatureFlagUtils;
 
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -49,22 +48,10 @@
                 return mCanDisplayLocaleUi;
             }
         };
-        FeatureFlagUtils
-                .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, true);
     }
 
     @Test
-    public void getAvailabilityStatus_canShowUiButFeatureFlagOff_shouldReturnUnavailable() {
-        mCanDisplayLocaleUi = true;
-        FeatureFlagUtils
-                .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, false);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_canShowUiAndFeatureFlagOn_shouldReturnAvailable() {
+    public void getAvailabilityStatus_canShowUi_shouldReturnAvailable() {
         mCanDisplayLocaleUi = true;
 
         assertThat(mController.getAvailabilityStatus())
@@ -72,20 +59,10 @@
     }
 
     @Test
-    public void getAvailabilityStatus_featureFlagOnButCanNotShowUi_shouldReturnUnavailable() {
+    public void getAvailabilityStatus_canNotShowUi_shouldReturnUnavailable() {
         mCanDisplayLocaleUi = false;
 
         assertThat(mController.getAvailabilityStatus())
                 .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
     }
-
-    @Test
-    public void getAvailabilityStatus_featureFlagOffAndCanNotShowUi_shouldReturnUnavailable() {
-        mCanDisplayLocaleUi = false;
-        FeatureFlagUtils
-                .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, false);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
-    }
 }
diff --git a/tests/unit/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceControllerTest.java
deleted file mode 100644
index 648c757..0000000
--- a/tests/unit/src/com/android/settings/applications/appinfo/ManageAppLocalePreferenceControllerTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.applications.appinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-import android.util.FeatureFlagUtils;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-
-import com.android.settings.core.BasePreferenceController;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-public class ManageAppLocalePreferenceControllerTest {
-    private Context mContext;
-    private ManageAppLocalePreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(ApplicationProvider.getApplicationContext());
-        mController = spy(new ManageAppLocalePreferenceController(mContext, "a key"));
-
-        FeatureFlagUtils
-                .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, true);
-    }
-
-    @Test
-    public void getAvailabilityStatus_featureFlagOff_shouldReturnUnavailable() {
-        FeatureFlagUtils
-                .setEnabled(mContext, FeatureFlagUtils.SETTINGS_APP_LANGUAGE_SELECTION, false);
-
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_featureFlagOn_shouldReturnAvailable() {
-        assertThat(mController.getAvailabilityStatus())
-                .isEqualTo(BasePreferenceController.AVAILABLE);
-    }
-}
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
diff --git a/tests/unit/src/com/android/settings/localepicker/LocaleHelperPreferenceControllerTest.java b/tests/unit/src/com/android/settings/localepicker/LocaleHelperPreferenceControllerTest.java
new file mode 100644
index 0000000..31b8e79
--- /dev/null
+++ b/tests/unit/src/com/android/settings/localepicker/LocaleHelperPreferenceControllerTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.localepicker;
+
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.os.Looper;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settingslib.widget.FooterPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class LocaleHelperPreferenceControllerTest {
+    private Context mContext;
+    private LocaleHelperPreferenceController mLocaleHelperPreferenceController;
+
+    @Mock
+    private FooterPreference mMockFooterPreference;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mContext = ApplicationProvider.getApplicationContext();
+        mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(mContext);
+    }
+
+    @Test
+    public void updateFooterPreference_setFooterPreference_hasClickAction() {
+        mLocaleHelperPreferenceController.updateFooterPreference(mMockFooterPreference);
+        verify(mMockFooterPreference).setLearnMoreText(anyString());
+    }
+}