省電模式手動(dòng)開啟流程
`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);
}
}
首先檢查調(diào)用者是否有 android.Manifest.permission.DEVICE_POWER 權(quán)限。
private boolean setLowPowerModeInternal(boolean enabled) {
synchronized (mLock) {
if (DEBUG) {
Slog.d(TAG, "setLowPowerModeInternal " + enabled + " mIsPowered=" + mIsPowered);
}
if (mIsPowered) {//充電狀態(tài)不允許改變 低電量模式 狀態(tài)
return false;
}
mBatterySaverStateMachine.setBatterySaverEnabledManually(enabled);
return true;
}
}
frameworks\base\services\core\java\com\android\server\power\batterysaver\BatterySaverStateMachine.java
手動(dòng)開關(guān) 省電模式:
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();
//省電模式狀態(tài)沒有改變的話直接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;
}
//記錄此次改變省電模式狀態(tài)的 reason ,各個(gè) reason 的值定義在 BatterySaverController 中
mLastChangedIntReason = intReason;
mLastChangedStrReason = strReason;
//mBatterySaverSnoozing 主要是用于記錄 低電量情況下,用戶是否手動(dòng)關(guān)閉 了省電模式,防止用戶手動(dòng)關(guān)閉 省電模式后,又被自動(dòng)打開
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;
//更新 省電模式狀態(tài) 到 settings 數(shù)據(jù)庫字段中
putGlobalSetting(Global.LOW_POWER_MODE, enable ? 1 : 0);
if (manual) {
mSettingBatterySaverEnabledSticky = enable;
putGlobalSetting(Global.LOW_POWER_MODE_STICKY, enable ? 1 : 0);
}
//好了,前面這些全部都是前戲,這里才開始真正的做 省電的動(dòng)作
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);
}
}
消息經(jīng)過分發(fā),最終執(zhí)行 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 用于標(biāo)志設(shè)備是否處于可交互狀態(tài)
final boolean isInteractive = getPowerManager().isInteractive();
final ArrayMap<String, String> fileValues;
synchronized (mLock) {
//battery_saver_mode: [1,0,1,,1] event log的格式,大致含義根據(jù)變量名就可以看出來
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 頻率相關(guān)的設(shè)置,下面是 到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);
//回調(diào) 所有注冊(cè)了 LowPowerModeListener 的client
//主要有 VibratorService,NetworkPolicyManagerService,WindowManagerService
for (LowPowerModeListener listener : listeners) {
final PowerSaveState result =
mBatterySaverPolicy.getBatterySaverPolicy(
listener.getServiceType(), enabled);
listener.onLowPowerModeChanged(result);
}
}
}
主要關(guān)注 ACTION_POWER_SAVE_MODE_CHANGED 這個(gè) 廣播的分發(fā):
| 接收類 | 作用 |
|---|---|
| BatteryBroadcastReceiver(Settings) | 通知了電池電量的改變,進(jìn)入power save的模式 |
| PowerUI(SystemUI) | 如果在power save的模式下,就忽略電池低電的提醒 |
| DeviceStateMonitor(Telephony) | 設(shè)置modem為power save的模式 |
| SoundTriggerHelper (framework) | 關(guān)閉語音互動(dòng)的功能 |
| GnssLocationProvider(framework) | 限制gps使用,滅屏后會(huì)關(guān)閉gps |
總結(jié)一下 手動(dòng)打開 省電模式的過程:
- 先判斷是否有
android.Manifest.permission.DEVICE_POWER權(quán)限 - 判斷是否允許改變 省電模式的狀態(tài) (檢查充電狀態(tài),原生 省電模式 和 充電是互斥的)
- 更新省電模式狀態(tài)到
System.Global.LOW_POWER_MODE中 - 發(fā)送
ACTION_POWER_SAVE_MODE_CHANGING, ACTION_POWER_SAVE_MODE_CHANGED, ACTION_POWER_SAVE_MODE_CHANGED_INTERNAL三種廣播到 動(dòng)態(tài)注冊(cè)的組件中 - 回調(diào)所有注冊(cè)的
LowPowerModeListener(onLowPowerModeChanged)和plugin(onBatterySaverChanged)
到這里我們還沒看到 省電模式 具體是如何省電的?下一篇我們繼續(xù).....