Merge "Add a flow to keep special apps in the battery unrestricted mode" into main
diff --git a/res/values/config.xml b/res/values/config.xml
index f60b58c..99052ca 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -529,10 +529,14 @@
         <item>content://com.android.settings.slices/intent/media_output_indicator</item>
     </string-array>
 
-    <!-- List containing the apps keep in battery mode = "Optimize" -->
+    <!-- List containing the apps keep in battery mode = "Optimized" -->
     <string-array name="config_force_battery_optimize_mode_apps" translatable="false">
     </string-array>
 
+    <!-- List containing the apps keep in battery mode = "Unrestricted" -->
+    <string-array name="config_force_battery_unrestrict_mode_apps" translatable="false">
+    </string-array>
+
     <!-- Uri to query non-public Slice Uris. -->
     <string name="config_non_public_slice_query_uri" translatable="false"></string>
 
diff --git a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
index 76200fe..821501c 100644
--- a/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
+++ b/src/com/android/settings/fuelgauge/BatteryBackupHelper.java
@@ -342,7 +342,7 @@
 
     private boolean isSystemOrDefaultApp(String packageName, int uid) {
         return BatteryOptimizeUtils.isSystemOrDefaultApp(
-                getPowerAllowlistBackend(), packageName, uid);
+                mContext, getPowerAllowlistBackend(), packageName, uid);
     }
 
     private ArraySet<ApplicationInfo> getInstalledApplications() {
diff --git a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
index 3ced790..7b3a6ad 100644
--- a/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryOptimizeUtils.java
@@ -45,6 +45,10 @@
     private static final String TAG = "BatteryOptimizeUtils";
     private static final String UNKNOWN_PACKAGE = "unknown";
 
+    // Avoid reload the data again since it is predefined in the resource/config.
+    private static List<String> sBatteryOptimizeModeList = null;
+    private static List<String> sBatteryUnrestrictModeList = null;
+
     @VisibleForTesting AppOpsManager mAppOpsManager;
     @VisibleForTesting BatteryUtils mBatteryUtils;
     @VisibleForTesting PowerAllowlistBackend mPowerAllowListBackend;
@@ -139,7 +143,7 @@
      */
     public boolean isSystemOrDefaultApp() {
         mPowerAllowListBackend.refreshList();
-        return isSystemOrDefaultApp(mPowerAllowListBackend, mPackageName, mUid);
+        return isSystemOrDefaultApp(mContext, mPowerAllowListBackend, mPackageName, mUid);
     }
 
     /**
@@ -191,7 +195,8 @@
             // Ignores default optimized/unknown state or system/default apps.
             if (optimizationMode == MODE_OPTIMIZED
                     || optimizationMode == MODE_UNKNOWN
-                    || isSystemOrDefaultApp(allowlistBackend, info.packageName, info.uid)) {
+                    || isSystemOrDefaultApp(
+                            context, allowlistBackend, info.packageName, info.uid)) {
                 continue;
             }
 
@@ -211,14 +216,32 @@
     }
 
     static boolean isSystemOrDefaultApp(
-            PowerAllowlistBackend powerAllowlistBackend, String packageName, int uid) {
+            Context context,
+            PowerAllowlistBackend powerAllowlistBackend,
+            String packageName,
+            int uid) {
         return powerAllowlistBackend.isSysAllowlisted(packageName)
+                // Always forced unrestricted apps are one type of system important apps.
+                || getForceBatteryUnrestrictModeList(context).contains(packageName)
                 || powerAllowlistBackend.isDefaultActiveApp(packageName, uid);
     }
 
     static List<String> getForceBatteryOptimizeModeList(Context context) {
-        return Arrays.asList(context.getResources().getStringArray(
-                R.array.config_force_battery_optimize_mode_apps));
+        if (sBatteryOptimizeModeList == null) {
+            sBatteryOptimizeModeList = Arrays.asList(
+                    context.getResources().getStringArray(
+                            R.array.config_force_battery_optimize_mode_apps));
+        }
+        return sBatteryOptimizeModeList;
+    }
+
+    static List<String> getForceBatteryUnrestrictModeList(Context context) {
+        if (sBatteryUnrestrictModeList == null) {
+            sBatteryUnrestrictModeList = Arrays.asList(
+                    context.getResources().getStringArray(
+                            R.array.config_force_battery_unrestrict_mode_apps));
+        }
+        return sBatteryUnrestrictModeList;
     }
 
     private static void setAppUsageStateInternal(
diff --git a/src/com/android/settings/fuelgauge/BatterySettingsMigrateChecker.java b/src/com/android/settings/fuelgauge/BatterySettingsMigrateChecker.java
index dac2abf..b41e153 100644
--- a/src/com/android/settings/fuelgauge/BatterySettingsMigrateChecker.java
+++ b/src/com/android/settings/fuelgauge/BatterySettingsMigrateChecker.java
@@ -56,12 +56,21 @@
     /** Avoid users set important apps into the unexpected battery optimize modes */
     static void verifyBatteryOptimizeModes(Context context) {
         Log.d(TAG, "invoke verifyOptimizationModes()");
-        verifyBatteryOptimizeModes(context,
+        verifyBatteryOptimizeModeApps(
+                context,
+                BatteryOptimizeUtils.MODE_OPTIMIZED,
                 BatteryOptimizeUtils.getForceBatteryOptimizeModeList(context));
+        verifyBatteryOptimizeModeApps(
+                context,
+                BatteryOptimizeUtils.MODE_UNRESTRICTED,
+                BatteryOptimizeUtils.getForceBatteryUnrestrictModeList(context));
     }
 
     @VisibleForTesting
-    static void verifyBatteryOptimizeModes(Context context, List<String> allowList) {
+    static void verifyBatteryOptimizeModeApps(
+            Context context,
+            @BatteryOptimizeUtils.OptimizationMode int optimizationMode,
+            List<String> allowList) {
         allowList.forEach(packageName -> {
             final BatteryOptimizeUtils batteryOptimizeUtils =
                     BatteryBackupHelper.newBatteryOptimizeUtils(context, packageName,
@@ -69,10 +78,10 @@
             if (batteryOptimizeUtils == null) {
                 return;
             }
-            if (batteryOptimizeUtils.getAppOptimizationMode() !=
-                    BatteryOptimizeUtils.MODE_OPTIMIZED) {
-                Log.w(TAG, "Reset optimization mode for: " + packageName);
-                batteryOptimizeUtils.setAppUsageState(BatteryOptimizeUtils.MODE_OPTIMIZED,
+            if (batteryOptimizeUtils.getAppOptimizationMode() != optimizationMode) {
+                Log.w(TAG, "Reset " + packageName + " battery mode into " + optimizationMode);
+                batteryOptimizeUtils.setAppUsageState(
+                        optimizationMode,
                         BatteryOptimizeHistoricalLogEntry.Action.FORCE_RESET);
             }
         });
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
index 16b7895..e2058e7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatterySettingsMigrateCheckerTest.java
@@ -151,12 +151,15 @@
     }
 
     @Test
-    public void verifyBatteryOptimizeModes_inAllowList_resetOptimizationMode() throws Exception {
+    public void verifyBatteryOptimizeModeApps_inAllowList_resetOptimizationMode()
+            throws Exception {
         doReturn(BatteryOptimizeUtils.MODE_RESTRICTED).when(mBatteryOptimizeUtils)
                 .getAppOptimizationMode();
 
-        mBatterySettingsMigrateChecker.verifyBatteryOptimizeModes(
-                mContext, Arrays.asList(PACKAGE_NAME));
+        mBatterySettingsMigrateChecker.verifyBatteryOptimizeModeApps(
+                mContext,
+                BatteryOptimizeUtils.MODE_OPTIMIZED,
+                Arrays.asList(PACKAGE_NAME));
 
         final InOrder inOrder = inOrder(mBatteryOptimizeUtils);
         inOrder.verify(mBatteryOptimizeUtils).getAppOptimizationMode();
@@ -166,23 +169,27 @@
     }
 
     @Test
-    public void verifyBatteryOptimizeModes_optimizedMode_noAction() throws Exception {
+    public void verifyBatteryOptimizeModeApps_optimizedMode_noAction() throws Exception {
         doReturn(BatteryOptimizeUtils.MODE_OPTIMIZED).when(mBatteryOptimizeUtils)
                 .getAppOptimizationMode();
 
-        mBatterySettingsMigrateChecker.verifyBatteryOptimizeModes(
-                mContext, Arrays.asList(PACKAGE_NAME));
+        mBatterySettingsMigrateChecker.verifyBatteryOptimizeModeApps(
+                mContext,
+                BatteryOptimizeUtils.MODE_OPTIMIZED,
+                Arrays.asList(PACKAGE_NAME));
 
         verify(mBatteryOptimizeUtils, never()).setAppUsageState(anyInt(), any());
     }
 
     @Test
-    public void verifyBatteryOptimizeModes_notInAllowList_noAction() throws Exception {
+    public void verifyBatteryOptimizeModeApps_notInAllowList_noAction() throws Exception {
         doReturn(BatteryOptimizeUtils.MODE_RESTRICTED).when(mBatteryOptimizeUtils)
                 .getAppOptimizationMode();
 
-        mBatterySettingsMigrateChecker.verifyBatteryOptimizeModes(
-                mContext, new ArrayList<String>());
+        mBatterySettingsMigrateChecker.verifyBatteryOptimizeModeApps(
+                mContext,
+                BatteryOptimizeUtils.MODE_OPTIMIZED,
+                new ArrayList<String>());
 
         verifyNoInteractions(mBatteryOptimizeUtils);
     }