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     /** @deprecated Old key used to set CPU frequency caps directly in sys files. */
133     @Deprecated
134     private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i";
135     /** @deprecated Old key used to set CPU frequency caps directly in sys files. */
136     @Deprecated
137     private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n";
138 
139     private static final String KEY_SUFFIX_ADAPTIVE = "_adaptive";
140 
141     @VisibleForTesting
142     static final Policy OFF_POLICY = new Policy(
143             1f,    /* adjustBrightnessFactor */
144             false, /* advertiseIsEnabled */
145             false, /* deferFullBackup */
146             false, /* deferKeyValueBackup */
147             false, /* disableAnimation */
148             false, /* disableAod */
149             false, /* disableLaunchBoost */
150             false, /* disableOptionalSensors */
151             false, /* disableVibration */
152             false, /* enableAdjustBrightness */
153             false, /* enableDataSaver */
154             false, /* enableFireWall */
155             false, /* enableNightMode */
156             false, /* enableQuickDoze */
157             false, /* forceAllAppsStandby */
158             false, /* forceBackgroundCheck */
159             PowerManager.LOCATION_MODE_NO_CHANGE, /* locationMode */
160             PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED /* soundTriggerMode */
161     );
162 
163     private static final Policy DEFAULT_ADAPTIVE_POLICY = OFF_POLICY;
164 
165     private static final Policy DEFAULT_FULL_POLICY = new Policy(
166             0.5f,  /* adjustBrightnessFactor */
167             true,  /* advertiseIsEnabled */
168             true,  /* deferFullBackup */
169             true,  /* deferKeyValueBackup */
170             false, /* disableAnimation */
171             true,  /* disableAod */
172             true,  /* disableLaunchBoost */
173             true,  /* disableOptionalSensors */
174             false,  /* 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#onBootPhase}, *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.deferFullBackup,
491                 rawPolicy.deferKeyValueBackup,
492                 rawPolicy.disableAnimation,
493                 rawPolicy.disableAod,
494                 rawPolicy.disableLaunchBoost,
495                 rawPolicy.disableOptionalSensors,
496                 // Don't disable vibration when accessibility is on.
497                 rawPolicy.disableVibration && !mAccessibilityEnabled.get(),
498                 rawPolicy.enableAdjustBrightness,
499                 rawPolicy.enableDataSaver,
500                 rawPolicy.enableFirewall,
501                 // Don't force night mode when car projection is enabled.
502                 rawPolicy.enableNightMode && !mAutomotiveProjectionActive.get(),
503                 rawPolicy.enableQuickDoze,
504                 rawPolicy.forceAllAppsStandby,
505                 rawPolicy.forceBackgroundCheck,
506                 locationMode,
507                 rawPolicy.soundTriggerMode
508         );
509 
510 
511         final StringBuilder sb = new StringBuilder();
512 
513         if (mEffectivePolicyRaw.forceAllAppsStandby) sb.append("A");
514         if (mEffectivePolicyRaw.forceBackgroundCheck) sb.append("B");
515 
516         if (mEffectivePolicyRaw.disableVibration) sb.append("v");
517         if (mEffectivePolicyRaw.disableAnimation) sb.append("a");
518 
519         sb.append(mEffectivePolicyRaw.soundTriggerMode);
520 
521         if (mEffectivePolicyRaw.deferFullBackup) sb.append("F");
522         if (mEffectivePolicyRaw.deferKeyValueBackup) sb.append("K");
523         if (mEffectivePolicyRaw.enableFirewall) sb.append("f");
524         if (mEffectivePolicyRaw.enableDataSaver) sb.append("d");
525         if (mEffectivePolicyRaw.enableAdjustBrightness) sb.append("b");
526 
527         if (mEffectivePolicyRaw.disableLaunchBoost) sb.append("l");
528         if (mEffectivePolicyRaw.disableOptionalSensors) sb.append("S");
529         if (mEffectivePolicyRaw.disableAod) sb.append("o");
530         if (mEffectivePolicyRaw.enableQuickDoze) sb.append("q");
531 
532         sb.append(mEffectivePolicyRaw.locationMode);
533 
534         mEventLogKeys = sb.toString();
535     }
536 
537     static class Policy {
538         /**
539          * This is the flag to decide the how much to adjust the screen brightness. This is
540          * the float value from 0 to 1 where 1 means don't change brightness.
541          *
542          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
543          * @see #KEY_ADJUST_BRIGHTNESS_FACTOR
544          */
545         public final float adjustBrightnessFactor;
546 
547         /**
548          * {@code true} if the Policy should advertise to the rest of the system that battery saver
549          * is enabled. This advertising could cause other system components to change their
550          * behavior. This will not affect other policy flags and what they change.
551          *
552          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
553          * @see #KEY_ADVERTISE_IS_ENABLED
554          */
555         public final boolean advertiseIsEnabled;
556 
557         /**
558          * {@code true} if full backup is deferred in battery saver mode.
559          *
560          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
561          * @see #KEY_DEFER_FULL_BACKUP
562          */
563         public final boolean deferFullBackup;
564 
565         /**
566          * {@code true} if key value backup is deferred in battery saver mode.
567          *
568          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
569          * @see #KEY_DEFER_KEYVALUE_BACKUP
570          */
571         public final boolean deferKeyValueBackup;
572 
573         /**
574          * {@code true} if animation is disabled in battery saver mode.
575          *
576          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
577          * @see #KEY_DISABLE_ANIMATION
578          */
579         public final boolean disableAnimation;
580 
581         /**
582          * {@code true} if AOD is disabled in battery saver mode.
583          */
584         public final boolean disableAod;
585 
586         /**
587          * {@code true} if launch boost should be disabled on battery saver.
588          */
589         public final boolean disableLaunchBoost;
590 
591         /**
592          * Whether to show non-essential sensors (e.g. edge sensors) or not.
593          */
594         public final boolean disableOptionalSensors;
595 
596         /**
597          * {@code true} if sound trigger is disabled in battery saver mode
598          * in battery saver mode.
599          *
600          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
601          * @see #KEY_SOUNDTRIGGER_MODE
602          */
603         public final int soundTriggerMode;
604 
605         /**
606          * {@code true} if vibration is disabled in battery saver mode.
607          *
608          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
609          * @see #KEY_DISABLE_VIBRATION
610          */
611         public final boolean disableVibration;
612 
613         /**
614          * {@code true} if low power mode brightness adjustment should be turned on in battery saver
615          * mode.
616          *
617          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
618          * @see #KEY_ENABLE_BRIGHTNESS_ADJUSTMENT
619          */
620         public final boolean enableAdjustBrightness;
621 
622         /**
623          * {@code true} if data saver should be turned on in battery saver mode.
624          *
625          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
626          * @see #KEY_ENABLE_DATASAVER
627          */
628         public final boolean enableDataSaver;
629 
630         /**
631          * {@code true} if network policy firewall should be turned on in battery saver mode.
632          *
633          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
634          * @see #KEY_ENABLE_FIREWALL
635          */
636         public final boolean enableFirewall;
637 
638         /**
639          * Whether to enable night mode or not.
640          */
641         public final boolean enableNightMode;
642 
643         /**
644          * Whether Quick Doze is enabled or not.
645          */
646         public final boolean enableQuickDoze;
647 
648         /**
649          * Whether to put all apps in the stand-by mode.
650          */
651         public final boolean forceAllAppsStandby;
652 
653         /**
654          * Whether to force background check.
655          */
656         public final boolean forceBackgroundCheck;
657 
658         /**
659          * This is the flag to decide the location mode in battery saver mode. This was
660          * previously called gpsMode.
661          *
662          * @see Settings.Global#BATTERY_SAVER_CONSTANTS
663          * @see #KEY_LOCATION_MODE
664          */
665         public final int locationMode;
666 
667         private final int mHashCode;
668 
Policy( float adjustBrightnessFactor, boolean advertiseIsEnabled, 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)669         Policy(
670                 float adjustBrightnessFactor,
671                 boolean advertiseIsEnabled,
672                 boolean deferFullBackup,
673                 boolean deferKeyValueBackup,
674                 boolean disableAnimation,
675                 boolean disableAod,
676                 boolean disableLaunchBoost,
677                 boolean disableOptionalSensors,
678                 boolean disableVibration,
679                 boolean enableAdjustBrightness,
680                 boolean enableDataSaver,
681                 boolean enableFirewall,
682                 boolean enableNightMode,
683                 boolean enableQuickDoze,
684                 boolean forceAllAppsStandby,
685                 boolean forceBackgroundCheck,
686                 int locationMode,
687                 int soundTriggerMode) {
688 
689             this.adjustBrightnessFactor = Math.min(1, Math.max(0, adjustBrightnessFactor));
690             this.advertiseIsEnabled = advertiseIsEnabled;
691             this.deferFullBackup = deferFullBackup;
692             this.deferKeyValueBackup = deferKeyValueBackup;
693             this.disableAnimation = disableAnimation;
694             this.disableAod = disableAod;
695             this.disableLaunchBoost = disableLaunchBoost;
696             this.disableOptionalSensors = disableOptionalSensors;
697             this.disableVibration = disableVibration;
698             this.enableAdjustBrightness = enableAdjustBrightness;
699             this.enableDataSaver = enableDataSaver;
700             this.enableFirewall = enableFirewall;
701             this.enableNightMode = enableNightMode;
702             this.enableQuickDoze = enableQuickDoze;
703             this.forceAllAppsStandby = forceAllAppsStandby;
704             this.forceBackgroundCheck = forceBackgroundCheck;
705 
706             if (locationMode < PowerManager.MIN_LOCATION_MODE
707                     || PowerManager.MAX_LOCATION_MODE < locationMode) {
708                 Slog.e(TAG, "Invalid location mode: " + locationMode);
709                 this.locationMode = PowerManager.LOCATION_MODE_NO_CHANGE;
710             } else {
711                 this.locationMode = locationMode;
712             }
713 
714             if (soundTriggerMode < PowerManager.MIN_SOUND_TRIGGER_MODE
715                     || soundTriggerMode > PowerManager.MAX_SOUND_TRIGGER_MODE) {
716                 Slog.e(TAG, "Invalid SoundTrigger mode: " + soundTriggerMode);
717                 this.soundTriggerMode = PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED;
718             } else {
719                 this.soundTriggerMode = soundTriggerMode;
720             }
721 
722             mHashCode = Objects.hash(
723                     adjustBrightnessFactor,
724                     advertiseIsEnabled,
725                     deferFullBackup,
726                     deferKeyValueBackup,
727                     disableAnimation,
728                     disableAod,
729                     disableLaunchBoost,
730                     disableOptionalSensors,
731                     disableVibration,
732                     enableAdjustBrightness,
733                     enableDataSaver,
734                     enableFirewall,
735                     enableNightMode,
736                     enableQuickDoze,
737                     forceAllAppsStandby,
738                     forceBackgroundCheck,
739                     locationMode,
740                     soundTriggerMode);
741         }
742 
fromConfig(BatterySaverPolicyConfig config)743         static Policy fromConfig(BatterySaverPolicyConfig config) {
744             if (config == null) {
745                 Slog.e(TAG, "Null config passed down to BatterySaverPolicy");
746                 return OFF_POLICY;
747             }
748 
749             // Device-specific parameters.
750             Map<String, String> deviceSpecificSettings = config.getDeviceSpecificSettings();
751 
752             return new Policy(
753                     config.getAdjustBrightnessFactor(),
754                     config.getAdvertiseIsEnabled(),
755                     config.getDeferFullBackup(),
756                     config.getDeferKeyValueBackup(),
757                     config.getDisableAnimation(),
758                     config.getDisableAod(),
759                     config.getDisableLaunchBoost(),
760                     config.getDisableOptionalSensors(),
761                     config.getDisableVibration(),
762                     config.getEnableAdjustBrightness(),
763                     config.getEnableDataSaver(),
764                     config.getEnableFirewall(),
765                     config.getEnableNightMode(),
766                     config.getEnableQuickDoze(),
767                     config.getForceAllAppsStandby(),
768                     config.getForceBackgroundCheck(),
769                     config.getLocationMode(),
770                     config.getSoundTriggerMode()
771             );
772         }
773 
toConfig()774         BatterySaverPolicyConfig toConfig() {
775             return new BatterySaverPolicyConfig.Builder()
776                     .setAdjustBrightnessFactor(adjustBrightnessFactor)
777                     .setAdvertiseIsEnabled(advertiseIsEnabled)
778                     .setDeferFullBackup(deferFullBackup)
779                     .setDeferKeyValueBackup(deferKeyValueBackup)
780                     .setDisableAnimation(disableAnimation)
781                     .setDisableAod(disableAod)
782                     .setDisableLaunchBoost(disableLaunchBoost)
783                     .setDisableOptionalSensors(disableOptionalSensors)
784                     .setDisableVibration(disableVibration)
785                     .setEnableAdjustBrightness(enableAdjustBrightness)
786                     .setEnableDataSaver(enableDataSaver)
787                     .setEnableFirewall(enableFirewall)
788                     .setEnableNightMode(enableNightMode)
789                     .setEnableQuickDoze(enableQuickDoze)
790                     .setForceAllAppsStandby(forceAllAppsStandby)
791                     .setForceBackgroundCheck(forceBackgroundCheck)
792                     .setLocationMode(locationMode)
793                     .setSoundTriggerMode(soundTriggerMode)
794                     .build();
795         }
796 
797         @VisibleForTesting
fromSettings(String settings, String deviceSpecificSettings, DeviceConfig.Properties properties, String configSuffix)798         static Policy fromSettings(String settings, String deviceSpecificSettings,
799                 DeviceConfig.Properties properties, String configSuffix) {
800             return fromSettings(settings, deviceSpecificSettings, properties, configSuffix,
801                     OFF_POLICY);
802         }
803 
fromSettings(String settings, String deviceSpecificSettings, DeviceConfig.Properties properties, String configSuffix, Policy defaultPolicy)804         private static Policy fromSettings(String settings, String deviceSpecificSettings,
805                 DeviceConfig.Properties properties, String configSuffix, Policy defaultPolicy) {
806             final KeyValueListParser parser = new KeyValueListParser(',');
807             configSuffix = TextUtils.emptyIfNull(configSuffix);
808 
809             // Device-specific parameters.
810             try {
811                 parser.setString(deviceSpecificSettings == null ? "" : deviceSpecificSettings);
812             } catch (IllegalArgumentException e) {
813                 Slog.wtf(TAG, "Bad device specific battery saver constants: "
814                         + deviceSpecificSettings);
815             }
816 
817             // Non-device-specific parameters.
818             try {
819                 parser.setString(settings == null ? "" : settings);
820             } catch (IllegalArgumentException e) {
821                 Slog.wtf(TAG, "Bad battery saver constants: " + settings);
822             }
823 
824             // The Settings value overrides everything, since that will be set by the user.
825             // The DeviceConfig value takes second place, with the default as the last choice.
826             final float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR,
827                     properties.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR + configSuffix,
828                             defaultPolicy.adjustBrightnessFactor));
829             final boolean advertiseIsEnabled = parser.getBoolean(KEY_ADVERTISE_IS_ENABLED,
830                     properties.getBoolean(KEY_ADVERTISE_IS_ENABLED + configSuffix,
831                             defaultPolicy.advertiseIsEnabled));
832             final boolean deferFullBackup = parser.getBoolean(KEY_DEFER_FULL_BACKUP,
833                     properties.getBoolean(KEY_DEFER_FULL_BACKUP + configSuffix,
834                             defaultPolicy.deferFullBackup));
835             final boolean deferKeyValueBackup = parser.getBoolean(KEY_DEFER_KEYVALUE_BACKUP,
836                     properties.getBoolean(KEY_DEFER_KEYVALUE_BACKUP + configSuffix,
837                             defaultPolicy.deferKeyValueBackup));
838             final boolean disableAnimation = parser.getBoolean(KEY_DISABLE_ANIMATION,
839                     properties.getBoolean(KEY_DISABLE_ANIMATION + configSuffix,
840                             defaultPolicy.disableAnimation));
841             final boolean disableAod = parser.getBoolean(KEY_DISABLE_AOD,
842                     properties.getBoolean(KEY_DISABLE_AOD + configSuffix,
843                             defaultPolicy.disableAod));
844             final boolean disableLaunchBoost = parser.getBoolean(KEY_DISABLE_LAUNCH_BOOST,
845                     properties.getBoolean(KEY_DISABLE_LAUNCH_BOOST + configSuffix,
846                             defaultPolicy.disableLaunchBoost));
847             final boolean disableOptionalSensors = parser.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS,
848                     properties.getBoolean(KEY_DISABLE_OPTIONAL_SENSORS + configSuffix,
849                             defaultPolicy.disableOptionalSensors));
850             final boolean disableVibrationConfig = parser.getBoolean(KEY_DISABLE_VIBRATION,
851                     properties.getBoolean(KEY_DISABLE_VIBRATION + configSuffix,
852                             defaultPolicy.disableVibration));
853             final boolean enableBrightnessAdjustment = parser.getBoolean(
854                     KEY_ENABLE_BRIGHTNESS_ADJUSTMENT,
855                     properties.getBoolean(KEY_ENABLE_BRIGHTNESS_ADJUSTMENT + configSuffix,
856                             defaultPolicy.enableAdjustBrightness));
857             final boolean enableDataSaver = parser.getBoolean(KEY_ENABLE_DATASAVER,
858                     properties.getBoolean(KEY_ENABLE_DATASAVER + configSuffix,
859                             defaultPolicy.enableDataSaver));
860             final boolean enableFirewall = parser.getBoolean(KEY_ENABLE_FIREWALL,
861                     properties.getBoolean(KEY_ENABLE_FIREWALL + configSuffix,
862                             defaultPolicy.enableFirewall));
863             final boolean enableNightMode = parser.getBoolean(KEY_ENABLE_NIGHT_MODE,
864                     properties.getBoolean(KEY_ENABLE_NIGHT_MODE + configSuffix,
865                             defaultPolicy.enableNightMode));
866             final boolean enableQuickDoze = parser.getBoolean(KEY_ENABLE_QUICK_DOZE,
867                     properties.getBoolean(KEY_ENABLE_QUICK_DOZE + configSuffix,
868                             defaultPolicy.enableQuickDoze));
869             final boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY,
870                     properties.getBoolean(KEY_FORCE_ALL_APPS_STANDBY + configSuffix,
871                             defaultPolicy.forceAllAppsStandby));
872             final boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK,
873                     properties.getBoolean(KEY_FORCE_BACKGROUND_CHECK + configSuffix,
874                             defaultPolicy.forceBackgroundCheck));
875             final int locationMode = parser.getInt(KEY_LOCATION_MODE,
876                     properties.getInt(KEY_LOCATION_MODE + configSuffix,
877                             defaultPolicy.locationMode));
878             final int soundTriggerMode = parser.getInt(KEY_SOUNDTRIGGER_MODE,
879                     properties.getInt(KEY_SOUNDTRIGGER_MODE + configSuffix,
880                             defaultPolicy.soundTriggerMode));
881             return new Policy(
882                     adjustBrightnessFactor,
883                     advertiseIsEnabled,
884                     deferFullBackup,
885                     deferKeyValueBackup,
886                     disableAnimation,
887                     disableAod,
888                     disableLaunchBoost,
889                     disableOptionalSensors,
890                     /* disableVibration */
891                     disableVibrationConfig,
892                     enableBrightnessAdjustment,
893                     enableDataSaver,
894                     enableFirewall,
895                     enableNightMode,
896                     enableQuickDoze,
897                     forceAllAppsStandby,
898                     forceBackgroundCheck,
899                     locationMode,
900                     soundTriggerMode
901             );
902         }
903 
904         @Override
equals(Object obj)905         public boolean equals(Object obj) {
906             if (this == obj) return true;
907             if (!(obj instanceof Policy)) return false;
908             Policy other = (Policy) obj;
909             return Float.compare(other.adjustBrightnessFactor, adjustBrightnessFactor) == 0
910                     && advertiseIsEnabled == other.advertiseIsEnabled
911                     && deferFullBackup == other.deferFullBackup
912                     && deferKeyValueBackup == other.deferKeyValueBackup
913                     && disableAnimation == other.disableAnimation
914                     && disableAod == other.disableAod
915                     && disableLaunchBoost == other.disableLaunchBoost
916                     && disableOptionalSensors == other.disableOptionalSensors
917                     && disableVibration == other.disableVibration
918                     && enableAdjustBrightness == other.enableAdjustBrightness
919                     && enableDataSaver == other.enableDataSaver
920                     && enableFirewall == other.enableFirewall
921                     && enableNightMode == other.enableNightMode
922                     && enableQuickDoze == other.enableQuickDoze
923                     && forceAllAppsStandby == other.forceAllAppsStandby
924                     && forceBackgroundCheck == other.forceBackgroundCheck
925                     && locationMode == other.locationMode
926                     && soundTriggerMode == other.soundTriggerMode;
927         }
928 
929         @Override
hashCode()930         public int hashCode() {
931             return mHashCode;
932         }
933     }
934 
935     /**
936      * Get the {@link PowerSaveState} based on the current policy level.
937      * The result will have {@link PowerSaveState#batterySaverEnabled} and some other
938      * parameters when necessary.
939      *
940      * @param type   type of the service, one of {@link ServiceType}
941      * @return State data that contains battery saver data
942      */
getBatterySaverPolicy(@erviceType int type)943     public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
944         synchronized (mLock) {
945             final Policy currPolicy = getCurrentPolicyLocked();
946             final PowerSaveState.Builder builder = new PowerSaveState.Builder()
947                     .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
948             switch (type) {
949                 case ServiceType.LOCATION:
950                     boolean isEnabled = currPolicy.advertiseIsEnabled
951                             || currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE;
952                     return builder.setBatterySaverEnabled(isEnabled)
953                             .setLocationMode(currPolicy.locationMode)
954                             .build();
955                 case ServiceType.ANIMATION:
956                     return builder.setBatterySaverEnabled(currPolicy.disableAnimation)
957                             .build();
958                 case ServiceType.FULL_BACKUP:
959                     return builder.setBatterySaverEnabled(currPolicy.deferFullBackup)
960                             .build();
961                 case ServiceType.KEYVALUE_BACKUP:
962                     return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup)
963                             .build();
964                 case ServiceType.NETWORK_FIREWALL:
965                     return builder.setBatterySaverEnabled(currPolicy.enableFirewall)
966                             .build();
967                 case ServiceType.SCREEN_BRIGHTNESS:
968                     return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
969                             .setBrightnessFactor(currPolicy.adjustBrightnessFactor)
970                             .build();
971                 case ServiceType.DATA_SAVER:
972                     return builder.setBatterySaverEnabled(currPolicy.enableDataSaver)
973                             .build();
974                 case ServiceType.SOUND:
975                     boolean soundTriggerBatterySaverEnabled = currPolicy.advertiseIsEnabled
976                             || currPolicy.soundTriggerMode
977                             != PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED;
978                     return builder.setBatterySaverEnabled(soundTriggerBatterySaverEnabled)
979                             .setSoundTriggerMode(currPolicy.soundTriggerMode)
980                             .build();
981                 case ServiceType.VIBRATION:
982                     return builder.setBatterySaverEnabled(currPolicy.disableVibration)
983                             .build();
984                 case ServiceType.FORCE_ALL_APPS_STANDBY:
985                     return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
986                             .build();
987                 case ServiceType.FORCE_BACKGROUND_CHECK:
988                     return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck)
989                             .build();
990                 case ServiceType.NIGHT_MODE:
991                     return builder.setBatterySaverEnabled(currPolicy.enableNightMode)
992                             .build();
993                 case ServiceType.OPTIONAL_SENSORS:
994                     return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors)
995                             .build();
996                 case ServiceType.AOD:
997                     return builder.setBatterySaverEnabled(currPolicy.disableAod)
998                             .build();
999                 case ServiceType.QUICK_DOZE:
1000                     return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze)
1001                             .build();
1002                 default:
1003                     return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled)
1004                             .build();
1005             }
1006         }
1007     }
1008 
1009     /**
1010      * Sets the current policy.
1011      *
1012      * @return true if the policy level was changed.
1013      */
setPolicyLevel(@olicyLevel int level)1014     boolean setPolicyLevel(@PolicyLevel int level) {
1015         synchronized (mLock) {
1016             if (mPolicyLevel == level) {
1017                 return false;
1018             }
1019             // If we are leaving the full policy level, then any overrides to the full policy set
1020             // through #setFullPolicyLocked should be cleared.
1021             if (mPolicyLevel == POLICY_LEVEL_FULL) {
1022                 mFullPolicy = mDefaultFullPolicy;
1023             }
1024             switch (level) {
1025                 case POLICY_LEVEL_FULL:
1026                 case POLICY_LEVEL_ADAPTIVE:
1027                 case POLICY_LEVEL_OFF:
1028                     mPolicyLevel = level;
1029                     break;
1030                 default:
1031                     Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level);
1032                     return false;
1033             }
1034             updatePolicyDependenciesLocked();
1035             return true;
1036         }
1037     }
1038 
1039     /**
1040      * Get the current policy for the provided policy level.
1041      */
getPolicyLocked(@olicyLevel int policyLevel)1042     Policy getPolicyLocked(@PolicyLevel int policyLevel) {
1043         switch (policyLevel) {
1044             case POLICY_LEVEL_OFF:
1045                 return OFF_POLICY;
1046             case POLICY_LEVEL_ADAPTIVE:
1047                 return mAdaptivePolicy;
1048             case POLICY_LEVEL_FULL:
1049                 return mFullPolicy;
1050         }
1051 
1052         throw new IllegalArgumentException(
1053                 "getPolicyLocked: incorrect policy level provided - " + policyLevel);
1054     }
1055 
1056     /**
1057      * Updates the default policy with the passed in policy.
1058      * If the full policy is not overridden with runtime settings, then the full policy will be
1059      * updated.
1060      *
1061      * @return True if the active policy requires an update, false if not.
1062      */
maybeUpdateDefaultFullPolicy(Policy p)1063     private boolean maybeUpdateDefaultFullPolicy(Policy p) {
1064         boolean fullPolicyChanged = false;
1065         if (!mDefaultFullPolicy.equals(p)) {
1066             // default policy can be overridden by #setFullPolicyLocked
1067             boolean isDefaultFullPolicyOverridden = !mDefaultFullPolicy.equals(mFullPolicy);
1068             if (!isDefaultFullPolicyOverridden) {
1069                 mFullPolicy = p;
1070                 fullPolicyChanged = (mPolicyLevel == POLICY_LEVEL_FULL);
1071             }
1072             mDefaultFullPolicy = p;
1073         }
1074         return fullPolicyChanged;
1075     }
1076 
1077     /** @return true if the current policy changed and the policy level is FULL. */
setFullPolicyLocked(Policy p)1078     boolean setFullPolicyLocked(Policy p) {
1079         if (p == null) {
1080             Slog.wtf(TAG, "setFullPolicy given null policy");
1081             return false;
1082         }
1083         if (mFullPolicy.equals(p)) {
1084             return false;
1085         }
1086 
1087         mFullPolicy = p;
1088         if (mPolicyLevel == POLICY_LEVEL_FULL) {
1089             updatePolicyDependenciesLocked();
1090             return true;
1091         }
1092         return false;
1093     }
1094 
1095     /** @return true if the current policy changed and the policy level is ADAPTIVE. */
setAdaptivePolicyLocked(Policy p)1096     boolean setAdaptivePolicyLocked(Policy p) {
1097         if (p == null) {
1098             Slog.wtf(TAG, "setAdaptivePolicy given null policy");
1099             return false;
1100         }
1101         if (mAdaptivePolicy.equals(p)) {
1102             return false;
1103         }
1104 
1105         mAdaptivePolicy = p;
1106         if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE) {
1107             updatePolicyDependenciesLocked();
1108             return true;
1109         }
1110         return false;
1111     }
1112 
1113     /** @return true if the current policy changed and the policy level is ADAPTIVE. */
resetAdaptivePolicyLocked()1114     boolean resetAdaptivePolicyLocked() {
1115         return setAdaptivePolicyLocked(mDefaultAdaptivePolicy);
1116     }
1117 
getCurrentPolicyLocked()1118     private Policy getCurrentPolicyLocked() {
1119         return mEffectivePolicyRaw;
1120     }
1121 
getCurrentRawPolicyLocked()1122     private Policy getCurrentRawPolicyLocked() {
1123         switch (mPolicyLevel) {
1124             case POLICY_LEVEL_FULL:
1125                 return mFullPolicy;
1126             case POLICY_LEVEL_ADAPTIVE:
1127                 return mAdaptivePolicy;
1128             case POLICY_LEVEL_OFF:
1129             default:
1130                 return OFF_POLICY;
1131         }
1132     }
1133 
getGpsMode()1134     public int getGpsMode() {
1135         synchronized (mLock) {
1136             return getCurrentPolicyLocked().locationMode;
1137         }
1138     }
1139 
isLaunchBoostDisabled()1140     public boolean isLaunchBoostDisabled() {
1141         synchronized (mLock) {
1142             return getCurrentPolicyLocked().disableLaunchBoost;
1143         }
1144     }
1145 
shouldAdvertiseIsEnabled()1146     boolean shouldAdvertiseIsEnabled() {
1147         synchronized (mLock) {
1148             return getCurrentPolicyLocked().advertiseIsEnabled;
1149         }
1150     }
1151 
toEventLogString()1152     public String toEventLogString() {
1153         synchronized (mLock) {
1154             return mEventLogKeys;
1155         }
1156     }
1157 
dump(PrintWriter pw)1158     public void dump(PrintWriter pw) {
1159         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
1160 
1161         synchronized (mLock) {
1162             ipw.println();
1163             mBatterySavingStats.dump(ipw);
1164 
1165             ipw.println();
1166             ipw.println("Battery saver policy (*NOTE* they only apply when battery saver is ON):");
1167             ipw.increaseIndent();
1168             ipw.println("Settings: " + Settings.Global.BATTERY_SAVER_CONSTANTS);
1169             ipw.increaseIndent();
1170             ipw.println("value: " + mSettings);
1171             ipw.decreaseIndent();
1172             ipw.println("Settings: " + mDeviceSpecificSettingsSource);
1173             ipw.increaseIndent();
1174             ipw.println("value: " + mDeviceSpecificSettings);
1175             ipw.decreaseIndent();
1176             ipw.println("DeviceConfig: " + DeviceConfig.NAMESPACE_BATTERY_SAVER);
1177             ipw.increaseIndent();
1178             final Set<String> keys = mLastDeviceConfigProperties.getKeyset();
1179             if (keys.size() == 0) {
1180                 ipw.println("N/A");
1181             } else {
1182                 for (final String key : keys) {
1183                     ipw.print(key);
1184                     ipw.print(": ");
1185                     ipw.println(mLastDeviceConfigProperties.getString(key, null));
1186                 }
1187             }
1188             ipw.decreaseIndent();
1189 
1190             ipw.println("mAccessibilityEnabled=" + mAccessibilityEnabled.get());
1191             ipw.println("mAutomotiveProjectionActive=" + mAutomotiveProjectionActive.get());
1192             ipw.println("mPolicyLevel=" + mPolicyLevel);
1193 
1194             dumpPolicyLocked(ipw, "default full", mDefaultFullPolicy);
1195             dumpPolicyLocked(ipw, "current full", mFullPolicy);
1196             dumpPolicyLocked(ipw, "default adaptive", mDefaultAdaptivePolicy);
1197             dumpPolicyLocked(ipw, "current adaptive", mAdaptivePolicy);
1198             dumpPolicyLocked(ipw, "effective", mEffectivePolicyRaw);
1199 
1200             ipw.decreaseIndent();
1201         }
1202     }
1203 
dumpPolicyLocked(IndentingPrintWriter pw, String label, Policy p)1204     private void dumpPolicyLocked(IndentingPrintWriter pw, String label, Policy p) {
1205         pw.println();
1206         pw.println("Policy '" + label + "'");
1207         pw.increaseIndent();
1208         pw.println(KEY_ADVERTISE_IS_ENABLED + "=" + p.advertiseIsEnabled);
1209         pw.println(KEY_DISABLE_VIBRATION + "=" + p.disableVibration);
1210         pw.println(KEY_DISABLE_ANIMATION + "=" + p.disableAnimation);
1211         pw.println(KEY_DEFER_FULL_BACKUP + "=" + p.deferFullBackup);
1212         pw.println(KEY_DEFER_KEYVALUE_BACKUP + "=" + p.deferKeyValueBackup);
1213         pw.println(KEY_ENABLE_FIREWALL + "=" + p.enableFirewall);
1214         pw.println(KEY_ENABLE_DATASAVER + "=" + p.enableDataSaver);
1215         pw.println(KEY_DISABLE_LAUNCH_BOOST + "=" + p.disableLaunchBoost);
1216         pw.println(KEY_ENABLE_BRIGHTNESS_ADJUSTMENT + "=" + p.enableAdjustBrightness);
1217         pw.println(KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor);
1218         pw.println(KEY_LOCATION_MODE + "=" + p.locationMode);
1219         pw.println(KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby);
1220         pw.println(KEY_FORCE_BACKGROUND_CHECK + "=" + p.forceBackgroundCheck);
1221         pw.println(KEY_DISABLE_OPTIONAL_SENSORS + "=" + p.disableOptionalSensors);
1222         pw.println(KEY_DISABLE_AOD + "=" + p.disableAod);
1223         pw.println(KEY_SOUNDTRIGGER_MODE + "=" + p.soundTriggerMode);
1224         pw.println(KEY_ENABLE_QUICK_DOZE + "=" + p.enableQuickDoze);
1225         pw.println(KEY_ENABLE_NIGHT_MODE + "=" + p.enableNightMode);
1226 
1227         // Decrease from indent right after "Policy" line
1228         pw.decreaseIndent();
1229     }
1230 
dumpMap(PrintWriter pw, ArrayMap<String, String> map)1231     private void dumpMap(PrintWriter pw, ArrayMap<String, String> map) {
1232         if (map == null || map.size() == 0) {
1233             pw.println("N/A");
1234             return;
1235         }
1236         final int size = map.size();
1237         for (int i = 0; i < size; i++) {
1238             pw.print(map.keyAt(i));
1239             pw.print(": '");
1240             pw.print(map.valueAt(i));
1241             pw.println("'");
1242         }
1243     }
1244 
1245     /**
1246      * A boolean value which should trigger a policy update when it changes.
1247      */
1248     @VisibleForTesting
1249     class PolicyBoolean {
1250         private final String mDebugName;
1251         @GuardedBy("mLock")
1252         private boolean mValue;
1253 
PolicyBoolean(String debugName)1254         private PolicyBoolean(String debugName) {
1255             mDebugName = debugName;
1256         }
1257 
1258         /** Sets the initial value without triggering a policy update. */
initialize(boolean initialValue)1259         private void initialize(boolean initialValue) {
1260             synchronized (mLock) {
1261                 mValue = initialValue;
1262             }
1263         }
1264 
get()1265         private boolean get() {
1266             synchronized (mLock) {
1267                 return mValue;
1268             }
1269         }
1270 
1271         /** Sets a value, which if different from the current value, triggers a policy update. */
1272         @VisibleForTesting
update(boolean newValue)1273         void update(boolean newValue) {
1274             synchronized (mLock) {
1275                 if (mValue != newValue) {
1276                     Slog.d(TAG, mDebugName + " changed to " + newValue + ", updating policy.");
1277                     mValue = newValue;
1278                     updatePolicyDependenciesLocked();
1279                     maybeNotifyListenersOfPolicyChange();
1280                 }
1281             }
1282         }
1283     }
1284 }
1285