Merge "Refactor background optimization mode in Power Usage Detail page." into main
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0dae688..1eb58ee 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5434,6 +5434,10 @@
 
     <!-- Category title for battery background settings in power usage detail page [CHAR LIMIT=NONE] -->
     <string name="manager_battery_usage_category_title">Manage battery usage</string>
+    <!-- Title for allow background usage [CHAR LIMIT=NONE] -->
+    <string name="manager_battery_usage_allow_background_usage_title">Allow background usage</string>
+    <!-- Summary for allow background usage [CHAR LIMIT=NONE] -->
+    <string name="manager_battery_usage_allow_background_usage_summary">Enable for real-time updates, disable to save battery</string>
     <!-- Title for the battery unrestricted settings [CHAR_LIMIT=40] -->
     <string name="manager_battery_usage_unrestricted_title">Unrestricted</string>
     <!-- Title for the battery optimized settings [CHAR_LIMIT=40] -->
diff --git a/res/xml/power_background_usage_detail.xml b/res/xml/power_background_usage_detail.xml
new file mode 100644
index 0000000..fb089fd
--- /dev/null
+++ b/res/xml/power_background_usage_detail.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2023 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/manager_battery_usage_allow_background_usage_title">
+
+    <com.android.settingslib.widget.LayoutPreference
+        android:key="header_view"
+        android:layout="@layout/settings_entity_header"
+        android:selectable="false"/>
+
+    <com.android.settingslib.widget.MainSwitchPreference
+        android:key="allow_background_usage"
+        android:title="@string/manager_battery_usage_allow_background_usage_title"
+        settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
+
+    <com.android.settingslib.widget.SelectorWithWidgetPreference
+        android:key="optimized_preference"
+        android:title="@string/manager_battery_usage_optimized_title"
+        android:summary="@string/manager_battery_usage_optimized_summary"
+        settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
+
+    <com.android.settingslib.widget.SelectorWithWidgetPreference
+        android:key="unrestricted_preference"
+        android:title="@string/manager_battery_usage_unrestricted_title"
+        android:summary="@string/manager_battery_usage_unrestricted_summary"
+        settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
+
+    <com.android.settingslib.widget.FooterPreference
+        android:key="app_usage_footer_preference"
+        android:title="@string/manager_battery_usage_footer"
+        android:selectable="false"
+        settings:searchable="false"/>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/power_usage_detail.xml b/res/xml/power_usage_detail.xml
index 7b92f99..f3b30b6 100644
--- a/res/xml/power_usage_detail.xml
+++ b/res/xml/power_usage_detail.xml
@@ -50,30 +50,11 @@
         android:title="@string/manager_battery_usage_category_title"
         android:key="manage_battery_usage_category">
 
-        <com.android.settingslib.widget.SelectorWithWidgetPreference
-            android:key="unrestricted_pref"
-            android:summary="@string/manager_battery_usage_unrestricted_summary"
-            android:title="@string/manager_battery_usage_unrestricted_title"
-            settings:controller="com.android.settings.fuelgauge.UnrestrictedPreferenceController"/>
-
-        <com.android.settingslib.widget.SelectorWithWidgetPreference
-            android:key="optimized_pref"
-            android:summary="@string/manager_battery_usage_optimized_summary"
-            android:title="@string/manager_battery_usage_optimized_title"
-            settings:controller="com.android.settings.fuelgauge.OptimizedPreferenceController"/>
-
-        <com.android.settingslib.widget.SelectorWithWidgetPreference
-            android:key="restricted_pref"
-            android:summary="@string/manager_battery_usage_restricted_summary"
-            android:title="@string/manager_battery_usage_restricted_title"
-            settings:controller="com.android.settings.fuelgauge.RestrictedPreferenceController"/>
+        <com.android.settingslib.PrimarySwitchPreference
+            android:key="allow_background_usage"
+            android:title="@string/manager_battery_usage_allow_background_usage_title"
+            settings:controller="com.android.settings.fuelgauge.AllowBackgroundPreferenceController"/>
 
     </PreferenceCategory>
 
-    <com.android.settingslib.widget.FooterPreference
-        android:key="app_usage_footer_preference"
-        android:title="@string/manager_battery_usage_footer"
-        android:selectable="false"
-        settings:searchable="false"/>
-
 </PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index 82917d2..5262ba9 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -27,10 +27,13 @@
 import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
@@ -45,14 +48,12 @@
 import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.EntityHeaderController;
-import com.android.settingslib.HelpUtils;
+import com.android.settingslib.PrimarySwitchPreference;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.Instrumentable;
-import com.android.settingslib.widget.FooterPreference;
 import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -67,8 +68,8 @@
  */
 public class AdvancedPowerUsageDetail extends DashboardFragment implements
         ButtonActionDialogFragment.AppButtonsDialogListener,
