Add BatterySaverPolicy for power save mode

The BatterySaverPolicy is designed to consolidate all battery saver
knobs into a central location. Usually it is consistent to
mLowPowerModeEnabled unless it gets different data for specific
service. By adding these knobs, we can effectively tune the battery
saver.

This cl sets up the framework for BatterySaverPolicy and updates
following service to get battery saver data from BatterySaverPolicy

1. GnssLocationProvider
2. VibratorService
3. WindowManagerService
4. BackupManagerService
5. SoundTriggerService
6. NetworkPolicyManagerService

Screen brightness will come in a following cl.

Bug: 34693888
Test: FrameworksServicesTests

Change-Id: I6b040e93391614b44d136a485faa4a332c396e51
This commit is contained in:
jackqdyulei
2017-02-09 15:29:16 -08:00
parent acc9668235
commit 455e90add2
19 changed files with 750 additions and 65 deletions

View File

@@ -2,22 +2,23 @@
**
** Copyright 2007, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.os;
import android.os.WorkSource;
import android.os.PowerSaveState;
/** @hide */
@@ -45,6 +46,7 @@ interface IPowerManager
void nap(long time);
boolean isInteractive();
boolean isPowerSaveMode();
PowerSaveState getPowerSaveState(int serviceType);
boolean setPowerSaveMode(boolean mode);
boolean isDeviceIdleMode();
boolean isLightDeviceIdleMode();

View File

