1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.fuelgauge;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.provider.Settings;
24 import android.util.Log;
25 
26 import androidx.annotation.VisibleForTesting;
27 
28 import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController;
29 import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager;
30 import com.android.settingslib.fuelgauge.BatterySaverUtils;
31 
32 import java.util.List;
33 
34 /** Execute battery settings migration tasks in the device booting stage. */
35 public final class BatterySettingsMigrateChecker extends BroadcastReceiver {
36     private static final String TAG = "BatterySettingsMigrateChecker";
37 
38     @VisibleForTesting static BatteryOptimizeUtils sBatteryOptimizeUtils = null;
39 
40     @Override
onReceive(Context context, Intent intent)41     public void onReceive(Context context, Intent intent) {
42         Log.d(TAG, "onReceive: " + intent + " owner: " + BatteryBackupHelper.isOwner());
43         if (intent != null
44                 && Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())
45                 && BatteryBackupHelper.isOwner()) {
46             verifyConfiguration(context);
47         }
48     }
49 
verifyConfiguration(Context context)50     static void verifyConfiguration(Context context) {
51         context = context.getApplicationContext();
52         verifySaverConfiguration(context);
53         verifyBatteryOptimizeModes(context);
54         DynamicDenylistManager.getInstance(context).onBootComplete();
55     }
56 
57     /** Avoid users set important apps into the unexpected battery optimize modes */
verifyBatteryOptimizeModes(Context context)58     static void verifyBatteryOptimizeModes(Context context) {
59         Log.d(TAG, "invoke verifyOptimizationModes()");
60         verifyBatteryOptimizeModeApps(
61                 context,
62                 BatteryOptimizeUtils.MODE_OPTIMIZED,
63                 BatteryOptimizeUtils.getForceBatteryOptimizeModeList(context));
64         verifyBatteryOptimizeModeApps(
65                 context,
66                 BatteryOptimizeUtils.MODE_UNRESTRICTED,
67                 BatteryOptimizeUtils.getForceBatteryUnrestrictModeList(context));
68     }
69 
70     @VisibleForTesting
verifyBatteryOptimizeModeApps( Context context, @BatteryOptimizeUtils.OptimizationMode int optimizationMode, List<String> allowList)71     static void verifyBatteryOptimizeModeApps(
72             Context context,
73             @BatteryOptimizeUtils.OptimizationMode int optimizationMode,
74             List<String> allowList) {
75         allowList.forEach(
76                 packageName -> {
77                     final BatteryOptimizeUtils batteryOptimizeUtils =
78                             BatteryBackupHelper.newBatteryOptimizeUtils(
79                                     context,
80                                     packageName,
81                                     /* testOptimizeUtils */ sBatteryOptimizeUtils);
82                     if (batteryOptimizeUtils == null) {
83                         return;
84                     }
85                     if (batteryOptimizeUtils.getAppOptimizationMode() != optimizationMode) {
86                         Log.w(
87                                 TAG,
88                                 "Reset " + packageName + " battery mode into " + optimizationMode);
89                         batteryOptimizeUtils.setAppUsageState(
90                                 optimizationMode,
91                                 BatteryOptimizeHistoricalLogEntry.Action.FORCE_RESET);
92                     }
93                 });
94     }
95 
verifySaverConfiguration(Context context)96     static void verifySaverConfiguration(Context context) {
97         Log.d(TAG, "invoke verifySaverConfiguration()");
98         final ContentResolver resolver = context.getContentResolver();
99         final int threshold =
100                 Settings.Global.getInt(resolver, Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
101         // Force refine the invalid scheduled battery level.
102         if (threshold < BatterySaverScheduleRadioButtonsController.TRIGGER_LEVEL_MIN
103                 && threshold > 0) {
104             Settings.Global.putInt(
105                     resolver,
106                     Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL,
107                     BatterySaverScheduleRadioButtonsController.TRIGGER_LEVEL_MIN);
108             Log.w(TAG, "Reset invalid scheduled battery level from: " + threshold);
109         }
110         // Force removing the 'schedule by routine' state.
111         BatterySaverUtils.revertScheduleToNoneIfNeeded(context);
112     }
113 }
114