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

相关推荐
有位神秘人1 天前
Android中Notification的使用详解
android·java·javascript
·云扬·1 天前
MySQL Binlog落盘机制深度解析:性能与安全性的平衡艺术
android·mysql·adb
独自破碎E1 天前
【BISHI9】田忌赛马
android·java·开发语言
代码s贝多芬的音符1 天前
android 两个人脸对比 mlkit
android
darkb1rd1 天前
五、PHP类型转换与类型安全
android·安全·php
gjxDaniel1 天前
Kotlin编程语言入门与常见问题
android·开发语言·kotlin
csj501 天前
安卓基础之《(22)—高级控件(4)碎片Fragment》
android
峥嵘life1 天前
Android16 【CTS】CtsMediaCodecTestCases等一些列Media测试存在Failed项
android·linux·学习
stevenzqzq1 天前
Compose 中的状态可变性体系
android·compose
似霰1 天前
Linux timerfd 的基本使用
android·linux·c++