目录
[一. battery saver模式的policy](#一. battery saver模式的policy)
[(1) DEFAULT_FULL_POLICY 对应的配置和解释:](#(1) DEFAULT_FULL_POLICY 对应的配置和解释:)
[(2) OFF_POLICY 对应的配置也就说不使用policy](#(2) OFF_POLICY 对应的配置也就说不使用policy)
[(3) 获取省电模式下的policy:](#(3) 获取省电模式下的policy:)
[二. 对各个参数代码讲解](#二. 对各个参数代码讲解)
[(1) adjustBrightnessFactor](#(1) adjustBrightnessFactor)
[(2) enableAdjustBrightness](#(2) enableAdjustBrightness)
[(3) advertiseIsEnabled](#(3) advertiseIsEnabled)
[(4) deferFullBackup](#(4) deferFullBackup)
[(5) deferKeyValueBackup](#(5) deferKeyValueBackup)
[(6) disableAnimation](#(6) disableAnimation)
[(7) disableAod](#(7) disableAod)
[(8) disableLaunchBoost](#(8) disableLaunchBoost)
[(9) disableOptionalSensors](#(9) disableOptionalSensors)
[(10) disableSoundTrigger](#(10) disableSoundTrigger)
[(11) disableVibration](#(11) disableVibration)
[(12) enableDataSaver](#(12) enableDataSaver)
[(13) enableFirewall](#(13) enableFirewall)
[(14) enableNightMode](#(14) enableNightMode)
[(15) enableQuickDoze](#(15) enableQuickDoze)
[(16) filesForInteractive](#(16) filesForInteractive)
[(17) filesForNoninteractive](#(17) filesForNoninteractive)
[(18) forceAllAppsStandby](#(18) forceAllAppsStandby)
[(19) forceBackgroundCheck](#(19) forceBackgroundCheck)
[(20) locationMode](#(20) locationMode)
[三. 进入省电模式的入口](#三. 进入省电模式的入口)
[四. modem进入低电模式入口](#四. modem进入低电模式入口)
[五. 屏幕亮度将会变成原来的50%的流程](#五. 屏幕亮度将会变成原来的50%的流程)
[六. 自动进入省电模式](#六. 自动进入省电模式)
[八. 总结](#八. 总结)
一. battery saver模式的policy
(1) DEFAULT_FULL_POLICY 对应的配置和解释:
|------------------------|---------------------------------------------------------------------------------------------|--------------------|
| 字段 | 描述 | 默认值 |
| adjustBrightnessFactor | 将亮度调节为原来的百分比 | 0.5f |
| advertiseIsEnabled | 这是基本属性控制到部分省电的策略,譬如:控制location或者匹配不到对应type | true |
| deferFullBackup | 在省电模式下是否延迟备份 | true |
| deferKeyValueBackup | 在省电模式下是否延迟备份 | true |
| disableAnimation | 在省电模式下Window 动画是否被禁用 | false |
| disableAod | 在省电模式下,并且在doze 中是否禁用heads up | true |
| disableLaunchBoost | 在省电模式下是否禁用启动boost | true |
| disableOptionalSensors | 是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码. | true |
| disableSoundTrigger | 如果在省电模式下是否禁用声音触发的事件,譬如:语音识别 | true |
| disableVibration | 当省电模式模式下,除了来电显示的震动(有条件的震动) | true |
| enableAdjustBrightness | 如果在省电模式下,否打开低功耗模式亮度调节 | false |
| enableDataSaver | 在省电模式下,是否开启DataSaver模式 | false |
| enableFirewall | 是否应在省电模式下开启网络策略防火墙 | true |
| enableNightMode | 是否启用夜间模式 | true |
| enableQuickDoze | 是否启用快速打瞌睡模式 | true |
| filesForInteractive | 激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| filesForNoninteractive | 激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| forceAllAppsStandby | 是否将所有应用程序置于待机模式 | true |
| forceBackgroundCheck | 是否强制后台检查,譬如:强制停止idle UIDs | true |
| locationMode | 这是决定省电模式下定位模式的标志。 这以前称为 gpsMode。默认是PowerManager. LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF | |
(2) OFF_POLICY 对应的配置也就说不使用policy
|------------------------|--------------------------------------------------------------------------|--------------------|
| 字段 | 描述 | 默认值 |
| adjustBrightnessFactor | 将亮度调节为原来的百分比 | 1f |
| advertiseIsEnabled | 这是基本属性控制到部分省电的策略,譬如:控制location或者匹配不到对应type | false |
| deferFullBackup | 在省电模式下是否延迟备份 | false |
| deferKeyValueBackup | 在省电模式下是否延迟备份 | false |
| disableAnimation | 在省电模式下Window 动画是否被禁用 | false |
| disableAod | 在省电模式下,并且在doze 中是否禁用heads up | false |
| disableLaunchBoost | 在省电模式下是否禁用启动boost | false |
| disableOptionalSensors | 是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码. | false |
| disableSoundTrigger | 如果在省电模式下是否禁用声音触发的事件,譬如:语音识别 | false |
| disableVibration | 当省电模式模式下,除了来电显示的震动(有条件的震动) | false |
| enableAdjustBrightness | 如果在省电模式下,否打开低功耗模式亮度调节 | false |
| enableDataSaver | 在省电模式下,是否开启DataSaver模式 | false |
| enableFirewall | 是否应在省电模式下开启网络策略防火墙 | false |
| enableNightMode | 是否启用夜间模式 | false |
| enableQuickDoze | 是否启用快速打瞌睡模式 | false |
| filesForInteractive | 激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| filesForNoninteractive | 激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| forceAllAppsStandby | 是否将所有应用程序置于待机模式 | false |
| forceBackgroundCheck | 是否强制后台检查,譬如:强制停止idle UIDs | false |
| locationMode | 这是决定省电模式下定位模式的标志。 这以前称为 gpsMode。默认是PowerManager. LOCATION_MODE_NO_CHANGE | |
(3) 获取省电模式下的policy:
通过getBatterySaverPolicy函数获取各个type对应的参数:
SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
/**
* Get the {@link PowerSaveState} based on the current policy level.
* The result will have {@link PowerSaveState#batterySaverEnabled} and some other
* parameters when necessary.
*
* @param type type of the service, one of {@link ServiceType}
* @return State data that contains battery saver data
*/
public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
synchronized (mLock) {
final Policy currPolicy = getCurrentPolicyLocked();
final PowerSaveState.Builder builder = new PowerSaveState.Builder()
.setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
switch (type) {
case ServiceType.LOCATION:
boolean isEnabled = currPolicy.advertiseIsEnabled
|| currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE;
return builder.setBatterySaverEnabled(isEnabled)
.setLocationMode(currPolicy.locationMode)
.build();
case ServiceType.ANIMATION:
return builder.setBatterySaverEnabled(currPolicy.disableAnimation)
.build();
case ServiceType.FULL_BACKUP:
return builder.setBatterySaverEnabled(currPolicy.deferFullBackup)
.build();
case ServiceType.KEYVALUE_BACKUP:
return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup)
.build();
case ServiceType.NETWORK_FIREWALL:
return builder.setBatterySaverEnabled(currPolicy.enableFirewall)
.build();
case ServiceType.SCREEN_BRIGHTNESS:
return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
.setBrightnessFactor(currPolicy.adjustBrightnessFactor)
.build();
case ServiceType.DATA_SAVER:
return builder.setBatterySaverEnabled(currPolicy.enableDataSaver)
.build();
case ServiceType.SOUND:
return builder.setBatterySaverEnabled(currPolicy.disableSoundTrigger)
.build();
case ServiceType.VIBRATION:
return builder.setBatterySaverEnabled(currPolicy.disableVibration)
.build();
case ServiceType.FORCE_ALL_APPS_STANDBY :
return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
.build();
case ServiceType.FORCE_BACKGROUND_CHECK:
return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck)
.build();
case ServiceType.NIGHT_MODE:
return builder.setBatterySaverEnabled(currPolicy.enableNightMode)
.build();
case ServiceType.OPTIONAL_SENSORS :
return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors)
.build();
case ServiceType.AOD:
return builder.setBatterySaverEnabled(currPolicy.disableAod)
.build();
case ServiceType.QUICK_DOZE:
return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze)
.build();
default:
return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled)
.build();
}
}
}
二. 对各个参数代码讲解
(1) adjustBrightnessFactor
这是决定屏幕亮度调整多少的标志。 这是从 0 到 1 的浮点值,其中 1 表示不改变亮度. 1) LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@VisibleForTesting
void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
PowerSaveState state = mBatterySaverPolicy.
getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
}
- 更新power 状态
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void updatePowerState() {
...
// If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
// as long as it is above the minimum threshold.
if (mPowerRequest.lowPowerMode) {
if (brightnessState > mScreenBrightnessRangeMinimum) {
//获取screenLowPowerBrightnessFactor 参数作为缩放亮度的因数
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
//获取最小亮度值
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
//亮度值不能小于最小的亮度值
brightnessState = Math.max(lowPowerBrightnessFloat,
mScreenBrightnessRangeMinimum);
}
...
}
3)分发powerFactor 的数值
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void notifyBrightnessChanged(int brightness, boolean userInitiated,
boolean hadUserDataPoint) {
final float brightnessInNits = convertToNits(brightness);
if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
&& mAutomaticBrightnessController != null) {
// We only want to track changes on devices that can actually map the display backlight
// values into a physical brightness unit since the value provided by the API is in
// nits and not using the arbitrary backlight units.
//若低电量模式,则获取policy中的配置值
final float powerFactor = mPowerRequest.lowPowerMode
? mPowerRequest.screenLowPowerBrightnessFactor
: 1.0f;
//将更改的powerFactor 分发下去
mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
powerFactor, hadUserDataPoint,
mAutomaticBrightnessController.isDefaultConfig());
}
}
(2) enableAdjustBrightness
enableAdjustBrightness 和adjustBrightnessFactor是搭配起来用的。使用方法和adjustBrightnessFactor 一样。
在省电模式下是否打开低功耗模式亮度调节应。
(3) advertiseIsEnabled
若获取的policy的type匹配不上则,则使用此值作为默认值。
(4) deferFullBackup
在省电模式下是否推迟完整备份。
LAW.BR.5.1/LINUX/android/frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
/**
* Conditions are right for a full backup operation, so run one. The model we use is
* to perform one app backup per scheduled job execution, and to reschedule the job
* with zero latency as long as conditions remain right and we still have work to do.
*
* <p>This is the "start a full backup operation" entry point called by the scheduled job.
*
* @return Whether ongoing work will continue. The return value here will be passed
* along as the return value to the scheduled job's onStartJob() callback.
*/
public boolean beginFullBackup(FullBackupJob scheduledJob) {
// Don't run the backup if we're in battery saver mode, but reschedule
// to try again in the not-so-distant future.
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
if (result.batterySaverEnabled) {
//如果处于省电模式,请不要运行备份,但要重新安排在不久的将来重试。
FullBackupJob.schedule(mUserId, mContext, keyValueBackupInterval, mConstants);
return false;
}
}
(5) deferKeyValueBackup
在省电模式下是否推迟键值(Key-value Backup)备份。
关于Key-value Backup 可以参考: 全面复盘Android开发者容易忽视的Backup功能 - 掘金
LAW.BR.5.1/LINUX/android/frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
/**
* Run a backup pass immediately for any applications that have declared that they have pending
* updates.
*/
public void backupNow() {
...
try {
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP );
if (result.batterySaverEnabled) {
// Try again in several hours.
//推迟执行
KeyValueBackupJob.schedule(mUserId, mContext, mConstants);
}
...
(6) disableAnimation
在省电模式下是否禁止window 动画。
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
Supplier<Surface> surfaceFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
...
if (mPowerManagerInternal != null) {
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public int getServiceType() {
return ServiceType.ANIMATION;
}
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
synchronized (mGlobalLock) {
final boolean enabled = result.batterySaverEnabled;
if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
mAnimationsDisabled = enabled ;
dispatchNewAnimatorScaleLocked(null);
}
}
}
});
mAnimationsDisabled = mPowerManagerInternal
.getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
}
...
}
获取动画播放时长的缩放比例
@Override
public float getCurrentAnimatorScale() {
synchronized (mGlobalLock) {
return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
}
}
(7) disableAod
在省电模式下是否禁用 AOD。
当手机打瞌睡时,通知是否应在用户的显示屏上"闪烁"。
代码在Systemui中实现
LAW.BR.5.1/LINUX/android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
private void setPowerSave(boolean powerSave) {
if (powerSave == mPowerSave) return;
mPowerSave = powerSave;
// AOD power saving setting might be different from PowerManager power saving mode.
PowerSaveState state = mPowerManager.getPowerSaveState(PowerManager.ServiceType.AOD);
//获取aod的值
mAodPowerSave = state.batterySaverEnabled;
firePowerSaveChanged();
}
LAW.BR.5.1/LINUX/android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
/**
* Whether or not the notification should "pulse" on the user's display when the phone is
* dozing. This displays the ambient view of the notification.
*
* @param entry the entry to check
* @return true if the entry should ambient pulse, false otherwise
*/
private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) {
if (mBatteryController.isAodPowerSave() ) {
if (DEBUG_HEADS_UP) {
Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey());
}
return false;
}
(8) disableLaunchBoost
在省电模式下是否禁用启动boost
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
private void powerHintInternal(int hintId, int data) {
// Maybe filter the event.
switch (hintId) {
case PowerHint.LAUNCH: // 1: activate launch boost 0: deactivate.
if (data == 1 && mBatterySaverController.isLaunchBoostDisabled ()) {
return;
}
break;
}
mNativeWrapper.nativeSendPowerHint(hintId, data);
}
(9) disableOptionalSensors
是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码.
(10) disableSoundTrigger
在省电模式下是否禁用声音触发的事件,譬如:语音识别
LAW.BR.5.1/LINUX/android/frameworks/base/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
class PowerSaveModeListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
return;
}
boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
.batterySaverEnabled;
if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
synchronized (mLock) {
onPowerSaveModeChangedLocked(active);
}
}
}
// Whether we are allowed to run any recognition at all. The conditions that let us run// a recognition include: no active phone call or not being in a power save mode. Also,
// the native service should be enabled.
private boolean isRecognitionAllowed() {
// if mRecognitionRequested is false, call and power state listeners are not registered so
// we read current state directly from services
if (!mRecognitionRequested) {
mCallActive = mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK;
mIsPowerSaveMode =
mPowerManager.getPowerSaveState(ServiceType.SOUND).batterySaverEnabled;
}
return !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
}
(11) disableVibration
当省电模式模式下,除了来电显示的震动(有条件的震动)
- 震动将取消(原来如果有震动的话)
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/VibratorService.java
private boolean updateLowPowerModeLocked() {
boolean lowPowerMode = mPowerManagerInternal
.getLowPowerState(ServiceType.VIBRATION ).batterySaverEnabled;
if (lowPowerMode != mLowPowerMode) {
mLowPowerMode = lowPowerMode;
return true;
}
return false;
}
2)当省电模式模式下,除了来电显示的震动(有条件的震动),其它都将关闭震动。
代码如下:
//监听各种变化,取消震动.
private void updateVibrators() {
synchronized (mLock) {
boolean devicesUpdated = updateInputDeviceVibratorsLocked();
boolean lowPowerModeUpdated = updateLowPowerModeLocked();
updateVibrationIntensityLocked();
if (devicesUpdated || lowPowerModeUpdated) {
// If the state changes out from under us then just reset.
doCancelVibrateLocked();
}
updateAlwaysOnLocked();
}
}
private boolean isAllowedToVibrateLocked(Vibration vib) {
//若不是低电量模式,则直接允许
if (**!**mLowPowerMode ) {
return true;
}
int usage = vib.attrs.getUsage();
//若在低电量模式下,则允许USAGE_RINGTONE,USAGE_ALARM,USAGE_COMMUNICATION_REQUEST 模式下有震动.
return usage == VibrationAttributes.USAGE_RINGTONE
|| usage == VibrationAttributes.USAGE_ALARM
|| usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
}
private boolean shouldVibrate(Vibration vib, int intensity) {if (!isAllowedToVibrateLocked(vib)) {
return false;
}
...
return true;
}
(12) enableDataSaver
是否开启data saver模式
- 找到控制开关
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
private void initService(CountDownLatch initCompleteSignal) {
mRestrictBackgroundLowPowerMode = mPowerManagerInternal
.getLowPowerState(ServiceType.DATA_SAVER ).batterySaverEnabled;
if (mRestrictBackgroundLowPowerMode && !mLoadedRestrictBackground) {
mLoadedRestrictBackground = true;
}
setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");
}
- 对后台UL进行限制
@GuardedBy("mUidRulesFirstLock")
private void setRestrictBackgroundUL(boolean restrictBackground , String reason) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackgroundUL");
try {
//restrictBackground 默认值是true
if (restrictBackground == mRestrictBackground) {
// Ideally, UI should never allow this scenario...
return;
}
final boolean oldRestrictBackground = mRestrictBackground;
mRestrictBackground = restrictBackground;
// Must whitelist foreground apps before turning data saver mode on.
// TODO: there is no need to iterate through all apps here, just those in the foreground,
// so it could call AM to get the UIDs of such apps, and iterate through them instead.
//
updateRulesForRestrictBackgroundUL();
try {
//
if (!mNetworkManager.setDataSaverModeEnabled (mRestrictBackground)) {
Slog.e(TAG,
"Could not change Data Saver Mode on NMS to " + mRestrictBackground);
mRestrictBackground = oldRestrictBackground;
// TODO: if it knew the foreground apps (see TODO above), it could call
// updateRulesForRestrictBackgroundUL() again to restore state.
return;
}
} catch (RemoteException e) {
// ignored; service lives in system_server
}
...
}
- NetdService 对网络限制
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java
@Override
public boolean setDataSaverModeEnabled(boolean enable) {
mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
synchronized (mQuotaLock) {
if (mDataSaverMode == enable) {
Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
return true;
}
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
try {
//Enables or disables data saver mode on costly network interfaces.
final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
if (changed) {
mDataSaverMode = enable;
} else {
Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
}
return changed;
} catch (RemoteException e) {
Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
return false;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
}
(13) enableFirewall
在省电模式下是否开启网络策略防火墙
- 获取引用enableFirewall 值。
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
private void initService(CountDownLatch initCompleteSignal) {
mRestrictPower = mPowerManagerInternal.getLowPowerState(
ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
}
- 触发调用Restrict Power的函数:
[1] 当处于省电模式发生变化
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();
}
}
}
});
[2] 当收到ACTION_POWER_SAVE_WHITELIST_CHANGED action时:
final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
synchronized (mUidRulesFirstLock) {
updatePowerSaveWhitelistUL();
updateRulesForRestrictPowerUL ();
updateRulesForAppIdleUL();
}
}
};
[3] 当触发updateRulesForGlobalChangeAL 时:
/**
* Update rules that might be changed by {@link #mRestrictBackground},
* {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
*/
@GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
private void updateRulesForGlobalChangeAL(boolean restrictedNetworksChanged) {
try {
updateRulesForAppIdleUL();
updateRulesForRestrictPowerUL ();
updateRulesForRestrictBackgroundUL();
// If the set of restricted networks may have changed, re-evaluate those.
if (restrictedNetworksChanged) {
normalizePoliciesNL();
updateNetworkRulesNL();
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
- updateRulesForRestrictPowerUL函数解析:
// TODO: rename / document to make it clear these are global (not app-specific) rules
@GuardedBy("mUidRulesFirstLock")
private void updateRulesForRestrictPowerUL () {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL");
try {
updateRulesForDeviceIdleUL();
updateRulesForPowerSaveUL();
updateRulesForAllAppsUL(TYPE_RESTRICT_POWER);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
- updateRulesForPowerSaveUL 就是调用updateRulesForWhitelistedPowerSaveUL
@GuardedBy("mUidRulesFirstLock")
void updateRulesForPowerSaveUL() {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForPowerSaveUL");
try {
updateRulesForWhitelistedPowerSaveUL (mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
mUidFirewallPowerSaveRules);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
- 更新白名单范围(允许访问的网络的范围),范围之外的通过防火墙停止网络链接
// NOTE: since both fw_dozable and fw_powersave uses the same map
// (mPowerSaveTempWhitelistAppIds) for whitelisting, we can reuse their logic in this method.
@GuardedBy("mUidRulesFirstLock")
private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain,
SparseIntArray rules) {
if (enabled ) {
// Sync the whitelists before enabling the chain. We don't care about the rules if
// we are disabling the chain.
final SparseIntArray uidRules = rules;
uidRules.clear();
final List<UserInfo> users = mUserManager.getUsers();
for (int ui = users.size() - 1; ui >= 0; ui--) {
UserInfo user = users.get(ui);
updateRulesForWhitelistedAppIds(uidRules, mPowerSaveTempWhitelistAppIds, user.id);
updateRulesForWhitelistedAppIds(uidRules, mPowerSaveWhitelistAppIds, user.id);
//若是FIREWALL_CHAIN_POWERSAVE chain 则将mPowerSaveWhitelistExceptIdleAppIds里面的UID 增加在uidRules 白名单中.
if (chain == FIREWALL_CHAIN_POWERSAVE) {
updateRulesForWhitelistedAppIds(uidRules,
mPowerSaveWhitelistExceptIdleAppIds, user.id);
}
}
for (int i = mUidState.size() - 1; i >= 0; i--) {
if (isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.valueAt(i))) {
uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
}
}
setUidFirewallRulesUL(chain, uidRules, CHAIN_TOGGLE_ENABLE);
} else {
setUidFirewallRulesUL(chain, null, CHAIN_TOGGLE_DISABLE );
}
}
6)增加白名单
private void updateRulesForWhitelistedAppIds(final SparseIntArray uidRules,
final SparseBooleanArray whitelistedAppIds, int userId) {
for (int i = whitelistedAppIds.size() - 1; i >= 0; --i) {
if (whitelistedAppIds.valueAt(i)) {
final int appId = whitelistedAppIds.keyAt(i);
final int uid = UserHandle.getUid(userId, appId);
uidRules.put(uid, FIREWALL_RULE_ALLOW);
}
}
}
- 更新所有应用的访问规则,除了前台进程和在白名单内的进程,都将不允许访问网络
@GuardedBy("mUidRulesFirstLock")
private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules,
boolean isUidIdle) {
if (!isUidValidForBlacklistRulesUL(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
return RULE_NONE;
}
//mRestrictPower 表示低电量模式
final boolean restrictMode = isUidIdle || mRestrictPower || mDeviceIdleMode;
final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid);
final boolean isWhitelisted = isWhitelistedFromPowerSaveUL(uid, mDeviceIdleMode);
final int oldRule = oldUidRules & MASK_ALL_NETWORKS;
int newRule = RULE_NONE;
// First step: define the new rule based on user restrictions and foreground state.
// NOTE: if statements below could be inlined, but it's easier to understand the logic
// by considering the foreground and non-foreground states.
if (isForeground) {
//针对前台进程会放开
if (restrictMode) {
newRule = RULE_ALLOW_ALL;
}
} else if (restrictMode) {
//表示若低电量模式下,会限制规则。但是,对白名单会放开限制.
newRule = isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
}
final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
// Second step: notify listeners if state changed.
mHandler.obtainMessage(MSG_RULES_CHANGED, uid, newUidRules).sendToTarget();
}
return newUidRules;
}
(14) enableNightMode
是否启用夜间模式,不包含汽车模式.
- 获取引用enableNightMode 值。
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/UiModeManagerService.java
private void initPowerSave() {
mPowerSave =
mLocalPowerManager.getLowPowerState(ServiceType.NIGHT_MODE)
.batterySaverEnabled;
mLocalPowerManager.registerLowPowerModeObserver(ServiceType.NIGHT_MODE , state -> {
synchronized (mLock) {
if (mPowerSave == state.batterySaverEnabled) {
return;
}
mPowerSave = state.batterySaverEnabled ;
if (mSystemReady) {
updateLocked(0, 0);
}
}
});
}
2)更改uiMode
private void updateConfigurationLocked() {
// Override night mode in power save mode if not in car mode
//如果不在汽车模式下,则在省电模式下覆盖夜间模式
if (mPowerSave && !mCarModeEnabled && !mCar) {
uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
uiMode |= Configuration.UI_MODE_NIGHT_YES;
} else {
uiMode = getComputedUiModeConfiguration(uiMode);
}
(15) enableQuickDoze
是否启用快速打瞌睡模式
LAW.BR.5.1/LINUX/android/frameworks/base/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
- 获取引用enableQuickDoze 值。
mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE ,
state -> {
synchronized (DeviceIdleController.this) {
updateQuickDozeFlagLocked(state.batterySaverEnabled );
}
});
updateQuickDozeFlagLocked(
mLocalPowerManager.getLowPowerState(
ServiceType.QUICK_DOZE).batterySaverEnabled);
- 省电模式下,否可以快速进入doze
/** Updates the quick doze flag and enters deep doze if appropriate. */
@VisibleForTesting
void updateQuickDozeFlagLocked(boolean enabled) {
if (DEBUG) Slog.i(TAG, "updateQuickDozeFlagLocked: enabled=" + enabled);
mQuickDozeActivated = enabled;
mQuickDozeActivatedWhileIdling =
mQuickDozeActivated && (mState == STATE_IDLE || mState == STATE_IDLE_MAINTENANCE);
if (enabled) {
// If Quick Doze is enabled, see if we should go straight into it.
becomeInactiveIfAppropriateLocked();
}
// Going from Deep Doze to Light Idle (if quick doze becomes disabled) is tricky and
// probably not worth the overhead, so leave in deep doze if that's the case until the
// next natural time to come out of it.
}
(16) filesForInteractive
激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 用它来更改最大 CPU 频率。 目前没有理解filesForInteractive的作用.
- filesForInteractive定义:
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
public ArrayMap<String, String> getFileValues(boolean interactive) {
synchronized (mLock) {
return interactive ? getCurrentPolicyLocked().filesForInteractive
: getCurrentPolicyLocked().filesForNoninteractive;
}
}
- 写入fileValues
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
if (enabled) {
fileValues = mBatterySaverPolicy.getFileValues (isInteractive);
} else {
fileValues = null;
}
if (ArrayUtils.isEmpty(fileValues)) {
mFileUpdater.restoreDefault();
} else {
mFileUpdater.writeFiles(fileValues );
}
}
(17) filesForNoninteractive
激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 目前没有理解filesForNoninteractive的作用.
和filesForInteractive 一样的,只不过getFileValues函数的传参不一样
(18) forceAllAppsStandby
是否将所有应用程序置于待机模式
- forceAllAppsStandby 获取地方
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/AppStateTracker.java
public void onSystemServicesReady() {
...
mPowerManagerInternal.registerLowPowerModeObserver(
ServiceType.FORCE_ALL_APPS_STANDBY ,
(state) -> {
synchronized (mLock) {
mBatterySaverEnabled = state.batterySaverEnabled;
updateForceAllAppStandbyState ();
}
});
mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;
updateForceAllAppStandbyState();
...
}
- updateForceAllAppStandbyState 函数
private void updateForceAllAppStandbyState() {
synchronized (mLock) {
if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {
toggleForceAllAppsStandbyLocked (!mIsPluggedIn);
} else {
toggleForceAllAppsStandbyLocked (mBatterySaverEnabled);
}
}
}
- 对mForceAllAppsStandby 赋值,并且 便利onForceAllAppsStandbyChanged callback
/**
* Update {@link #mForceAllAppsStandby} and notifies the listeners.
*/
@GuardedBy("mLock")
private void toggleForceAllAppsStandbyLocked(boolean enable) {
if (enable == mForceAllAppsStandby) {
return;
}
mForceAllAppsStandby = enable;
mHandler.notifyForceAllAppsStandbyChanged();
}
public void notifyForceAllAppsStandbyChanged() {
removeMessages(MSG_FORCE_ALL_CHANGED);
obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
}
case MSG_FORCE_ALL_CHANGED:for (Listener l : cloneListeners()) {
l.onForceAllAppsStandbyChanged (sender);
}
return;
(19) forceBackgroundCheck
是否强制后台检查,譬如:强制停止idle UIDs
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
...
if (pmi != null) {
pmi.registerLowPowerModeObserver(ServiceType.FORCE_BACKGROUND_CHECK,
state -> updateForceBackgroundCheck(state.batterySaverEnabled ));
updateForceBackgroundCheck(
pmi.getLowPowerState(ServiceType.FORCE_BACKGROUND_CHECK).batterySaverEnabled);
} else {
Slog.wtf(TAG, "PowerManagerInternal not found.");
}
...
- updateForceBackgroundCheck
private void updateForceBackgroundCheck(boolean enabled) {
synchronized (this) {
if (mForceBackgroundCheck != enabled) {
mForceBackgroundCheck = enabled;
if (DEBUG_BACKGROUND_CHECK) {
Slog.i(TAG, "Force background check " + (enabled ? "enabled" : "disabled"));
}
if (mForceBackgroundCheck ) {
// Stop background services for idle UIDs.
mProcessList.doStopUidForIdleUidsLocked ();
}
}
}
}
(20) locationMode
有三处定义,分别从三处分析:
- 定义来自PowerManager.
[1] PowerManager.java 中getLocationPowerSaveMode函数
LAW.BR.5.1/LINUX/android/frameworks/base/core/java/android/os/PowerManager.java
/**
* Returns how location features should behave when battery saver is on. When battery saver
* is off, this will always return {@link #LOCATION_MODE_NO_CHANGE}.
*
* <p>This API is normally only useful for components that provide location features.
*
* @see #isPowerSaveMode()
* @see #ACTION_POWER_SAVE_MODE_CHANGED
*/
@LocationPowerSaveMode
public int getLocationPowerSaveMode () {
final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.LOCATION);
if (**!**powerSaveState.batterySaverEnabled) {
return LOCATION_MODE_NO_CHANGE;
}
return powerSaveState.locationMode;
}
[2] getLocationPowerSaveMode 作为公共接口,为LocationManagerService.java 提供使用函数.
- GnssLocationProvider.java 中updateLowPowerMode
[1] 定义:
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
private void updateLowPowerMode () {
// Disable GPS if we are in device idle mode and the device is stationary.
boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION);
switch (result.locationMode) {
case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
// If we are in battery saver mode and the screen is off, disable GPS.
disableGpsForPowerManager |=
result.batterySaverEnabled && !mPowerManager.isInteractive();
break;
}
if (disableGpsForPowerManager != mDisableGpsForPowerManager) {
mDisableGpsForPowerManager = disableGpsForPowerManager;
updateEnabled();
updateRequirements();
}
}
[2] 当收到mDeviceIdleStationaryListener 变化和ACTION_POWER_SAVE_MODE_CHANGED/ACTION_SCREEN_OFF/ACTION_SCREEN_ON时,会触发UPDATE_LOW_POWER_MODE handle
private final DeviceIdleInternal.StationaryListener mDeviceIdleStationaryListener =
isStationary -> {
mIsDeviceStationary = isStationary;
// Call updateLowPowerMode on handler thread so it's always called from the same
// thread.
mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
};
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {@Override
public void onReceive(Context context, Intent intent) {
...
case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
case Intent.ACTION_SCREEN_OFF:
case Intent.ACTION_SCREEN_ON:
// Call updateLowPowerMode on handler thread so it's always called from the
// same thread.
mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
break;
}
};
[3] 收到UPDATE_LOW_POWER_MODE 之后更新updateLowPowerMode
SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
private final class ProviderHandler extends Handler {
@Override
public void handleMessage(Message msg) {
int message = msg.what;
switch (message) {
case UPDATE_LOW_POWER_MODE:
updateLowPowerMode**()**;
break;
}
[4] updateLowPowerMode函数更新mDisableGpsForPowerManager变量
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode and the device is stationary.
boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION);
switch (result.locationMode) {
case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
// If we are in battery saver mode and the screen is off, disable GPS.
disableGpsForPowerManager |=
result.batterySaverEnabled && !mPowerManager.isInteractive();
break;
}
if (disableGpsForPowerManager != mDisableGpsForPowerManager) {
mDisableGpsForPowerManager = disableGpsForPowerManager;
updateEnabled();
updateRequirements();
}
}
[5] 更新enabled 数据并且做相应的逻辑。
private void updateEnabled() {
// Generally follow location setting for current user
boolean enabled = mContext.getSystemService(LocationManager.class)
.isLocationEnabledForUser(UserHandle.CURRENT);
// ... but disable if PowerManager overrides
enabled &= !mDisableGpsForPowerManager;
// .. but enable anyway, if there's an active settings-ignored request (e.g. ELS)
enabled |= (mProviderRequest != null && mProviderRequest.reportLocation
&& mProviderRequest.locationSettingsIgnored);
// ... and, finally, disable anyway, if device is being shut down
enabled &= !mShutdown;
if (enabled == isGpsEnabled()) {
return;
}
if (enabled) {
handleEnable();
} else {
handleDisable();
}
}
[5] 处理禁止的事情
private void handleDisable() {
if (DEBUG) Log.d(TAG, "handleDisable");
setGpsEnabled(false);
updateClientUids(new WorkSource());
stopNavigating();
mAlarmManager.cancel(mWakeupIntent);
mAlarmManager.cancel(mTimeoutIntent);
if (mGnssVisibilityControl != null) {
mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ false);
}
mGnssBatchingProvider.disable();
// do this before releasing wakelock
native_cleanup();
mGnssAntennaInfoProvider.onGpsEnabledChanged();
mGnssMeasurementsProvider.onGpsEnabledChanged();
mGnssNavigationMessageProvider.onGpsEnabledChanged();
}
- LocationManagerService 中onSystemReady函数
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/location/LocationManagerService.java
LocalServices.getService(PowerManagerInternal.class).registerLowPowerModeObserver(
ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of
// blocking ui thread
mHandler.post(() -> {
synchronized (mLock) {
onBatterySaverModeChangedLocked(state.locationMode);
}
});
});
三. 进入省电模式的入口
(1)通过 PowerManager 进入,需要DEVICE_POWER 和POWER_SAVER权限.
LAW.BR.5.1/LINUX/android/frameworks/base/core/java/android/os/PowerManager.java
/**
* Set the current power save mode.
*
* @return True if the set was allowed.
*
* @hide
* @see #isPowerSaveMode()
*/
@SystemApi
@TestApi
@RequiresPermission(anyOf = {
android.Manifest.permission.DEVICE_POWER ,
android.Manifest.permission.POWER_SAVER
})
public boolean setPowerSaveModeEnabled(boolean mode) {
try {
return mService.setPowerSaveModeEnabled(mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
(2) 进入PowerManagerService:
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@Override // Binder call
public boolean setPowerSaveModeEnabled(boolean enabled) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER)
!= PackageManager.PERMISSION_GRANTED) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
}
final long ident = Binder.clearCallingIdentity();
try {
return setLowPowerModeInternal(enabled);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private boolean setLowPowerModeInternal(boolean enabled) {
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "setLowPowerModeInternal " + enabled + " mIsPowered=" + mIsPowered);
}
if (mIsPowered) {
return false;
}
mBatterySaverStateMachine.setBatterySaverEnabledManually(enabled);
return true;
}
}
(3) 进入:/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
/**
* {@link com.android.server.power.PowerManagerService} calls it when
* {@link android.os.PowerManager#setPowerSaveModeEnabled} is called.
*
* Note this could? be called before {@link #onBootCompleted} too.
*/
public void setBatterySaverEnabledManually(boolean enabled) {
if (DEBUG) {
Slog.d(TAG, "setBatterySaverEnabledManually: enabled=" + enabled);
}
synchronized (mLock) {
updateStateLocked(true, enabled);
// TODO: maybe turn off adaptive if it's on and advertiseIsEnabled is true and
// enabled is false
}
}
4)updateStateLocked 函数下面内容再讲.
四. modem进入低电模式入口
SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/opt/telephony/src/java/com/android/internal/telephony/DeviceStateMonitor.java
(1)定义mBroadcastReceiver,当收到ACTION_POWER_SAVE_MODE_CHANGED 之后,则使用handle发送EVENT_POWER_SAVE_MODE_CHANGED.
/** * Device state broadcast receiver */ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { log("received: " + intent, true); Message msg; switch (intent.getAction()) { case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED: msg = obtainMessage(EVENT_POWER_SAVE_MODE_CHANGED); msg.arg1 = isPowerSaveModeOn() ? 1 : 0; log("Power Save mode " + ((msg.arg1 == 1) ? "on" : "off"), true); break; case BatteryManager.ACTION_CHARGING: msg = obtainMessage(EVENT_CHARGING_STATE_CHANGED); msg.arg1 = 1; // charging break; ... default: log("Unexpected broadcast intent: " + intent, false); return; } sendMessage(msg); } };
(2) 注册mBroadcastReceiver
/** * Device state monitor constructor. Note that each phone object should have its own device * state monitor, meaning there will be two device monitors on the multi-sim device. * * @param phone Phone object */ public DeviceStateMonitor(Phone phone) { mPhone = phone; mPhone.getContext().registerReceiver(mBroadcastReceiver, filter, null, mPhone); }
(3)接收到EVENT_POWER_SAVE_MODE_CHANGED
/** * Message handler * * @param msg The message */ @Override public void handleMessage(Message msg) { log("handleMessage msg=" + msg, false); switch (msg.what) { case EVENT_RIL_CONNECTED: case EVENT_RADIO_AVAILABLE: onReset(); break; case EVENT_SCREEN_STATE_CHANGED: case EVENT_POWER_SAVE_MODE_CHANGED: case EVENT_CHARGING_STATE_CHANGED: case EVENT_TETHERING_STATE_CHANGED: case EVENT_UPDATE_ALWAYS_REPORT_SIGNAL_STRENGTH: case EVENT_CAR_MODE_CHANGED: onUpdateDeviceState(msg.what, msg.arg1 != 0); break; case EVENT_WIFI_CONNECTION_CHANGED: onUpdateDeviceState(msg.what, msg.arg1 != WIFI_UNAVAILABLE); break; default: throw new IllegalStateException("Unexpected message arrives. msg = " + msg.what); } }
(4) onUpdateDeviceState函数
/**
* Update the device and send the information to the modem.
*
* @param eventType Device state event type
* @param state True if enabled/on, otherwise disabled/off.
*/
private void onUpdateDeviceState(int eventType, boolean state) {
final boolean shouldEnableBarringInfoReportsOld = shouldEnableBarringInfoReports();
switch (eventType) {
...
case EVENT_POWER_SAVE_MODE_CHANGED:
if (mIsPowerSaveOn == state) return;
mIsPowerSaveOn = state;
sendDeviceState (POWER_SAVE_MODE, mIsPowerSaveOn);
break;
}
(5) sendDeviceState函数
/** * Send the device state to the modem. * * @param type Device state type. See DeviceStateType defined in types.hal. * @param state True if enabled/on, otherwise disabled/off */ private void sendDeviceState(int type, boolean state) { log("send type: " + deviceTypeToString(type) + ", state=" + state, true); mPhone.mCi.sendDeviceState(type, state, null); }
五. 屏幕亮度将会变成原来的50%的流程
(1) 监听电池变化.
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
public void systemReady(IAppOpsService appOps) {
...
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BatteryReceiver (), filter, null, mHandler);
...}
@VisibleForTestingfinal class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
handleBatteryStateChangedLocked();
}
}
}
private void handleBatteryStateChangedLocked() {mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
/*** Updates the global power state based on dirty bits recorded in mDirty.
*
* This is the main function that performs power state transitions.
* We centralize them here so that we can recompute the power state completely
* each time something important changes, and ensure that we do it the same
* way each time. The point is to gather all of the transition logic here.
*/
private void updatePowerStateLocked() {
...
// Phase 3: Update display power state.
final boolean displayBecameReady = updateDisplayPowerStateLocked (dirtyPhase2);
...
/*** Updates the display power state asynchronously.
* When the update is finished, mDisplayReady will be set to true. The display
* controller posts a message to tell us when the actual display power state
* has been updated so we come back here to double-check and finish up.
*
* This function recalculates the display power state each time.
*
* @return True if the display became ready.
*/
private boolean updateDisplayPowerStateLocked (int dirty) {
...
updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
//
mDisplayReady = mDisplayManagerInternal.requestPowerState (mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
..
}
//向 lowPowerMode赋值看是否低电量模式
@VisibleForTesting
void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
PowerSaveState state = mBatterySaverPolicy.
getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
displayPowerRequest.lowPowerMode = state.batterySaverEnabled ;
displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
}
(2) updatePowerState函数
SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void updatePowerState() {
...
// If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
// as long as it is above the minimum threshold.
//对于低电量模式进行定制
if (mPowerRequest.lowPowerMode ) {
if (brightnessState > mScreenBrightnessRangeMinimum) {
//使用screenLowPowerBrightnessFactor 参数作为缩放亮度的因数
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor , 1);
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
//
brightnessState = Math.max(lowPowerBrightnessFloat,
mScreenBrightnessRangeMinimum);
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
}
if (!mAppliedLowPower) {
slowChange = false;
}
mAppliedLowPower = true;
} else if (mAppliedLowPower) {
slowChange = false;
mAppliedLowPower = false;
}
...
(3) screenLowPowerBrightnessFactor 的默认值
LAW.BR.5.1/LINUX/android/frameworks/base/core/java/android/hardware/display/DisplayManagerInternal.java
// The factor to adjust the screen brightness in low power mode in the range
// 0 (screen off) to 1 (no change)
public float screenLowPowerBrightnessFactor;
public DisplayPowerRequest() {
...
screenLowPowerBrightnessFactor = 0.5f;
}
六. 自动进入省电模式
(1) 配置文件:
LAW.BR.5.1/LINUX/android/frameworks/base/core/res/res/values/config.xml
<!-- Display low battery warning when battery level dips to this value -->
<integer name="config_lowBatteryWarningLevel">15</integer>
<!-- Close low battery warning when battery level reaches the lowBatteryWarningLevel
plus this -->
<integer name="config_lowBatteryCloseWarningBump">5</integer>
<!-- Config flag to track default disable threshold for Dynamic power savings enabled battery saver. -->
<!--动态退出省电模式的阈值-->
<integer name="config_dynamicPowerSavingsDefaultDisableThreshold">80</integer>
(2) 分析BatteryService.java
/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/BatteryService.java
- 初始化:
public BatteryService(Context context) {
...
//进入低电量模式的阈值,默认值是15%
mLowBatteryWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
//退出低电量模式的阈值,默认值是20%
mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningBump);
..
}
- healthInfoChanged()函数回调
private final class HealthHalCallback extends IHealthInfoCallback.Stub
implements HealthServiceWrapper.Callback {
@Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
android.hardware.health.V2_1.HealthInfo propsLatest =
new android.hardware.health.V2_1.HealthInfo();
propsLatest.legacy = props;
propsLatest.batteryCapacityLevel = BatteryCapacityLevel.UNSUPPORTED;
propsLatest.batteryChargeTimeToFullNowSeconds =
Constants.BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED;
BatteryService.this.update (propsLatest);
}
- update函数调用
private void update(android.hardware.health.V2_1.HealthInfo info) {
synchronized (mLock) {
if (!mUpdatesStopped) {
mHealthInfo = info.legacy.legacy;
mHealthInfo2p1 = info;
// Process the new values.
processValuesLocked(false);
mLock.notifyAll(); // for any waiters on new info
} else {
copy(mLastHealthInfo, info.legacy.legacy);
}
}
}
- processValuesLocked函数
private void processValuesLocked (boolean force) {
...
if (!mBatteryLevelLow) {
// Should we now switch in to low battery mode?
if (mPlugType == BATTERY_PLUGGED_NONE
&& mHealthInfo.batteryStatus !=
BatteryManager.BATTERY_STATUS_UNKNOWN
&& mHealthInfo.batteryLevel <= mLowBatteryWarningLevel) {
mBatteryLevelLow = true;
}
}
...
}
- getBatteryLevelLow函数暴露给其他对象
@Override
public boolean getBatteryLevelLow() {
synchronized (mLock) {
return mBatteryLevelLow;
}
}
(3) 同7 (1) 中监听电池信息变化.
1)当电池信息发生改变时,会触发updatePowerStateLocked函数,在上面已经讲过。
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
private void updatePowerStateLocked() {
...
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
...
}
- 获取低电量模式,并传递至BatterySaverStateMachine
/**
* Updates the value of mIsPowered.
* Sets DIRTY_IS_POWERED if a change occurred.
*/
private void updateIsPoweredLocked(int dirty) {
...
//获取Battery Level
mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();//获取当前是否处于低电量模式
mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();...
//更新BatterySaverStateMachine中的Battery Status
mBatterySaverStateMachine.setBatteryStatus(mIsPowered , mBatteryLevel, mBatteryLevelLow);
...
}
(3)分析 BatterySaverStateMachine.java:
- setBatteryStatus函数
/**
* {@link com.android.server.power.PowerManagerService} calls it when battery state changes.
*
* Note this may be called before {@link #onBootCompleted} too.
*/
public void setBatteryStatus(boolean newPowered, int newLevel, boolean newBatteryLevelLow) {
synchronized (mLock) {
mBatteryStatusSet = true;
final boolean poweredChanged = mIsPowered != newPowered;
final boolean levelChanged = mBatteryLevel != newLevel;
final boolean lowChanged = mIsBatteryLevelLow != newBatteryLevelLow;
if (!(poweredChanged || levelChanged || lowChanged)) {
return;
}
mIsPowered = newPowered;
mBatteryLevel = newLevel;
mIsBatteryLevelLow = newBatteryLevelLow;
doAutoBatterySaverLocked();
}
}
- 变量定义:
/** Whether the device is connected to any power source. */
@GuardedBy("mLock")
//是否处于充电状态
private boolean mIsPowered;
/** Current battery level in %, 0-100. (Currently only used in dumpsys.) */
@GuardedBy("mLock")
//当前电池电量的level
private int mBatteryLevel;
/** Whether the battery level is considered to be "low" or not. */
@GuardedBy("mLock")
//是否处于低电量
private boolean mIsBatteryLevelLow;
- doAutoBatterySaverLocked函数:
/**
* Decide whether to auto-start / stop battery saver.
*/
@GuardedBy("mLock")
private void doAutoBatterySaverLocked() {
updateStateLocked(false, false);
// Adaptive control.
//统计时间是否超过ADAPTIVE_CHANGE_TIMEOUT_MS(24小时)
if (SystemClock.elapsedRealtime() - mLastAdaptiveBatterySaverChangedExternallyElapsed
> ADAPTIVE_CHANGE_TIMEOUT_MS) {
//退出POLICY_LEVEL_ADAPTIVE模式
mBatterySaverController.setAdaptivePolicyEnabledLocked(
false, BatterySaverController.REASON_TIMEOUT);
mBatterySaverController.resetAdaptivePolicyLocked(
BatterySaverController.REASON_TIMEOUT);
} else if (mIsPowered && mBatteryLevel >= ADAPTIVE_AUTO_DISABLE_BATTERY_LEVEL) {
//若是充电 并且电池电量超过80%
//退出POLICY_LEVEL_ADAPTIVE模式
mBatterySaverController.setAdaptivePolicyEnabledLocked(false,
BatterySaverController.REASON_PLUGGED_IN);
}
}
- updateStateLocked 函数
/**
* Update the state machine based on the current settings and battery/charge status.
*
* @param manual Whether the change was made by the user.
* @param enable Whether the user wants to turn battery saver on or off. Is only used if {@param
* manual} is true.
*/
@GuardedBy("mLock")
private void updateStateLocked (boolean manual, boolean enable) {
if (!manual && !(mBootCompleted && mSettingsLoaded && mBatteryStatusSet)) {
return; // Not fully initialized yet.
}
switch (mState) {
case STATE_OFF: {
//没有充电
if (**!**mIsPowered) {
if (manual) {
if (!enable) {
Slog.e(TAG, "Tried to disable BS when it's already OFF");
return;
}
enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
BatterySaverController.REASON_MANUAL_ON);
hideStickyDisabledNotification();
mState = STATE_MANUAL_ON;
} else if (isAutomaticModeActiveLocked() && isInAutomaticLowZoneLocked()) {
//若是自动模式 并且 属于低电量
enableBatterySaverLocked(/*enable*/ true , /*manual*/ false,
BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_ON);
hideStickyDisabledNotification();
mState = STATE_AUTOMATIC_ON;
} else if (isDynamicModeActiveLocked() && isInDynamicLowZoneLocked()) {
enableBatterySaverLocked(/*enable*/ true, /*manual*/ false,
BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON);
hideStickyDisabledNotification();
mState = STATE_AUTOMATIC_ON;
}
}
break;
}
case STATE_MANUAL_ON: {
if (manual) {
if (enable) {
Slog.e(TAG, "Tried to enable BS when it's already MANUAL_ON");
return;
}
enableBatterySaverLocked(/*enable*/ false, /*manual*/ true,
BatterySaverController.REASON_MANUAL_OFF);
mState = STATE_OFF;
} else if (mIsPowered) {
enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
BatterySaverController.REASON_PLUGGED_IN);
if (mSettingBatterySaverEnabledSticky
&& !mBatterySaverStickyBehaviourDisabled) {
mState = STATE_PENDING_STICKY_ON;
} else {
mState = STATE_OFF;
}
}
break;
}
case STATE_AUTOMATIC_ON: {
if (mIsPowered) {
enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
BatterySaverController.REASON_PLUGGED_IN);
mState = STATE_OFF;
} else if (manual) {
if (enable) {
Slog.e(TAG, "Tried to enable BS when it's already AUTO_ON");
return;
}
enableBatterySaverLocked(/*enable*/ false, /*manual*/ true,
BatterySaverController.REASON_MANUAL_OFF);
// When battery saver is disabled manually (while battery saver is enabled)
// when the battery level is low, we "snooze" BS -- i.e. disable auto battery
// saver.
// We resume auto-BS once the battery level is not low, or the device is
// plugged in.
mState = STATE_OFF_AUTOMATIC_SNOOZED;
} else if (isAutomaticModeActiveLocked() && !isInAutomaticLowZoneLocked()) {
enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
BatterySaverController.REASON_PERCENTAGE_AUTOMATIC_OFF);
mState = STATE_OFF;
} else if (isDynamicModeActiveLocked() && !isInDynamicLowZoneLocked()) {
enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF);
mState = STATE_OFF;
} else if (!isAutomaticModeActiveLocked() && !isDynamicModeActiveLocked()) {
enableBatterySaverLocked(/*enable*/ false, /*manual*/ false,
BatterySaverController.REASON_SETTING_CHANGED);
mState = STATE_OFF;
}
break;
}
case STATE_OFF_AUTOMATIC_SNOOZED: {
if (manual) {
if (!enable) {
Slog.e(TAG, "Tried to disable BS when it's already AUTO_SNOOZED");
return;
}
enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
BatterySaverController.REASON_MANUAL_ON);
mState = STATE_MANUAL_ON;
} else if (mIsPowered // Plugging in resets snooze.
|| (isAutomaticModeActiveLocked() && !isInAutomaticLowZoneLocked())
|| (isDynamicModeActiveLocked() && !isInDynamicLowZoneLocked())
|| (!isAutomaticModeActiveLocked() && !isDynamicModeActiveLocked())) {
mState = STATE_OFF;
}
break;
}
case STATE_PENDING_STICKY_ON: {
if (manual) {
// This shouldn't be possible. We'll only be in this state when the device is
// plugged in, so the user shouldn't be able to manually change state.
Slog.e(TAG, "Tried to manually change BS state from PENDING_STICKY_ON");
return;
}
final boolean shouldTurnOffSticky = mSettingBatterySaverStickyAutoDisableEnabled
&& mBatteryLevel >= mSettingBatterySaverStickyAutoDisableThreshold;
final boolean isStickyDisabled =
mBatterySaverStickyBehaviourDisabled || !mSettingBatterySaverEnabledSticky;
if (isStickyDisabled || shouldTurnOffSticky) {
mState = STATE_OFF;
setStickyActive(false);
triggerStickyDisabledNotification();
} else if (!mIsPowered) {
// Re-enable BS.
enableBatterySaverLocked(/*enable*/ true, /*manual*/ true,
BatterySaverController.REASON_STICKY_RESTORE);
mState = STATE_MANUAL_ON;
}
break;
}
default:
Slog.wtf(TAG, "Unknown state: " + mState);
break;
}
- isAutomaticModeActiveLocked 函数:
/** @return true if the automatic percentage based mode should be used */
private boolean isAutomaticModeActiveLocked() {
return mSettingAutomaticBatterySaver == PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE
&& mSettingBatterySaverTriggerThreshold > 0;
}
- refreshSettingsLocked 函数:
主要获取变量automaticBatterySaverMode值
@GuardedBy("mLock")
private void refreshSettingsLocked() {
final boolean lowPowerModeEnabled = getGlobalSetting(
Settings.Global.LOW_POWER_MODE, 0) != 0;
final boolean lowPowerModeEnabledSticky = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
final boolean dynamicPowerSavingsBatterySaver = getGlobalSetting(
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0;
final int lowPowerModeTriggerLevel = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
//默认值:POWER_SAVE_MODE_TRIGGER_PERCENTAGE 为0
final int automaticBatterySaverMode = getGlobalSetting(
Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
final int dynamicPowerSavingsDisableThreshold = getGlobalSetting(
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD,
mDynamicPowerSavingsDefaultDisableThreshold);
final boolean isStickyAutoDisableEnabled = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 1) != 0;
final int stickyAutoDisableThreshold = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 90);
setSettingsLocked(lowPowerModeEnabled, lowPowerModeEnabledSticky,
lowPowerModeTriggerLevel,
isStickyAutoDisableEnabled, stickyAutoDisableThreshold,
automaticBatterySaverMode ,
dynamicPowerSavingsBatterySaver, dynamicPowerSavingsDisableThreshold);
}
- mSettingsObserver对象监听url 变化
意图是动态刷新变量值:
private final ContentObserver mSettingsObserver = new ContentObserver(null) {
@Override
public void onChange (boolean selfChange) {
synchronized (mLock) {
refreshSettingsLocked();
}
}
};
- setSettingsLocked函数:
在此流程中主要的目的是mSettingAutomaticBatterySaver 赋值:
/**
* {@link com.android.server.power.PowerManagerService} calls it when relevant global settings
* have changed.
*
* Note this will be called before {@link #onBootCompleted} too.
*/
@GuardedBy("mLock")
@VisibleForTesting
void setSettingsLocked(boolean batterySaverEnabled, boolean batterySaverEnabledSticky,
int batterySaverTriggerThreshold,
boolean isStickyAutoDisableEnabled, int stickyAutoDisableThreshold,
int automaticBatterySaver ,
boolean dynamicPowerSavingsBatterySaver, int dynamicPowerSavingsDisableThreshold) {
...
mSettingAutomaticBatterySaver = automaticBatterySaver;
...
}
- enableBatterySaverLocked 函数分析:
@GuardedBy("mLock")
private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason) {
enableBatterySaverLocked(enable, manual, intReason, reasonToString(intReason));
}
/**
* Actually enable / disable battery saver. Write the new state to the global settings
* and propagate it to {@link #mBatterySaverController}.
*/
@GuardedBy("mLock")
private void enableBatterySaverLocked(boolean enable, boolean manual , int intReason,
String strReason) {
final boolean wasEnabled = mBatterySaverController.isFullEnabled();
if (wasEnabled == enable) {
return;
}
if (enable && mIsPowered) {
return;
}
mLastChangedIntReason = intReason;
mLastChangedStrReason = strReason;
mSettingBatterySaverEnabled = enable;
putGlobalSetting(Settings.Global.LOW_POWER_MODE, enable ? 1 : 0);
if (manual) {
setStickyActive(!mBatterySaverStickyBehaviourDisabled && enable);
}
//会发送低电量广播,后面会讲解:
mBatterySaverController.enableBatterySaver (enable, intReason);
// Handle triggering the notification to show/hide when appropriate
//UI上控制
if (intReason == BatterySaverController.REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON) {
triggerDynamicModeNotification();
} else if (!enable) {
hideDynamicModeNotification();
}
}
(4) BatterySaverController.java 中涉及到的流程讲解:
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
- enableBatterySaver 函数:
/** Enable or disable full battery saver. */
@VisibleForTesting
public void enableBatterySaver(boolean enable, int reason) {
synchronized (mLock) {
if (getFullEnabledLocked() == enable) {
return;
}
//在此流程中enable为true
setFullEnabledLocked(enable);
//updatePolicyLevelLocked 函数下面会讲解
if (updatePolicyLevelLocked()) {
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
}
}
}
- setFullEnabledLocked 函数:
主要目的是mFullEnabledRaw赋值为true
@GuardedBy("mLock")
private void setFullEnabledLocked(boolean value) {
if (mFullEnabledRaw == value) {
return;
}
PowerManager.invalidatePowerSaveModeCaches();
mFullEnabledRaw = value;
}
- getFullEnabledLocked 函数:
主要目的是判断full 策略是否支持: 在此流程中,是支持的(true)
/** Non-blocking getter exists as a reminder not to directly modify the cached field */
private boolean getFullEnabledLocked() {
return mFullEnabledRaw;
}
- updatePolicyLevelLocked函数:
上面讲到:enableBatterySaver 函数里面会调用到updatePolicyLevelLocked
private boolean updatePolicyLevelLocked() {
//从上面流程可以看到getFullEnabledLocked()获取值是true
if (getFullEnabledLocked()) {
//配置策略为POLICY_LEVEL_FULL
return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_FULL);
} else if (getAdaptiveEnabledLocked()) {
return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_ADAPTIVE);
} else {
return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_OFF);
}
}
(5) BatterySaverPolicy.java 涉及到流程:
1)setPolicyLevel 函数讲解:
其目的mPolicyLevel赋值和updatePolicyDependenciesLocked函数执行
/**
* Sets the current policy.
*
* @return true if the policy level was changed.
*/
boolean setPolicyLevel(@PolicyLevel int level) {
synchronized (mLock) {
if (mPolicyLevel == level) {
return false;
}
switch (level) {
case POLICY_LEVEL_FULL:
case POLICY_LEVEL_ADAPTIVE:
case POLICY_LEVEL_OFF:
mPolicyLevel = level;
break;
default:
Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level);
return false;
}
updatePolicyDependenciesLocked();
return true;
}
}
- updatePolicyDependenciesLocked函数:
其目的:
@GuardedBy("mLock")
private void updatePolicyDependenciesLocked() {
//获取当前Policy
final Policy rawPolicy = getCurrentRawPolicyLocked ();
final int locationMode;
invalidatePowerSaveModeCaches();
if (mCarModeEnabled
&& rawPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE
&& rawPolicy.locationMode != PowerManager.LOCATION_MODE_FOREGROUND_ONLY) {
// If car projection is enabled, ensure that navigation works.
locationMode = PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
} else {
locationMode = rawPolicy.locationMode;
}
//mEffectivePolicyRaw重新赋值
mEffectivePolicyRaw = new Policy(
rawPolicy.adjustBrightnessFactor,
rawPolicy.advertiseIsEnabled,
rawPolicy.deferFullBackup,
rawPolicy.deferKeyValueBackup,
rawPolicy.disableAnimation,
rawPolicy.disableAod,
rawPolicy.disableLaunchBoost,
rawPolicy.disableOptionalSensors,
rawPolicy.disableSoundTrigger,
// Don't disable vibration when accessibility is on.
rawPolicy.disableVibration && !mAccessibilityEnabled,
rawPolicy.enableAdjustBrightness,
rawPolicy.enableDataSaver,
rawPolicy.enableFirewall,
// Don't force night mode when car projection is enabled.
rawPolicy.enableNightMode && !mCarModeEnabled,
rawPolicy.enableQuickDoze,
rawPolicy.filesForInteractive,
rawPolicy.filesForNoninteractive,
rawPolicy.forceAllAppsStandby,
rawPolicy.forceBackgroundCheck,
locationMode
);
}
- getCurrentRawPolicyLocked函数:
其目的是获取对应的policy,当前流程policy是mFullPolicy
private Policy getCurrentRawPolicyLocked() {
switch (mPolicyLevel) {
case POLICY_LEVEL_FULL:
return mFullPolicy;
case POLICY_LEVEL_ADAPTIVE:
return mAdaptivePolicy;
case POLICY_LEVEL_OFF:
default:
return OFF_POLICY;
}
}
- mFullPolicy的定义:
/** The policy to be used for full battery saver. */
@GuardedBy("mLock")
//这是默认值:
private Policy mFullPolicy = DEFAULT_FULL_POLICY;
//通过deviceSpecificSetting 动态获取,若配置信息没有则从DEFAULT_FULL_POLICY中获取信息.在源码中没有发现有客户端触发deviceSpecificSetting。 预留接口: PowerManager.java::setAdaptivePowerSavePolicy(@NonNull BatterySaverPolicyConfig config), 目前逻辑就认为是polic 就复制DEFAULT_FULL_POLICY 里面的内容。
Policy newFullPolicy = Policy.fromSettings(setting, deviceSpecificSetting,
DEFAULT_FULL_POLICY);
mFullPolicy = newFullPolicy;
- DEFAULT_FULL_POLICY 定义:
private static final Policy DEFAULT_FULL_POLICY = new Policy(
0.5f, /* adjustBrightnessFactor */
true, /* advertiseIsEnabled */
true, /* deferFullBackup */
true, /* deferKeyValueBackup */
false, /* disableAnimation */
true, /* disableAod */
true, /* disableLaunchBoost */
true, /* disableOptionalSensors */
true, /* disableSoundTrigger */
true, /* disableVibration */
false, /* enableAdjustBrightness */
false, /* enableDataSaver */
true, /* enableFirewall */
true, /* enableNightMode */
true, /* enableQuickDoze */
new ArrayMap<>(), /* filesForInteractive */
new ArrayMap<>(), /* filesForNoninteractive */
true, /* forceAllAppsStandby */
true, /* forceBackgroundCheck */
PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF /* locationMode */
);
- 前面讲了那么多,其实是为updatePowerRequestFromBatterySaverPolicy 函数里面,获取PowerSaveState 铺垫:
再此阅读updatePowerRequestFromBatterySaverPolicy
@VisibleForTesting
void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
//很明显mBatterySaverPolicy 的值就是来自DEFAULT_FULL_POLICY,
PowerSaveState state = mBatterySaverPolicy.
getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
//若是使用默认DEFAULT_FULL_POLICY的获取到state.batterySaverEnabled 为false
displayPowerRequest.lowPowerMode = state.batterySaverEnabled ;
displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
}
/*** Get the {@link PowerSaveState} based on the current policy level.
* The result will have {@link PowerSaveState#batterySaverEnabled} and some other
* parameters when necessary.
*
* @param type type of the service, one of {@link ServiceType}
* @return State data that contains battery saver data
*/
public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
synchronized (mLock) {
final Policy currPolicy = getCurrentPolicyLocked();
final PowerSaveState.Builder builder = new PowerSaveState.Builder()
.setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
switch (type) {
..
case ServiceType.SCREEN_BRIGHTNESS:
//enableAdjustBrightness是false ,adjustBrightnessFactor 是0.5
return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
.setBrightnessFactor(currPolicy.adjustBrightnessFactor)
.build();
..
七.低电量广播发送
(1) 广播发送定义: 在handleBatterySaverStateChanged函数中.
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
1)广播发送:
/**
* Dispatch power save events to the listeners.
*
* This method is always called on the handler thread.
*
* This method is called only in the following cases:
* - When battery saver becomes activated.
* - When battery saver becomes deactivated.
* - When battery saver is on and the interactive state changes.
* - When battery saver is on and the battery saver policy changes.
* - When adaptive battery saver becomes activated.
* - When adaptive battery saver becomes deactivated.
* - When adaptive battery saver is active (and full is off) and the policy changes.
*/
void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
final LowPowerModeListener[] listeners;
final boolean enabled;
final boolean isInteractive = getPowerManager().isInteractive();
final ArrayMap<String, String> fileValues;
synchronized (mLock) {
enabled = getFullEnabledLocked() || getAdaptiveEnabledLocked();
EventLogTags.writeBatterySaverMode(
mFullPreviouslyEnabled ? 1 : 0, // Previously off or on.
mAdaptivePreviouslyEnabled ? 1 : 0, // Previously off or on.
getFullEnabledLocked() ? 1 : 0, // Now off or on.
getAdaptiveEnabledLocked() ? 1 : 0, // Now off or on.
isInteractive ? 1 : 0, // Device interactive state.
enabled ? mBatterySaverPolicy.toEventLogString() : "",
reason);
mFullPreviouslyEnabled = getFullEnabledLocked();
mAdaptivePreviouslyEnabled = getAdaptiveEnabledLocked();
listeners = mListeners.toArray(new LowPowerModeListener[0]);
mIsInteractive = isInteractive;
if (enabled) {
fileValues = mBatterySaverPolicy.getFileValues(isInteractive);
} else {
fileValues = null;
}
}
final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
if (pmi != null) {
pmi.powerHint(PowerHint.LOW_POWER, isEnabled() ? 1 : 0);
}
updateBatterySavingStats();
if (ArrayUtils.isEmpty(fileValues)) {
mFileUpdater.restoreDefault();
} else {
mFileUpdater.writeFiles(fileValues);
}
for (Plugin p : mPlugins) {
p.onBatterySaverChanged(this);
}
//sendBroadcast 为true 时才发送广播
if (sendBroadcast) {
if (DEBUG) {
Slog.i(TAG, "Sending broadcasts for mode: " + isEnabled());
}
// Send the broadcasts and notify the listeners. We only do this when the battery saver
// mode changes, but not when only the screen state changes.
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
.putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, isEnabled())
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
// Send the broadcast to a manifest-registered receiver that is specified in the config.
if (getPowerSaveModeChangedListenerPackage().isPresent()) {
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)
.setPackage(getPowerSaveModeChangedListenerPackage().get())
.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
| Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
// Send internal version that requires signature permission.
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
Manifest.permission.DEVICE_POWER);
//对listeners做callback
for (LowPowerModeListener listener : listeners) {
final PowerSaveState result =
mBatterySaverPolicy.getBatterySaverPolicy(listener.getServiceType());
listener.onLowPowerModeChanged(result);
}
}
}
- 通过接收MSG_STATE_CHANGED进行判断是否要发送广播;postStateChanged函数触发MSG_STATE_CHANGED handle 机制。
private class MyHandler extends Handler { private static final int MSG_STATE_CHANGED = 1; void postStateChanged(boolean sendBroadcast, int reason) { obtainMessage(MSG_STATE_CHANGED, sendBroadcast ? ARG_SEND_BROADCAST : ARG_DONT_SEND_BROADCAST, reason).sendToTarget(); } @Override public void dispatchMessage(Message msg) { switch (msg.what) { case MSG_STATE_CHANGED: handleBatterySaverStateChanged( msg.arg1 == ARG_SEND_BROADCAST, msg.arg2); break; } } }
- 触发postStateChanged函数的地方: onBatterySaverPolicyChanged/enableBatterySaver/setAdaptivePolicyLocked/resetAdaptivePolicyLocked/setAdaptivePolicyEnabledLocked
@Override
public void onBatterySaverPolicyChanged(BatterySaverPolicy policy) {
if (!isPolicyEnabled()) {
return; // No need to send it if not enabled.
}
mHandler.postStateChanged(/*sendBroadcast=*/ true, REASON_POLICY_CHANGED);
}
/** Enable or disable full battery saver. */
@VisibleForTesting
public void enableBatterySaver(boolean enable, int reason) {
synchronized (mLock) {
if (getFullEnabledLocked() == enable) {
return;
}
setFullEnabledLocked(enable);
if (updatePolicyLevelLocked()) {
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
}
}
}
boolean setAdaptivePolicyLocked(Policy policy, int reason) {
if (mBatterySaverPolicy.setAdaptivePolicyLocked(policy)) {
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
return true;
}
return false;
}
boolean resetAdaptivePolicyLocked(int reason) {
if (mBatterySaverPolicy.resetAdaptivePolicyLocked()) {
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
return true;
}
return false;
}
boolean setAdaptivePolicyEnabledLocked(boolean enabled, int reason) {
if (getAdaptiveEnabledLocked() == enabled) {
return false;
}
setAdaptiveEnabledLocked(enabled);
if (updatePolicyLevelLocked()) {
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
return true;
}
return false;
}
八. 总结
1.低电量广播何时发送?
当处于低电量时,电量小于15%时, 会触发ACTION_POWER_SAVE_MODE_CHANGED,下发给各个接受者。
- 已经处于低电量状态,是否重复下发ACTION_POWER_SAVE_MODE_CHANGED 下发给各个接受者,告知还是处于低电量模式?
从源码上看,是不会重新下发告知是处于低电量,除非当手机充电或者手动关闭等退出省电模式。
- 自动进入省电模式,都会影响那些方面?
主要看使用那种省电模式的policy,默认是full policy ,主要影响的有:DEFAULT_FULL_POLICY 和OFF_POLICY .当然,可以自定义policy.
- 什么情况下会退出省电模式?
(1) 有充电行为,譬如: AC ,USB ,无线充电。
(2) 电量大于等于20%(默认)
(3) 当电量大于等于15%(默认) 并且在Setting中手动关闭省电模式。
- 在哪里配置进入省电模式和退出省电模式的等级?
LAW.BR.5.1/LINUX/android/frameworks/base/core/res/res/values/config.xml
<!-- Display low battery warning when battery level dips to this value -->
<integer name="config_lowBatteryWarningLevel">15</integer>
<!-- Close low battery warning when battery level reaches the lowBatteryWarningLevel
plus this -->
<integer name="config_lowBatteryCloseWarningBump">5</integer>
<!-- Config flag to track default disable threshold for Dynamic power savings enabled battery saver. -->
- 省电模式的policy 动态配置信息,保存在哪里?
adb shell settings get Global battery_saver_device_specific_constants