@@ -970,6 +970,24 @@ public final class PowerManager {
}
}
/**
* Get data about the battery saver mode for a specific service
* @param serviceType unique key for the service, one of
* {@link com.android.server.power.BatterySaverPolicy.ServiceType}
* @return Battery saver state data.
*
* @hide
* @see com.android.server.power.BatterySaverPolicy
* @see PowerSaveState
*/
public PowerSaveState getPowerSaveState(int serviceType) {
try {
return mService.getPowerSaveState(serviceType);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Returns true if the device is currently in idle mode. This happens when a device
* has been sitting unused and unmoving for a sufficiently long period of time, so that

View File

@@ -131,12 +131,13 @@ public abstract class PowerManagerInternal {
public abstract void setDozeOverrideFromDreamManager(
int screenState, int screenBrightness);
public abstract boolean getLowPowerModeEnabled();
public abstract PowerSaveState getLowPowerState(int serviceType);
public abstract void registerLowPowerModeObserver(LowPowerModeListener listener);
public interface LowPowerModeListener {
public void onLowPowerModeChanged(boolean enabled);
int getServiceType();
void onLowPowerModeChanged(PowerSaveState state);
}
public abstract boolean setDeviceIdleMode(boolean enabled);

View File

@@ -0,0 +1,19 @@
/*
** Copyright 2017, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.os;
parcelable PowerSaveState;

View File

@@ -0,0 +1,95 @@
/* Copyright 2017, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os;
/**
* Data class for battery saver state. It contains the data
* <p>
* 1. Whether battery saver mode is enabled
* 2. Specific parameters to use in battery saver mode(i.e. screen brightness, gps mode)
*
* @hide
*/
public class PowerSaveState implements Parcelable {
public final boolean batterySaverEnabled;
public final int gpsMode;
public final float brightnessFactor;
public PowerSaveState(Builder builder) {
batterySaverEnabled = builder.mBatterySaverEnabled;
gpsMode = builder.mGpsMode;
brightnessFactor = builder.mBrightnessFactor;
}
public PowerSaveState(Parcel in) {
batterySaverEnabled = in.readByte() != 0;
gpsMode = in.readInt();
brightnessFactor = in.readFloat();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeByte((byte) (batterySaverEnabled ? 1 : 0));
dest.writeInt(gpsMode);
dest.writeFloat(brightnessFactor);
}
public static final class Builder {
private boolean mBatterySaverEnabled = false;
private int mGpsMode = 0;
private float mBrightnessFactor = 0.5f;
public Builder() {}
public Builder setBatterySaverEnabled(boolean enabled) {
mBatterySaverEnabled = enabled;
return this;
}
public Builder setGpsMode(int mode) {
mGpsMode = mode;
return this;
}
public Builder setBrightnessFactor(float factor) {
mBrightnessFactor = factor;
return this;
}
public PowerSaveState build() {
return new PowerSaveState(this);
}
}
public static final Parcelable.Creator<PowerSaveState>
CREATOR = new Parcelable.Creator<PowerSaveState>() {
@Override
public PowerSaveState createFromParcel(Parcel source) {
return new PowerSaveState(source);
}
@Override
public PowerSaveState[] newArray(int size) {
return new PowerSaveState[size];
}
};
}

View File

@@ -8955,6 +8955,30 @@ public final class Settings {
*/
public static final String DEVICE_IDLE_CONSTANTS_WATCH = "device_idle_constants_watch";
/**
* Battery Saver specific settings
* This is encoded as a key=value list, separated by commas. Ex:
*
* "vibration_disabled=true,adjust_brightness_factor=0.5"
*
* The following keys are supported:
*
* <pre>
* vibration_disabled (boolean)
* animation_disabled (boolean)
* soundtrigger_disabled (boolean)
* fullbackup_deferred (boolean)
* keyvaluebackup_deferred (boolean)
* firewall_disabled (boolean)
* gps_mode (int)
* adjust_brightness_disabled (boolean)
* adjust_brightness_factor (float)
* </pre>
* @hide
* @see com.android.server.power.BatterySaverPolicy
*/
public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
/**
* App standby (app idle) specific settings.
* This is encoded as a key=value list, separated by commas. Ex:

View File

@@ -158,6 +158,7 @@ public class SettingsBackupTest {
Settings.Global.DEVICE_DEMO_MODE,
Settings.Global.DEVICE_IDLE_CONSTANTS,
Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH,
Settings.Global.BATTERY_SAVER_CONSTANTS,
Settings.Global.DEVICE_NAME,
Settings.Global.DEVICE_PROVISIONED,
Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,

View File

@@ -80,6 +80,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -122,6 +123,7 @@ import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.backup.PackageManagerBackupAgent.Metadata;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.io.IoUtils;
import java.io.BufferedInputStream;
@@ -5440,7 +5442,9 @@ public class BackupManagerService {
// Don't run the backup if we're in battery saver mode, but reschedule
// to try again in the not-so-distant future.
if (mPowerManager.isPowerSaveMode()) {
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
if (result.batterySaverEnabled) {
if (DEBUG) Slog.i(TAG, "Deferring scheduled full backups in battery saver mode");
FullBackupJob.schedule(mContext, KeyValueBackupJob.BATCH_INTERVAL);
return false;
@@ -9889,7 +9893,9 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
public void backupNow() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "backupNow");
if (mPowerManager.isPowerSaveMode()) {
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP);
if (result.batterySaverEnabled) {
if (DEBUG) Slog.v(TAG, "Not running backup while in battery save mode");
KeyValueBackupJob.schedule(mContext); // try again in several hours
} else {

View File

@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.media.AudioManager;
import android.os.PowerSaveState;
import android.os.BatteryStats;
import android.os.Handler;
import android.os.IVibratorService;
@@ -50,6 +51,7 @@ import android.media.AudioAttributes;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -233,10 +235,15 @@ public class VibratorService extends IVibratorService.Stub
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(boolean enabled) {
updateInputDeviceVibrators();
}
@Override
public int getServiceType() {
return ServiceType.VIBRATION;
}
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
updateInputDeviceVibrators();
}
});
mContext.getContentResolver().registerContentObserver(
@@ -553,7 +560,8 @@ public class VibratorService extends IVibratorService.Stub
} catch (SettingNotFoundException snfe) {
}
mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled();
mLowPowerMode = mPowerManagerInternal
.getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
if (mVibrateInputDevicesSetting) {
if (!mInputDeviceListenerRegistered) {

View File

@@ -24,6 +24,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiActivityEnergyInfo;
import android.os.PowerSaveState;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
@@ -60,6 +61,7 @@ import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.PowerProfile;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import java.io.File;
import java.io.FileDescriptor;
@@ -232,7 +234,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void initPowerManagement() {
final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
powerMgr.registerLowPowerModeObserver(this);
mStats.notePowerSaveMode(powerMgr.getLowPowerModeEnabled());
mStats.notePowerSaveMode(
powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
.batterySaverEnabled);
(new WakeupReasonThread()).start();
}
@@ -258,9 +262,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
@Override
public void onLowPowerModeChanged(boolean enabled) {
public int getServiceType() {
return ServiceType.BATTERY_STATS;
}
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
synchronized (mStats) {
mStats.notePowerSaveMode(enabled);
mStats.notePowerSaveMode(result.batterySaverEnabled);
}
}

View File

@@ -16,13 +16,6 @@
package com.android.server.location;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -55,6 +48,7 @@ import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.PowerSaveState;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
@@ -81,6 +75,17 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.NtpTrustedTime;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.server.power.BatterySaverPolicy;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.io.IoUtils;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -96,7 +101,6 @@ import java.util.Map.Entry;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;
import libcore.io.IoUtils;
/**
* A GNSS implementation of LocationProvider used by LocationManager.
@@ -243,14 +247,6 @@ public class GnssLocationProvider implements LocationProviderInterface {
private static final int TCP_MIN_PORT = 0;
private static final int TCP_MAX_PORT = 0xffff;
// Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
// Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
// is enabled and the screen is off.
private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
// Secure setting for GPS behavior when battery saver mode is on.
private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
/** simpler wrapper for ProviderRequest + Worksource */
private static class GpsRequest {
public ProviderRequest request;
@@ -548,11 +544,12 @@ public class GnssLocationProvider implements LocationProviderInterface {
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode.
boolean disableGps = mPowerManager.isDeviceIdleMode();
switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.GPS);
switch (result.gpsMode) {
case BatterySaverPolicy.GPS_MODE_DISABLED_WHEN_SCREEN_OFF:
// If we are in battery saver mode and the screen is off, disable GPS.
disableGps |= mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
break;
}
if (disableGps != mDisableGps) {

View File

@@ -131,6 +131,7 @@ import android.net.NetworkTemplate;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
@@ -180,6 +181,7 @@ import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.io.IoUtils;
import com.google.android.collect.Lists;
@@ -590,18 +592,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(boolean enabled) {
if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
synchronized (mUidRulesFirstLock) {
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
updateRulesForRestrictPowerUL();
@Override
public int getServiceType() {
return ServiceType.NETWORK_FIREWALL;
}
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
final boolean enabled = result.batterySaverEnabled;
if (LOGD) Slog.d(TAG,
"onLowPowerModeChanged(" + enabled + ")");
synchronized (mUidRulesFirstLock) {
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
updateRulesForRestrictPowerUL();
}
}
}
}
}
});
mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
mRestrictPower = mPowerManagerInternal.getLowPowerState(
ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
mSystemReady = true;

View File

@@ -0,0 +1,270 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.power;
import android.annotation.IntDef;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.Slog;
import android.os.PowerSaveState;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Class to decide whether to turn on battery saver mode for specific service
*/
public class BatterySaverPolicy extends ContentObserver {
@Retention(RetentionPolicy.SOURCE)
@IntDef({ServiceType.GPS,
ServiceType.VIBRATION,
ServiceType.ANIMATION,
ServiceType.FULL_BACKUP,
ServiceType.KEYVALUE_BACKUP,
ServiceType.NETWORK_FIREWALL,
ServiceType.SCREEN_BRIGHTNESS,
ServiceType.SOUND,
ServiceType.BATTERY_STATS})
public @interface ServiceType {
int NULL = 0;
int GPS = 1;
int VIBRATION = 2;
int ANIMATION = 3;
int FULL_BACKUP = 4;
int KEYVALUE_BACKUP = 5;
int NETWORK_FIREWALL = 6;
int SCREEN_BRIGHTNESS = 7;
int SOUND = 8;
int BATTERY_STATS = 9;
}
private static final String TAG = "BatterySaverPolicy";
// Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
public static final int GPS_MODE_NO_CHANGE = 0;
// Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
// is enabled and the screen is off.
public static final int GPS_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
// Secure setting for GPS behavior when battery saver mode is on.
public static final String SECURE_KEY_GPS_MODE = "batterySaverGpsMode";
private static final String KEY_GPS_MODE = "gps_mode";
private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
private static final String KEY_ANIMATION_DISABLED = "animation_disabled";
private static final String KEY_SOUNDTRIGGER_DISABLED = "soundtrigger_disabled";
private static final String KEY_FIREWALL_DISABLED = "firewall_disabled";
private static final String KEY_ADJUST_BRIGHTNESS_DISABLED = "adjust_brightness_disabled";
private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
private static final String KEY_KEYVALUE_DEFERRED = "keyvaluebackup_deferred";
private final KeyValueListParser mParser = new KeyValueListParser(',');
/**
* {@code true} if vibration is disabled in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_VIBRATION_DISABLED
*/
private boolean mVibrationDisabled;
/**
* {@code true} if animation is disabled in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_ANIMATION_DISABLED
*/
private boolean mAnimationDisabled;
/**
* {@code true} if sound trigger is disabled in battery saver mode
* in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_SOUNDTRIGGER_DISABLED
*/
private boolean mSoundTriggerDisabled;
/**
* {@code true} if full backup is deferred in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_FULLBACKUP_DEFERRED
*/
private boolean mFullBackupDeferred;
/**
* {@code true} if key value backup is deferred in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_KEYVALUE_DEFERRED
*/
private boolean mKeyValueBackupDeferred;
/**
* {@code true} if network policy firewall is disabled in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_FIREWALL_DISABLED
*/
private boolean mFireWallDisabled;
/**
* {@code true} if adjust brightness is disabled in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_ADJUST_BRIGHTNESS_DISABLED
*/
private boolean mAdjustBrightnessDisabled;
/**
* This is the flag to decide the gps mode in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_GPS_MODE
*/
private int mGpsMode;
/**
* This is the flag to decide the how much to adjust the screen brightness. This is
* the float value from 0 to 1 where 1 means don't change brightness.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
* @see #KEY_ADJUST_BRIGHTNESS_FACTOR
*/
private float mAdjustBrightnessFactor;
private ContentResolver mContentResolver;
public BatterySaverPolicy(Handler handler) {
super(handler);
}
public void start(ContentResolver contentResolver) {
mContentResolver = contentResolver;
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
onChange(true, null);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
final String value = Settings.Global.getString(mContentResolver,
Settings.Global.BATTERY_SAVER_CONSTANTS);
updateConstants(value);
}
@VisibleForTesting
void updateConstants(final String value) {
synchronized (BatterySaverPolicy.this) {
try {
mParser.setString(value);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Bad battery saver constants");
}
mVibrationDisabled = mParser.getBoolean(KEY_VIBRATION_DISABLED, true);
mAnimationDisabled = mParser.getBoolean(KEY_ANIMATION_DISABLED, true);
mSoundTriggerDisabled = mParser.getBoolean(KEY_SOUNDTRIGGER_DISABLED, true);
mFullBackupDeferred = mParser.getBoolean(KEY_FULLBACKUP_DEFERRED, true);
mKeyValueBackupDeferred = mParser.getBoolean(KEY_KEYVALUE_DEFERRED, true);
mFireWallDisabled = mParser.getBoolean(KEY_FIREWALL_DISABLED, false);
mAdjustBrightnessDisabled = mParser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED, false);
mAdjustBrightnessFactor = mParser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR, 0.5f);
// Get default value from Settings.Secure
final int defaultGpsMode = Settings.Secure.getInt(mContentResolver, SECURE_KEY_GPS_MODE,
GPS_MODE_DISABLED_WHEN_SCREEN_OFF);
mGpsMode = mParser.getInt(KEY_GPS_MODE, defaultGpsMode);
}
}
/**
* Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}.
* The result will have {@link PowerSaveState#batterySaverEnabled} and some other
* parameters when necessary.
*
* @param type type of the service, one of {@link ServiceType}
* @param realMode whether the battery saver is on by default
* @return State data that contains battery saver data
*/
public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) {
synchronized (BatterySaverPolicy.this) {
final PowerSaveState.Builder builder = new PowerSaveState.Builder();
if (!realMode) {
return builder.setBatterySaverEnabled(realMode)
.build();
}
switch (type) {
case ServiceType.GPS:
return builder.setBatterySaverEnabled(realMode)
.setGpsMode(mGpsMode)
.build();
case ServiceType.ANIMATION:
return builder.setBatterySaverEnabled(mAnimationDisabled)
.build();
case ServiceType.FULL_BACKUP:
return builder.setBatterySaverEnabled(mFullBackupDeferred)
.build();
case ServiceType.KEYVALUE_BACKUP:
return builder.setBatterySaverEnabled(mKeyValueBackupDeferred)
.build();
case ServiceType.NETWORK_FIREWALL:
return builder.setBatterySaverEnabled(!mFireWallDisabled)
.build();
case ServiceType.SCREEN_BRIGHTNESS:
return builder.setBatterySaverEnabled(!mAdjustBrightnessDisabled)
.setBrightnessFactor(mAdjustBrightnessFactor)
.build();
case ServiceType.SOUND:
return builder.setBatterySaverEnabled(mSoundTriggerDisabled)
.build();
case ServiceType.VIBRATION:
return builder.setBatterySaverEnabled(mVibrationDisabled)
.build();
default:
return builder.setBatterySaverEnabled(realMode)
.build();
}
}
}
public void dump(PrintWriter pw) {
pw.println();
pw.println("Battery saver policy");
pw.println(" Settings " + Settings.Global.BATTERY_SAVER_CONSTANTS);
pw.println(" value: " + Settings.Global.getString(mContentResolver,
Settings.Global.BATTERY_SAVER_CONSTANTS));
pw.println();
pw.println(" " + KEY_VIBRATION_DISABLED + "=" + mVibrationDisabled);
pw.println(" " + KEY_ANIMATION_DISABLED + "=" + mAnimationDisabled);
pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + mFullBackupDeferred);
pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + mKeyValueBackupDeferred);
pw.println(" " + KEY_FIREWALL_DISABLED + "=" + mFireWallDisabled);
pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + mAdjustBrightnessDisabled);
pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mAdjustBrightnessFactor);
pw.println(" " + KEY_GPS_MODE + "=" + mGpsMode);
}
}

