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); > > } > > } 3) 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); > > } > > } 4) 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); > > } > > } 5) 更新白名单范围(允许访问的网络的范围),范围之外的通过防火墙停止网络链接 > // 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\ 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**); > > } > > } > > } 7) 更新所有应用的访问规则,除了前台进程和在白名单内的进程,都将不允许访问网络 > @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**); 2) 省电模式下,否可以快速进入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\ **getFileValues**(boolean interactive) { > > synchronized (mLock) { > > return interactive ? getCurrentPolicyLocked().**filesForInteractive** > > : getCurrentPolicyLocked().filesForNoninteractive; > > } > > } 2) 写入**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**(); > > ... > > } 2) **updateForceAllAppStandbyState** 函数 > private void updateForceAllAppStandbyState() { > > synchronized (mLock) { > > if (mForceAllAppStandbyForSmallBattery \&\& isSmallBatteryDevice()) { > > **toggleForceAllAppsStandbyLocked** (!mIsPluggedIn); > > } else { > > **toggleForceAllAppsStandbyLocked** (mBatterySaverEnabled); > > } > > } > > } 3) 对**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."); > > } > > ... 2) 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}. > > \* > > \* \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 提供使用函数. 2) 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(); > > } 3) 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); > > ...} > @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 > \

相关推荐
顾林海19 分钟前
Android ClassLoader加载机制详解
android·面试·源码
用户20187928316720 分钟前
🎨 童话:Android画布王国的奇妙冒险
android
whysqwhw1 小时前
OkHttp框架的全面深入架构分析
android
你过来啊你1 小时前
Android App冷启动流程详解
android
泓博2 小时前
KMP(Kotlin Multiplatform)改造(Android/iOS)老项目
android·ios·kotlin
移动开发者1号2 小时前
使用Baseline Profile提升Android应用启动速度的终极指南
android·kotlin
移动开发者1号2 小时前
解析 Android Doze 模式与唤醒对齐
android·kotlin
菠萝加点糖4 小时前
Kotlin Data包含ByteArray类型
android·开发语言·kotlin
IAM四十二9 天前
Google 端侧 AI 框架 LiteRT 初探
android·深度学习·tensorflow
CYRUS_STUDIO10 天前
手把手教你用 Chrome 断点调试 Frida 脚本,JS 调试不再是黑盒
android·app·逆向