-        SelectorWithWidgetPreference.OnClickListener {
-
+        Preference.OnPreferenceClickListener,
+        Preference.OnPreferenceChangeListener {
     public static final String TAG = "AdvancedPowerDetail";
     public static final String EXTRA_UID = "extra_uid";
     public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
@@ -85,19 +86,16 @@
     public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
 
     private static final String KEY_PREF_HEADER = "header_view";
-    private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
-    private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
-    private static final String KEY_PREF_RESTRICTED = "restricted_pref";
-    private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
-    private static final String PACKAGE_NAME_NONE = "none";
-
-    private static final String HEADER_SUMMARY_FORMAT = "%s\n(%s)";
+    private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
 
     private static final int REQUEST_UNINSTALL = 0;
     private static final int REQUEST_REMOVE_DEVICE_ADMIN = 1;
 
     private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
 
+    private AppButtonsPreferenceController mAppButtonsPreferenceController;
+    private PowerUsageTimeController mPowerUsageTimeController;
+
     @VisibleForTesting
     LayoutPreference mHeaderPreference;
     @VisibleForTesting
@@ -107,13 +105,7 @@
     @VisibleForTesting
     BatteryOptimizeUtils mBatteryOptimizeUtils;
     @VisibleForTesting
-    FooterPreference mFooterPreference;
-    @VisibleForTesting
-    SelectorWithWidgetPreference mRestrictedPreference;
-    @VisibleForTesting
-    SelectorWithWidgetPreference mOptimizePreference;
-    @VisibleForTesting
-    SelectorWithWidgetPreference mUnrestrictedPreference;
+    PrimarySwitchPreference mAllowBackgroundUsagePreference;
     @VisibleForTesting
     @BatteryOptimizeUtils.OptimizationMode
     int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
@@ -122,9 +114,6 @@
     @VisibleForTesting
     StringBuilder mLogStringBuilder;
 
-    private AppButtonsPreferenceController mAppButtonsPreferenceController;
-    private PowerUsageTimeController mPowerUsageTimeController;
-
     // A wrapper class to carry LaunchBatteryDetailPage required arguments.
     private static final class LaunchBatteryDetailPageArgs {
         private String mUsagePercent;
@@ -209,7 +198,7 @@
         args.putString(EXTRA_ANOMALY_HINT_PREF_KEY, launchArgs.mAnomalyHintPrefKey);
         args.putString(EXTRA_ANOMALY_HINT_TEXT, launchArgs.mAnomalyHintText);
         final int userId = launchArgs.mIsUserEntry ? ActivityManager.getCurrentUser()
-            : UserHandle.getUserId(launchArgs.mUid);
+                : UserHandle.getUserId(launchArgs.mUid);
 
         new SubSettingLauncher(context)
                 .setDestination(AdvancedPowerUsageDetail.class.getName())
@@ -257,7 +246,7 @@
         super.onCreate(icicle);
 
         final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
-        onCreateForTriState(packageName);
+        onCreateBackgroundUsageState(packageName);
         mHeaderPreference = findPreference(KEY_PREF_HEADER);
 
         if (packageName != null) {
@@ -271,10 +260,10 @@
 
         initHeader();
         mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
-        initPreferenceForTriState(getContext());
+        initFooter();
         mExecutor.execute(() -> {
-            String packageName =
-                    getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+            final String packageName = BatteryUtils
+                    .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
             FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
                     .action(
                             getContext(),
@@ -288,11 +277,10 @@
     public void onPause() {
         super.onPause();
 
-        final int selectedPreference = getSelectedPreference();
-
         notifyBackupManager();
-        mLogStringBuilder.append(", onPause mode = ").append(selectedPreference);
-        logMetricCategory(selectedPreference);
+        final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
+        mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
+        logMetricCategory(currentOptimizeMode);
 
         mExecutor.execute(() -> {
             BatteryOptimizeLogUtils.writeLog(
@@ -302,7 +290,7 @@
                             mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()),
                     mLogStringBuilder.toString());
         });
-        Log.d(TAG, "Leave with mode: " + selectedPreference);
+        Log.d(TAG, "Leave with mode: " + currentOptimizeMode);
     }
 
     @VisibleForTesting
@@ -353,33 +341,28 @@
     }
 
     @VisibleForTesting
-    void initPreferenceForTriState(Context context) {
+    void initFooter() {
         final String stateString;
-        final String footerString;
+        final String detailInfoString;
+        final Context context = getContext();
 
         if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
             // Present optimized only string when the package name is invalid.
             stateString = context.getString(R.string.manager_battery_usage_optimized_only);
-            footerString = context.getString(
-                    R.string.manager_battery_usage_footer_limited, stateString);
+            detailInfoString =
+                    context.getString(R.string.manager_battery_usage_footer_limited, stateString);
         } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
             // Present unrestricted only string when the package is system or default active app.
             stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
-            footerString = context.getString(
-                    R.string.manager_battery_usage_footer_limited, stateString);
+            detailInfoString =
+                    context.getString(R.string.manager_battery_usage_footer_limited, stateString);
         } else {
             // Present default string to normal app.
-            footerString = context.getString(R.string.manager_battery_usage_footer);
+            detailInfoString =
+                    context.getString(
+                            R.string.manager_battery_usage_allow_background_usage_summary);
         }
-        mFooterPreference.setTitle(footerString);
-        final Intent helpIntent = HelpUtils.getHelpIntent(context, context.getString(
-                R.string.help_url_app_usage_settings), /*backupContext=*/ "");
-        if (helpIntent != null) {
-            mFooterPreference.setLearnMoreAction(v ->
-                    startActivityForResult(helpIntent, /*requestCode=*/ 0));
-            mFooterPreference.setLearnMoreText(
-                    context.getString(R.string.manager_battery_usage_link_a11y));
-        }
+        mAllowBackgroundUsagePreference.setSummary(detailInfoString);
     }
 
     @Override
@@ -412,9 +395,7 @@
             controllers.add(mPowerUsageTimeController);
         }
         controllers.add(mAppButtonsPreferenceController);
-        controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
-        controllers.add(new OptimizedPreferenceController(context, uid, packageName));
-        controllers.add(new RestrictedPreferenceController(context, uid, packageName));
+        controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
 
         return controllers;
     }
@@ -435,34 +416,45 @@
     }
 
     @Override
-    public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
-        final String selectedKey = selected.getKey();
-        updatePreferenceState(mUnrestrictedPreference, selectedKey);
-        updatePreferenceState(mOptimizePreference, selectedKey);
-        updatePreferenceState(mRestrictedPreference, selectedKey);
-        mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY);
+    public boolean onPreferenceClick(Preference preference) {
+        if (!(preference instanceof PrimarySwitchPreference)
+                || !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
+            return false;
+        }
+        PowerBackgroundUsageDetail.startPowerBackgroundUsageDetailPage(
+                getContext(), getArguments());
+        return true;
     }
 
-    private void updatePreferenceState(SelectorWithWidgetPreference preference,
-            String selectedKey) {
-        preference.setChecked(selectedKey.equals(preference.getKey()));
+    @Override
+    public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
+        if (!(preference instanceof PrimarySwitchPreference)
+                || !TextUtils.equals(preference.getKey(), KEY_ALLOW_BACKGROUND_USAGE)) {
+            return false;
+        }
+        if (newValue instanceof Boolean) {
+            final boolean isAllowBackgroundUsage = (boolean) newValue;
+            mBatteryOptimizeUtils.setAppUsageState(
+                    isAllowBackgroundUsage
+                            ? BatteryOptimizeUtils.MODE_OPTIMIZED
+                            : BatteryOptimizeUtils.MODE_RESTRICTED,
+                    Action.APPLY);
+        }
+        return true;
     }
 