View File

@@ -35,6 +35,7 @@ import android.hardware.power.V1_0.PowerHint;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -80,7 +81,7 @@ import com.android.server.Watchdog;
import com.android.server.am.BatteryStatsService;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import libcore.util.Objects;
import java.io.FileDescriptor;
@@ -192,6 +193,7 @@ public final class PowerManagerService extends SystemService
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
private final BatterySaverPolicy mBatterySaverPolicy;
private LightsManager mLightsManager;
private BatteryManagerInternal mBatteryManagerInternal;
@@ -605,6 +607,7 @@ public final class PowerManagerService extends SystemService
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
mConstants = new Constants(mHandler);
mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
synchronized (mLock) {
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
@@ -704,6 +707,7 @@ public final class PowerManagerService extends SystemService
final ContentResolver resolver = mContext.getContentResolver();
mConstants.start(resolver);
mBatterySaverPolicy.start(resolver);
// Register for settings changes.
resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -939,8 +943,12 @@ public final class PowerManagerService extends SystemService
listeners = new ArrayList<PowerManagerInternal.LowPowerModeListener>(
mLowPowerModeListeners);
}
for (int i=0; i<listeners.size(); i++) {
listeners.get(i).onLowPowerModeChanged(lowPowerModeEnabled);
for (int i = 0; i < listeners.size(); i++) {
final PowerManagerInternal.LowPowerModeListener listener = listeners.get(i);
final PowerSaveState result =
mBatterySaverPolicy.getBatterySaverPolicy(
listener.getServiceType(), lowPowerModeEnabled);
listener.onLowPowerModeChanged(result);
}
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -3245,6 +3253,8 @@ public final class PowerManagerService extends SystemService
pw.println();
pw.println("Display Power: " + mDisplayPowerCallbacks);
mBatterySaverPolicy.dump(pw);
wcd = mWirelessChargerDetector;
}
@@ -4201,6 +4211,19 @@ public final class PowerManagerService extends SystemService
}
}
// Binder call
public PowerSaveState getPowerSaveState(@ServiceType int serviceType) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
return mBatterySaverPolicy.getBatterySaverPolicy(
serviceType, isLowPowerModeInternal());
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean setPowerSaveMode(boolean mode) {
mContext.enforceCallingOrSelfPermission(
@@ -4519,9 +4542,9 @@ public final class PowerManagerService extends SystemService
}
@Override
public boolean getLowPowerModeEnabled() {
public PowerSaveState getLowPowerState(@ServiceType int serviceType) {
synchronized (mLock) {
return mLowPowerModeEnabled;
return mBatterySaverPolicy.getBatterySaverPolicy(serviceType, mLowPowerModeEnabled);
}
}

View File

@@ -129,6 +129,7 @@ import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.PowerSaveState;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -219,6 +220,7 @@ import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.Watchdog;
import com.android.server.input.InputManagerService;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import com.android.server.power.ShutdownThread;
import java.io.BufferedWriter;
@@ -1009,15 +1011,26 @@ public class WindowManagerService extends IWindowManager.Stub
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
if (mPowerManagerInternal != null) {
mPowerManagerInternal.registerLowPowerModeObserver((enabled) -> {
synchronized (mWindowMap) {
if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
mAnimationsDisabled = enabled;
dispatchNewAnimatorScaleLocked(null);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public int getServiceType() {
return ServiceType.ANIMATION;
}
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
synchronized (mWindowMap) {
final boolean enabled = result.batterySaverEnabled;
if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
mAnimationsDisabled = enabled;
dispatchNewAnimatorScaleLocked(null);
}
}
}
});
mAnimationsDisabled = mPowerManagerInternal.getLowPowerModeEnabled();
mAnimationsDisabled = mPowerManagerInternal
.getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
}
mScreenFrozenLock = mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "SCREEN_FROZEN");

