目录
[一. battery saver模式的policy](#一. battery saver模式的policy)
[(1) DEFAULT_FULL_POLICY 对应的配置和解释:](#(1) DEFAULT_FULL_POLICY 对应的配置和解释:)
[(2) OFF_POLICY 对应的配置也就说不使用policy](#(2) OFF_POLICY 对应的配置也就说不使用policy)
[(3) 获取省电模式下的policy:](#(3) 获取省电模式下的policy:)
[二. 对各个参数代码讲解](#二. 对各个参数代码讲解)
[(1) adjustBrightnessFactor](#(1) adjustBrightnessFactor)
[(2) enableAdjustBrightness](#(2) enableAdjustBrightness)
[(3) advertiseIsEnabled](#(3) advertiseIsEnabled)
[(4) deferFullBackup](#(4) deferFullBackup)
[(5) deferKeyValueBackup](#(5) deferKeyValueBackup)
[(6) disableAnimation](#(6) disableAnimation)
[(7) disableAod](#(7) disableAod)
[(8) disableLaunchBoost](#(8) disableLaunchBoost)
[(9) disableOptionalSensors](#(9) disableOptionalSensors)
[(10) disableSoundTrigger](#(10) disableSoundTrigger)
[(11) disableVibration](#(11) disableVibration)
[(12) enableDataSaver](#(12) enableDataSaver)
[(13) enableFirewall](#(13) enableFirewall)
[(14) enableNightMode](#(14) enableNightMode)
[(15) enableQuickDoze](#(15) enableQuickDoze)
[(16) filesForInteractive](#(16) filesForInteractive)
[(17) filesForNoninteractive](#(17) filesForNoninteractive)
[(18) forceAllAppsStandby](#(18) forceAllAppsStandby)
[(19) forceBackgroundCheck](#(19) forceBackgroundCheck)
[(20) locationMode](#(20) locationMode)
[三. 进入省电模式的入口](#三. 进入省电模式的入口)
[四. modem进入低电模式入口](#四. modem进入低电模式入口)
[五. 屏幕亮度将会变成原来的50%的流程](#五. 屏幕亮度将会变成原来的50%的流程)
[六. 自动进入省电模式](#六. 自动进入省电模式)
[八. 总结](#八. 总结)
一. battery saver模式的policy
(1) DEFAULT_FULL_POLICY 对应的配置和解释:
|------------------------|---------------------------------------------------------------------------------------------|--------------------|
| 字段 | 描述 | 默认值 |
| adjustBrightnessFactor | 将亮度调节为原来的百分比 | 0.5f |
| advertiseIsEnabled | 这是基本属性控制到部分省电的策略,譬如:控制location或者匹配不到对应type | true |
| deferFullBackup | 在省电模式下是否延迟备份 | true |
| deferKeyValueBackup | 在省电模式下是否延迟备份 | true |
| disableAnimation | 在省电模式下Window 动画是否被禁用 | false |
| disableAod | 在省电模式下,并且在doze 中是否禁用heads up | true |
| disableLaunchBoost | 在省电模式下是否禁用启动boost | true |
| disableOptionalSensors | 是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码. | true |
| disableSoundTrigger | 如果在省电模式下是否禁用声音触发的事件,譬如:语音识别 | true |
| disableVibration | 当省电模式模式下,除了来电显示的震动(有条件的震动) | true |
| enableAdjustBrightness | 如果在省电模式下,否打开低功耗模式亮度调节 | false |
| enableDataSaver | 在省电模式下,是否开启DataSaver模式 | false |
| enableFirewall | 是否应在省电模式下开启网络策略防火墙 | true |
| enableNightMode | 是否启用夜间模式 | true |
| enableQuickDoze | 是否启用快速打瞌睡模式 | true |
| filesForInteractive | 激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| filesForNoninteractive | 激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| forceAllAppsStandby | 是否将所有应用程序置于待机模式 | true |
| forceBackgroundCheck | 是否强制后台检查,譬如:强制停止idle UIDs | true |
| locationMode | 这是决定省电模式下定位模式的标志。 这以前称为 gpsMode。默认是PowerManager. LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF | |
(2) OFF_POLICY 对应的配置也就说不使用policy
|------------------------|--------------------------------------------------------------------------|--------------------|
| 字段 | 描述 | 默认值 |
| adjustBrightnessFactor | 将亮度调节为原来的百分比 | 1f |
| advertiseIsEnabled | 这是基本属性控制到部分省电的策略,譬如:控制location或者匹配不到对应type | false |
| deferFullBackup | 在省电模式下是否延迟备份 | false |
| deferKeyValueBackup | 在省电模式下是否延迟备份 | false |
| disableAnimation | 在省电模式下Window 动画是否被禁用 | false |
| disableAod | 在省电模式下,并且在doze 中是否禁用heads up | false |
| disableLaunchBoost | 在省电模式下是否禁用启动boost | false |
| disableOptionalSensors | 是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码. | false |
| disableSoundTrigger | 如果在省电模式下是否禁用声音触发的事件,譬如:语音识别 | false |
| disableVibration | 当省电模式模式下,除了来电显示的震动(有条件的震动) | false |
| enableAdjustBrightness | 如果在省电模式下,否打开低功耗模式亮度调节 | false |
| enableDataSaver | 在省电模式下,是否开启DataSaver模式 | false |
| enableFirewall | 是否应在省电模式下开启网络策略防火墙 | false |
| enableNightMode | 是否启用夜间模式 | false |
| enableQuickDoze | 是否启用快速打瞌睡模式 | false |
| filesForInteractive | 激活省电模式且设备处于交互状态时应写入的 [文件名 -> 内容] 列表。 我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| filesForNoninteractive | 激活省电模式且设备非交互式时应写入的 [文件名 -> 内容] 列表。我们用它来更改最大 CPU 频率。 | new ArrayMap<>() |
| forceAllAppsStandby | 是否将所有应用程序置于待机模式 | false |
| forceBackgroundCheck | 是否强制后台检查,譬如:强制停止idle UIDs | false |
| locationMode | 这是决定省电模式下定位模式的标志。 这以前称为 gpsMode。默认是PowerManager. LOCATION_MODE_NO_CHANGE | |
(3) 获取省电模式下的policy:
通过getBatterySaverPolicy函数获取各个type对应的参数:
SDM4100_AOSP_DEV/LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
/**
* Get the {@link PowerSaveState} based on the current policy level.
* The result will have {@link PowerSaveState#batterySaverEnabled} and some other
* parameters when necessary.
*
* @param type type of the service, one of {@link ServiceType}
* @return State data that contains battery saver data
*/
public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
synchronized (mLock) {
final Policy currPolicy = getCurrentPolicyLocked();
final PowerSaveState.Builder builder = new PowerSaveState.Builder()
.setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
switch (type) {
case ServiceType.LOCATION:
boolean isEnabled = currPolicy.advertiseIsEnabled
|| currPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE;
return builder.setBatterySaverEnabled(isEnabled)
.setLocationMode(currPolicy.locationMode)
.build();
case ServiceType.ANIMATION:
return builder.setBatterySaverEnabled(currPolicy.disableAnimation)
.build();
case ServiceType.FULL_BACKUP:
return builder.setBatterySaverEnabled(currPolicy.deferFullBackup)
.build();
case ServiceType.KEYVALUE_BACKUP:
return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup)
.build();
case ServiceType.NETWORK_FIREWALL:
return builder.setBatterySaverEnabled(currPolicy.enableFirewall)
.build();
case ServiceType.SCREEN_BRIGHTNESS:
return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
.setBrightnessFactor(currPolicy.adjustBrightnessFactor)
.build();
case ServiceType.DATA_SAVER:
return builder.setBatterySaverEnabled(currPolicy.enableDataSaver)
.build();
case ServiceType.SOUND:
return builder.setBatterySaverEnabled(currPolicy.disableSoundTrigger)
.build();
case ServiceType.VIBRATION:
return builder.setBatterySaverEnabled(currPolicy.disableVibration)
.build();
case ServiceType.FORCE_ALL_APPS_STANDBY :
return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
.build();
case ServiceType.FORCE_BACKGROUND_CHECK:
return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck)
.build();
case ServiceType.NIGHT_MODE:
return builder.setBatterySaverEnabled(currPolicy.enableNightMode)
.build();
case ServiceType.OPTIONAL_SENSORS :
return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors)
.build();
case ServiceType.AOD:
return builder.setBatterySaverEnabled(currPolicy.disableAod)
.build();
case ServiceType.QUICK_DOZE:
return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze)
.build();
default:
return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled)
.build();
}
}
}
二. 对各个参数代码讲解
(1) adjustBrightnessFactor
这是决定屏幕亮度调整多少的标志。 这是从 0 到 1 的浮点值,其中 1 表示不改变亮度. 1) LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
@VisibleForTesting
void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
PowerSaveState state = mBatterySaverPolicy.
getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
}
- 更新power 状态
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void updatePowerState() {
...
// If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor
// as long as it is above the minimum threshold.
if (mPowerRequest.lowPowerMode) {
if (brightnessState > mScreenBrightnessRangeMinimum) {
//获取screenLowPowerBrightnessFactor 参数作为缩放亮度的因数
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
//获取最小亮度值
final float lowPowerBrightnessFloat = (brightnessState * brightnessFactor);
//亮度值不能小于最小的亮度值
brightnessState = Math.max(lowPowerBrightnessFloat,
mScreenBrightnessRangeMinimum);
}
...
}
3)分发powerFactor 的数值
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java
private void notifyBrightnessChanged(int brightness, boolean userInitiated,
boolean hadUserDataPoint) {
final float brightnessInNits = convertToNits(brightness);
if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
&& mAutomaticBrightnessController != null) {
// We only want to track changes on devices that can actually map the display backlight
// values into a physical brightness unit since the value provided by the API is in
// nits and not using the arbitrary backlight units.
//若低电量模式,则获取policy中的配置值
final float powerFactor = mPowerRequest.lowPowerMode
? mPowerRequest.screenLowPowerBrightnessFactor
: 1.0f;
//将更改的powerFactor 分发下去
mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
powerFactor, hadUserDataPoint,
mAutomaticBrightnessController.isDefaultConfig());
}
}
(2) enableAdjustBrightness
enableAdjustBrightness 和adjustBrightnessFactor是搭配起来用的。使用方法和adjustBrightnessFactor 一样。
在省电模式下是否打开低功耗模式亮度调节应。
(3) advertiseIsEnabled
若获取的policy的type匹配不上则,则使用此值作为默认值。
(4) deferFullBackup
在省电模式下是否推迟完整备份。
LAW.BR.5.1/LINUX/android/frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
/**
* Conditions are right for a full backup operation, so run one. The model we use is
* to perform one app backup per scheduled job execution, and to reschedule the job
* with zero latency as long as conditions remain right and we still have work to do.
*
* <p>This is the "start a full backup operation" entry point called by the scheduled job.
*
* @return Whether ongoing work will continue. The return value here will be passed
* along as the return value to the scheduled job's onStartJob() callback.
*/
public boolean beginFullBackup(FullBackupJob scheduledJob) {
// Don't run the backup if we're in battery saver mode, but reschedule
// to try again in the not-so-distant future.
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.FULL_BACKUP);
if (result.batterySaverEnabled) {
//如果处于省电模式,请不要运行备份,但要重新安排在不久的将来重试。
FullBackupJob.schedule(mUserId, mContext, keyValueBackupInterval, mConstants);
return false;
}
}
(5) deferKeyValueBackup
在省电模式下是否推迟键值(Key-value Backup)备份。
关于Key-value Backup 可以参考: 全面复盘Android开发者容易忽视的Backup功能 - 掘金
LAW.BR.5.1/LINUX/android/frameworks/base/services/backup/java/com/android/server/backup/UserBackupManagerService.java
/**
* Run a backup pass immediately for any applications that have declared that they have pending
* updates.
*/
public void backupNow() {
...
try {
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.KEYVALUE_BACKUP );
if (result.batterySaverEnabled) {
// Try again in several hours.
//推迟执行
KeyValueBackupJob.schedule(mUserId, mContext, mConstants);
}
...
(6) disableAnimation
在省电模式下是否禁止window 动画。
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
Supplier<Surface> surfaceFactory,
Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
...
if (mPowerManagerInternal != null) {
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public int getServiceType() {
return ServiceType.ANIMATION;
}
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
synchronized (mGlobalLock) {
final boolean enabled = result.batterySaverEnabled;
if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
mAnimationsDisabled = enabled ;
dispatchNewAnimatorScaleLocked(null);
}
}
}
});
mAnimationsDisabled = mPowerManagerInternal
.getLowPowerState(ServiceType.ANIMATION).batterySaverEnabled;
}
...
}
获取动画播放时长的缩放比例
@Override
public float getCurrentAnimatorScale() {
synchronized (mGlobalLock) {
return mAnimationsDisabled ? 0 : mAnimatorDurationScaleSetting;
}
}
(7) disableAod
在省电模式下是否禁用 AOD。
当手机打瞌睡时,通知是否应在用户的显示屏上"闪烁"。
代码在Systemui中实现
LAW.BR.5.1/LINUX/android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
private void setPowerSave(boolean powerSave) {
if (powerSave == mPowerSave) return;
mPowerSave = powerSave;
// AOD power saving setting might be different from PowerManager power saving mode.
PowerSaveState state = mPowerManager.getPowerSaveState(PowerManager.ServiceType.AOD);
//获取aod的值
mAodPowerSave = state.batterySaverEnabled;
firePowerSaveChanged();
}
LAW.BR.5.1/LINUX/android/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
/**
* Whether or not the notification should "pulse" on the user's display when the phone is
* dozing. This displays the ambient view of the notification.
*
* @param entry the entry to check
* @return true if the entry should ambient pulse, false otherwise
*/
private boolean shouldHeadsUpWhenDozing(NotificationEntry entry) {
if (mBatteryController.isAodPowerSave() ) {
if (DEBUG_HEADS_UP) {
Log.d(TAG, "No pulsing: disabled by battery saver: " + sbn.getKey());
}
return false;
}
(8) disableLaunchBoost
在省电模式下是否禁用启动boost
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
private void powerHintInternal(int hintId, int data) {
// Maybe filter the event.
switch (hintId) {
case PowerHint.LAUNCH: // 1: activate launch boost 0: deactivate.
if (data == 1 && mBatterySaverController.isLaunchBoostDisabled ()) {
return;
}
break;
}
mNativeWrapper.nativeSendPowerHint(hintId, data);
}
(9) disableOptionalSensors
是否禁用非必要传感器(例如边缘传感器),但是,目前没有找到实现的代码.
(10) disableSoundTrigger
在省电模式下是否禁用声音触发的事件,譬如:语音识别
LAW.BR.5.1/LINUX/android/frameworks/base/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
class PowerSaveModeListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
return;
}
boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
.batterySaverEnabled;
if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
synchronized (mLock) {
onPowerSaveModeChangedLocked(active);
}
}
}
// Whether we are allowed to run any recognition at all. The conditions that let us run// a recognition include: no active phone call or not being in a power save mode. Also,
// the native service should be enabled.
private boolean isRecognitionAllowed() {
// if mRecognitionRequested is false, call and power state listeners are not registered so
// we read current state directly from services
if (!mRecognitionRequested) {
mCallActive = mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK;
mIsPowerSaveMode =
mPowerManager.getPowerSaveState(ServiceType.SOUND).batterySaverEnabled;
}
return !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
}
(11) disableVibration
当省电模式模式下,除了来电显示的震动(有条件的震动)
- 震动将取消(原来如果有震动的话)
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/VibratorService.java
private boolean updateLowPowerModeLocked() {
boolean lowPowerMode = mPowerManagerInternal
.getLowPowerState(ServiceType.VIBRATION ).batterySaverEnabled;
if (lowPowerMode != mLowPowerMode) {
mLowPowerMode = lowPowerMode;
return true;
}
return false;
}
2)当省电模式模式下,除了来电显示的震动(有条件的震动),其它都将关闭震动。
代码如下:
//监听各种变化,取消震动.
private void updateVibrators() {
synchronized (mLock) {
boolean devicesUpdated = updateInputDeviceVibratorsLocked();
boolean lowPowerModeUpdated = updateLowPowerModeLocked();
updateVibrationIntensityLocked();
if (devicesUpdated || lowPowerModeUpdated) {
// If the state changes out from under us then just reset.
doCancelVibrateLocked();
}
updateAlwaysOnLocked();
}
}
private boolean isAllowedToVibrateLocked(Vibration vib) {
//若不是低电量模式,则直接允许
if (**!**mLowPowerMode ) {
return true;
}
int usage = vib.attrs.getUsage();
//若在低电量模式下,则允许USAGE_RINGTONE,USAGE_ALARM,USAGE_COMMUNICATION_REQUEST 模式下有震动.
return usage == VibrationAttributes.USAGE_RINGTONE
|| usage == VibrationAttributes.USAGE_ALARM
|| usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
}
private boolean shouldVibrate(Vibration vib, int intensity) {if (!isAllowedToVibrateLocked(vib)) {
return false;
}
...
return true;
}
(12) enableDataSaver
是否开启data saver模式
- 找到控制开关
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
private void initService(CountDownLatch initCompleteSignal) {
mRestrictBackgroundLowPowerMode = mPowerManagerInternal
.getLowPowerState(ServiceType.DATA_SAVER ).batterySaverEnabled;
if (mRestrictBackgroundLowPowerMode && !mLoadedRestrictBackground) {
mLoadedRestrictBackground = true;
}
setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");
}
- 对后台UL进行限制
@GuardedBy("mUidRulesFirstLock")
private void setRestrictBackgroundUL(boolean restrictBackground , String reason) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setRestrictBackgroundUL");
try {
//restrictBackground 默认值是true
if (restrictBackground == mRestrictBackground) {
// Ideally, UI should never allow this scenario...
return;
}
final boolean oldRestrictBackground = mRestrictBackground;
mRestrictBackground = restrictBackground;
// Must whitelist foreground apps before turning data saver mode on.
// TODO: there is no need to iterate through all apps here, just those in the foreground,
// so it could call AM to get the UIDs of such apps, and iterate through them instead.
//
updateRulesForRestrictBackgroundUL();
try {
//
if (!mNetworkManager.setDataSaverModeEnabled (mRestrictBackground)) {
Slog.e(TAG,
"Could not change Data Saver Mode on NMS to " + mRestrictBackground);
mRestrictBackground = oldRestrictBackground;
// TODO: if it knew the foreground apps (see TODO above), it could call
// updateRulesForRestrictBackgroundUL() again to restore state.
return;
}
} catch (RemoteException e) {
// ignored; service lives in system_server
}
...
}
- NetdService 对网络限制
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/NetworkManagementService.java
@Override
public boolean setDataSaverModeEnabled(boolean enable) {
mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
synchronized (mQuotaLock) {
if (mDataSaverMode == enable) {
Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
return true;
}
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
try {
//Enables or disables data saver mode on costly network interfaces.
final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
if (changed) {
mDataSaverMode = enable;
} else {
Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
}
return changed;
} catch (RemoteException e) {
Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
return false;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
}
}
}
(13) enableFirewall
在省电模式下是否开启网络策略防火墙
- 获取引用enableFirewall 值。
LAW.BR.5.1/LINUX/android/frameworks/base/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
private void initService(CountDownLatch initCompleteSignal) {
mRestrictPower = mPowerManagerInternal.getLowPowerState(
ServiceType.NETWORK_FIREWALL).batterySaverEnabled;
}
- 触发调用Restrict Power的函数:
1\] 当处于省电模式发生变化
> public void **onLowPowerModeChanged** (PowerSaveState result) {
>
> final boolean enabled = result.batterySaverEnabled;
>
> if (LOGD) {
>
> Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
>
> }
>
> synchronized (mUidRulesFirstLock) {
>
> if (mRestrictPower != enabled) {
>
> mRestrictPower = enabled;
>
> **updateRulesForRestrictPowerUL**();
>
> }
>
> }
>
> }
>
> });
\[2\] 当收到ACTION_POWER_SAVE_WHITELIST_CHANGED action时:
> final private BroadcastReceiver **mPowerSaveWhitelistReceiver** = new BroadcastReceiver() {
>
> @Override
>
> public void onReceive(Context context, Intent intent) {
>
> // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
>
> synchronized (mUidRulesFirstLock) {
>
> updatePowerSaveWhitelistUL();
>
> **updateRulesForRestrictPowerUL** ();
>
> updateRulesForAppIdleUL();
>
> }
>
> }
>
> };
\[3\] 当触发**updateRulesForGlobalChangeAL** 时:
> /\*\*
>
> \* Update rules that might be changed by {@link #mRestrictBackground},
>
> \* {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
>
> \*/
>
> @GuardedBy({"mUidRulesFirstLock", "mNetworkPoliciesSecondLock"})
>
> private void **updateRulesForGlobalChangeAL**(boolean restrictedNetworksChanged) {
>
>
> try {
>
> updateRulesForAppIdleUL();
>
> **updateRulesForRestrictPowerUL** ();
>
> updateRulesForRestrictBackgroundUL();
>
> // If the set of restricted networks may have changed, re-evaluate those.
>
> if (restrictedNetworksChanged) {
>
> normalizePoliciesNL();
>
> updateNetworkRulesNL();
>
> }
>
> } finally {
>
> Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
>
> }
>
> }
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\ 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
> \