-    private void logMetricCategory(int selectedKey) {
-        if (selectedKey == mOptimizationMode) {
+    private void logMetricCategory(int currentOptimizeMode) {
+        if (currentOptimizeMode == mOptimizationMode) {
             return;
         }
-
         int metricCategory = 0;
-        switch (selectedKey) {
+        switch (currentOptimizeMode) {
             case BatteryOptimizeUtils.MODE_UNRESTRICTED:
-                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED;
-                break;
             case BatteryOptimizeUtils.MODE_OPTIMIZED:
-                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED;
+                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND;
                 break;
             case BatteryOptimizeUtils.MODE_RESTRICTED:
-                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
+                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_DISABLE_BACKGROUND;
                 break;
         }
         if (metricCategory == 0) {
@@ -470,8 +462,8 @@
         }
         int finalMetricCategory = metricCategory;
         mExecutor.execute(() -> {
-            String packageName =
-                    getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+            String packageName = BatteryUtils
+                    .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
             FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
                     .action(
                             /* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
@@ -482,33 +474,15 @@
         });
     }
 
-    private void onCreateForTriState(String packageName) {
-        mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
-        mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
-        mRestrictedPreference = findPreference(KEY_PREF_RESTRICTED);
-        mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
-        mUnrestrictedPreference.setOnClickListener(this);
-        mOptimizePreference.setOnClickListener(this);
-        mRestrictedPreference.setOnClickListener(this);
-
-        mBatteryOptimizeUtils = new BatteryOptimizeUtils(
-                getContext(), getArguments().getInt(EXTRA_UID), packageName);
-    }
-
-    private int getSelectedPreference() {
-        if (mRestrictedPreference.isChecked()) {
-            return BatteryOptimizeUtils.MODE_RESTRICTED;
-        } else if (mUnrestrictedPreference.isChecked()) {
-            return BatteryOptimizeUtils.MODE_UNRESTRICTED;
-        } else if (mOptimizePreference.isChecked()) {
-            return BatteryOptimizeUtils.MODE_OPTIMIZED;
-        } else {
-            return BatteryOptimizeUtils.MODE_UNKNOWN;
+    private void onCreateBackgroundUsageState(String packageName) {
+        mAllowBackgroundUsagePreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
+        if (mAllowBackgroundUsagePreference != null) {
+            mAllowBackgroundUsagePreference.setOnPreferenceClickListener(this);
+            mAllowBackgroundUsagePreference.setOnPreferenceChangeListener(this);
         }
-    }
 
-    private static String getLoggingPackageName(Context context, String originalPackingName) {
-        return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
-                ? originalPackingName : PACKAGE_NAME_NONE;
+        mBatteryOptimizeUtils =
+                new BatteryOptimizeUtils(
+                        getContext(), getArguments().getInt(EXTRA_UID), packageName);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java b/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java
new file mode 100644
index 0000000..d722bad
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceController.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.content.Context;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.PrimarySwitchPreference;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.MainSwitchPreference;
+
+/** Controller to update the app background usage state */
+public class AllowBackgroundPreferenceController extends AbstractPreferenceController
+        implements PreferenceControllerMixin {
+
+    private static final String TAG = "AllowBackgroundPreferenceController";
+
+    @VisibleForTesting static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+
+    @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+    public AllowBackgroundPreferenceController(Context context, int uid, String packageName) {
+        super(context);
+        mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+    }
+
+    private void setChecked(Preference preference, boolean checked) {
+        if (preference instanceof PrimarySwitchPreference) {
+            ((PrimarySwitchPreference) preference).setChecked(checked);
+        } else if (preference instanceof MainSwitchPreference) {
+            ((MainSwitchPreference) preference).setChecked(checked);
+        }
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        preference.setEnabled(mBatteryOptimizeUtils.isOptimizeModeMutable());
+
+        final boolean isAllowBackground = mBatteryOptimizeUtils.getAppOptimizationMode()
+                != BatteryOptimizeUtils.MODE_RESTRICTED;
+        setChecked(preference, isAllowBackground);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_ALLOW_BACKGROUND_USAGE;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        return getPreferenceKey().equals(preference.getKey());
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
index 7b3a6ad..003f771 100644
--- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
@@ -147,6 +147,22 @@
     }
 
     /**
+     * Return {@code true} if the optimization mode of this package can be changed
+     */
+    public boolean isOptimizeModeMutable() {
+        return !isDisabledForOptimizeModeOnly() && !isSystemOrDefaultApp();
+    }
+
+    /**
+     * Return {@code true} if the optimization mode is mutable and current state is not restricted
+     */
+    public boolean isSelectorPreferenceEnabled() {
+        // Enable the preference if apps are not set into restricted mode, otherwise disable it
+        return isOptimizeModeMutable()
+                && getAppOptimizationMode() != BatteryOptimizeUtils.MODE_RESTRICTED;
+    }
+
+    /**
       * Gets the list of installed applications.
       */
     public static ArraySet<ApplicationInfo> getInstalledApplications(
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 3b958ae..c38af07 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -88,6 +88,7 @@
     public static final String BYPASS_DOCK_DEFENDER_ACTION = "battery.dock.defender.bypass";
 
     private static final String GOOGLE_PLAY_STORE_PACKAGE = "com.android.vending";
+    private static final String PACKAGE_NAME_NONE = "none";
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({StatusType.SCREEN_USAGE,
@@ -140,6 +141,12 @@
                 FeatureFactory.getFeatureFactory().getPowerUsageFeatureProvider();
     }
 
+    /** For test to reset single instance. */
+    @VisibleForTesting
+    public void reset() {
+        sInstance = null;
+    }
+
     public long getProcessTimeMs(@StatusType int type, @Nullable BatteryStats.Uid uid,
             int which) {
         if (uid == null) {
@@ -616,6 +623,12 @@
                 && GOOGLE_PLAY_STORE_PACKAGE.equals(installSourceInfo.getInitiatingPackageName());
     }
 
+    /** Gets the logging package name. */
+    public static String getLoggingPackageName(Context context, String originalPackingName) {
+        return BatteryUtils.isAppInstalledFromGooglePlayStore(context, originalPackingName)
+                ? originalPackingName : PACKAGE_NAME_NONE;
+    }
+
     /** Gets the latest sticky battery intent from the Android system. */
     public static Intent getBatteryIntent(Context context) {
         return com.android.settingslib.fuelgauge.BatteryUtils.getBatteryIntent(context);
diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
index ca75b0e..3fed00c 100644
--- a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
@@ -17,7 +17,6 @@
 package com.android.settings.fuelgauge;
 
 import android.content.Context;
-import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -31,8 +30,10 @@
 
     private static final String TAG = "OPTIMIZED_PREF";
 
-    @VisibleForTesting String KEY_OPTIMIZED_PREF = "optimized_pref";
-    @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+    @VisibleForTesting
+    static final String KEY_OPTIMIZED_PREF = "optimized_preference";
+    @VisibleForTesting
+    BatteryOptimizeUtils mBatteryOptimizeUtils;
 
     public OptimizedPreferenceController(Context context, int uid, String packageName) {
         super(context);
@@ -46,24 +47,12 @@
 
     @Override
     public void updateState(Preference preference) {
-        if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
-            Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
-            preference.setEnabled(true);
-            ((SelectorWithWidgetPreference) preference).setChecked(true);
-            return;
-        }
+        preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
 
-        if (mBatteryOptimizeUtils.getAppOptimizationMode()
-                == BatteryOptimizeUtils.MODE_OPTIMIZED) {
-            Log.d(TAG, "is optimized states");
-            ((SelectorWithWidgetPreference) preference).setChecked(true);
-        } else {
-            ((SelectorWithWidgetPreference) preference).setChecked(false);
-            if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
-                Log.d(TAG, "is system or default app, disable pref");
-                preference.setEnabled(false);
-            }
-        }
+        final boolean isOptimized = mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()
+                || mBatteryOptimizeUtils.getAppOptimizationMode()
+                == BatteryOptimizeUtils.MODE_OPTIMIZED;
+        ((SelectorWithWidgetPreference) preference).setChecked(isOptimized);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
new file mode 100644
index 0000000..3bf4562
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetail.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+
+import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+
+import android.app.Activity;
+import android.app.backup.BackupManager;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Switch;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.HelpUtils;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.LayoutPreference;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.OnMainSwitchChangeListener;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Allow background usage fragment for each app
+ */
+public class PowerBackgroundUsageDetail extends DashboardFragment implements
+        SelectorWithWidgetPreference.OnClickListener,
+        OnMainSwitchChangeListener {
+    private static final String TAG = "PowerBackgroundUsageDetail";
+
+    public static final String EXTRA_UID = "extra_uid";
+    public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
+    public static final String EXTRA_LABEL = "extra_label";
+    public static final String EXTRA_POWER_USAGE_AMOUNT = "extra_power_usage_amount";
+    public static final String EXTRA_ICON_ID = "extra_icon_id";
+    private static final String KEY_PREF_HEADER = "header_view";
+    private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
+    private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
+    private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+    private static final String KEY_FOOTER_PREFERENCE = "app_usage_footer_preference";
+
+    private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+
+    @VisibleForTesting
+    LayoutPreference mHeaderPreference;
+    @VisibleForTesting
+    ApplicationsState mState;
+    @VisibleForTesting
+    ApplicationsState.AppEntry mAppEntry;
+    @VisibleForTesting
+    BatteryOptimizeUtils mBatteryOptimizeUtils;
+    @VisibleForTesting
+    SelectorWithWidgetPreference mOptimizePreference;
+    @VisibleForTesting
+    SelectorWithWidgetPreference mUnrestrictedPreference;
+    @VisibleForTesting
+    MainSwitchPreference mMainSwitchPreference;
+    @VisibleForTesting
+    FooterPreference mFooterPreference;
+    @VisibleForTesting
+    BackupManager mBackupManager;
+    @VisibleForTesting
+    StringBuilder mLogStringBuilder;
+    @VisibleForTesting
+    @BatteryOptimizeUtils.OptimizationMode
+    int mOptimizationMode = BatteryOptimizeUtils.MODE_UNKNOWN;
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+
+        mState = ApplicationsState.getInstance(getActivity().getApplication());
+    }
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        final String packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
+        onCreateBackgroundUsageState(packageName);
+        mHeaderPreference = findPreference(KEY_PREF_HEADER);
+
+        if (packageName != null) {
+            mAppEntry = mState.getEntry(packageName, UserHandle.myUserId());
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        initHeader();
+        mOptimizationMode = mBatteryOptimizeUtils.getAppOptimizationMode();
+        initFooter();
+        mExecutor.execute(() -> {
+            String packageName = BatteryUtils
+                    .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+            FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
+                    .action(
+                            getContext(),
+                            SettingsEnums.OPEN_APP_BATTERY_USAGE,
+                            packageName);
+        });
+        mLogStringBuilder = new StringBuilder("onResume mode = ").append(mOptimizationMode);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        notifyBackupManager();
+        final int currentOptimizeMode = mBatteryOptimizeUtils.getAppOptimizationMode();
+        mLogStringBuilder.append(", onPause mode = ").append(currentOptimizeMode);
+        logMetricCategory(currentOptimizeMode);
+
+        mExecutor.execute(() -> {
+            BatteryOptimizeLogUtils.writeLog(
+                    getContext().getApplicationContext(),
+                    Action.LEAVE,
+                    BatteryOptimizeLogUtils.getPackageNameWithUserId(
+                            mBatteryOptimizeUtils.getPackageName(), UserHandle.myUserId()),
+                    mLogStringBuilder.toString());
+        });
+        Log.d(TAG, "Leave with mode: " + currentOptimizeMode);
+    }
+
+    @Override
+    public void onRadioButtonClicked(SelectorWithWidgetPreference selected) {
+        final String selectedKey = selected == null ? null : selected.getKey();
+        updateSelectorPreferenceState(mUnrestrictedPreference, selectedKey);
+        updateSelectorPreferenceState(mOptimizePreference, selectedKey);
+        mBatteryOptimizeUtils.setAppUsageState(getSelectedPreference(), Action.APPLY);
+    }
+
+    @Override
+    public void onSwitchChanged(Switch switchView, boolean isChecked) {
+        mMainSwitchPreference.setChecked(isChecked);
+        updateSelectorPreference(isChecked);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND;
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+        final List<AbstractPreferenceController> controllers = new ArrayList<>();
+        final Bundle bundle = getArguments();
+        final int uid = bundle.getInt(EXTRA_UID, 0);
+        final String packageName = bundle.getString(EXTRA_PACKAGE_NAME);
+
+        controllers.add(new AllowBackgroundPreferenceController(context, uid, packageName));
+        controllers.add(new OptimizedPreferenceController(context, uid, packageName));
+        controllers.add(new UnrestrictedPreferenceController(context, uid, packageName));
+
+        return controllers;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.power_background_usage_detail;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @VisibleForTesting
+    void updateSelectorPreference(boolean isEnabled) {
+        mOptimizePreference.setEnabled(isEnabled);
+        mUnrestrictedPreference.setEnabled(isEnabled);
+        onRadioButtonClicked(isEnabled ? mOptimizePreference : null);
+    }
+
+    @VisibleForTesting
+    void notifyBackupManager() {
+        if (mOptimizationMode != mBatteryOptimizeUtils.getAppOptimizationMode()) {
+            final BackupManager backupManager = mBackupManager != null
+                    ? mBackupManager : new BackupManager(getContext());
+            backupManager.dataChanged();
+        }
+    }
+
+    @VisibleForTesting
+    int getSelectedPreference() {
+        if (!mMainSwitchPreference.isChecked()) {
+            return BatteryOptimizeUtils.MODE_RESTRICTED;
+        } else if (mUnrestrictedPreference.isChecked()) {
+            return BatteryOptimizeUtils.MODE_UNRESTRICTED;
+        } else if (mOptimizePreference.isChecked()) {
+            return BatteryOptimizeUtils.MODE_OPTIMIZED;
+        } else {
+            return BatteryOptimizeUtils.MODE_UNKNOWN;
+        }
+    }
+
+    static void startPowerBackgroundUsageDetailPage(
+            Context context, Bundle args) {
+        new SubSettingLauncher(context)
+                .setDestination(PowerBackgroundUsageDetail.class.getName())
+                .setArguments(args)
+                .setSourceMetricsCategory(SettingsEnums.FUELGAUGE_POWER_USAGE_MANAGE_BACKGROUND)
+                .launch();
+    }
+
+    @VisibleForTesting
+    void initHeader() {
+        final View appSnippet = mHeaderPreference.findViewById(R.id.entity_header);
+        final Activity context = getActivity();
+        final Bundle bundle = getArguments();
+        EntityHeaderController controller = EntityHeaderController
+                .newInstance(context, this, appSnippet)
+                .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
+                        EntityHeaderController.ActionType.ACTION_NONE);
+
+        if (mAppEntry == null) {
+            controller.setLabel(bundle.getString(EXTRA_LABEL));
+
+            final int iconId = bundle.getInt(EXTRA_ICON_ID, 0);
+            if (iconId == 0) {
+                controller.setIcon(context.getPackageManager().getDefaultActivityIcon());
+            } else {
+                controller.setIcon(context.getDrawable(bundle.getInt(EXTRA_ICON_ID)));
+            }
+        } else {
+            mState.ensureIcon(mAppEntry);
+            controller.setLabel(mAppEntry);
+            controller.setIcon(mAppEntry);
+            controller.setIsInstantApp(AppUtils.isInstant(mAppEntry.info));
+        }
+
+        controller.done(true /* rebindActions */);
+    }
+
+    @VisibleForTesting
+    void initFooter() {
+        final String stateString;
+        final String footerString;
+        final Context context = getContext();
+
+        if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
+            // Present optimized only string when the package name is invalid.
+            stateString = context.getString(R.string.manager_battery_usage_optimized_only);
+            footerString = context.getString(
+                    R.string.manager_battery_usage_footer_limited, stateString);
+        } else if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+            // Present unrestricted only string when the package is system or default active app.
+            stateString = context.getString(R.string.manager_battery_usage_unrestricted_only);
+            footerString = context.getString(
+                    R.string.manager_battery_usage_footer_limited, stateString);
+        } else {
+            // Present default string to normal app.
+            footerString = context.getString(R.string.manager_battery_usage_footer);
+        }
+        mFooterPreference.setTitle(footerString);
+        final Intent helpIntent = HelpUtils.getHelpIntent(context, context.getString(
+                R.string.help_url_app_usage_settings), /*backupContext=*/ "");
+        if (helpIntent != null) {
+            mFooterPreference.setLearnMoreAction(v ->
+                    startActivityForResult(helpIntent, /*requestCode=*/ 0));
+            mFooterPreference.setLearnMoreText(
+                    context.getString(R.string.manager_battery_usage_link_a11y));
+        }
+    }
+
+    private void onCreateBackgroundUsageState(String packageName) {
+        mOptimizePreference = findPreference(KEY_PREF_OPTIMIZED);
+        mUnrestrictedPreference = findPreference(KEY_PREF_UNRESTRICTED);
+        mMainSwitchPreference = findPreference(KEY_ALLOW_BACKGROUND_USAGE);
+        mFooterPreference = findPreference(KEY_FOOTER_PREFERENCE);
+
+        mOptimizePreference.setOnClickListener(this);
+        mUnrestrictedPreference.setOnClickListener(this);
+        mMainSwitchPreference.addOnSwitchChangeListener(this);
+
+        mBatteryOptimizeUtils = new BatteryOptimizeUtils(
+                getContext(), getArguments().getInt(EXTRA_UID), packageName);
+    }
+
+    private void updateSelectorPreferenceState(SelectorWithWidgetPreference preference,
+            String selectedKey) {
+        preference.setChecked(TextUtils.equals(selectedKey, preference.getKey()));
+    }
+
+    private void logMetricCategory(int currentOptimizeMode) {
+        if (currentOptimizeMode == mOptimizationMode) {
+            return;
+        }
+        int metricCategory = 0;
+        switch (currentOptimizeMode) {
+            case BatteryOptimizeUtils.MODE_UNRESTRICTED:
+                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_UNRESTRICTED;
+                break;
+            case BatteryOptimizeUtils.MODE_OPTIMIZED:
+                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED;
+                break;
+            case BatteryOptimizeUtils.MODE_RESTRICTED:
+                metricCategory = SettingsEnums.ACTION_APP_BATTERY_USAGE_RESTRICTED;
+                break;
+        }
+        if (metricCategory == 0) {
+            return;
+        }
+        int finalMetricCategory = metricCategory;
+        mExecutor.execute(() -> {
+            String packageName = BatteryUtils
+                    .getLoggingPackageName(getContext(), mBatteryOptimizeUtils.getPackageName());
+            FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
+                    .action(
+                            /* attribution */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
+                            /* action */ finalMetricCategory,
+                            /* pageId */ SettingsEnums.OPEN_APP_BATTERY_USAGE,
+                            packageName,
+                            getArguments().getInt(EXTRA_POWER_USAGE_AMOUNT));
+        });
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
deleted file mode 100644
index 7db77f1..0000000
--- a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
+++ /dev/null
@@ -1,80 +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.fuelgauge;
-
-import android.content.Context;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-public class RestrictedPreferenceController extends AbstractPreferenceController
-        implements PreferenceControllerMixin {
-
-    private static final String TAG = "RESTRICTED_PREF";
-
-    @VisibleForTesting String KEY_RESTRICTED_PREF = "restricted_pref";
-    @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
-
-    public RestrictedPreferenceController(Context context, int uid, String packageName) {
-        super(context);
-        mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-
-        if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
-            Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
-            preference.setEnabled(false);
-            return;
-        } else {
-            preference.setEnabled(true);
-        }
-
-        if (mBatteryOptimizeUtils.getAppOptimizationMode()
-                == BatteryOptimizeUtils.MODE_RESTRICTED) {
-            Log.d(TAG, "is restricted states");
-            ((SelectorWithWidgetPreference) preference).setChecked(true);
-        } else {
-            ((SelectorWithWidgetPreference) preference).setChecked(false);
-            if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
-                Log.d(TAG, "is system or default app, disable pref");
-                preference.setEnabled(false);
-            }
-        }
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return true;
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY_RESTRICTED_PREF;
-    }
-
-    @Override
-    public boolean handlePreferenceTreeClick(Preference preference) {
-        return getPreferenceKey().equals(preference.getKey());
-    }
-}
diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
index 4578723..b06b7e2 100644
--- a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
@@ -17,7 +17,6 @@
 package com.android.settings.fuelgauge;
 
 import android.content.Context;
-import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
@@ -31,7 +30,9 @@
 
     private static final String TAG = "UNRESTRICTED_PREF";
 
-    @VisibleForTesting String KEY_UNRESTRICTED_PREF = "unrestricted_pref";
+    @VisibleForTesting
+    static final String KEY_UNRESTRICTED_PREF = "unrestricted_preference";
+
     @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
 
     public UnrestrictedPreferenceController(Context context, int uid, String packageName) {
@@ -41,26 +42,11 @@
 
     @Override
     public void updateState(Preference preference) {
+        preference.setEnabled(mBatteryOptimizeUtils.isSelectorPreferenceEnabled());
 
-        if (mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()) {
-            Log.d(TAG, "disable preference for " + mBatteryOptimizeUtils.getPackageName());
-            preference.setEnabled(false);
-            return;
-        } else {
-            preference.setEnabled(true);
-        }
-
-        if (mBatteryOptimizeUtils.getAppOptimizationMode()
-                == BatteryOptimizeUtils.MODE_UNRESTRICTED) {
-            Log.d(TAG, "is unrestricted states");
-            ((SelectorWithWidgetPreference) preference).setChecked(true);
-        } else {
-            ((SelectorWithWidgetPreference) preference).setChecked(false);
-            if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
-                Log.d(TAG, "is system or default app, disable pref");
-                preference.setEnabled(false);
-            }
-        }
+        final boolean isUnrestricted = mBatteryOptimizeUtils.getAppOptimizationMode()
+                == BatteryOptimizeUtils.MODE_UNRESTRICTED;
+        ((SelectorWithWidgetPreference) preference).setChecked(isUnrestricted);
     }
 
     @Override
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 9131051..80486cb 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.fuelgauge;
 
 import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
+import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -53,13 +54,12 @@
 import com.android.settings.testutils.shadow.ShadowActivityManager;
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
 import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.PrimarySwitchPreference;
 import com.android.settingslib.applications.AppUtils;
 import com.android.settingslib.applications.ApplicationsState;
 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.widget.FooterPreference;
 import com.android.settingslib.widget.LayoutPreference;
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
 
 import org.junit.After;
 import org.junit.Before;
@@ -95,9 +95,7 @@
     private static final long FOREGROUND_SERVICE_TIME_MS = 444;
     private static final long FOREGROUND_TIME_MS =
             FOREGROUND_ACTIVITY_TIME_MS + FOREGROUND_SERVICE_TIME_MS;
-    private static final String KEY_PREF_UNRESTRICTED = "unrestricted_pref";
-    private static final String KEY_PREF_OPTIMIZED = "optimized_pref";
-    private static final String KEY_PREF_RESTRICTED = "restricted_pref";
+    private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private FragmentActivity mActivity;
@@ -127,10 +125,7 @@
     private BackupManager mBackupManager;
 
     private Context mContext;
-    private FooterPreference mFooterPreference;
-    private SelectorWithWidgetPreference mRestrictedPreference;
-    private SelectorWithWidgetPreference mOptimizePreference;
-    private SelectorWithWidgetPreference mUnrestrictedPreference;
+    private PrimarySwitchPreference mAllowBackgroundUsagePreference;
     private AdvancedPowerUsageDetail mFragment;
     private SettingsActivity mTestActivity;
     private FakeFeatureFactory mFeatureFactory;
@@ -198,14 +193,9 @@
                 nullable(UserHandle.class));
         doAnswer(callable).when(mActivity).startActivity(captor.capture());
 
-        mFooterPreference = new FooterPreference(mContext);
-        mRestrictedPreference = new SelectorWithWidgetPreference(mContext);
-        mOptimizePreference = new SelectorWithWidgetPreference(mContext);
-        mUnrestrictedPreference = new SelectorWithWidgetPreference(mContext);
-        mFragment.mFooterPreference = mFooterPreference;
-        mFragment.mRestrictedPreference = mRestrictedPreference;
-        mFragment.mOptimizePreference = mOptimizePreference;
-        mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
+        mAllowBackgroundUsagePreference = new PrimarySwitchPreference(mContext);
+        mAllowBackgroundUsagePreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
+        mFragment.mAllowBackgroundUsagePreference = mAllowBackgroundUsagePreference;
     }
 
     @After
@@ -307,70 +297,60 @@
     }
 
     @Test
-    public void initPreferenceForTriState_isValidPackageName_hasCorrectString() {
+    public void initFooter_isValidPackageName_hasCorrectString() {
         when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
 
-        mFragment.initPreferenceForTriState(mContext);
+        mFragment.initFooter();
 
-        assertThat(mFooterPreference.getTitle().toString())
+        assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
                 .isEqualTo("This app requires optimized battery usage.");
     }
 
     @Test
-    public void initPreferenceForTriState_isSystemOrDefaultApp_hasCorrectString() {
+    public void initFooter_isSystemOrDefaultApp_hasCorrectString() {
         when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
         when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
 
-        mFragment.initPreferenceForTriState(mContext);
+        mFragment.initFooter();
 
-        assertThat(mFooterPreference.getTitle()
-                .toString()).isEqualTo("This app requires unrestricted battery usage.");
+        assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
+                .isEqualTo("This app requires unrestricted battery usage.");
     }
 
     @Test
-    public void initPreferenceForTriState_hasCorrectString() {
+    public void initFooter_hasCorrectString() {
         when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
         when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
 
-        mFragment.initPreferenceForTriState(mContext);
+        mFragment.initFooter();
 
-        assertThat(mFooterPreference.getTitle().toString())
-                .isEqualTo("Changing how an app uses your battery can affect its performance.");
-    }
-
-    @Test
-    public void onRadioButtonClicked_clickOptimizePref_optimizePreferenceChecked() {
-        mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
-        mRestrictedPreference.setKey(KEY_PREF_RESTRICTED);
-        mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
-        mFragment.onRadioButtonClicked(mOptimizePreference);
-
-        assertThat(mOptimizePreference.isChecked()).isTrue();
-        assertThat(mRestrictedPreference.isChecked()).isFalse();
-        assertThat(mUnrestrictedPreference.isChecked()).isFalse();
+        assertThat(mAllowBackgroundUsagePreference.getSummary().toString())
+                .isEqualTo("Enable for real-time updates, disable to save battery");
     }
 
     @Test
     public void onPause_optimizationModeChanged_logPreference()
             throws PackageManager.NameNotFoundException, InterruptedException {
         final String packageName = "testPackageName";
-        final int mode = BatteryOptimizeUtils.MODE_RESTRICTED;
-        mFragment.mOptimizationMode = mode;
-        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
+        final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+        final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+        mFragment.mOptimizationMode = restrictedMode;
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
         when(mBatteryOptimizeUtils.getPackageName()).thenReturn(packageName);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
         when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
-        mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
 
-        mFragment.onRadioButtonClicked(mOptimizePreference);
+        mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
+        verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
         mFragment.onPause();
 
         TimeUnit.SECONDS.sleep(1);
         verify(mMetricsFeatureProvider)
                 .action(
                         SettingsEnums.OPEN_APP_BATTERY_USAGE,
-                        SettingsEnums.ACTION_APP_BATTERY_USAGE_OPTIMIZED,
+                        SettingsEnums.ACTION_APP_BATTERY_USAGE_ALLOW_BACKGROUND,
                         SettingsEnums.OPEN_APP_BATTERY_USAGE,
                         packageName,
                         /* consumed battery */ 0);
@@ -379,15 +359,20 @@
     @Test
     public void onPause_optimizationModeIsNotChanged_notInvokeLogging()
             throws PackageManager.NameNotFoundException, InterruptedException {
-        final int mode = BatteryOptimizeUtils.MODE_OPTIMIZED;
-        mFragment.mOptimizationMode = mode;
-        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(mode);
+        final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+        final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+        mFragment.mOptimizationMode = restrictedMode;
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getInstallSourceInfo(anyString())).thenReturn(mInstallSourceInfo);
         when(mInstallSourceInfo.getInitiatingPackageName()).thenReturn("com.android.vending");
-        mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
 
-        mFragment.onRadioButtonClicked(mOptimizePreference);
+        mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, true);
+        verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(optimizedMode);
+        mFragment.onPreferenceChange(mAllowBackgroundUsagePreference, false);
+        verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(restrictedMode);
         mFragment.onPause();
 
         TimeUnit.SECONDS.sleep(1);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java
new file mode 100644
index 0000000..be80e1e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AllowBackgroundPreferenceControllerTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import com.android.settingslib.widget.MainSwitchPreference;
+
+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 AllowBackgroundPreferenceControllerTest {
+    private static final int UID = 12345;
+    private static final String PACKAGE_NAME = "com.android.app";
+
+    private AllowBackgroundPreferenceController mController;
+    private MainSwitchPreference mMainSwitchPreference;
+    private BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+    @Mock private PackageManager mMockPackageManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        Context context = spy(RuntimeEnvironment.application);
+        BatteryUtils.getInstance(context).reset();
+        doReturn(UID)
+                .when(mMockPackageManager)
+                .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
+
+        mController = new AllowBackgroundPreferenceController(context, UID, PACKAGE_NAME);
+        mMainSwitchPreference = new MainSwitchPreference(RuntimeEnvironment.application);
+        mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
+        mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
+    }
+
+    @Test
+    public void testUpdateState_isValidPackage_prefEnabled() {
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
+
+        mController.updateState(mMainSwitchPreference);
+
+        assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
+        assertThat(mMainSwitchPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_invalidPackage_prefDisabled() {
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
+
+        mController.updateState(mMainSwitchPreference);
+
+        assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
+        assertThat(mMainSwitchPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+                BatteryOptimizeUtils.MODE_RESTRICTED);
+
+        mController.updateState(mMainSwitchPreference);
+
+        assertThat(mMainSwitchPreference.isEnabled()).isFalse();
+        assertThat(mMainSwitchPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+                BatteryOptimizeUtils.MODE_OPTIMIZED);
+
+        mController.updateState(mMainSwitchPreference);
+
+        assertThat(mMainSwitchPreference.isEnabled()).isFalse();
+        assertThat(mMainSwitchPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_isRestrictedStates_prefChecked() {
+        when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+                BatteryOptimizeUtils.MODE_RESTRICTED);
+
+        mController.updateState(mMainSwitchPreference);
+
+        assertThat(mMainSwitchPreference.isEnabled()).isTrue();
+        assertThat(mMainSwitchPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_prefUnchecked() {
+        when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+                BatteryOptimizeUtils.MODE_OPTIMIZED);
+
+        mController.updateState(mMainSwitchPreference);
+
+        assertThat(mMainSwitchPreference.isEnabled()).isTrue();
+        assertThat(mMainSwitchPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+        mMainSwitchPreference.setKey(
+                AllowBackgroundPreferenceController.KEY_ALLOW_BACKGROUND_USAGE);
+        mController.handlePreferenceTreeClick(mMainSwitchPreference);
+
+        assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isTrue();
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+        assertThat(mController.handlePreferenceTreeClick(mMainSwitchPreference)).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
index b8c72ee..350d2ef 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryBackupHelperTest.java
@@ -121,6 +121,7 @@
         mContext = spy(RuntimeEnvironment.application);
         mStringWriter = new StringWriter();
         mPrintWriter = new PrintWriter(mStringWriter);
+        BatteryUtils.getInstance(mContext).reset();
         doReturn(mContext).when(mContext).getApplicationContext();
         doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
         doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
index e2058e7..bab19e5 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
@@ -31,10 +31,8 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.UserHandle;
-import android.os.UserManager;
 
 import com.android.settings.TestUtils;
-import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry;
 import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController;
 
 import org.junit.After;
@@ -75,6 +73,7 @@
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
+        BatteryUtils.getInstance(mContext).reset();
         doReturn(mContext).when(mContext).getApplicationContext();
         doReturn(mPackageManager).when(mContext).getPackageManager();
         doReturn(UID).when(mPackageManager)
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
index 71bb998..bfed149 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
@@ -18,8 +18,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
+import android.content.pm.PackageManager;
+
 import com.android.settingslib.widget.SelectorWithWidgetPreference;
 
 import org.junit.Before;
@@ -37,34 +42,41 @@
 
     private OptimizedPreferenceController mController;
     private SelectorWithWidgetPreference mPreference;
+    private BatteryOptimizeUtils mBatteryOptimizeUtils;
 
-    @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+    @Mock PackageManager mMockPackageManager;
 
     @Before
-    public void setUp() {
+    public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        mController = new OptimizedPreferenceController(
-                RuntimeEnvironment.application, UID, PACKAGE_NAME);
+        Context context = spy(RuntimeEnvironment.application);
+        BatteryUtils.getInstance(context).reset();
+        doReturn(UID)
+                .when(mMockPackageManager)
+                .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
+
+        mController = new OptimizedPreferenceController(context, UID, PACKAGE_NAME);
         mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
-        mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+        mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
+        mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
     }
 
     @Test
     public void testUpdateState_invalidPackage_prefEnabled() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
 
         mController.updateState(mPreference);
 
-        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreference.isEnabled()).isFalse();
         assertThat(mPreference.isChecked()).isTrue();
     }
 
     @Test
     public void testUpdateState_isSystemOrDefaultAppAndOptimizeStates_prefChecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
-        when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
                 BatteryOptimizeUtils.MODE_OPTIMIZED);
 
         mController.updateState(mPreference);
@@ -74,8 +86,8 @@
 
     @Test
     public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
 
         mController.updateState(mPreference);
 
@@ -85,8 +97,8 @@
 
     @Test
     public void testUpdateState_isOptimizedStates_prefChecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
                 BatteryOptimizeUtils.MODE_OPTIMIZED);
 
         mController.updateState(mPreference);
@@ -96,7 +108,7 @@
 
     @Test
     public void testUpdateState_prefUnchecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
 
         mController.updateState(mPreference);
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java
new file mode 100644
index 0000000..e6caf78
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerBackgroundUsageDetailTest.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS;
+import static com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AppOpsManager;
+import android.app.backup.BackupManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.widget.Switch;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.loader.app.LoaderManager;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.fuelgauge.batteryusage.BatteryEntry;
+import com.android.settings.testutils.shadow.ShadowActivityManager;
+import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+import com.android.settingslib.widget.FooterPreference;
+import com.android.settingslib.widget.LayoutPreference;
+import com.android.settingslib.widget.MainSwitchPreference;
+import com.android.settingslib.widget.SelectorWithWidgetPreference;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+        ShadowEntityHeaderController.class,
+        ShadowActivityManager.class,
+        com.android.settings.testutils.shadow.ShadowFragment.class,
+})
+public class PowerBackgroundUsageDetailTest {
+    private static final String APP_LABEL = "app label";
+    private static final String SUMMARY = "summary";
+    private static final int ICON_ID = 123;
+    private static final int UID = 1;
+    private static final String KEY_PREF_UNRESTRICTED = "unrestricted_preference";
+    private static final String KEY_PREF_OPTIMIZED = "optimized_preference";
+    private static final String KEY_ALLOW_BACKGROUND_USAGE = "allow_background_usage";
+
+    private Context mContext;
+    private PowerBackgroundUsageDetail mFragment;
+    private FooterPreference mFooterPreference;
+    private MainSwitchPreference mMainSwitchPreference;
+    private SelectorWithWidgetPreference mOptimizePreference;
+    private SelectorWithWidgetPreference mUnrestrictedPreference;
+    private SettingsActivity mTestActivity;
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private FragmentActivity mActivity;
+    @Mock
+    private EntityHeaderController mEntityHeaderController;
+    @Mock
+    private BatteryOptimizeUtils mBatteryOptimizeUtils;
+    @Mock
+    private LayoutPreference mHeaderPreference;
+    @Mock
+    private ApplicationsState mState;
+    @Mock
+    private Bundle mBundle;
+    @Mock
+    private LoaderManager mLoaderManager;
+    @Mock
+    private ApplicationsState.AppEntry mAppEntry;
+    @Mock
+    private BatteryEntry mBatteryEntry;
+    @Mock
+    private BackupManager mBackupManager;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private AppOpsManager mAppOpsManager;
+    @Mock
+    private Switch mMockSwitch;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getPackageName()).thenReturn("foo");
+
+        mFragment = spy(new PowerBackgroundUsageDetail());
+        doReturn(mContext).when(mFragment).getContext();
+        doReturn(mActivity).when(mFragment).getActivity();
+        doReturn(SUMMARY).when(mFragment).getString(anyInt());
+        doReturn(APP_LABEL).when(mBundle).getString(nullable(String.class));
+        when(mFragment.getArguments()).thenReturn(mBundle);
+        doReturn(mLoaderManager).when(mFragment).getLoaderManager();
+
+        ShadowEntityHeaderController.setUseMock(mEntityHeaderController);
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setButtonActions(anyInt(), anyInt());
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setIcon(nullable(Drawable.class));
+        doReturn(mEntityHeaderController).when(mEntityHeaderController).setIcon(nullable(
+                ApplicationsState.AppEntry.class));
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setLabel(nullable(String.class));
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setLabel(nullable(String.class));
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setLabel(nullable(ApplicationsState.AppEntry.class));
+        doReturn(mEntityHeaderController).when(mEntityHeaderController)
+                .setSummary(nullable(String.class));
+
+        when(mBatteryEntry.getUid()).thenReturn(UID);
+        when(mBatteryEntry.getLabel()).thenReturn(APP_LABEL);
+        mBatteryEntry.mIconId = ICON_ID;
+
+        mFragment.mHeaderPreference = mHeaderPreference;
+        mFragment.mState = mState;
+        mFragment.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
+        mFragment.mBackupManager = mBackupManager;
+        mAppEntry.info = mock(ApplicationInfo.class);
+
+        mTestActivity = spy(new SettingsActivity());
+        doReturn(mPackageManager).when(mTestActivity).getPackageManager();
+        doReturn(mPackageManager).when(mActivity).getPackageManager();
+        doReturn(mAppOpsManager).when(mTestActivity).getSystemService(Context.APP_OPS_SERVICE);
+
+        final ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
+
+        Answer<Void> callable = invocation -> {
+            mBundle = captor.getValue().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+            System.out.println("mBundle = " + mBundle);
+            return null;
+        };
+        doAnswer(callable).when(mActivity).startActivityAsUser(captor.capture(),
+                nullable(UserHandle.class));
+        doAnswer(callable).when(mActivity).startActivity(captor.capture());
+
+        mFooterPreference = spy(new FooterPreference(mContext));
+        mMainSwitchPreference = spy(new MainSwitchPreference(mContext));
+        mMainSwitchPreference.setKey(KEY_ALLOW_BACKGROUND_USAGE);
+        mOptimizePreference = spy(new SelectorWithWidgetPreference(mContext));
+        mOptimizePreference.setKey(KEY_PREF_OPTIMIZED);
+        mUnrestrictedPreference = spy(new SelectorWithWidgetPreference(mContext));
+        mUnrestrictedPreference.setKey(KEY_PREF_UNRESTRICTED);
+        mFragment.mFooterPreference = mFooterPreference;
+        mFragment.mMainSwitchPreference = mMainSwitchPreference;
+        mFragment.mOptimizePreference = mOptimizePreference;
+        mFragment.mUnrestrictedPreference = mUnrestrictedPreference;
+    }
+
+    @After
+    public void reset() {
+        ShadowEntityHeaderController.reset();
+    }
+
+    @Test
+    public void initHeader_NoAppEntry_BuildByBundle() {
+        mFragment.mAppEntry = null;
+        mFragment.initHeader();
+
+        verify(mEntityHeaderController).setIcon(nullable(Drawable.class));
+        verify(mEntityHeaderController).setLabel(APP_LABEL);
+    }
+
+    @Test
+    public void initHeader_HasAppEntry_BuildByAppEntry() {
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                new InstantAppDataProvider() {
+                    @Override
+                    public boolean isInstantApp(ApplicationInfo info) {
+                        return false;
+                    }
+                });
+        mFragment.mAppEntry = mAppEntry;
+        mFragment.initHeader();
+
+        verify(mEntityHeaderController).setIcon(mAppEntry);
+        verify(mEntityHeaderController).setLabel(mAppEntry);
+        verify(mEntityHeaderController).setIsInstantApp(false);
+    }
+
+    @Test
+    public void initHeader_HasAppEntry_InstantApp() {
+        ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+                new InstantAppDataProvider() {
+                    @Override
+                    public boolean isInstantApp(ApplicationInfo info) {
+                        return true;
+                    }
+                });
+        mFragment.mAppEntry = mAppEntry;
+        mFragment.initHeader();
+
+        verify(mEntityHeaderController).setIcon(mAppEntry);
+        verify(mEntityHeaderController).setLabel(mAppEntry);
+        verify(mEntityHeaderController).setIsInstantApp(true);
+    }
+
+    @Test
+    public void initFooter_hasCorrectString() {
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
+
+        mFragment.initFooter();
+
+        assertThat(mFooterPreference.getTitle().toString())
+                .isEqualTo("Changing how an app uses your battery can affect its performance.");
+    }
+
+    @Test
+    public void onSwitchChanged_fromUnrestrictedModeSetDisabled_becomeRestrictedMode() {
+        final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+        final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+        mFragment.mOptimizationMode = optimizedMode;
+
+        mFragment.onSwitchChanged(mMockSwitch, /*isChecked=*/ false);
+
+        verify(mOptimizePreference).setEnabled(false);
+        verify(mUnrestrictedPreference).setEnabled(false);
+        verify(mFragment).onRadioButtonClicked(null);
+        verify(mMainSwitchPreference).setChecked(false);
+        assertThat(mFragment.getSelectedPreference()).isEqualTo(restrictedMode);
+        verify(mBatteryOptimizeUtils).setAppUsageState(restrictedMode, Action.APPLY);
+    }
+
+    @Test
+    public void onSwitchChanged_fromRestrictedModeSetEnabled_becomeOptimizedMode() {
+        final int restrictedMode = BatteryOptimizeUtils.MODE_RESTRICTED;
+        final int optimizedMode = BatteryOptimizeUtils.MODE_OPTIMIZED;
+        mFragment.mOptimizationMode = restrictedMode;
+
+        mFragment.onSwitchChanged(mMockSwitch, /*isChecked=*/ true);
+
+        verify(mOptimizePreference).setEnabled(true);
+        verify(mUnrestrictedPreference).setEnabled(true);
+        verify(mFragment).onRadioButtonClicked(mOptimizePreference);
+        verify(mMainSwitchPreference).setChecked(true);
+        verify(mOptimizePreference).setChecked(true);
+        assertThat(mFragment.getSelectedPreference()).isEqualTo(optimizedMode);
+        verify(mBatteryOptimizeUtils).setAppUsageState(optimizedMode, Action.APPLY);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
deleted file mode 100644
index bcddbc2..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
+++ /dev/null
@@ -1,126 +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.fuelgauge;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import com.android.settingslib.widget.SelectorWithWidgetPreference;
-
-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 RestrictedPreferenceControllerTest {
-    private static final int UID = 12345;
-    private static final String PACKAGE_NAME = "com.android.app";
-
-    private RestrictedPreferenceController mController;
-    private SelectorWithWidgetPreference mPreference;
-
-    @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        mController = new RestrictedPreferenceController(
-                RuntimeEnvironment.application, UID, PACKAGE_NAME);
-        mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
-        mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
-    }
-
-    @Test
-    public void testUpdateState_isValidPackage_prefEnabled() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isEnabled()).isTrue();
-    }
-
-    @Test
-    public void testUpdateState_invalidPackage_prefDisabled() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isEnabled()).isFalse();
-    }
-
-    @Test
-    public void testUpdateState_isSystemOrDefaultAppAndRestrictedStates_prefChecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
-        when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
-                BatteryOptimizeUtils.MODE_RESTRICTED);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isChecked()).isTrue();
-    }
-
-    @Test
-    public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isChecked()).isFalse();
-        assertThat(mPreference.isEnabled()).isFalse();
-    }
-
-    @Test
-    public void testUpdateState_isRestrictedStates_prefChecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
-                BatteryOptimizeUtils.MODE_RESTRICTED);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isChecked()).isTrue();
-    }
-
-    @Test
-    public void testUpdateState_prefUnchecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-
-        mController.updateState(mPreference);
-
-        assertThat(mPreference.isChecked()).isFalse();
-    }
-
-    @Test
-    public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
-        mPreference.setKey(mController.KEY_RESTRICTED_PREF);
-        mController.handlePreferenceTreeClick(mPreference);
-
-        assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
-    }
-
-    @Test
-    public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
-        assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
index 9bed9ba..5489196 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
@@ -18,8 +18,13 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.content.Context;
+import android.content.pm.PackageManager;
+
 import com.android.settingslib.widget.SelectorWithWidgetPreference;
 
 import org.junit.Before;
