Android P 省电模式(LowPowerMode)(一)
2019-03-15 本文已影响0人
最忆是深秋
省电模式手动开启流程
`frameworks\base\services\core\java\com\android\server\power\PowerManagerService.java
public boolean setPowerSaveMode(boolean enabled) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
return setLowPowerModeInternal(enabled);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
首先检查调用者是否有 android.Manifest.permission.DEVICE_POWER
权限。
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;
}
}
frameworks\base\services\core\java\com\android\server\power\batterysaver\BatterySaverStateMachine.java
手动开关 省电模式:
public void setBatterySaverEnabledManually(boolean enabled) {
if (DEBUG) {
Slog.d(TAG, "setBatterySaverEnabledManually: enabled=" + enabled);
}
synchronized (mLock) {
enableBatterySaverLocked(/*enable=*/ enabled, /*manual=*/ true,
(enabled ? BatterySaverController.REASON_MANUAL_ON
: BatterySaverController.REASON_MANUAL_OFF),
(enabled ? "Manual ON" : "Manual OFF"));
}
}
/**
* Actually enable / disable battery saver. Write the new state to the global settings
* and propagate it to {@link #mBatterySaverController}.
*/
private void enableBatterySaverLocked(boolean enable, boolean manual, int intReason,
String strReason) {
if (DEBUG) {
Slog.d(TAG, "enableBatterySaver: enable=" + enable + " manual=" + manual
+ " reason=" + strReason + "(" + intReason + ")");
}
final boolean wasEnabled = mBatterySaverController.isEnabled();
//省电模式状态没有改变的话直接return
if (wasEnabled == enable) {
if (DEBUG) {
Slog.d(TAG, "Already " + (enable ? "enabled" : "disabled"));
}
return;
}
//充电情况下尝试打开 省电模式 直接return
if (enable && mIsPowered) {
if (DEBUG) Slog.d(TAG, "Can't enable: isPowered");
return;
}
//记录此次改变省电模式状态的 reason ,各个 reason 的值定义在 BatterySaverController 中
mLastChangedIntReason = intReason;
mLastChangedStrReason = strReason;
//mBatterySaverSnoozing 主要是用于记录 低电量情况下,用户是否手动关闭 了省电模式,防止用户手动关闭 省电模式后,又被自动打开
if (manual) {
if (enable) {
updateSnoozingLocked(false, "Manual snooze OFF");
} else {
// When battery saver is disabled manually (while battery saver is enabled)
// when the battery level is low, we "snooze" BS -- i.e. disable auto battery saver.
// We resume auto-BS once the battery level is not low, or the device is plugged in.
if (isBatterySaverEnabled() && mIsBatteryLevelLow) {
updateSnoozingLocked(true, "Manual snooze");
}
}
}
mSettingBatterySaverEnabled = enable;
//更新 省电模式状态 到 settings 数据库字段中
putGlobalSetting(Global.LOW_POWER_MODE, enable ? 1 : 0);
if (manual) {
mSettingBatterySaverEnabledSticky = enable;
putGlobalSetting(Global.LOW_POWER_MODE_STICKY, enable ? 1 : 0);
}
//好了,前面这些全部都是前戏,这里才开始真正的做 省电的动作
mBatterySaverController.enableBatterySaver(enable, intReason);
if (DEBUG) {
Slog.d(TAG, "Battery saver: Enabled=" + enable
+ " manual=" + manual
+ " reason=" + strReason + "(" + intReason + ")");
}
}
frameworks\base\services\core\java\com\android\server\power\batterysaver\BatterySaverController.java
/**
* Called by {@link PowerManagerService} to update the battery saver stete.
*/
public void enableBatterySaver(boolean enable, int reason) {
synchronized (mLock) {
if (mEnabled == enable) {
return;
}
mEnabled = enable;
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
}
}
消息经过分发,最终执行 handleBatterySaverStateChanged
/**
* Dispatch power save events to the listeners.
*
* This method is always called on the handler thread.
*
* This method is called only in the following cases:
* - When battery saver becomes activated.
* - When battery saver becomes deactivated.
* - When battery saver is on the interactive state changes.
* - When battery saver is on the battery saver policy changes.
*/
void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
final LowPowerModeListener[] listeners;
final boolean enabled;
//isInteractive 用于标志设备是否处于可交互状态
final boolean isInteractive = getPowerManager().isInteractive();
final ArrayMap<String, String> fileValues;
synchronized (mLock) {
//battery_saver_mode: [1,0,1,,1] event log的格式,大致含义根据变量名就可以看出来
EventLogTags.writeBatterySaverMode(
mPreviouslyEnabled ? 1 : 0, // Previously off or on.
mEnabled ? 1 : 0, // Now off or on.
isInteractive ? 1 : 0, // Device interactive state.
mEnabled ? mBatterySaverPolicy.toEventLogString() : "",
reason);
mPreviouslyEnabled = mEnabled;
listeners = mListeners.toArray(new LowPowerModeListener[mListeners.size()]);
enabled = mEnabled;
mIsInteractive = isInteractive;
if (enabled) {
fileValues = mBatterySaverPolicy.getFileValues(isInteractive);
} else {
fileValues = null;
}
}
//似乎是 CPU 频率相关的设置,下面是 到JNI里,没有去跟
final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
if (pmi != null) {
pmi.powerHint(PowerHint.LOW_POWER, enabled ? 1 : 0);
}
updateBatterySavingStats();
if (ArrayUtils.isEmpty(fileValues)) {
mFileUpdater.restoreDefault();
} else {
mFileUpdater.writeFiles(fileValues);
}
//目前来看,原生的代码里只有一种 BatterySaverLocationPlugin
// plugins.add(new BatterySaverLocationPlugin(mContext));
for (Plugin p : mPlugins) {
p.onBatterySaverChanged(this);
}
if (sendBroadcast) {
if (DEBUG) {
Slog.i(TAG, "Sending broadcasts for mode: " + enabled);
}
// Send the broadcasts and notify the listeners. We only do this when the battery saver
// mode changes, but not when only the screen state changes.
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
.putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, enabled)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
// Send internal version that requires signature permission.
intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
Manifest.permission.DEVICE_POWER);
//回调 所有注册了 LowPowerModeListener 的client
//主要有 VibratorService,NetworkPolicyManagerService,WindowManagerService
for (LowPowerModeListener listener : listeners) {
final PowerSaveState result =
mBatterySaverPolicy.getBatterySaverPolicy(
listener.getServiceType(), enabled);
listener.onLowPowerModeChanged(result);
}
}
}
主要关注 ACTION_POWER_SAVE_MODE_CHANGED
这个 广播的分发:
接收类 | 作用 |
---|---|
BatteryBroadcastReceiver(Settings) | 通知了电池电量的改变,进入power save的模式 |
PowerUI(SystemUI) | 如果在power save的模式下,就忽略电池低电的提醒 |
DeviceStateMonitor(Telephony) | 设置modem为power save的模式 |
SoundTriggerHelper (framework) | 关闭语音互动的功能 |
GnssLocationProvider(framework) | 限制gps使用,灭屏后会关闭gps |
总结一下 手动打开 省电模式的过程:
- 先判断是否有
android.Manifest.permission.DEVICE_POWER
权限 - 判断是否允许改变 省电模式的状态 (检查充电状态,原生 省电模式 和 充电是互斥的)
- 更新省电模式状态到
System.Global.LOW_POWER_MODE
中 - 发送
ACTION_POWER_SAVE_MODE_CHANGING, ACTION_POWER_SAVE_MODE_CHANGED, ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL
三种广播到 动态注册的组件中 - 回调所有注册的
LowPowerModeListener(onLowPowerModeChanged)
和plugin(onBatterySaverChanged)
到这里我们还没看到 省电模式 具体是如何省电的?下一篇我们继续.....