Android battery saver 简单记录

目录

[一. 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;

}

  1. 更新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

当省电模式模式下,除了来电显示的震动(有条件的震动)

  1. 震动将取消(原来如果有震动的话)

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模式

  1. 找到控制开关

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");

}

  1. 对后台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

}

...

}

  1. 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

在省电模式下是否开启网络策略防火墙

  1. 获取引用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;

}

  1. 触发调用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);

}

}

  1. 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);

}

}

  1. 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);

}

}

  1. 更新白名单范围(允许访问的网络的范围),范围之外的通过防火墙停止网络链接

// 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);

}

}

}

  1. 更新所有应用的访问规则,除了前台进程和在白名单内的进程,都将不允许访问网络

@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

是否启用夜间模式,不包含汽车模式.

  1. 获取引用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

  1. 获取引用enableQuickDoze 值。

mLocalPowerManager.registerLowPowerModeObserver(ServiceType.QUICK_DOZE ,

state -> {

synchronized (DeviceIdleController.this) {

updateQuickDozeFlagLocked(state.batterySaverEnabled );

}

});

updateQuickDozeFlagLocked(

mLocalPowerManager.getLowPowerState(

ServiceType.QUICK_DOZE).batterySaverEnabled);

  1. 省电模式下,否可以快速进入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的作用.

  1. 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;

}

}

  1. 写入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

是否将所有应用程序置于待机模式

  1. 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();

...

}

  1. updateForceAllAppStandbyState 函数

private void updateForceAllAppStandbyState() {

synchronized (mLock) {

if (mForceAllAppStandbyForSmallBattery && isSmallBatteryDevice()) {

toggleForceAllAppsStandbyLocked (!mIsPluggedIn);

} else {

toggleForceAllAppsStandbyLocked (mBatterySaverEnabled);

}

}

}

  1. 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.");

}

...

  1. 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

有三处定义,分别从三处分析:

  1. 定义来自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 提供使用函数.

  1. 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();

}

  1. 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_POWERPOWER_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);

...}
@VisibleForTesting

final 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

  1. 初始化:

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);

..

}

  1. 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);

}

  1. 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);

}

}

}

  1. 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;

}

}

...

}

  1. 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);

...

}

  1. 获取低电量模式,并传递至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:

  1. 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();

}

}

  1. 变量定义:

/** 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;

  1. 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);

}

}

  1. 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;

}

  1. 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;

}

  1. 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);

}

  1. mSettingsObserver对象监听url 变化

意图是动态刷新变量值:

private final ContentObserver mSettingsObserver = new ContentObserver(null) {

@Override

public void onChange (boolean selfChange) {

synchronized (mLock) {

refreshSettingsLocked();

}

}

};

  1. 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;

...

}

  1. 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

  1. enableBatterySaver 函数:

/** Enable or disable full battery saver. */

@VisibleForTesting

public void enableBatterySaver(boolean enable, int reason) {

synchronized (mLock) {

if (getFullEnabledLocked() == enable) {

return;

}

//在此流程中enabletrue

setFullEnabledLocked(enable);

//updatePolicyLevelLocked 函数下面会讲解

if (updatePolicyLevelLocked()) {

mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);

}

}

}

  1. setFullEnabledLocked 函数:

主要目的是mFullEnabledRaw赋值为true

@GuardedBy("mLock")

private void setFullEnabledLocked(boolean value) {

if (mFullEnabledRaw == value) {

return;

}

PowerManager.invalidatePowerSaveModeCaches();

mFullEnabledRaw = value;

}

  1. getFullEnabledLocked 函数:

主要目的是判断full 策略是否支持: 在此流程中,是支持的(true)

/** Non-blocking getter exists as a reminder not to directly modify the cached field */

private boolean getFullEnabledLocked() {

return mFullEnabledRaw;

}

  1. 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;

}

}

  1. 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

);

}

  1. 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;

}

}

  1. 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;

  1. 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 */

);

  1. 前面讲了那么多,其实是为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);

}

}

}

  1. 通过接收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;
            }
        }
    }
  1. 触发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,下发给各个接受者。

  1. 已经处于低电量状态,是否重复下发ACTION_POWER_SAVE_MODE_CHANGED 下发给各个接受者,告知还是处于低电量模式?

从源码上看,是不会重新下发告知是处于低电量,除非当手机充电或者手动关闭等退出省电模式。

  1. 自动进入省电模式,都会影响那些方面?

主要看使用那种省电模式的policy,默认是full policy ,主要影响的有:DEFAULT_FULL_POLICY 和OFF_POLICY .当然,可以自定义policy.

  1. 什么情况下会退出省电模式?

(1) 有充电行为,譬如: AC ,USB ,无线充电。

(2) 电量大于等于20%(默认)

(3) 当电量大于等于15%(默认) 并且在Setting中手动关闭省电模式。

  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. -->

  1. 省电模式的policy 动态配置信息,保存在哪里?

adb shell settings get Global battery_saver_device_specific_constants

相关推荐
勿问东西1 小时前
【Android】设备操作
android
五味香1 小时前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
图王大胜3 小时前
Android Framework AMS(01)AMS启动及相关初始化1-4
android·framework·ams·systemserver
工程师老罗5 小时前
Android Button “No speakable text present” 问题解决
android
小雨cc5566ru6 小时前
hbuilderx+uniapp+Android健身房管理系统 微信小程序z488g
android·微信小程序·uni-app
小雨cc5566ru7 小时前
微信小程序hbuilderx+uniapp+Android 新农村综合风貌旅游展示平台
android·微信小程序·uni-app
小雨cc5566ru7 小时前
小程序 uniapp+Android+hbuilderx体育场地预约管理系统的设计与实现
android·小程序·uni-app
佛系小嘟嘟9 小时前
Android-由switch-case和view.getId()引起的bug:错误:需要常量表达式 的解决办法
android·bug
勿问东西9 小时前
【Android】事件
android
连连斯基12 小时前
Android Framework(八)WMS-窗口动效概述
android·dubbo