@@ -37,42 +42,53 @@
 
     private UnrestrictedPreferenceController mController;
     private SelectorWithWidgetPreference mPreference;
+    private BatteryOptimizeUtils mBatteryOptimizeUtils;
 
-    @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+    @Mock PackageManager mMockPackageManager;
 
     @Before
-    public void setUp() {
+    public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
-        mController = new UnrestrictedPreferenceController(
-                RuntimeEnvironment.application, UID, PACKAGE_NAME);
+        Context context = spy(RuntimeEnvironment.application);
+        BatteryUtils.getInstance(context).reset();
+        doReturn(UID)
+                .when(mMockPackageManager)
+                .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
+
+        mController = new UnrestrictedPreferenceController(context, UID, PACKAGE_NAME);
         mPreference = new SelectorWithWidgetPreference(RuntimeEnvironment.application);
-        mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+        mBatteryOptimizeUtils = spy(new BatteryOptimizeUtils(context, UID, PACKAGE_NAME));
+        mController.mBatteryOptimizeUtils = mBatteryOptimizeUtils;
     }
 
     @Test
     public void testUpdateState_isValidPackage_prefEnabled() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
 
         mController.updateState(mPreference);
 
+        assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isTrue();
         assertThat(mPreference.isEnabled()).isTrue();
     }
 
     @Test
     public void testUpdateState_invalidPackage_prefDisabled() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(true);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(false);
 
         mController.updateState(mPreference);
 
