1 /*
2  * Copyright (C) 2017 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 package com.android.server.power.batterysaver;
17 
18 import android.annotation.IntDef;
19 import android.content.ContentResolver;
20 import android.content.Context;
21 import android.database.ContentObserver;
22 import android.net.Uri;
23 import android.os.BatterySaverPolicyConfig;
24 import android.os.Handler;
25 import android.os.PowerManager;
26 import android.os.PowerManager.ServiceType;
27 import android.os.PowerSaveState;
28 import android.provider.Settings;
29 import android.text.TextUtils;
30 import android.util.ArrayMap;
31 import android.util.KeyValueListParser;
32 import android.util.Slog;
33 import android.view.accessibility.AccessibilityManager;
34 
35 import com.android.internal.R;
36 import com.android.internal.annotations.GuardedBy;
37 import com.android.internal.annotations.VisibleForTesting;
38 import com.android.internal.os.BackgroundThread;
39 import com.android.internal.util.ConcurrentUtils;
40 import com.android.server.power.PowerManagerService;
41 
42 import java.io.PrintWriter;
43 import java.lang.annotation.Retention;
44 import java.lang.annotation.RetentionPolicy;
45 import java.util.ArrayList;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Objects;
49 
50 /**
51  * Class to decide whether to turn on battery saver mode for specific services.
52  *
53  * IMPORTANT: This class shares the power manager lock, which is very low in the lock hierarchy.
54  * Do not call out with the lock held, such as AccessibilityManager. (Settings provider is okay.)
55  *
56  * Test: atest com.android.server.power.batterysaver.BatterySaverPolicyTest
57  */
58 public class BatterySaverPolicy extends ContentObserver {
59     private static final String TAG = "BatterySaverPolicy";
60 
61     static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE.
62 
63     private static final String KEY_GPS_MODE = "gps_mode";
64     private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
65     private static final String KEY_ANIMATION_DISABLED = "animation_disabled";
66     private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
67 
68     /**
69      * Disable turning on the network firewall when Battery Saver is turned on.
70      * If set to false, the firewall WILL be turned on when Battery Saver is turned on.
71      * If set to true, the firewall WILL NOT be turned on when Battery Saver is turned on.
72      */
73     private static final String KEY_ACTIVATE_FIREWALL_DISABLED = "firewall_disabled";
74 
75     /**
76      * Disable turning on the special low power screen brightness dimming when Battery Saver is
77      * turned on.
78      * If set to false, the screen brightness dimming WILL be turned on by Battery Saver.
79      * If set to true, the screen brightness WILL NOT be turned on by Battery Saver.
80      */
81     private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
82 
83     /**
84      * Disable turning on Data Saver when Battery Saver is turned on.
85      * If set to false, Data Saver WILL be turned on when Battery Saver is turned on.
86      * If set to true, Data Saver WILL NOT be turned on when Battery Saver is turned on.
87      */
88     private static final String KEY_ACTIVATE_DATASAVER_DISABLED = "datasaver_disabled";
89 
90     /**
91      * {@code true} if the Policy should advertise to the rest of the system that battery saver
92      * is enabled. This advertising could cause other system components to change their
93      * behavior. This will not affect other policy flags and what they change.
94      */
95     private static final String KEY_ADVERTISE_IS_ENABLED = "advertise_is_enabled";
96 
97     private static final String KEY_LAUNCH_BOOST_DISABLED = "launch_boost_disabled";
98     private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
99     private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
100     private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred";
101     private static final String KEY_FORCE_ALL_APPS_STANDBY = "force_all_apps_standby";
102     private static final String KEY_FORCE_BACKGROUND_CHECK = "force_background_check";
103     private static final String KEY_OPTIONAL_SENSORS_DISABLED = "optional_sensors_disabled";
104     private static final String KEY_AOD_DISABLED = "aod_disabled";
105     // Go into deep Doze as soon as the screen turns off.
106     private static final String KEY_QUICK_DOZE_ENABLED = "quick_doze_enabled";
107     private static final String KEY_ENABLE_NIGHT_MODE = "enable_night_mode";
108 
109     private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i";
110     private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n";
111 
112     @VisibleForTesting
113     static final Policy OFF_POLICY = new Policy(
114             1f,    /* adjustBrightnessFactor */
115             false, /* advertiseIsEnabled */
116             false, /* deferFullBackup */
117             false, /* deferKeyValueBackup */
118             false, /* disableAnimation */
119             false, /* disableAod */
120             false, /* disableLaunchBoost */
121             false, /* disableOptionalSensors */
122             false, /* disableSoundTrigger */
123             false, /* disableVibration */
124             false, /* enableAdjustBrightness */
125             false, /* enableDataSaver */
126             false, /* enableFireWall */
127             false, /* enableNightMode */
128             false, /* enableQuickDoze */
129             new ArrayMap<>(), /* filesForInteractive */
130             new ArrayMap<>(), /* filesForNoninteractive */
131             false, /* forceAllAppsStandby */
132             false, /* forceBackgroundCheck */
133             PowerManager.LOCATION_MODE_NO_CHANGE /* locationMode */
134     );
135 
136     private static final Policy DEFAULT_ADAPTIVE_POLICY = OFF_POLICY;
137 
138     private static final Policy DEFAULT_FULL_POLICY = new Policy(
139             0.5f,  /* adjustBrightnessFactor */
140             true,  /* advertiseIsEnabled */
141             true,  /* deferFullBackup */
142             true,  /* deferKeyValueBackup */
143             false, /* disableAnimation */
144             true,  /* disableAod */
145             true,  /* disableLaunchBoost */
146             true,  /* disableOptionalSensors */
147             true,  /* disableSoundTrigger */
148             true,  /* disableVibration */
149             false, /* enableAdjustBrightness */
150             false, /* enableDataSaver */
151             true,  /* enableFirewall */
152             true, /* enableNightMode */
153             true, /* enableQuickDoze */
154             new ArrayMap<>(), /* filesForInteractive */
155             new ArrayMap<>(), /* filesForNoninteractive */
156             true, /* forceAllAppsStandby */
157             true, /* forceBackgroundCheck */
158             PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF /* locationMode */
159     );
160 
161     private final Object mLock;
162     private final Handler mHandler;
163 
164     @GuardedBy("mLock")
165     private String mSettings;
166 
167     @GuardedBy("mLock")
168     private String mDeviceSpecificSettings;
169 
170     @GuardedBy("mLock")
171     private String mDeviceSpecificSettingsSource; // For dump() only.
172 
173     @GuardedBy("mLock")
174     private String mAdaptiveSettings;
175 
176     @GuardedBy("mLock")
177     private String mAdaptiveDeviceSpecificSettings;
178 
179     /**
180      * A short string describing which battery saver is now enabled, which we dump in the eventlog.
181      */
182     @GuardedBy("mLock")
183     private String mEventLogKeys;
184 
185     /**
186      * Whether vibration should *really* be disabled -- i.e. {@link Policy#disableVibration}
187      * is true *and* {@link #mAccessibilityEnabled} is false.
188      */
189     @GuardedBy("mLock")
190     private boolean mDisableVibrationEffective;
191 
192     /**
193      * Whether accessibility is currently enabled or not.
194      */
195     @GuardedBy("mLock")
196     private boolean mAccessibilityEnabled;
197 
198     /** The current default adaptive policy. */
199     @GuardedBy("mLock")
200     private Policy mDefaultAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY;
201 
202     /** The policy that will be used for adaptive battery saver. */
203     @GuardedBy("mLock")
204     private Policy mAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY;
205 
206     /** The policy to be used for full battery saver. */
207     @GuardedBy("mLock")
208     private Policy mFullPolicy = DEFAULT_FULL_POLICY;
209 
210     @IntDef(prefix = {"POLICY_LEVEL_"}, value = {
211             POLICY_LEVEL_OFF,
212             POLICY_LEVEL_ADAPTIVE,
213             POLICY_LEVEL_FULL,
214     })
215     @Retention(RetentionPolicy.SOURCE)
216     @interface PolicyLevel {}
217 
218     static final int POLICY_LEVEL_OFF = 0;
219     static final int POLICY_LEVEL_ADAPTIVE = 1;
220     static final int POLICY_LEVEL_FULL = 2;
221 
222     @GuardedBy("mLock")
223     private int mPolicyLevel = POLICY_LEVEL_OFF;
224 
225     private final Context mContext;
226     private final ContentResolver mContentResolver;
227     private final BatterySavingStats mBatterySavingStats;
228 
229     @GuardedBy("mLock")
230     private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>();
231 
232     public interface BatterySaverPolicyListener {
onBatterySaverPolicyChanged(BatterySaverPolicy policy)233         void onBatterySaverPolicyChanged(BatterySaverPolicy policy);
234     }
235 
BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats)236     public BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats) {
237         super(BackgroundThread.getHandler());
238         mLock = lock;
239         mHandler = BackgroundThread.getHandler();
240         mContext = context;
241         mContentResolver = context.getContentResolver();
242         mBatterySavingStats = batterySavingStats;
243     }
244 
245     /**
246      * Called by {@link PowerManagerService#systemReady}, *with no lock held.*
247      */
systemReady()248     public void systemReady() {
249         ConcurrentUtils.wtfIfLockHeld(TAG, mLock);
250 
251         mContentResolver.registerContentObserver(Settings.Global.getUriFor(
252                 Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
253         mContentResolver.registerContentObserver(Settings.Global.getUriFor(
254                 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this);
255         mContentResolver.registerContentObserver(Settings.Global.getUriFor(
256                 Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS), false, this);
257         mContentResolver.registerContentObserver(Settings.Global.getUriFor(
258                 Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS), false, this);
259 
260         final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class);
261 
262         acm.addAccessibilityStateChangeListener((enabled) -> {
263             synchronized (mLock) {
264                 mAccessibilityEnabled = enabled;
265             }
266             refreshSettings();
267         });
268         final boolean enabled = acm.isEnabled();
269         synchronized (mLock) {
270             mAccessibilityEnabled = enabled;
271         }
272         onChange(true, null);
273     }
274 
275     @VisibleForTesting
addListener(BatterySaverPolicyListener listener)276     public void addListener(BatterySaverPolicyListener listener) {
277         synchronized (mLock) {
278             // TODO: set this in the constructor instead
279             mListeners.add(listener);
280         }
281     }
282 
283     @VisibleForTesting
getGlobalSetting(String key)284     String getGlobalSetting(String key) {
285         return Settings.Global.getString(mContentResolver, key);
286     }
287 
288     @VisibleForTesting
getDeviceSpecificConfigResId()289     int getDeviceSpecificConfigResId() {
290         return R.string.config_batterySaverDeviceSpecificConfig;
291     }
292 
293     @Override
onChange(boolean selfChange, Uri uri)294     public void onChange(boolean selfChange, Uri uri) {
295         refreshSettings();
296     }
297 
refreshSettings()298     private void refreshSettings() {
299         final BatterySaverPolicyListener[] listeners;
300         synchronized (mLock) {
301             // Load the non-device-specific setting.
302             final String setting = getGlobalSetting(Settings.Global.BATTERY_SAVER_CONSTANTS);
303 
304             // Load the device specific setting.
305             // We first check the global setting, and if it's empty or the string "null" is set,
306             // use the default value from config.xml.
307             String deviceSpecificSetting = getGlobalSetting(
308                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS);
309             mDeviceSpecificSettingsSource =
310                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS;
311 
312             if (TextUtils.isEmpty(deviceSpecificSetting) || "null".equals(deviceSpecificSetting)) {
313                 deviceSpecificSetting =
314                         mContext.getString(getDeviceSpecificConfigResId());
315                 mDeviceSpecificSettingsSource = "(overlay)";
316             }
317 
318             final String adaptiveSetting =
319                     getGlobalSetting(Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS);
320             final String adaptiveDeviceSpecificSetting = getGlobalSetting(
321                     Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS);
322 
323             if (!updateConstantsLocked(setting, deviceSpecificSetting,
324                     adaptiveSetting, adaptiveDeviceSpecificSetting)) {
325                 // Nothing of note changed.
326                 return;
327             }
328 
329             listeners = mListeners.toArray(new BatterySaverPolicyListener[0]);
330         }
331 
332         // Notify the listeners.
333         mHandler.post(() -> {
334             for (BatterySaverPolicyListener listener : listeners) {
335                 listener.onBatterySaverPolicyChanged(this);
336             }
337         });
338     }
339 
340     @GuardedBy("mLock")
341     @VisibleForTesting
updateConstantsLocked(final String setting, final String deviceSpecificSetting)342     void updateConstantsLocked(final String setting, final String deviceSpecificSetting) {
343         updateConstantsLocked(setting, deviceSpecificSetting, "", "");
344     }
345 
346     /** @return true if the currently active policy changed. */
updateConstantsLocked(String setting, String deviceSpecificSetting, String adaptiveSetting, String adaptiveDeviceSpecificSetting)347     private boolean updateConstantsLocked(String setting, String deviceSpecificSetting,
348             String adaptiveSetting, String adaptiveDeviceSpecificSetting) {
349         setting = TextUtils.emptyIfNull(setting);
350         deviceSpecificSetting = TextUtils.emptyIfNull(deviceSpecificSetting);
351         adaptiveSetting = TextUtils.emptyIfNull(adaptiveSetting);
352         adaptiveDeviceSpecificSetting = TextUtils.emptyIfNull(adaptiveDeviceSpecificSetting);
353 
354         if (setting.equals(mSettings)
355                 && deviceSpecificSetting.equals(mDeviceSpecificSettings)
356                 && adaptiveSetting.equals(mAdaptiveSettings)
357                 && adaptiveDeviceSpecificSetting.equals(mAdaptiveDeviceSpecificSettings)) {
358             return false;
359         }
360 
361         mSettings = setting;
362         mDeviceSpecificSettings = deviceSpecificSetting;
363         mAdaptiveSettings = adaptiveSetting;
364         mAdaptiveDeviceSpecificSettings = adaptiveDeviceSpecificSetting;
365 
366         if (DEBUG) {
367             Slog.i(TAG, "mSettings=" + mSettings);
368             Slog.i(TAG, "mDeviceSpecificSettings=" + mDeviceSpecificSettings);
369             Slog.i(TAG, "mAdaptiveSettings=" + mAdaptiveSettings);
370             Slog.i(TAG, "mAdaptiveDeviceSpecificSettings=" + mAdaptiveDeviceSpecificSettings);
371         }
372 
373         boolean changed = false;
374         Policy newFullPolicy = Policy.fromSettings(setting, deviceSpecificSetting,
375                 DEFAULT_FULL_POLICY);
376         if (mPolicyLevel == POLICY_LEVEL_FULL && !mFullPolicy.equals(newFullPolicy)) {
377             changed = true;
378         }
379         mFullPolicy = newFullPolicy;
380 
381         mDefaultAdaptivePolicy = Policy.fromSettings(adaptiveSetting, adaptiveDeviceSpecificSetting,
382                 DEFAULT_ADAPTIVE_POLICY);
383         if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE
384                 && !mAdaptivePolicy.equals(mDefaultAdaptivePolicy)) {
385             changed = true;
386         }
387         // This will override any config set by an external source. This should be fine for now.
388         // TODO: make sure it doesn't override what's set externally
389         mAdaptivePolicy = mDefaultAdaptivePolicy;
390 
391         updatePolicyDependenciesLocked();
392 
393         return changed;
394     }
395 
396     @GuardedBy("mLock")
updatePolicyDependenciesLocked()397     private void updatePolicyDependenciesLocked() {
398         final Policy currPolicy = getCurrentPolicyLocked();
399         // Update the effective vibration policy.
400         mDisableVibrationEffective = currPolicy.disableVibration
401                 && !mAccessibilityEnabled; // Don't disable vibration when accessibility is on.
402 
403         final StringBuilder sb = new StringBuilder();
404 
405         if (currPolicy.forceAllAppsStandby) sb.append("A");
406         if (currPolicy.forceBackgroundCheck) sb.append("B");
407 
408         if (mDisableVibrationEffective) sb.append("v");
409         if (currPolicy.disableAnimation) sb.append("a");
410         if (currPolicy.disableSoundTrigger) sb.append("s");
411         if (currPolicy.deferFullBackup) sb.append("F");
412         if (currPolicy.deferKeyValueBackup) sb.append("K");
413         if (currPolicy.enableFirewall) sb.append("f");
414         if (currPolicy.enableDataSaver) sb.append("d");
415         if (currPolicy.enableAdjustBrightness) sb.append("b");
416 
417         if (currPolicy.disableLaunchBoost) sb.append("l");
418         if (currPolicy.disableOptionalSensors) sb.append("S");
419         if (currPolicy.disableAod) sb.append("o");
420         if (currPolicy.enableQuickDoze) sb.append("q");
421 
422         sb.append(currPolicy.locationMode);
423 
424         mEventLogKeys = sb.toString();
425     }
426 
427     static class Policy {
428         /**
429          * This is the flag to decide the how much to adjust the screen brightness. This is
430          * the float value from 0 to 1 where 1 means don't change brightness.
431          *
432          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
433          * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
434          */
435         public final float adjustBrightnessFactor;
436 
437         /**
438          * {@code true} if the Policy should advertise to the rest of the system that battery saver
439          * is enabled. This advertising could cause other system components to change their
440          * behavior. This will not affect other policy flags and what they change.
441          *
442          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
443          * @see #KEY_ADVERTISE_IS_ENABLED
444          */
445         public final boolean advertiseIsEnabled;
446 
447         /**
448          * {@code true} if full backup is deferred in battery saver mode.
449          *
450          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
451          * @see #KEY_FULLBACKUP_DEFERRED
452          */
453         public final boolean deferFullBackup;
454 
455         /**
456          * {@code true} if key value backup is deferred in battery saver mode.
457          *
458          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
459          * @see #KEY_KEYVALUE_DEFERRED
460          */
461         public final boolean deferKeyValueBackup;
462 
463         /**
464          * {@code true} if animation is disabled in battery saver mode.
465          *
466          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
467          * @see #KEY_ANIMATION_DISABLED
468          */
469         public final boolean disableAnimation;
470 
471         /**
472          * {@code true} if AOD is disabled in battery saver mode.
473          */
474         public final boolean disableAod;
475 
476         /**
477          * {@code true} if launch boost should be disabled on battery saver.
478          */
479         public final boolean disableLaunchBoost;
480 
481         /**
482          * Whether to show non-essential sensors (e.g. edge sensors) or not.
483          */
484         public final boolean disableOptionalSensors;
485 
486         /**
487          * {@code true} if sound trigger is disabled in battery saver mode
488          * in battery saver mode.
489          *
490          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
491          * @see #KEY_SOUNDTRIGGER_DISABLED
492          */
493         public final boolean disableSoundTrigger;
494 
495         /**
496          * {@code true} if vibration is disabled in battery saver mode.
497          *
498          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
499          * @see #KEY_VIBRATION_DISABLED
500          */
501         public final boolean disableVibration;
502 
503         /**
504          * {@code true} if low power mode brightness adjustment should be turned on in battery saver
505          * mode.
506          *
507          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
508          * @see #KEY_ADJUST_BRIGHTNESS_DISABLED
509          */
510         public final boolean enableAdjustBrightness;
511 
512         /**
513          * {@code true} if data saver should be turned on in battery saver mode.
514          *
515          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
516          * @see #KEY_ACTIVATE_DATASAVER_DISABLED
517          */
518         public final boolean enableDataSaver;
519 
520         /**
521          * {@code true} if network policy firewall should be turned on in battery saver mode.
522          *
523          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
524          * @see #KEY_ACTIVATE_FIREWALL_DISABLED
525          */
526         public final boolean enableFirewall;
527 
528         /**
529          * Whether to enable night mode or not.
530          */
531         public final boolean enableNightMode;
532 
533         /**
534          * Whether Quick Doze is enabled or not.
535          */
536         public final boolean enableQuickDoze;
537 
538         /**
539          * List of [Filename -> content] that should be written when battery saver is activated
540          * and the device is interactive.
541          *
542          * We use this to change the max CPU frequencies.
543          */
544         public final ArrayMap<String, String> filesForInteractive;
545 
546         /**
547          * List of [Filename -> content] that should be written when battery saver is activated
548          * and the device is non-interactive.
549          *
550          * We use this to change the max CPU frequencies.
551          */
552         public final ArrayMap<String, String> filesForNoninteractive;
553 
554         /**
555          * Whether to put all apps in the stand-by mode.
556          */
557         public final boolean forceAllAppsStandby;
558 
559         /**
560          * Whether to force background check.
561          */
562         public final boolean forceBackgroundCheck;
563 
564         /**
565          * This is the flag to decide the location mode in battery saver mode. This was
566          * previously called gpsMode.
567          *
568          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
569          * @see #KEY_GPS_MODE
570          */
571         public final int locationMode;
572 
573         private final int mHashCode;
574 
Policy( float adjustBrightnessFactor, boolean advertiseIsEnabled, boolean deferFullBackup, boolean deferKeyValueBackup, boolean disableAnimation, boolean disableAod, boolean disableLaunchBoost, boolean disableOptionalSensors, boolean disableSoundTrigger, boolean disableVibration, boolean enableAdjustBrightness, boolean enableDataSaver, boolean enableFirewall, boolean enableNightMode, boolean enableQuickDoze, ArrayMap<String, String> filesForInteractive, ArrayMap<String, String> filesForNoninteractive, boolean forceAllAppsStandby, boolean forceBackgroundCheck, int locationMode)575         Policy(
576                 float adjustBrightnessFactor,
577                 boolean advertiseIsEnabled,
578                 boolean deferFullBackup,
579                 boolean deferKeyValueBackup,
580                 boolean disableAnimation,
581                 boolean disableAod,
582                 boolean disableLaunchBoost,
583                 boolean disableOptionalSensors,
584                 boolean disableSoundTrigger,
585                 boolean disableVibration,
586                 boolean enableAdjustBrightness,
587                 boolean enableDataSaver,
588                 boolean enableFirewall,
589                 boolean enableNightMode,
590                 boolean enableQuickDoze,
591                 ArrayMap<String, String> filesForInteractive,
592                 ArrayMap<String, String> filesForNoninteractive,
593                 boolean forceAllAppsStandby,
594                 boolean forceBackgroundCheck,
595                 int locationMode) {
596 
597             this.adjustBrightnessFactor = Math.min(1, Math.max(0, adjustBrightnessFactor));
598             this.advertiseIsEnabled = advertiseIsEnabled;
599             this.deferFullBackup = deferFullBackup;
600             this.deferKeyValueBackup = deferKeyValueBackup;
601             this.disableAnimation = disableAnimation;
602             this.disableAod = disableAod;
603             this.disableLaunchBoost = disableLaunchBoost;
604             this.disableOptionalSensors = disableOptionalSensors;
605             this.disableSoundTrigger = disableSoundTrigger;
606             this.disableVibration = disableVibration;
607             this.enableAdjustBrightness = enableAdjustBrightness;
608             this.enableDataSaver = enableDataSaver;
609             this.enableFirewall = enableFirewall;
610             this.enableNightMode = enableNightMode;
611             this.enableQuickDoze = enableQuickDoze;
612             this.filesForInteractive = filesForInteractive;
613             this.filesForNoninteractive = filesForNoninteractive;
614             this.forceAllAppsStandby = forceAllAppsStandby;
615             this.forceBackgroundCheck = forceBackgroundCheck;
616 
617             if (locationMode < PowerManager.MIN_LOCATION_MODE
618                     || PowerManager.MAX_LOCATION_MODE < locationMode) {
619                 Slog.e(TAG, "Invalid location mode: " + locationMode);
620                 this.locationMode = PowerManager.LOCATION_MODE_NO_CHANGE;
621             } else {
622                 this.locationMode = locationMode;
623             }
624 
625             mHashCode = Objects.hash(
626                     adjustBrightnessFactor,
627                     advertiseIsEnabled,
628                     deferFullBackup,
629                     deferKeyValueBackup,
630                     disableAnimation,
631                     disableAod,
632                     disableLaunchBoost,
633                     disableOptionalSensors,
634                     disableSoundTrigger,
635                     disableVibration,
636                     enableAdjustBrightness,
637                     enableDataSaver,
638                     enableFirewall,
639                     enableNightMode,
640                     enableQuickDoze,
641                     filesForInteractive,
642                     filesForNoninteractive,
643                     forceAllAppsStandby,
644                     forceBackgroundCheck,
645                     locationMode);
646         }
647 
fromConfig(BatterySaverPolicyConfig config)648         static Policy fromConfig(BatterySaverPolicyConfig config) {
649             if (config == null) {
650                 Slog.e(TAG, "Null config passed down to BatterySaverPolicy");
651                 return OFF_POLICY;
652             }
653 
654             // Device-specific parameters.
655             Map<String, String> deviceSpecificSettings = config.getDeviceSpecificSettings();
656             final String cpuFreqInteractive =
657                     deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_INTERACTIVE, "");
658             final String cpuFreqNoninteractive =
659                     deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_NONINTERACTIVE, "");
660 
661             return new Policy(
662                     config.getAdjustBrightnessFactor(),
663                     config.getAdvertiseIsEnabled(),
664                     config.getDeferFullBackup(),
665                     config.getDeferKeyValueBackup(),
666                     config.getDisableAnimation(),
667                     config.getDisableAod(),
668                     config.getDisableLaunchBoost(),
669                     config.getDisableOptionalSensors(),
670                     config.getDisableSoundTrigger(),
671                     config.getDisableVibration(),
672                     config.getEnableAdjustBrightness(),
673                     config.getEnableDataSaver(),
674                     config.getEnableFirewall(),
675                     config.getEnableNightMode(),
676                     config.getEnableQuickDoze(),
677                     /* filesForInteractive */
678                     (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(),
679                     /* filesForNoninteractive */
680                     (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(),
681                     config.getForceAllAppsStandby(),
682                     config.getForceBackgroundCheck(),
683                     config.getLocationMode()
684             );
685         }
686 
fromSettings(String settings, String deviceSpecificSettings)687         static Policy fromSettings(String settings, String deviceSpecificSettings) {
688             return fromSettings(settings, deviceSpecificSettings, OFF_POLICY);
689         }
690 
fromSettings(String settings, String deviceSpecificSettings, Policy defaultPolicy)691         static Policy fromSettings(String settings, String deviceSpecificSettings,
692                 Policy defaultPolicy) {
693             final KeyValueListParser parser = new KeyValueListParser(',');
694 
695             // Device-specific parameters.
696             try {
697                 parser.setString(deviceSpecificSettings == null ? "" : deviceSpecificSettings);
698             } catch (IllegalArgumentException e) {
699                 Slog.wtf(TAG, "Bad device specific battery saver constants: "
700                         + deviceSpecificSettings);
701             }
702 
703             final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, "");
704             final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "");
705 
706             // Non-device-specific parameters.
707             try {
708                 parser.setString(settings == null ? "" : settings);
709             } catch (IllegalArgumentException e) {
710                 Slog.wtf(TAG, "Bad battery saver constants: " + settings);
711             }
712 
713             float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR,
714                     defaultPolicy.adjustBrightnessFactor);
715             boolean advertiseIsEnabled = parser.getBoolean(KEY_ADVERTISE_IS_ENABLED,
716                     defaultPolicy.advertiseIsEnabled);
717             boolean deferFullBackup = parser.getBoolean(KEY_FULLBACKUP_DEFERRED,
718                     defaultPolicy.deferFullBackup);
719             boolean deferKeyValueBackup = parser.getBoolean(KEY_KEYVALUE_DEFERRED,
720                     defaultPolicy.deferKeyValueBackup);
721             boolean disableAnimation = parser.getBoolean(KEY_ANIMATION_DISABLED,
722                     defaultPolicy.disableAnimation);
723             boolean disableAod = parser.getBoolean(KEY_AOD_DISABLED, defaultPolicy.disableAod);
724             boolean disableLaunchBoost = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED,
725                     defaultPolicy.disableLaunchBoost);
726             boolean disableOptionalSensors = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED,
727                     defaultPolicy.disableOptionalSensors);
728             boolean disableSoundTrigger = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED,
729                     defaultPolicy.disableSoundTrigger);
730             boolean disableVibrationConfig = parser.getBoolean(KEY_VIBRATION_DISABLED,
731                     defaultPolicy.disableVibration);
732             boolean enableAdjustBrightness = !parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED,
733                     !defaultPolicy.enableAdjustBrightness);
734             boolean enableDataSaver = !parser.getBoolean(KEY_ACTIVATE_DATASAVER_DISABLED,
735                     !defaultPolicy.enableDataSaver);
736             boolean enableFirewall = !parser.getBoolean(KEY_ACTIVATE_FIREWALL_DISABLED,
737                     !defaultPolicy.enableFirewall);
738             boolean enableNightMode = parser.getBoolean(KEY_ENABLE_NIGHT_MODE,
739                     defaultPolicy.enableNightMode);
740             boolean enableQuickDoze = parser.getBoolean(KEY_QUICK_DOZE_ENABLED,
741                     defaultPolicy.enableQuickDoze);
742             boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY,
743                     defaultPolicy.forceAllAppsStandby);
744             boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK,
745                     defaultPolicy.forceBackgroundCheck);
746             int locationMode = parser.getInt(KEY_GPS_MODE, defaultPolicy.locationMode);
747 
748             return new Policy(
749                     adjustBrightnessFactor,
750                     advertiseIsEnabled,
751                     deferFullBackup,
752                     deferKeyValueBackup,
753                     disableAnimation,
754                     disableAod,
755                     disableLaunchBoost,
756                     disableOptionalSensors,
757                     disableSoundTrigger,
758                     /* disableVibration */
759                     disableVibrationConfig,
760                     enableAdjustBrightness,
761                     enableDataSaver,
762                     enableFirewall,
763                     enableNightMode,
764                     enableQuickDoze,
765                     /* filesForInteractive */
766                     (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(),
767                     /* filesForNoninteractive */
768                     (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(),
769                     forceAllAppsStandby,
770                     forceBackgroundCheck,
771                     locationMode
772             );
773         }
774 
775         @Override
equals(Object obj)776         public boolean equals(Object obj) {
777             if (this == obj) return true;
778             if (!(obj instanceof Policy)) return false;
779             Policy other = (Policy) obj;
780             return Float.compare(other.adjustBrightnessFactor, adjustBrightnessFactor) == 0
781                     && advertiseIsEnabled == other.advertiseIsEnabled
782                     && deferFullBackup == other.deferFullBackup
783                     && deferKeyValueBackup == other.deferKeyValueBackup
784                     && disableAnimation == other.disableAnimation
785                     && disableAod == other.disableAod
786                     && disableLaunchBoost == other.disableLaunchBoost
787                     && disableOptionalSensors == other.disableOptionalSensors
788                     && disableSoundTrigger == other.disableSoundTrigger
789                     && disableVibration == other.disableVibration
790                     && enableAdjustBrightness == other.enableAdjustBrightness
791                     && enableDataSaver == other.enableDataSaver
792                     && enableFirewall == other.enableFirewall
793                     && enableNightMode == other.enableNightMode
794                     && enableQuickDoze == other.enableQuickDoze
795                     && forceAllAppsStandby == other.forceAllAppsStandby
796                     && forceBackgroundCheck == other.forceBackgroundCheck
797                     && locationMode == other.locationMode
798                     && filesForInteractive.equals(other.filesForInteractive)
799                     && filesForNoninteractive.equals(other.filesForNoninteractive);
800         }
801 
802         @Override
hashCode()803         public int hashCode() {
804             return mHashCode;
805         }
806     }
807 
808     /**
809      * Get the {@link PowerSaveState} based on the current policy level.
810      * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
811      * parameters when necessary.
812      *
813      * @param type   type of the service, one of {@link ServiceType}
814      * @return State data that contains battery saver data
815      */
getBatterySaverPolicy(@erviceType int type)816     public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
817         synchronized (mLock) {
818             final Policy currPolicy = getCurrentPolicyLocked();
819             final PowerSaveState.Builder builder = new PowerSaveState.Builder()
820                     .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
821             switch (type) {
822                 case ServiceType.LOCATION:
823                     boolean isEnabled = currPolicy.advertiseIsEnabled
824                             || currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE;
825                     return builder.setBatterySaverEnabled(isEnabled)
826                             .setLocationMode(currPolicy.locationMode)
827                             .build();
828                 case ServiceType.ANIMATION:
829                     return builder.setBatterySaverEnabled(currPolicy.disableAnimation)
830                             .build();
831                 case ServiceType.FULL_BACKUP:
832                     return builder.setBatterySaverEnabled(currPolicy.deferFullBackup)
833                             .build();
834                 case ServiceType.KEYVALUE_BACKUP:
835                     return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup)
836                             .build();
837                 case ServiceType.NETWORK_FIREWALL:
838                     return builder.setBatterySaverEnabled(currPolicy.enableFirewall)
839                             .build();
840                 case ServiceType.SCREEN_BRIGHTNESS:
841                     return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
842                             .setBrightnessFactor(currPolicy.adjustBrightnessFactor)
843                             .build();
844                 case ServiceType.DATA_SAVER:
845                     return builder.setBatterySaverEnabled(currPolicy.enableDataSaver)
846                             .build();
847                 case ServiceType.SOUND:
848                     return builder.setBatterySaverEnabled(currPolicy.disableSoundTrigger)
849                             .build();
850                 case ServiceType.VIBRATION:
851                     return builder.setBatterySaverEnabled(mDisableVibrationEffective)
852                             .build();
853                 case ServiceType.FORCE_ALL_APPS_STANDBY:
854                     return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
855                             .build();
856                 case ServiceType.FORCE_BACKGROUND_CHECK:
857                     return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck)
858                             .build();
859                 case ServiceType.NIGHT_MODE:
860                     return builder.setBatterySaverEnabled(currPolicy.enableNightMode)
861                             .build();
862                 case ServiceType.OPTIONAL_SENSORS:
863                     return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors)
864                             .build();
865                 case ServiceType.AOD:
866                     return builder.setBatterySaverEnabled(currPolicy.disableAod)
867                             .build();
868                 case ServiceType.QUICK_DOZE:
869                     return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze)
870                             .build();
871                 default:
872                     return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled)
873                             .build();
874             }
875         }
876     }
877 
878     /**
879      * Sets the current policy.
880      *
881      * @return true if the policy level was changed.
882      */
setPolicyLevel(@olicyLevel int level)883     boolean setPolicyLevel(@PolicyLevel int level) {
884         synchronized (mLock) {
885             if (mPolicyLevel == level) {
886                 return false;
887             }
888             switch (level) {
889                 case POLICY_LEVEL_FULL:
890                 case POLICY_LEVEL_ADAPTIVE:
891                 case POLICY_LEVEL_OFF:
892                     mPolicyLevel = level;
893                     break;
894                 default:
895                     Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level);
896                     return false;
897             }
898             updatePolicyDependenciesLocked();
899             return true;
900         }
901     }
902 
903     /** @return true if the current policy changed and the policy level is ADAPTIVE. */
setAdaptivePolicyLocked(Policy p)904     boolean setAdaptivePolicyLocked(Policy p) {
905         if (p == null) {
906             Slog.wtf(TAG, "setAdaptivePolicy given null policy");
907             return false;
908         }
909         if (mAdaptivePolicy.equals(p)) {
910             return false;
911         }
912 
913         mAdaptivePolicy = p;
914         if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE) {
915             updatePolicyDependenciesLocked();
916             return true;
917         }
918         return false;
919     }
920 
921     /** @return true if the current policy changed and the policy level is ADAPTIVE. */
resetAdaptivePolicyLocked()922     boolean resetAdaptivePolicyLocked() {
923         return setAdaptivePolicyLocked(mDefaultAdaptivePolicy);
924     }
925 
getCurrentPolicyLocked()926     private Policy getCurrentPolicyLocked() {
927         switch (mPolicyLevel) {
928             case POLICY_LEVEL_FULL:
929                 return mFullPolicy;
930             case POLICY_LEVEL_ADAPTIVE:
931                 return mAdaptivePolicy;
932             case POLICY_LEVEL_OFF:
933             default:
934                 return OFF_POLICY;
935         }
936     }
937 
getGpsMode()938     public int getGpsMode() {
939         synchronized (mLock) {
940             return getCurrentPolicyLocked().locationMode;
941         }
942     }
943 
getFileValues(boolean interactive)944     public ArrayMap<String, String> getFileValues(boolean interactive) {
945         synchronized (mLock) {
946             return interactive ? getCurrentPolicyLocked().filesForInteractive
947                     : getCurrentPolicyLocked().filesForNoninteractive;
948         }
949     }
950 
isLaunchBoostDisabled()951     public boolean isLaunchBoostDisabled() {
952         synchronized (mLock) {
953             return getCurrentPolicyLocked().disableLaunchBoost;
954         }
955     }
956 
shouldAdvertiseIsEnabled()957     boolean shouldAdvertiseIsEnabled() {
958         synchronized (mLock) {
959             return getCurrentPolicyLocked().advertiseIsEnabled;
960         }
961     }
962 
toEventLogString()963     public String toEventLogString() {
964         synchronized (mLock) {
965             return mEventLogKeys;
966         }
967     }
968 
dump(PrintWriter pw)969     public void dump(PrintWriter pw) {
970         synchronized (mLock) {
971             pw.println();
972             mBatterySavingStats.dump(pw, "");
973 
974             pw.println();
975             pw.println("Battery saver policy (*NOTE* they only apply when battery saver is ON):");
976             pw.println("  Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS);
977             pw.println("    value: " + mSettings);
978             pw.println("  Settings: " + mDeviceSpecificSettingsSource);
979             pw.println("    value: " + mDeviceSpecificSettings);
980 
981             pw.println("  Adaptive Settings: " + Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS);
982             pw.println("    value: " + mAdaptiveSettings);
983             pw.println("  Adaptive Device Specific Settings: "
984                     + Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS);
985             pw.println("    value: " + mAdaptiveDeviceSpecificSettings);
986 
987             pw.println("  mAccessibilityEnabled=" + mAccessibilityEnabled);
988             pw.println("  mPolicyLevel=" + mPolicyLevel);
989 
990             dumpPolicyLocked(pw, "  ", "full", mFullPolicy);
991             dumpPolicyLocked(pw, "  ", "default adaptive", mDefaultAdaptivePolicy);
992             dumpPolicyLocked(pw, "  ", "current adaptive", mAdaptivePolicy);
993         }
994     }
995 
dumpPolicyLocked(PrintWriter pw, String indent, String label, Policy p)996     private void dumpPolicyLocked(PrintWriter pw, String indent, String label, Policy p) {
997         pw.println();
998         pw.print(indent);
999         pw.println("Policy '" + label + "'");
1000         pw.print(indent);
1001         pw.println("  " + KEY_ADVERTISE_IS_ENABLED + "=" + p.advertiseIsEnabled);
1002         pw.print(indent);
1003         pw.println("  " + KEY_VIBRATION_DISABLED + ":config=" + p.disableVibration);
1004         // mDisableVibrationEffective is based on the currently selected policy
1005         pw.print(indent);
1006         pw.println("  " + KEY_VIBRATION_DISABLED + ":effective=" + (p.disableVibration
1007                 && !mAccessibilityEnabled));
1008         pw.print(indent);
1009         pw.println("  " + KEY_ANIMATION_DISABLED + "=" + p.disableAnimation);
1010         pw.print(indent);
1011         pw.println("  " + KEY_FULLBACKUP_DEFERRED + "=" + p.deferFullBackup);
1012         pw.print(indent);
1013         pw.println("  " + KEY_KEYVALUE_DEFERRED + "=" + p.deferKeyValueBackup);
1014         pw.print(indent);
1015         pw.println("  " + KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !p.enableFirewall);
1016         pw.print(indent);
1017         pw.println("  " + KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !p.enableDataSaver);
1018         pw.print(indent);
1019         pw.println("  " + KEY_LAUNCH_BOOST_DISABLED + "=" + p.disableLaunchBoost);
1020         pw.println(
1021                 "    " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + !p.enableAdjustBrightness);
1022         pw.print(indent);
1023         pw.println("  " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor);
1024         pw.print(indent);
1025         pw.println("  " + KEY_GPS_MODE + "=" + p.locationMode);
1026         pw.print(indent);
1027         pw.println("  " + KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby);
1028         pw.print(indent);
1029         pw.println("  " + KEY_FORCE_BACKGROUND_CHECK + "=" + p.forceBackgroundCheck);
1030         pw.println(
1031                 "    " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + p.disableOptionalSensors);
1032         pw.print(indent);
1033         pw.println("  " + KEY_AOD_DISABLED + "=" + p.disableAod);
1034         pw.print(indent);
1035         pw.println("  " + KEY_SOUNDTRIGGER_DISABLED + "=" + p.disableSoundTrigger);
1036         pw.print(indent);
1037         pw.println("  " + KEY_QUICK_DOZE_ENABLED + "=" + p.enableQuickDoze);
1038         pw.print(indent);
1039         pw.println("  " + KEY_ENABLE_NIGHT_MODE + "=" + p.enableNightMode);
1040 
1041         pw.print("    Interactive File values:\n");
1042         dumpMap(pw, "      ", p.filesForInteractive);
1043         pw.println();
1044 
1045         pw.print("    Noninteractive File values:\n");
1046         dumpMap(pw, "      ", p.filesForNoninteractive);
1047     }
1048 
dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map)1049     private void dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map) {
1050         if (map == null) {
1051             return;
1052         }
1053         final int size = map.size();
1054         for (int i = 0; i < size; i++) {
1055             pw.print(prefix);
1056             pw.print(map.keyAt(i));
1057             pw.print(": '");
1058             pw.print(map.valueAt(i));
1059             pw.println("'");
1060         }
1061     }
1062 
1063     @VisibleForTesting
setAccessibilityEnabledForTest(boolean enabled)1064     public void setAccessibilityEnabledForTest(boolean enabled) {
1065         synchronized (mLock) {
1066             mAccessibilityEnabled = enabled;
1067             updatePolicyDependenciesLocked();
1068         }
1069     }
1070 }
1071