View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.power;
import android.os.PowerSaveState;
import android.os.Handler;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static com.google.common.truth.Truth.assertThat;
/**
* Tests for {@link com.android.server.power.BatterySaverPolicy}
*/
public class BatterySaverPolicyTest extends AndroidTestCase {
private static final boolean BATTERY_SAVER_ON = true;
private static final boolean BATTERY_SAVER_OFF = false;
private static final float BRIGHTNESS_FACTOR = 0.7f;
private static final float DEFAULT_BRIGHTNESS_FACTOR = 0.5f;
private static final float PRECISION = 0.001f;
private static final int GPS_MODE = 0;
private static final int DEFAULT_GPS_MODE = 1;
private static final String BATTERY_SAVER_CONSTANTS = "vibration_disabled=true,"
+ "animation_disabled=false,"
+ "soundtrigger_disabled=true,"
+ "firewall_disabled=false,"
+ "adjust_brightness_disabled=true,"
+ "adjust_brightness_factor=0.7,"
+ "fullbackup_deferred=true,"
+ "keyvaluebackup_deferred=false,"
+ "gps_mode=0";
private static final String BATTERY_SAVER_INCORRECT_CONSTANTS = "vi*,!=,,true";
@Mock
Handler mHandler;
private BatterySaverPolicy mBatterySaverPolicy;
public void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
mBatterySaverPolicy.start(getContext().getContentResolver());
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyNull_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.NULL);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyVibration_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.VIBRATION);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicySound_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.SOUND);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyFullBackup_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.FULL_BACKUP);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyKeyValueBackup_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.KEYVALUE_BACKUP);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyAnimation_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.ANIMATION);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyBatteryStats_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.BATTERY_STATS);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyNetworkFirewall_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.NETWORK_FIREWALL);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyScreenBrightness_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.SCREEN_BRIGHTNESS);
PowerSaveState stateOn =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, true);
assertThat(stateOn.brightnessFactor).isWithin(PRECISION).of(DEFAULT_BRIGHTNESS_FACTOR);
}
@SmallTest
public void testGetBatterySaverPolicy_PolicyGps_DefaultValueCorrect() {
testServiceDefaultValue(ServiceType.GPS);
PowerSaveState stateOn =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, true);
assertThat(stateOn.gpsMode).isEqualTo(DEFAULT_GPS_MODE);
}
@SmallTest
public void testUpdateConstants_getCorrectData() {
mBatterySaverPolicy.updateConstants(BATTERY_SAVER_CONSTANTS);
final PowerSaveState vibrationState =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION, BATTERY_SAVER_ON);
assertThat(vibrationState.batterySaverEnabled).isTrue();
final PowerSaveState animationState =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION, BATTERY_SAVER_ON);
assertThat(animationState.batterySaverEnabled).isFalse();
final PowerSaveState soundState =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SOUND, BATTERY_SAVER_ON);
assertThat(soundState.batterySaverEnabled).isTrue();
final PowerSaveState networkState = mBatterySaverPolicy.getBatterySaverPolicy(
ServiceType.NETWORK_FIREWALL, BATTERY_SAVER_ON);
assertThat(networkState.batterySaverEnabled).isTrue();
final PowerSaveState screenState =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, BATTERY_SAVER_ON);
assertThat(screenState.batterySaverEnabled).isFalse();
assertThat(screenState.brightnessFactor).isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
final PowerSaveState fullBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
ServiceType.FULL_BACKUP, BATTERY_SAVER_ON);
assertThat(fullBackupState.batterySaverEnabled).isTrue();
final PowerSaveState keyValueBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
ServiceType.KEYVALUE_BACKUP, BATTERY_SAVER_ON);
assertThat(keyValueBackupState.batterySaverEnabled).isFalse();
final PowerSaveState gpsState =
mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, BATTERY_SAVER_ON);
assertThat(gpsState.batterySaverEnabled).isTrue();
assertThat(gpsState.gpsMode).isEqualTo(GPS_MODE);
}
@SmallTest
public void testUpdateConstants_IncorrectData_NotCrash() {
//Should not crash
mBatterySaverPolicy.updateConstants(BATTERY_SAVER_INCORRECT_CONSTANTS);
mBatterySaverPolicy.updateConstants(null);
}
private void testServiceDefaultValue(@ServiceType int type) {
mBatterySaverPolicy.updateConstants("");
final PowerSaveState batterySaverStateOn =
mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
assertThat(batterySaverStateOn.batterySaverEnabled).isTrue();
final PowerSaveState batterySaverStateOff =
mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_OFF);
assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
}
}