+        assertThat(mBatteryOptimizeUtils.isOptimizeModeMutable()).isFalse();
         assertThat(mPreference.isEnabled()).isFalse();
     }
 
     @Test
     public void testUpdateState_isSystemOrDefaultAppAndUnrestrictedStates_prefChecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
-        when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
                 BatteryOptimizeUtils.MODE_UNRESTRICTED);
 
         mController.updateState(mPreference);
@@ -82,32 +98,38 @@
 
     @Test
     public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+        when(mBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+                BatteryOptimizeUtils.MODE_OPTIMIZED);
 
         mController.updateState(mPreference);
 
-        assertThat(mPreference.isChecked()).isFalse();
         assertThat(mPreference.isEnabled()).isFalse();
+        assertThat(mPreference.isChecked()).isFalse();
     }
 
     @Test
     public void testUpdateState_isUnrestrictedStates_prefChecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
-        when(mockBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+        when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
                 BatteryOptimizeUtils.MODE_UNRESTRICTED);
 
         mController.updateState(mPreference);
 
+        assertThat(mPreference.isEnabled()).isTrue();
         assertThat(mPreference.isChecked()).isTrue();
     }
 
     @Test
     public void testUpdateState_prefUnchecked() {
-        when(mockBatteryOptimizeUtils.isDisabledForOptimizeModeOnly()).thenReturn(false);
+        when(mBatteryOptimizeUtils.isOptimizeModeMutable()).thenReturn(true);
+        when(mBatteryOptimizeUtils.getAppOptimizationMode()).thenReturn(
+                BatteryOptimizeUtils.MODE_OPTIMIZED);
 
         mController.updateState(mPreference);
 
+        assertThat(mPreference.isEnabled()).isTrue();
         assertThat(mPreference.isChecked()).isFalse();
     }
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
index ae726b7..f43feec 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
@@ -82,6 +82,7 @@
         MockitoAnnotations.initMocks(this);
         ShadowUserHandle.reset();
         mContext = spy(RuntimeEnvironment.application);
+        BatteryUtils.getInstance(mContext).reset();
         doReturn(mContext).when(mContext).getApplicationContext();
         doReturn(mMockUserManager).when(mContext).getSystemService(UserManager.class);
         doReturn(mMockPackageManager).when(mContext).getPackageManager();
@@ -461,9 +462,6 @@
 
     @Test
     public void testIsUninstalledEntry_uninstalledApp_returnTrue() throws Exception {
-        doReturn(BatteryUtils.UID_NULL)
-                .when(mMockPackageManager)
-                .getPackageUid(PACKAGE_NAME, PackageManager.GET_META_DATA);
         final ContentValues values =
                 getContentValuesWithType(ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
         values.put(BatteryHistEntry.KEY_UID, UNINSTALLED_UID);