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.app.UiModeManager;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.database.ContentObserver;
23 import android.net.Uri;
24 import android.os.BatterySaverPolicyConfig;
25 import android.os.Handler;
26 import android.os.PowerManager;
27 import android.os.PowerManager.ServiceType;
28 import android.os.PowerSaveState;
29 import android.provider.DeviceConfig;
30 import android.provider.Settings;
31 import android.text.TextUtils;
32 import android.util.ArrayMap;
33 import android.util.IndentingPrintWriter;
34 import android.util.KeyValueListParser;
35 import android.util.Slog;
36 import android.view.accessibility.AccessibilityManager;
37 
38 import com.android.internal.R;
39 import com.android.internal.annotations.GuardedBy;
40 import com.android.internal.annotations.VisibleForTesting;
41 import com.android.internal.os.BackgroundThread;
42 import com.android.internal.util.ConcurrentUtils;
43 import com.android.server.power.PowerManagerService;
44 
45 import java.io.PrintWriter;
46 import java.lang.annotation.Retention;
47 import java.lang.annotation.RetentionPolicy;
48 import java.util.ArrayList;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Objects;
52 import java.util.Set;
53 
54 /**
55  * Class to decide whether to turn on battery saver mode for specific services.
56  *
57  * IMPORTANT: This class shares the power manager lock, which is very low in the lock hierarchy.
58  * Do not call out with the lock held, such as AccessibilityManager. (Settings provider is okay.)
59  *
60  * Test: atest com.android.server.power.batterysaver.BatterySaverPolicyTest
61  */
62 public class BatterySaverPolicy extends ContentObserver implements
63         DeviceConfig.OnPropertiesChangedListener {
64     private static final String TAG = "BatterySaverPolicy";
65 
66     static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE.
67 
68     @VisibleForTesting
69     static final String KEY_LOCATION_MODE = "location_mode";
70     @VisibleForTesting
71     static final String KEY_DISABLE_VIBRATION = "disable_vibration";
72     @VisibleForTesting
73     static final String KEY_DISABLE_ANIMATION = "disable_animation";
74     @VisibleForTesting
75     static final String KEY_SOUNDTRIGGER_MODE = "soundtrigger_mode";
76 
77     /**
78      * Turn on the network firewall when Battery Saver is turned on.
79      * If set to false, the firewall WILL NOT be turned on when Battery Saver is turned on.
80      * If set to true, the firewall WILL be turned on when Battery Saver is turned on.
81      */
82     @VisibleForTesting
83     static final String KEY_ENABLE_FIREWALL = "enable_firewall";
84 
85     /**
86      * Turn on the special low power screen brightness dimming when Battery Saver is
87      * turned on.
88      * If set to false, the screen brightness dimming WILL NOT be turned on by Battery Saver.
89      * If set to true, the screen brightness WILL be turned on by Battery Saver.
90      */
91     @VisibleForTesting
92     static final String KEY_ENABLE_BRIGHTNESS_ADJUSTMENT = "enable_brightness_adjustment";
93 
94     /**
95      * Turn on Data Saver when Battery Saver is turned on.
96      * If set to false, Data Saver WILL NOT be turned on when Battery Saver is turned on.
97      * If set to true, Data Saver WILL be turned on when Battery Saver is turned on.
98      */
99     @VisibleForTesting
100     static final String KEY_ENABLE_DATASAVER = "enable_datasaver";
101 
102     /**
103      * {@code true} if the Policy should advertise to the rest of the system that battery saver
104      * is enabled. This advertising could cause other system components to change their
105      * behavior. This will not affect other policy flags and what they change.
106      */
107     @VisibleForTesting
108     static final String KEY_ADVERTISE_IS_ENABLED = "advertise_is_enabled";
109 
110     @VisibleForTesting
111     static final String KEY_DISABLE_LAUNCH_BOOST = "disable_launch_boost";
112     @VisibleForTesting
113     static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
114     @VisibleForTesting
115     static final String KEY_DEFER_FULL_BACKUP = "defer_full_backup";
116     @VisibleForTesting
117     static final String KEY_DEFER_KEYVALUE_BACKUP = "defer_keyvalue_backup";
118     @VisibleForTesting
119     static final String KEY_FORCE_ALL_APPS_STANDBY = "force_all_apps_standby";
120     @VisibleForTesting
121     static final String KEY_FORCE_BACKGROUND_CHECK = "force_background_check";
122     @VisibleForTesting
123     static final String KEY_DISABLE_OPTIONAL_SENSORS = "disable_optional_sensors";
124     @VisibleForTesting
125     static final String KEY_DISABLE_AOD = "disable_aod";
126     // Go into deep Doze as soon as the screen turns off.
127     @VisibleForTesting
128     static final String KEY_ENABLE_QUICK_DOZE = "enable_quick_doze";
129     @VisibleForTesting
130     static final String KEY_ENABLE_NIGHT_MODE = "enable_night_mode";
131 
132     private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i";
133     private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n";
134 
135     private static final String KEY_SUFFIX_ADAPTIVE = "_adaptive";
136 
137     @VisibleForTesting
138     static final Policy OFF_POLICY = new Policy(
139             1f,    /* adjustBrightnessFactor */
140             false, /* advertiseIsEnabled */
141             new CpuFrequencies(), /* cpuFrequenciesForInteractive */
142             new CpuFrequencies(), /* cpuFrequenciesForNoninteractive */
143             false, /* deferFullBackup */
144             false, /* deferKeyValueBackup */
145             false, /* disableAnimation */
146             false, /* disableAod */
147             false, /* disableLaunchBoost */
148             false, /* disableOptionalSensors */
149             false, /* disableVibration */
150             false, /* enableAdjustBrightness */
151             false, /* enableDataSaver */
152             false, /* enableFireWall */
153             false, /* enableNightMode */
154             false, /* enableQuickDoze */
155             false, /* forceAllAppsStandby */
156             false, /* forceBackgroundCheck */
157             PowerManager.LOCATION_MODE_NO_CHANGE, /* locationMode */
158             PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED /* soundTriggerMode */
159     );
160 
161     private static final Policy DEFAULT_ADAPTIVE_POLICY = OFF_POLICY;
162 
163     private static final Policy DEFAULT_FULL_POLICY = new Policy(
164             0.5f,  /* adjustBrightnessFactor */
165             true,  /* advertiseIsEnabled */
166             new CpuFrequencies(), /* cpuFrequenciesForInteractive */
167             new CpuFrequencies(), /* cpuFrequenciesForNoninteractive */
168             true,  /* deferFullBackup */
169             true,  /* deferKeyValueBackup */
170             false, /* disableAnimation */
171             true,  /* disableAod */
172             true,  /* disableLaunchBoost */
173             true,  /* disableOptionalSensors */
174             true,  /* disableVibration */
175             false, /* enableAdjustBrightness */
176             false, /* enableDataSaver */
177             true,  /* enableFirewall */
178             true, /* enableNightMode */
179             true, /* enableQuickDoze */
180             true, /* forceAllAppsStandby */
181             true, /* forceBackgroundCheck */
182             PowerManager.LOCATION_MODE_FOREGROUND_ONLY, /* locationMode */
183             PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY /* soundTriggerMode */
184     );
185 
186     private final Object mLock;
187     private final Handler mHandler;
188 
189     @GuardedBy("mLock")
190     private String mSettings;
191 
192     @GuardedBy("mLock")
193     private String mDeviceSpecificSettings;
194 
195     @GuardedBy("mLock")
196     private String mDeviceSpecificSettingsSource; // For dump() only.
197 
198     @GuardedBy("mLock")
199     private DeviceConfig.Properties mLastDeviceConfigProperties;
200 
201     /**
202      * A short string describing which battery saver is now enabled, which we dump in the eventlog.
203      */
204     @GuardedBy("mLock")
205     private String mEventLogKeys;
206 
207     /**
208      * Whether accessibility is currently enabled or not.
209      */
210     @VisibleForTesting
211     final PolicyBoolean mAccessibilityEnabled = new PolicyBoolean("accessibility");
212 
213     /** Whether the phone has set automotive projection or not. */
214     @VisibleForTesting
215     final PolicyBoolean mAutomotiveProjectionActive = new PolicyBoolean("automotiveProjection");
216 
217     /** The current default adaptive policy. */
218     @GuardedBy("mLock")
219     private Policy mDefaultAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY;
220 
221     /** The policy that will be used for adaptive battery saver. */
222     @GuardedBy("mLock")
223     private Policy mAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY;
224 
225     /** The current default full policy. */
226     @GuardedBy("mLock")
227     private Policy mDefaultFullPolicy = DEFAULT_FULL_POLICY;
228 
229     /** The policy to be used for full battery saver. */
230     @GuardedBy("mLock")
231     private Policy mFullPolicy = DEFAULT_FULL_POLICY;
232 
233     /**
234      * The current effective policy. This is based on the current policy level's policy, with any
235      * required adjustments.
236      */
237     @GuardedBy("mLock")
238     private Policy mEffectivePolicyRaw = OFF_POLICY;
239 
240     @IntDef(prefix = {"POLICY_LEVEL_"}, value = {
241             POLICY_LEVEL_OFF,
242             POLICY_LEVEL_ADAPTIVE,
243             POLICY_LEVEL_FULL,
244     })
245     @Retention(RetentionPolicy.SOURCE)
246     @interface PolicyLevel {}
247 
248     static final int POLICY_LEVEL_OFF = 0;
249     static final int POLICY_LEVEL_ADAPTIVE = 1;
250     static final int POLICY_LEVEL_FULL = 2;
251 
252     @GuardedBy("mLock")
253     private int mPolicyLevel = POLICY_LEVEL_OFF;
254 
255     private final Context mContext;
256     private final ContentResolver mContentResolver;
257     private final BatterySavingStats mBatterySavingStats;
258 
259     private final UiModeManager.OnProjectionStateChangedListener mOnProjectionStateChangedListener =
260             (t, pkgs) -> mAutomotiveProjectionActive.update(!pkgs.isEmpty());
261 
262     @GuardedBy("mLock")
263     private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>();
264 
265     public interface BatterySaverPolicyListener {
onBatterySaverPolicyChanged(BatterySaverPolicy policy)266         void onBatterySaverPolicyChanged(BatterySaverPolicy policy);
267     }
268 
BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats)269     public BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats) {
270         super(BackgroundThread.getHandler());
271         mLock = lock;
272         mHandler = BackgroundThread.getHandler();
273         mContext = context;
274         mContentResolver = context.getContentResolver();
275         mBatterySavingStats = batterySavingStats;
276     }
277 
278     /**
279      * Called by {@link PowerManagerService#systemReady}, *with no lock held.*
280      */
systemReady()281     public void systemReady() {
282         ConcurrentUtils.wtfIfLockHeld(TAG, mLock);
283 
284         mContentResolver.registerContentObserver(Settings.Global.getUriFor(
285                 Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
286         mContentResolver.registerContentObserver(Settings.Global.getUriFor(
287                 Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this);
288 
289         final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class);
290 
291         acm.addAccessibilityStateChangeListener(enabled -> mAccessibilityEnabled.update(enabled));
292         mAccessibilityEnabled.initialize(acm.isEnabled());
293 
294         UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);
295         uiModeManager.addOnProjectionStateChangedListener(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE,
296                 mContext.getMainExecutor(), mOnProjectionStateChangedListener);
297         mAutomotiveProjectionActive.initialize(
298                 uiModeManager.getActiveProjectionTypes() != UiModeManager.PROJECTION_TYPE_NONE);
299 
300         DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_SAVER,
301                 mContext.getMainExecutor(), this);
302         mLastDeviceConfigProperties =
303                 DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_SAVER);
304         onChange(true, null);
305     }
306 
307     @VisibleForTesting
addListener(BatterySaverPolicyListener listener)308     public void addListener(BatterySaverPolicyListener listener) {
309         synchronized (mLock) {
310             // TODO: set this in the constructor instead
311             mListeners.add(listener);
312         }
313     }
314 
315     @VisibleForTesting
getGlobalSetting(String key)316     String getGlobalSetting(String key) {
317         return Settings.Global.getString(mContentResolver, key);
318     }
319 
320     @VisibleForTesting
getDeviceSpecificConfigResId()321     int getDeviceSpecificConfigResId() {
322         return R.string.config_batterySaverDeviceSpecificConfig;
323     }
324 
325     @VisibleForTesting
invalidatePowerSaveModeCaches()326     void invalidatePowerSaveModeCaches() {
327         PowerManager.invalidatePowerSaveModeCaches();
328     }
329 
330     /**
331      * Notifies listeners of a policy change on the handler thread only if the current policy level
332      * is not {@link #POLICY_LEVEL_OFF}.
333      */
maybeNotifyListenersOfPolicyChange()334     private void maybeNotifyListenersOfPolicyChange() {
335         final BatterySaverPolicyListener[] listeners;
336         synchronized (mLock) {
337             if (mPolicyLevel == POLICY_LEVEL_OFF) {
338                 // Current policy is OFF, so there's no change to notify listeners of.
339                 return;
340             }
341             // Don't call out to listeners with the lock held.
342             listeners = mListeners.toArray(new BatterySaverPolicyListener[mListeners.size()]);
343         }
344 
345         mHandler.post(() -> {
346             for (BatterySaverPolicyListener listener : listeners) {
347                 listener.onBatterySaverPolicyChanged(this);
348             }
349         });
350     }
351 
352     @Override
onChange(boolean selfChange, Uri uri)353     public void onChange(boolean selfChange, Uri uri) {
354         refreshSettings();
355     }
356 
357     @Override
onPropertiesChanged(DeviceConfig.Properties properties)358     public void onPropertiesChanged(DeviceConfig.Properties properties) {
359         // Need to get all of the flags atomically.
360         mLastDeviceConfigProperties =
361                 DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_SAVER);
362         Policy newAdaptivePolicy = null;
363         Policy newFullPolicy = null;
364 
365         boolean changed = false;
366 
367         synchronized (mLock) {
368             for (String name : properties.getKeyset()) {
369                 if (name == null) {
370                     continue;
371                 }
372                 if (name.endsWith(KEY_SUFFIX_ADAPTIVE)) {
373                     if (newAdaptivePolicy == null) {
374                         newAdaptivePolicy = Policy.fromSettings("", "",
375                                 mLastDeviceConfigProperties, KEY_SUFFIX_ADAPTIVE,
376                                 DEFAULT_ADAPTIVE_POLICY);
377                     }
378                 } else if (newFullPolicy == null) {
379                     newFullPolicy = Policy.fromSettings(mSettings, mDeviceSpecificSettings,
380                             mLastDeviceConfigProperties, null, DEFAULT_FULL_POLICY);
381                 }
382             }
383 
384             if (newFullPolicy != null) {
385                 changed |= maybeUpdateDefaultFullPolicy(newFullPolicy);
386             }
387 
388             if (newAdaptivePolicy != null && !mAdaptivePolicy.equals(newAdaptivePolicy)) {
389                 mDefaultAdaptivePolicy = newAdaptivePolicy;
390                 // This will override any config set by an external source. This should be fine
391                 // for now.
392                 // TODO(119261320): make sure it doesn't override what's set externally
393                 mAdaptivePolicy = mDefaultAdaptivePolicy;
394                 changed |= (mPolicyLevel == POLICY_LEVEL_ADAPTIVE);
395             }
396 
397             updatePolicyDependenciesLocked();
398         }
399 
400         if (changed) {
401             maybeNotifyListenersOfPolicyChange();
402         }
403     }
404 
refreshSettings()405     private void refreshSettings() {
406         synchronized (mLock) {
407             // Load the non-device-specific setting.
408             final String setting = getGlobalSetting(Settings.Global.BATTERY_SAVER_CONSTANTS);
409 
410             // Load the device specific setting.
411             // We first check the global setting, and if it's empty or the string "null" is set,
412             // use the default value from config.xml.
413             String deviceSpecificSetting = getGlobalSetting(
414                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS);
415             mDeviceSpecificSettingsSource =
416                     Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS;
417 
418             if (TextUtils.isEmpty(deviceSpecificSetting) || "null".equals(deviceSpecificSetting)) {
419                 deviceSpecificSetting =
420                         mContext.getString(getDeviceSpecificConfigResId());
421                 mDeviceSpecificSettingsSource = "(overlay)";
422             }
423 
424             if (!updateConstantsLocked(setting, deviceSpecificSetting)) {
425                 // Nothing of note changed.
426                 return;
427             }
428         }
429 
430         maybeNotifyListenersOfPolicyChange();
431     }
432 
433     @GuardedBy("mLock")
434     @VisibleForTesting
435     /** @return true if the currently active policy changed. */
updateConstantsLocked(String setting, String deviceSpecificSetting)436     boolean updateConstantsLocked(String setting, String deviceSpecificSetting) {
437         setting = TextUtils.emptyIfNull(setting);
438         deviceSpecificSetting = TextUtils.emptyIfNull(deviceSpecificSetting);
439 
440         if (setting.equals(mSettings)
441                 && deviceSpecificSetting.equals(mDeviceSpecificSettings)) {
442             return false;
443         }
444 
445         mSettings = setting;
446         mDeviceSpecificSettings = deviceSpecificSetting;
447 
448         if (DEBUG) {
449             Slog.i(TAG, "mSettings=" + mSettings);
450             Slog.i(TAG, "mDeviceSpecificSettings=" + mDeviceSpecificSettings);
451         }
452 
453         boolean changed = maybeUpdateDefaultFullPolicy(
454                 Policy.fromSettings(setting, deviceSpecificSetting,
455                         mLastDeviceConfigProperties, null, DEFAULT_FULL_POLICY));
456 
457         mDefaultAdaptivePolicy = Policy.fromSettings("", "",
458                 mLastDeviceConfigProperties, KEY_SUFFIX_ADAPTIVE, DEFAULT_ADAPTIVE_POLICY);
459         if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE
460                 && !mAdaptivePolicy.equals(mDefaultAdaptivePolicy)) {
461             changed = true;
462         }
463         // This will override any config set by an external source. This should be fine for now.
464         // TODO: make sure it doesn't override what's set externally
465         mAdaptivePolicy = mDefaultAdaptivePolicy;
466 
467         updatePolicyDependenciesLocked();
468 
469         return changed;
470     }
471 
472     @GuardedBy("mLock")
updatePolicyDependenciesLocked()473     private void updatePolicyDependenciesLocked() {
474         final Policy rawPolicy = getCurrentRawPolicyLocked();
475         final int locationMode;
476 
477         invalidatePowerSaveModeCaches();
478         if (mAutomotiveProjectionActive.get()
479                 && rawPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE
480                 && rawPolicy.locationMode != PowerManager.LOCATION_MODE_FOREGROUND_ONLY) {
481             // If car projection is enabled, ensure that navigation works.
482             locationMode = PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
483         } else {
484             locationMode = rawPolicy.locationMode;
485         }
486 
487         mEffectivePolicyRaw = new Policy(
488                 rawPolicy.adjustBrightnessFactor,
489                 rawPolicy.advertiseIsEnabled,
490                 rawPolicy.cpuFrequenciesForInteractive,
491                 rawPolicy.cpuFrequenciesForNoninteractive,
492                 rawPolicy.deferFullBackup,
493                 rawPolicy.deferKeyValueBackup,
494                 rawPolicy.disableAnimation,
495                 rawPolicy.disableAod,
496                 rawPolicy.disableLaunchBoost,
497                 rawPolicy.disableOptionalSensors,
498                 // Don't disable vibration when accessibility is on.
499                 rawPolicy.disableVibration && !mAccessibilityEnabled.get(),
500                 rawPolicy.enableAdjustBrightness,
501                 rawPolicy.enableDataSaver,
502                 rawPolicy.enableFirewall,
503                 // Don't force night mode when car projection is enabled.
504                 rawPolicy.enableNightMode && !mAutomotiveProjectionActive.get(),
505                 rawPolicy.enableQuickDoze,
506                 rawPolicy.forceAllAppsStandby,
507                 rawPolicy.forceBackgroundCheck,
508                 locationMode,
509                 rawPolicy.soundTriggerMode
510         );
511 
512 
513         final StringBuilder sb = new StringBuilder();
514 
515         if (mEffectivePolicyRaw.forceAllAppsStandby) sb.append("A");
516         if (mEffectivePolicyRaw.forceBackgroundCheck) sb.append("B");
517 
518         if (mEffectivePolicyRaw.disableVibration) sb.append("v");
519         if (mEffectivePolicyRaw.disableAnimation) sb.append("a");
520 
521         sb.append(mEffectivePolicyRaw.soundTriggerMode);
522 
523         if (mEffectivePolicyRaw.deferFullBackup) sb.append("F");
524         if (mEffectivePolicyRaw.deferKeyValueBackup) sb.append("K");
525         if (mEffectivePolicyRaw.enableFirewall) sb.append("f");
526         if (mEffectivePolicyRaw.enableDataSaver) sb.append("d");
527         if (mEffectivePolicyRaw.enableAdjustBrightness) sb.append("b");
528 
529         if (mEffectivePolicyRaw.disableLaunchBoost) sb.append("l");
530         if (mEffectivePolicyRaw.disableOptionalSensors) sb.append("S");
531         if (mEffectivePolicyRaw.disableAod) sb.append("o");
532         if (mEffectivePolicyRaw.enableQuickDoze) sb.append("q");
533 
534         sb.append(mEffectivePolicyRaw.locationMode);
535 
536         mEventLogKeys = sb.toString();
537     }
538 
539     static class Policy {
540         /**
541          * This is the flag to decide the how much to adjust the screen brightness. This is
542          * the float value from 0 to 1 where 1 means don't change brightness.
543          *
544          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
545          * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
546          */
547         public final float adjustBrightnessFactor;
548 
549         /**
550          * {@code true} if the Policy should advertise to the rest of the system that battery saver
551          * is enabled. This advertising could cause other system components to change their
552          * behavior. This will not affect other policy flags and what they change.
553          *
554          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
555          * @see #KEY_ADVERTISE_IS_ENABLED
556          */
557         public final boolean advertiseIsEnabled;
558 
559         /**
560          * {@code true} if full backup is deferred in battery saver mode.
561          *
562          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
563          * @see #KEY_DEFER_FULL_BACKUP
564          */
565         public final boolean deferFullBackup;
566 
567         /**
568          * {@code true} if key value backup is deferred in battery saver mode.
569          *
570          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
571          * @see #KEY_DEFER_KEYVALUE_BACKUP
572          */
573         public final boolean deferKeyValueBackup;
574 
575         /**
576          * {@code true} if animation is disabled in battery saver mode.
577          *
578          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
579          * @see #KEY_DISABLE_ANIMATION
580          */
581         public final boolean disableAnimation;
582 
583         /**
584          * {@code true} if AOD is disabled in battery saver mode.
585          */
586         public final boolean disableAod;
587 
588         /**
589          * {@code true} if launch boost should be disabled on battery saver.
590          */
591         public final boolean disableLaunchBoost;
592 
593         /**
594          * Whether to show non-essential sensors (e.g. edge sensors) or not.
595          */
596         public final boolean disableOptionalSensors;
597 
598         /**
599          * {@code true} if sound trigger is disabled in battery saver mode
600          * in battery saver mode.
601          *
602          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
603          * @see #KEY_SOUNDTRIGGER_MODE
604          */
605         public final int soundTriggerMode;
606 
607         /**
608          * {@code true} if vibration is disabled in battery saver mode.
609          *
610          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
611          * @see #KEY_DISABLE_VIBRATION
612          */
613         public final boolean disableVibration;
614 
615         /**
616          * {@code true} if low power mode brightness adjustment should be turned on in battery saver
617          * mode.
618          *
619          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
620          * @see #KEY_ENABLE_BRIGHTNESS_ADJUSTMENT
621          */
622         public final boolean enableAdjustBrightness;
623 
624         /**
625          * {@code true} if data saver should be turned on in battery saver mode.
626          *
627          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
628          * @see #KEY_ENABLE_DATASAVER
629          */
630         public final boolean enableDataSaver;
631 
632         /**
633          * {@code true} if network policy firewall should be turned on in battery saver mode.
634          *
635          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
636          * @see #KEY_ENABLE_FIREWALL
637          */
638         public final boolean enableFirewall;
639 
640         /**
641          * Whether to enable night mode or not.
642          */
643         public final boolean enableNightMode;
644 
645         /**
646          * Whether Quick Doze is enabled or not.
647          */
648         public final boolean enableQuickDoze;
649 
650         /**
651          * List of CPU frequencies that should be written when battery saver is activated
652          * and the device is interactive.
653          *
654          * We use this to change the max CPU frequencies.
655          */
656         public final CpuFrequencies cpuFrequenciesForInteractive;
657 
658         /**
659          * List of CPU frequencies that should be written when battery saver is activated
660          * and the device is non-interactive.
661          *
662          * We use this to change the max CPU frequencies.
663          */
664         public final CpuFrequencies cpuFrequenciesForNoninteractive;
665 
666         /**
667          * Whether to put all apps in the stand-by mode.
668          */
669         public final boolean forceAllAppsStandby;
670 
671         /**
672          * Whether to force background check.
673          */
674         public final boolean forceBackgroundCheck;
675 
676         /**
677          * This is the flag to decide the location mode in battery saver mode. This was
678          * previously called gpsMode.
679          *
680          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
681          * @see #KEY_LOCATION_MODE
682          */
683         public final int locationMode;
684 
685         private final int mHashCode;
686 
Policy( float adjustBrightnessFactor, boolean advertiseIsEnabled, CpuFrequencies cpuFrequenciesForInteractive, CpuFrequencies cpuFrequenciesForNoninteractive, boolean deferFullBackup, boolean deferKeyValueBackup, boolean disableAnimation, boolean disableAod, boolean disableLaunchBoost, boolean disableOptionalSensors, boolean disableVibration, boolean enableAdjustBrightness, boolean enableDataSaver, boolean enableFirewall, boolean enableNightMode, boolean enableQuickDoze, boolean forceAllAppsStandby, boolean forceBackgroundCheck, int locationMode, int soundTriggerMode)687         Policy(
688                 float adjustBrightnessFactor,
689                 boolean advertiseIsEnabled,
690                 CpuFrequencies cpuFrequenciesForInteractive,
691                 CpuFrequencies cpuFrequenciesForNoninteractive,
692                 boolean deferFullBackup,
693                 boolean deferKeyValueBackup,
694                 boolean disableAnimation,
695                 boolean disableAod,
696                 boolean disableLaunchBoost,
697                 boolean disableOptionalSensors,
698                 boolean disableVibration,
699                 boolean enableAdjustBrightness,
700                 boolean enableDataSaver,
701                 boolean enableFirewall,
702                 boolean enableNightMode,
703                 boolean enableQuickDoze,
704                 boolean forceAllAppsStandby,
705                 boolean forceBackgroundCheck,
706                 int locationMode,
707                 int soundTriggerMode) {
708 
709             this.adjustBrightnessFactor = Math.min(1, Math.max(0, adjustBrightnessFactor));
710             this.advertiseIsEnabled = advertiseIsEnabled;
711             this.cpuFrequenciesForInteractive = cpuFrequenciesForInteractive;
712             this.cpuFrequenciesForNoninteractive = cpuFrequenciesForNoninteractive;
713             this.deferFullBackup = deferFullBackup;
714             this.deferKeyValueBackup = deferKeyValueBackup;
715             this.disableAnimation = disableAnimation;
716             this.disableAod = disableAod;
717             this.disableLaunchBoost = disableLaunchBoost;
718             this.disableOptionalSensors = disableOptionalSensors;
719             this.disableVibration = disableVibration;
720             this.enableAdjustBrightness = enableAdjustBrightness;
721             this.enableDataSaver = enableDataSaver;
722             this.enableFirewall = enableFirewall;
723             this.enableNightMode = enableNightMode;
724             this.enableQuickDoze = enableQuickDoze;
725             this.forceAllAppsStandby = forceAllAppsStandby;
726             this.forceBackgroundCheck = forceBackgroundCheck;
727 
728             if (locationMode < PowerManager.MIN_LOCATION_MODE
729                     || PowerManager.MAX_LOCATION_MODE < locationMode) {
730                 Slog.e(TAG, "Invalid location mode: " + locationMode);
731                 this.locationMode = PowerManager.LOCATION_MODE_NO_CHANGE;
732             } else {
733                 this.locationMode = locationMode;
734             }
735 
736             if (soundTriggerMode < PowerManager.MIN_SOUND_TRIGGER_MODE
737                     || soundTriggerMode > PowerManager.MAX_SOUND_TRIGGER_MODE) {
738                 Slog.e(TAG, "Invalid SoundTrigger mode: " + soundTriggerMode);
739                 this.soundTriggerMode = PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED;
740             } else {
741                 this.soundTriggerMode = soundTriggerMode;
742             }
743 
744             mHashCode = Objects.hash(
745                     adjustBrightnessFactor,
746                     advertiseIsEnabled,
747                     cpuFrequenciesForInteractive,
748                     cpuFrequenciesForNoninteractive,
749                     deferFullBackup,
750                     deferKeyValueBackup,
751                     disableAnimation,
752                     disableAod,
753                     disableLaunchBoost,
754                     disableOptionalSensors,
755                     disableVibration,
756                     enableAdjustBrightness,
757                     enableDataSaver,
758                     enableFirewall,
759                     enableNightMode,
760                     enableQuickDoze,
761                     forceAllAppsStandby,
762                     forceBackgroundCheck,
763                     locationMode,
764                     soundTriggerMode);
765         }
766 
fromConfig(BatterySaverPolicyConfig config)767         static Policy fromConfig(BatterySaverPolicyConfig config) {
768             if (config == null) {
769                 Slog.e(TAG, "Null config passed down to BatterySaverPolicy");
770                 return OFF_POLICY;
771             }
772 
773             // Device-specific parameters.
774             Map<String, String> deviceSpecificSettings = config.getDeviceSpecificSettings();
775             final String cpuFreqInteractive =
776                     deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_INTERACTIVE, "");
777             final String cpuFreqNoninteractive =
778                     deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_NONINTERACTIVE, "");
779 
780             return new Policy(
781                     config.getAdjustBrightnessFactor(),
782                     config.getAdvertiseIsEnabled(),
783                     (new CpuFrequencies()).parseString(cpuFreqInteractive),
784                     (new CpuFrequencies()).parseString(cpuFreqNoninteractive),
785                     config.getDeferFullBackup(),
786                     config.getDeferKeyValueBackup(),
787                     config.getDisableAnimation(),
788                     config.getDisableAod(),
789                     config.getDisableLaunchBoost(),
790                     config.getDisableOptionalSensors(),
791                     config.getDisableVibration(),
792                     config.getEnableAdjustBrightness(),
793                     config.getEnableDataSaver(),
794                     config.getEnableFirewall(),
795                     config.getEnableNightMode(),
796                     config.getEnableQuickDoze(),
797                     config.getForceAllAppsStandby(),
798                     config.getForceBackgroundCheck(),
799                     config.getLocationMode(),
800                     config.getSoundTriggerMode()
801             );
802         }
803 
toConfig()804         BatterySaverPolicyConfig toConfig() {
805             return new BatterySaverPolicyConfig.Builder()
806                     .addDeviceSpecificSetting(KEY_CPU_FREQ_INTERACTIVE,
807                             cpuFrequenciesForInteractive.toString())
808                     .addDeviceSpecificSetting(KEY_CPU_FREQ_NONINTERACTIVE,
809                             cpuFrequenciesForNoninteractive.toString())
810                     .setAdjustBrightnessFactor(adjustBrightnessFactor)
811                     .setAdvertiseIsEnabled(advertiseIsEnabled)
812                     .setDeferFullBackup(deferFullBackup)
813                     .setDeferKeyValueBackup(deferKeyValueBackup)
814                     .setDisableAnimation(disableAnimation)
815                     .setDisableAod(disableAod)
816                     .setDisableLaunchBoost(disableLaunchBoost)
817                     .setDisableOptionalSensors(disableOptionalSensors)
818                     .setDisableVibration(disableVibration)
819                     .setEnableAdjustBrightness(enableAdjustBrightness)
820                     .setEnableDataSaver(enableDataSaver)
821                     .setEnableFirewall(enableFirewall)
822                     .setEnableNightMode(enableNightMode)
823                     .setEnableQuickDoze(enableQuickDoze)
824                     .setForceAllAppsStandby(forceAllAppsStandby)
825                     .setForceBackgroundCheck(forceBackgroundCheck)
826                     .setLocationMode(locationMode)
827                     .setSoundTriggerMode(soundTriggerMode)
828                     .build();
829         }
830 
831         @VisibleForTesting
fromSettings(String settings, String deviceSpecificSettings, DeviceConfig.Properties properties, String configSuffix)832         static Policy fromSettings(String settings, String deviceSpecificSettings,
833                 DeviceConfig.Properties properties, String configSuffix) {
834             return fromSettings(settings, deviceSpecificSettings, properties, configSuffix,
835                     OFF_POLICY);
836         }
837 
fromSettings(String settings, String deviceSpecificSettings, DeviceConfig.Properties properties, String configSuffix, Policy defaultPolicy)838         private static Policy fromSettings(String settings, String deviceSpecificSettings,
839                 DeviceConfig.Properties properties, String configSuffix, Policy defaultPolicy) {
840             final KeyValueListParser parser = new KeyValueListParser(',');
841             configSuffix = TextUtils.emptyIfNull(configSuffix);
842 
843             // Device-specific parameters.
844             try {
845                 parser.setString(deviceSpecificSettings == null ? "" : deviceSpecificSettings);
846             } catch (IllegalArgumentException e) {
847                 Slog.wtf(TAG, "Bad device specific battery saver constants: "
848                         + deviceSpecificSettings);
849             }
850 
851             final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, "");
852             final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "");
853 
854             // Non-device-specific parameters.
855             try {
856                 parser.setString(settings == null ? "" : settings);
857             } catch (IllegalArgumentException e) {
858                 Slog.wtf(TAG, "Bad battery saver constants: " + settings);
859             }
860 
861             // The Settings value overrides everything, since that will be set by the user.
862             // The DeviceConfig value takes second place, with the default as the last choice.
863             final float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR,
864                     properties.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR + configSuffix,
865                             defaultPolicy.adjustBrightnessFactor));
866             final boolean advertiseIsEnabled = parser.getBoolean(KEY_ADVERTISE_IS_ENABLED,
867                     properties.getBoolean(KEY_ADVERTISE_IS_ENABLED + configSuffix,
868                             defaultPolicy.advertiseIsEnabled));
869             final boolean deferFullBackup = parser.getBoolean(KEY_DEFER_FULL_BACKUP,
870                     properties.getBoolean(KEY_DEFER_FULL_BACKUP + configSuffix,
871                             defaultPolicy.deferFullBackup));
872             final boolean deferKeyValueBackup = parser.getBoolean(KEY_DEFER_KEYVALUE_BACKUP,
873                     properties.getBoolean(KEY_DEFER_KEYVALUE_BACKUP + configSuffix,
874                             defaultPolicy.deferKeyValueBackup));
875             final boolean disableAnimation = parser.getBoolean(KEY_DISABLE_ANIMATION,
876                     properties.getBoolean(KEY_DISABLE_ANIMATION + configSuffix,
877                             defaultPolicy.disableAnimation));
878             final boolean disableAod = parser.getBoolean(KEY_DISABLE_AOD,
879                     properties.getBoolean(KEY_DISABLE_AOD + configSuffix,
880                             defaultPolicy.disableAod));
881             final boolean disableLaunchBoost = parser.getBoolean(KEY_DISABLE_LAUNCH_BOOST,
882                     properties.getBoolean(KEY_DISABLE_LAUNCH_BOOST + configSuffix,
883                             defaultPolicy.disableLaunchBoost));
884             final boolean disableOptionalSensors = parser.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS,
885                     properties.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS + configSuffix,
886                             defaultPolicy.disableOptionalSensors));
887             final boolean disableVibrationConfig = parser.getBoolean(KEY_DISABLE_VIBRATION,
888                     properties.getBoolean(KEY_DISABLE_VIBRATION + configSuffix,
889                             defaultPolicy.disableVibration));
890             final boolean enableBrightnessAdjustment = parser.getBoolean(
891                     KEY_ENABLE_BRIGHTNESS_ADJUSTMENT,
892                     properties.getBoolean(KEY_ENABLE_BRIGHTNESS_ADJUSTMENT + configSuffix,
893                             defaultPolicy.enableAdjustBrightness));
894             final boolean enableDataSaver = parser.getBoolean(KEY_ENABLE_DATASAVER,
895                     properties.getBoolean(KEY_ENABLE_DATASAVER + configSuffix,
896                             defaultPolicy.enableDataSaver));
897             final boolean enableFirewall = parser.getBoolean(KEY_ENABLE_FIREWALL,
898                     properties.getBoolean(KEY_ENABLE_FIREWALL + configSuffix,
899                             defaultPolicy.enableFirewall));
900             final boolean enableNightMode = parser.getBoolean(KEY_ENABLE_NIGHT_MODE,
901                     properties.getBoolean(KEY_ENABLE_NIGHT_MODE + configSuffix,
902                             defaultPolicy.enableNightMode));
903             final boolean enableQuickDoze = parser.getBoolean(KEY_ENABLE_QUICK_DOZE,
904                     properties.getBoolean(KEY_ENABLE_QUICK_DOZE + configSuffix,
905                             defaultPolicy.enableQuickDoze));
906             final boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY,
907                     properties.getBoolean(KEY_FORCE_ALL_APPS_STANDBY + configSuffix,
908                             defaultPolicy.forceAllAppsStandby));
909             final boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK,
910                     properties.getBoolean(KEY_FORCE_BACKGROUND_CHECK + configSuffix,
911                             defaultPolicy.forceBackgroundCheck));
912             final int locationMode = parser.getInt(KEY_LOCATION_MODE,
913                     properties.getInt(KEY_LOCATION_MODE + configSuffix,
914                             defaultPolicy.locationMode));
915             final int soundTriggerMode = parser.getInt(KEY_SOUNDTRIGGER_MODE,
916                     properties.getInt(KEY_SOUNDTRIGGER_MODE + configSuffix,
917                             defaultPolicy.soundTriggerMode));
918             return new Policy(
919                     adjustBrightnessFactor,
920                     advertiseIsEnabled,
921                     (new CpuFrequencies()).parseString(cpuFreqInteractive),
922                     (new CpuFrequencies()).parseString(cpuFreqNoninteractive),
923                     deferFullBackup,
924                     deferKeyValueBackup,
925                     disableAnimation,
926                     disableAod,
927                     disableLaunchBoost,
928                     disableOptionalSensors,
929                     /* disableVibration */
930                     disableVibrationConfig,
931                     enableBrightnessAdjustment,
932                     enableDataSaver,
933                     enableFirewall,
934                     enableNightMode,
935                     enableQuickDoze,
936                     forceAllAppsStandby,
937                     forceBackgroundCheck,
938                     locationMode,
939                     soundTriggerMode
940             );
941         }
942 
943         @Override
equals(Object obj)944         public boolean equals(Object obj) {
945             if (this == obj) return true;
946             if (!(obj instanceof Policy)) return false;
947             Policy other = (Policy) obj;
948             return Float.compare(other.adjustBrightnessFactor, adjustBrightnessFactor) == 0
949                     && advertiseIsEnabled == other.advertiseIsEnabled
950                     && deferFullBackup == other.deferFullBackup
951                     && deferKeyValueBackup == other.deferKeyValueBackup
952                     && disableAnimation == other.disableAnimation
953                     && disableAod == other.disableAod
954                     && disableLaunchBoost == other.disableLaunchBoost
955                     && disableOptionalSensors == other.disableOptionalSensors
956                     && disableVibration == other.disableVibration
957                     && enableAdjustBrightness == other.enableAdjustBrightness
958                     && enableDataSaver == other.enableDataSaver
959                     && enableFirewall == other.enableFirewall
960                     && enableNightMode == other.enableNightMode
961                     && enableQuickDoze == other.enableQuickDoze
962                     && forceAllAppsStandby == other.forceAllAppsStandby
963                     && forceBackgroundCheck == other.forceBackgroundCheck
964                     && locationMode == other.locationMode
965                     && soundTriggerMode == other.soundTriggerMode
966                     && cpuFrequenciesForInteractive.equals(other.cpuFrequenciesForInteractive)
967                     && cpuFrequenciesForNoninteractive.equals(
968                             other.cpuFrequenciesForNoninteractive);
969         }
970 
971         @Override
hashCode()972         public int hashCode() {
973             return mHashCode;
974         }
975     }
976 
977     /**
978      * Get the {@link PowerSaveState} based on the current policy level.
979      * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
980      * parameters when necessary.
981      *
982      * @param type   type of the service, one of {@link ServiceType}
983      * @return State data that contains battery saver data
984      */
getBatterySaverPolicy(@erviceType int type)985     public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
986         synchronized (mLock) {
987             final Policy currPolicy = getCurrentPolicyLocked();
988             final PowerSaveState.Builder builder = new PowerSaveState.Builder()
989                     .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
990             switch (type) {
991                 case ServiceType.LOCATION:
992                     boolean isEnabled = currPolicy.advertiseIsEnabled
993                             || currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE;
994                     return builder.setBatterySaverEnabled(isEnabled)
995                             .setLocationMode(currPolicy.locationMode)
996                             .build();
997                 case ServiceType.ANIMATION:
998                     return builder.setBatterySaverEnabled(currPolicy.disableAnimation)
999                             .build();
1000                 case ServiceType.FULL_BACKUP:
1001                     return builder.setBatterySaverEnabled(currPolicy.deferFullBackup)
1002                             .build();
1003                 case ServiceType.KEYVALUE_BACKUP:
1004                     return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup)
1005                             .build();
1006                 case ServiceType.NETWORK_FIREWALL:
1007                     return builder.setBatterySaverEnabled(currPolicy.enableFirewall)
1008                             .build();
1009                 case ServiceType.SCREEN_BRIGHTNESS:
1010                     return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
1011                             .setBrightnessFactor(currPolicy.adjustBrightnessFactor)
1012                             .build();
1013                 case ServiceType.DATA_SAVER:
1014                     return builder.setBatterySaverEnabled(currPolicy.enableDataSaver)
1015                             .build();
1016                 case ServiceType.SOUND:
1017                     boolean soundTriggerBatterySaverEnabled = currPolicy.advertiseIsEnabled
1018                             || currPolicy.soundTriggerMode
1019                             != PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED;
1020                     return builder.setBatterySaverEnabled(soundTriggerBatterySaverEnabled)
1021                             .setSoundTriggerMode(currPolicy.soundTriggerMode)
1022                             .build();
1023                 case ServiceType.VIBRATION:
1024                     return builder.setBatterySaverEnabled(currPolicy.disableVibration)
1025                             .build();
1026                 case ServiceType.FORCE_ALL_APPS_STANDBY:
1027                     return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
1028                             .build();
1029                 case ServiceType.FORCE_BACKGROUND_CHECK:
1030                     return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck)
1031                             .build();
1032                 case ServiceType.NIGHT_MODE:
1033                     return builder.setBatterySaverEnabled(currPolicy.enableNightMode)
1034                             .build();
1035                 case ServiceType.OPTIONAL_SENSORS:
1036                     return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors)
1037                             .build();
1038                 case ServiceType.AOD:
1039                     return builder.setBatterySaverEnabled(currPolicy.disableAod)
1040                             .build();
1041                 case ServiceType.QUICK_DOZE:
1042                     return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze)
1043                             .build();
1044                 default:
1045                     return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled)
1046                             .build();
1047             }
1048         }
1049     }
1050 
1051     /**
1052      * Sets the current policy.
1053      *
1054      * @return true if the policy level was changed.
1055      */
setPolicyLevel(@olicyLevel int level)1056     boolean setPolicyLevel(@PolicyLevel int level) {
1057         synchronized (mLock) {
1058             if (mPolicyLevel == level) {
1059                 return false;
1060             }
1061             // If we are leaving the full policy level, then any overrides to the full policy set
1062             // through #setFullPolicyLocked should be cleared.
1063             if (mPolicyLevel == POLICY_LEVEL_FULL) {
1064                 mFullPolicy = mDefaultFullPolicy;
1065             }
1066             switch (level) {
1067                 case POLICY_LEVEL_FULL:
1068                 case POLICY_LEVEL_ADAPTIVE:
1069                 case POLICY_LEVEL_OFF:
1070                     mPolicyLevel = level;
1071                     break;
1072                 default:
1073                     Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level);
1074                     return false;
1075             }
1076             updatePolicyDependenciesLocked();
1077             return true;
1078         }
1079     }
1080 
1081     /**
1082      * Get the current policy for the provided policy level.
1083      */
getPolicyLocked(@olicyLevel int policyLevel)1084     Policy getPolicyLocked(@PolicyLevel int policyLevel) {
1085         switch (policyLevel) {
1086             case POLICY_LEVEL_OFF:
1087                 return OFF_POLICY;
1088             case POLICY_LEVEL_ADAPTIVE:
1089                 return mAdaptivePolicy;
1090             case POLICY_LEVEL_FULL:
1091                 return mFullPolicy;
1092         }
1093 
1094         throw new IllegalArgumentException(
1095                 "getPolicyLocked: incorrect policy level provided - " + policyLevel);
1096     }
1097 
1098     /**
1099      * Updates the default policy with the passed in policy.
1100      * If the full policy is not overridden with runtime settings, then the full policy will be
1101      * updated.
1102      *
1103      * @return True if the active policy requires an update, false if not.
1104      */
maybeUpdateDefaultFullPolicy(Policy p)1105     private boolean maybeUpdateDefaultFullPolicy(Policy p) {
1106         boolean fullPolicyChanged = false;
1107         if (!mDefaultFullPolicy.equals(p)) {
1108             // default policy can be overridden by #setFullPolicyLocked
1109             boolean isDefaultFullPolicyOverridden = !mDefaultFullPolicy.equals(mFullPolicy);
1110             if (!isDefaultFullPolicyOverridden) {
1111                 mFullPolicy = p;
1112                 fullPolicyChanged = (mPolicyLevel == POLICY_LEVEL_FULL);
1113             }
1114             mDefaultFullPolicy = p;
1115         }
1116         return fullPolicyChanged;
1117     }
1118 
1119     /** @return true if the current policy changed and the policy level is FULL. */
setFullPolicyLocked(Policy p)1120     boolean setFullPolicyLocked(Policy p) {
1121         if (p == null) {
1122             Slog.wtf(TAG, "setFullPolicy given null policy");
1123             return false;
1124         }
1125         if (mFullPolicy.equals(p)) {
1126             return false;
1127         }
1128 
1129         mFullPolicy = p;
1130         if (mPolicyLevel == POLICY_LEVEL_FULL) {
1131             updatePolicyDependenciesLocked();
1132             return true;
1133         }
1134         return false;
1135     }
1136 
1137     /** @return true if the current policy changed and the policy level is ADAPTIVE. */
setAdaptivePolicyLocked(Policy p)1138     boolean setAdaptivePolicyLocked(Policy p) {
1139         if (p == null) {
1140             Slog.wtf(TAG, "setAdaptivePolicy given null policy");
1141             return false;
1142         }
1143         if (mAdaptivePolicy.equals(p)) {
1144             return false;
1145         }
1146 
1147         mAdaptivePolicy = p;
1148         if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE) {
1149             updatePolicyDependenciesLocked();
1150             return true;
1151         }
1152         return false;
1153     }
1154 
1155     /** @return true if the current policy changed and the policy level is ADAPTIVE. */
resetAdaptivePolicyLocked()1156     boolean resetAdaptivePolicyLocked() {
1157         return setAdaptivePolicyLocked(mDefaultAdaptivePolicy);
1158     }
1159 
getCurrentPolicyLocked()1160     private Policy getCurrentPolicyLocked() {
1161         return mEffectivePolicyRaw;
1162     }
1163 
getCurrentRawPolicyLocked()1164     private Policy getCurrentRawPolicyLocked() {
1165         switch (mPolicyLevel) {
1166             case POLICY_LEVEL_FULL:
1167                 return mFullPolicy;
1168             case POLICY_LEVEL_ADAPTIVE:
1169                 return mAdaptivePolicy;
1170             case POLICY_LEVEL_OFF:
1171             default:
1172                 return OFF_POLICY;
1173         }
1174     }
1175 
getGpsMode()1176     public int getGpsMode() {
1177         synchronized (mLock) {
1178             return getCurrentPolicyLocked().locationMode;
1179         }
1180     }
1181 
getFileValues(boolean interactive)1182     public ArrayMap<String, String> getFileValues(boolean interactive) {
1183         synchronized (mLock) {
1184             return interactive
1185                     ? getCurrentPolicyLocked().cpuFrequenciesForInteractive.toSysFileMap()
1186                     : getCurrentPolicyLocked().cpuFrequenciesForNoninteractive.toSysFileMap();
1187         }
1188     }
1189 
isLaunchBoostDisabled()1190     public boolean isLaunchBoostDisabled() {
1191         synchronized (mLock) {
1192             return getCurrentPolicyLocked().disableLaunchBoost;
1193         }
1194     }
1195 
shouldAdvertiseIsEnabled()1196     boolean shouldAdvertiseIsEnabled() {
1197         synchronized (mLock) {
1198             return getCurrentPolicyLocked().advertiseIsEnabled;
1199         }
1200     }
1201 
toEventLogString()1202     public String toEventLogString() {
1203         synchronized (mLock) {
1204             return mEventLogKeys;
1205         }
1206     }
1207 
dump(PrintWriter pw)1208     public void dump(PrintWriter pw) {
1209         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
1210 
1211         synchronized (mLock) {
1212             ipw.println();
1213             mBatterySavingStats.dump(ipw);
1214 
1215             ipw.println();
1216             ipw.println("Battery saver policy (*NOTE* they only apply when battery saver is ON):");
1217             ipw.increaseIndent();
1218             ipw.println("Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS);
1219             ipw.increaseIndent();
1220             ipw.println("value: " + mSettings);
1221             ipw.decreaseIndent();
1222             ipw.println("Settings: " + mDeviceSpecificSettingsSource);
1223             ipw.increaseIndent();
1224             ipw.println("value: " + mDeviceSpecificSettings);
1225             ipw.decreaseIndent();
1226             ipw.println("DeviceConfig: " + DeviceConfig.NAMESPACE_BATTERY_SAVER);
1227             ipw.increaseIndent();
1228             final Set<String> keys = mLastDeviceConfigProperties.getKeyset();
1229             if (keys.size() == 0) {
1230                 ipw.println("N/A");
1231             } else {
1232                 for (final String key : keys) {
1233                     ipw.print(key);
1234                     ipw.print(": ");
1235                     ipw.println(mLastDeviceConfigProperties.getString(key, null));
1236                 }
1237             }
1238             ipw.decreaseIndent();
1239 
1240             ipw.println("mAccessibilityEnabled=" + mAccessibilityEnabled.get());
1241             ipw.println("mAutomotiveProjectionActive=" + mAutomotiveProjectionActive.get());
1242             ipw.println("mPolicyLevel=" + mPolicyLevel);
1243 
1244             dumpPolicyLocked(ipw, "default full", mDefaultFullPolicy);
1245             dumpPolicyLocked(ipw, "current full", mFullPolicy);
1246             dumpPolicyLocked(ipw, "default adaptive", mDefaultAdaptivePolicy);
1247             dumpPolicyLocked(ipw, "current adaptive", mAdaptivePolicy);
1248             dumpPolicyLocked(ipw, "effective", mEffectivePolicyRaw);
1249 
1250             ipw.decreaseIndent();
1251         }
1252     }
1253 
dumpPolicyLocked(IndentingPrintWriter pw, String label, Policy p)1254     private void dumpPolicyLocked(IndentingPrintWriter pw, String label, Policy p) {
1255         pw.println();
1256         pw.println("Policy '" + label + "'");
1257         pw.increaseIndent();
1258         pw.println(KEY_ADVERTISE_IS_ENABLED + "=" + p.advertiseIsEnabled);
1259         pw.println(KEY_DISABLE_VIBRATION + "=" + p.disableVibration);
1260         pw.println(KEY_DISABLE_ANIMATION + "=" + p.disableAnimation);
1261         pw.println(KEY_DEFER_FULL_BACKUP + "=" + p.deferFullBackup);
1262         pw.println(KEY_DEFER_KEYVALUE_BACKUP + "=" + p.deferKeyValueBackup);
1263         pw.println(KEY_ENABLE_FIREWALL + "=" + p.enableFirewall);
1264         pw.println(KEY_ENABLE_DATASAVER + "=" + p.enableDataSaver);
1265         pw.println(KEY_DISABLE_LAUNCH_BOOST + "=" + p.disableLaunchBoost);
1266         pw.println(KEY_ENABLE_BRIGHTNESS_ADJUSTMENT + "=" + p.enableAdjustBrightness);
1267         pw.println(KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor);
1268         pw.println(KEY_LOCATION_MODE + "=" + p.locationMode);
1269         pw.println(KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby);
1270         pw.println(KEY_FORCE_BACKGROUND_CHECK + "=" + p.forceBackgroundCheck);
1271         pw.println(KEY_DISABLE_OPTIONAL_SENSORS + "=" + p.disableOptionalSensors);
1272         pw.println(KEY_DISABLE_AOD + "=" + p.disableAod);
1273         pw.println(KEY_SOUNDTRIGGER_MODE + "=" + p.soundTriggerMode);
1274         pw.println(KEY_ENABLE_QUICK_DOZE + "=" + p.enableQuickDoze);
1275         pw.println(KEY_ENABLE_NIGHT_MODE + "=" + p.enableNightMode);
1276 
1277         pw.println("Interactive File values:");
1278         pw.increaseIndent();
1279         dumpMap(pw, p.cpuFrequenciesForInteractive.toSysFileMap());
1280         pw.decreaseIndent();
1281         pw.println();
1282 
1283         pw.println("Noninteractive File values:");
1284         pw.increaseIndent();
1285         dumpMap(pw, p.cpuFrequenciesForNoninteractive.toSysFileMap());
1286         pw.decreaseIndent();
1287 
1288         // Decrease from indent right after "Policy" line
1289         pw.decreaseIndent();
1290     }
1291 
dumpMap(PrintWriter pw, ArrayMap<String, String> map)1292     private void dumpMap(PrintWriter pw, ArrayMap<String, String> map) {
1293         if (map == null || map.size() == 0) {
1294             pw.println("N/A");
1295             return;
1296         }
1297         final int size = map.size();
1298         for (int i = 0; i < size; i++) {
1299             pw.print(map.keyAt(i));
1300             pw.print(": '");
1301             pw.print(map.valueAt(i));
1302             pw.println("'");
1303         }
1304     }
1305 
1306     /**
1307      * A boolean value which should trigger a policy update when it changes.
1308      */
1309     @VisibleForTesting
1310     class PolicyBoolean {
1311         private final String mDebugName;
1312         @GuardedBy("mLock")
1313         private boolean mValue;
1314 
PolicyBoolean(String debugName)1315         private PolicyBoolean(String debugName) {
1316             mDebugName = debugName;
1317         }
1318 
1319         /** Sets the initial value without triggering a policy update. */
initialize(boolean initialValue)1320         private void initialize(boolean initialValue) {
1321             synchronized (mLock) {
1322                 mValue = initialValue;
1323             }
1324         }
1325 
get()1326         private boolean get() {
1327             synchronized (mLock) {
1328                 return mValue;
1329             }
1330         }
1331 
1332         /** Sets a value, which if different from the current value, triggers a policy update. */
1333         @VisibleForTesting
update(boolean newValue)1334         void update(boolean newValue) {
1335             synchronized (mLock) {
1336                 if (mValue != newValue) {
1337                     Slog.d(TAG, mDebugName + " changed to " + newValue + ", updating policy.");
1338                     mValue = newValue;
1339                     updatePolicyDependenciesLocked();
1340                     maybeNotifyListenersOfPolicyChange();
1341                 }
1342             }
1343         }
1344     }
1345 }
1346