View File

@@ -17,9 +17,13 @@
package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import android.os.PowerSaveState;
import org.mockito.invocation.InvocationOnMock;
import android.annotation.Nullable;
@@ -67,6 +71,10 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
if (LocalServices.getService(PowerManagerInternal.class) == null) {
LocalServices.addService(PowerManagerInternal.class,
mock(PowerManagerInternal.class));
final PowerManagerInternal pm =
LocalServices.getService(PowerManagerInternal.class);
PowerSaveState state = new PowerSaveState.Builder().build();
doReturn(state).when(pm).getLowPowerState(anyInt());
}
if (LocalServices.getService(ActivityManagerInternal.class) == null) {
LocalServices.addService(ActivityManagerInternal.class,

View File

@@ -16,8 +16,6 @@
package com.android.server.soundtrigger;
import static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -42,6 +40,7 @@ import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Slog;
import com.android.internal.logging.MetricsLogger;
import com.android.server.power.BatterySaverPolicy.ServiceType;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -841,7 +840,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
return;
}
boolean active = mPowerManager.isPowerSaveMode();
boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
.batterySaverEnabled;
if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
synchronized (mLock) {
onPowerSaveModeChangedLocked(active);
@@ -874,7 +874,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
mContext.registerReceiver(mPowerSaveModeListener,
new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
}
mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
mIsPowerSaveMode = mPowerManager.getPowerSaveState(ServiceType.SOUND)
.batterySaverEnabled;
}
// Sends an error callback to all models with a valid registered callback.

View File

@@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.android;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.WorkSource;
@@ -42,6 +43,10 @@ public class BridgePowerManager implements IPowerManager {
return false;
}
public PowerSaveState getPowerSaveState(int serviceType) {
return null;
}
@Override
public IBinder asBinder() {
// pass for now.