public void setGooglePowerSave(boolean enable) {
PowerManager mPowerManager = ((PowerManager) getSystemService(Context.POWER_SERVICE));
mPowerManager.setPowerSaveMode(enable);
}
// 需要注册权限 android.Manifest.permission.DEVICE_POWER
public boolean setPowerSaveMode(boolean enabled) {
...
return setLowPowerModeInternal(enabled);
...
}
private boolean setLowPowerModeInternal(boolean enabled) {
...
mBatterySaverStateMachine.setBatterySaverEnabledManually(enabled);
...
}
public void setBatterySaverEnabledManually(boolean enabled) {
...
enableBatterySaverLocked(/*enable=*/ enabled, /*manual=*/ true,
(enabled ? BatterySaverController.REASON_MANUAL_ON
: BatterySaverController.REASON_MANUAL_OFF),
(enabled ? "Manual ON" : "Manual OFF"));
...
}
private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason,
String strReason) {
...
putGlobalSetting(Global.LOW_POWER_MODE, enable ? 1 : 0);
...
mBatterySaverController.enableBatterySaver(enable, intReason);
...
}
public void enableBatterySaver(boolean enable, int reason) {
...
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
...
}
public void postStateChanged(boolean sendBroadcast, int reason) {
obtainMessage(MSG_STATE_CHANGED, sendBroadcast ?
ARG_SEND_BROADCAST : ARG_DONT_SEND_BROADCAST, reason).sendToTarget();
}
private class MyHandler extends Handler {
@Override
public void dispatchMessage(Message msg) {
switch (msg.what) {
case MSG_STATE_CHANGED:
handleBatterySaverStateChanged(
msg.arg1 == ARG_SEND_BROADCAST,
msg.arg2);
break;
...
}
void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
...
// CPU 调低频
pmi.powerHint(PowerHint.LOW_POWER, enabled ? 1 : 0);
...
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
...
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
...
for (LowPowerModeListener listener : listeners) {
...
// 通知所有注册 LowPowerModeListener 的服务会发生改变
listener.onLowPowerModeChanged(result);
...
}
}
Google 原生省电模式开启后,以下注册 LowPowerModeListener 的服务会发生改变
// 省电模式变化广播 1
// 普通 APP 使用动态广播
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
// 省电模式是否开启
.putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, enabled)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
// 省电模式变化广播 2
// 普通 APP 可监听
// 需要重点查看接受这个广播的系统服务做了什么
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
// 省电模式变化广播 3
// 需要注册 Manifest.permission.DEVICE_POWER 权限且需要系统签名才能收到
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,Manifest.permission.DEVICE_POWER);
// 系统其它服务,主要注册监听 LowPowerModeListener 变化进行省电模式的开启
for (LowPowerModeListener listener : listeners) {
final PowerSaveState result =
mBatterySaverPolicy.getBatterySaverPolicy(
listener.getServiceType(), enabled);
listener.onLowPowerModeChanged(result);
}
上述中Google 省电中系统监听到省电模式变化,这里主要指的是 监听 LowPowerModeListener 和 ACTION_POWER_SAVE_MODE_CHANGED广播 执行对应的省电策略
public void systemReady() {
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
updateVibrators();
}
});
}
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();
}
}
}
private void doCancelVibrateLocked() {
...
doVibratorOff();
...
}
...
mPowerManagerInternal.registerLowPowerModeObserver(
...
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
final boolean enabled = result.batterySaverEnabled;
synchronized (mUidRulesFirstLock) {
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
updateRulesForRestrictPowerUL();
}
}
}
});
...
private void updateRulesForRestrictPowerUL() {
...
updateRulesForPowerSaveUL();
...
}
void updateRulesForPowerSaveUL() {
...
updateRulesForWhitelistedPowerSaveUL(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
mUidFirewallPowerSaveRules);
...
}
private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain,
...
if (enabled) {
setUidFirewallRulesUL(chain, uidRules, CHAIN_TOGGLE_ENABLE);
} else {
setUidFirewallRulesUL(chain, null, CHAIN_TOGGLE_DISABLE);
}
...
}
/**
* Calls {@link #setUidFirewallRules(int, SparseIntArray)} and
* {@link #enableFirewallChainUL(int, boolean)} synchronously.
*
* @param chain firewall chain.
* @param uidRules new UID rules; if {@code null}, only toggles chain state.
* @param toggle whether the chain should be enabled, disabled, or not changed.
*/
private void setUidFirewallRulesUL(int chain, @Nullable SparseIntArray uidRules,
...
if (toggle != CHAIN_TOGGLE_NONE) {
enableFirewallChainUL(chain, toggle == CHAIN_TOGGLE_ENABLE);
}
}
if (mPowerManagerInternal != null) {
mPowerManagerInternal.registerLowPowerModeObserver(
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(PowerSaveState result) {
synchronized (mWindowMap) {
final boolean enabled = result.batterySaverEnabled;
if (mAnimationsDisabled != enabled && !mAllowAnimationsInLowPowerMode) {
mAnimationsDisabled = enabled;
dispatchNewAnimatorScaleLocked(null);
}
}
}
});
private static native void nativeSendPowerHint(int hintId, int data);
private void powerHintInternal(int hintId, int data) {
nativeSendPowerHint(hintId, data);
}
Q/frameworks/base/services/core/java/com/android/server/UiModeManagerService.java
mPowerSave = localPowerManager.getLowPowerState(ServiceType.NIGHT_MODE).batterySaverEnabled
localPowerManager.registerLowPowerModeObserver(ServiceType.NIGHT_MODE,
state -> {
synchronized (mLock) {
if (mPowerSave == state.batterySaverEnabled) {
return;
}
mPowerSave = state.batterySaverEnabled;
if (mSystemReady) {
updateLocked(0, 0);
}
}
});
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
...
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
|| PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
|| Intent.ACTION_SCREEN_OFF.equals(action)
|| Intent.ACTION_SCREEN_ON.equals(action)) {
updateLowPowerMode();
...
}
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode.
boolean disableGps = mPowerManager.isDeviceIdleMode();
final PowerSaveState result =
mPowerManager.getPowerSaveState(ServiceType.GPS);
switch (result.gpsMode) {
case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
// If we are in battery saver mode and the screen is off, disable GPS.
// 省电模式开启,灭屏后开启GPS待机省电模式(stopNavigating)
disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
break;
}
if (disableGps != mDisableGps) {
mDisableGps = disableGps;
updateRequirements();
}
}
}
class PowerSaveModeListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
...
boolean active = mPowerManager.getPowerSaveState(ServiceType.SOUND)
.batterySaverEnabled;
if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
synchronized (mLock) {
onPowerSaveModeChangedLocked(active);
}
}
}
// 拦截语音交互功能
private void onPowerSaveModeChangedLocked(boolean isPowerSaveMode) {
if (mIsPowerSaveMode == isPowerSaveMode) {
return;
}
mIsPowerSaveMode = isPowerSaveMode;
updateAllRecognitionsLocked(true /* notify */);
}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
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;
}
}
public void handleMessage(Message msg) {
...
case EVENT_POWER_SAVE_MODE_CHANGED:
...
onUpdateDeviceState(msg.what, msg.arg1 != 0);
...
}
private void onUpdateDeviceState(int eventType, boolean state) {
...
sendDeviceState(POWER_SAVE_MODE, mIsPowerSaveOn);
...
}
/**
* 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);
}
@Override
public void onReceive(Context context, Intent intent) {
...
if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
ThreadUtils.postOnBackgroundThread(() -> {
if (mPowerManager.isPowerSaveMode()) {
// 取消低电量通知提醒
mWarnings.dismissLowBatteryWarning();
}
});
updatePowerStateLocked()是PowerManagerService最核心的函数,PMS中使用一个int值mDirty作为标志位判断电源状态是否发生变化,当电源状态发生改变时,如亮灭屏、电池状态改变、省电模式都会调用该方法。从而判断是否要根据省电模式进行亮度减半的策略
private void updatePowerStateLocked() {
...
// Phase 3: Update display power state.
final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
...
}
private boolean updateDisplayPowerStateLocked(int dirty) {
...
// 获取当前是否为省电模式
updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
...
// 重头戏
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
...
}
void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
...
displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
...
}
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
...
return mDisplayPowerController.requestPowerState(request,
waitForNegativeProximity);
}
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
...
sendUpdatePowerStateLocked();
...
}
private void sendUpdatePowerStateLocked() {
...
Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
...
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_POWER_STATE:
updatePowerState();
break;
}
...
}
private void updatePowerState() {
...
if (mPowerRequest.lowPowerMode) {
if (brightness > mScreenBrightnessRangeMinimum) {
// 由于 screenLowPowerBrightnessFactor = 0.5f
// 开启省电模式,亮度减半
final float brightnessFactor =
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final int lowPowerBrightness = (int) (brightness * brightnessFactor);
brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
}
...
}