初識(shí)Android?PowerManagerService省電模式
前言
最近遇到一些關(guān)于省電模式、電量消耗、Doze模式,等等相關(guān)問(wèn)題。于是,我決定對(duì)它們進(jìn)行徹底分析,那就先從省電模式開(kāi)啟。
功能介紹
可以在 Settings->Battery->Battery Saver 界面進(jìn)行省電模式的操作,如下圖:

界面中有三個(gè)開(kāi)關(guān),它們的意思如下:
- Use Battery Saver : 打開(kāi)/關(guān)閉省電模式。
- Set a Schedule : 設(shè)置一個(gè)電量百分比閾值,當(dāng)電量低于這個(gè)閾值的時(shí)候,就會(huì)觸發(fā)省電模式。設(shè)置閾值的界面如下圖

- Turn off when charging : 這個(gè)開(kāi)關(guān)的意思不能按表面意思理解,它真正的意思是,省電模式被打開(kāi)的情況下,拔掉充電器或者重啟,如果電量百分比大于90%,那么不會(huì)再次開(kāi)啟省電模式。
由于省電模式的功能涉及的代碼比較多,本文只分析省電模式環(huán)境的初始化,涉及的文件路徑如下
- frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
- frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
- frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
- frameworks/base/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
環(huán)境
省電模式屬于 PowerManagerService 的一部分功能,下面列出與省電模式環(huán)境相關(guān)的代碼:
PowerManagerService(Context context, Injector injector) {
super(context);
// ...
// Class to decide whether to turn on battery saver mode for specific services.
mBatterySaverPolicy =
mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);
// Responsible for battery saver mode transition logic.
mBatterySaverController = mInjector.createBatterySaverController(mLock, mContext,
mBatterySaverPolicy, mBatterySavingStats);
// Decides when to enable / disable battery saver.
mBatterySaverStateMachine = mInjector.createBatterySaverStateMachine(mLock, mContext,
mBatterySaverController);
// ...
}與省電模式相關(guān)的類有三個(gè),BatterySaverPolicy, BatterySaverController, BatterySaverStateMachine。
介紹下三個(gè)類的作用:
- BatterySaverPolicy : 省電模式的策略。
- BatterySaverController : 控制省電模式的打開(kāi)/關(guān)閉,并根據(jù)省電模式策略,控制某些功能,例如控制 CPU 頻率。
- BatterySaverStateMachine : 一個(gè)狀態(tài)機(jī),管理著省電模式相關(guān)的狀態(tài),并通過(guò) BatterySaverController 控制省電模式的開(kāi)啟/關(guān)閉。
這里創(chuàng)建三個(gè)類對(duì)象的方式,就是調(diào)用構(gòu)造函數(shù),下面大致看下這幾個(gè)構(gòu)造函數(shù)
public BatterySaverPolicy(Object lock, Context context, BatterySavingStats batterySavingStats) {
super(BackgroundThread.getHandler());
mLock = lock;
mHandler = BackgroundThread.getHandler();
mContext = context;
mContentResolver = context.getContentResolver();
mBatterySavingStats = batterySavingStats;
}
public BatterySaverController(Object lock, Context context, Looper looper,
BatterySaverPolicy policy, BatterySavingStats batterySavingStats) {
mLock = lock;
mContext = context;
mHandler = new MyHandler(looper);
mBatterySaverPolicy = policy;
// 注意,監(jiān)聽(tīng)了 policy change
mBatterySaverPolicy.addListener(this);
// FileUpdater 負(fù)責(zé)向底層文件節(jié)點(diǎn)寫值,例如向CPU頻率的節(jié)點(diǎn)寫值,控制CPU頻率
mFileUpdater = new FileUpdater(context);
mBatterySavingStats = batterySavingStats;
// 刷新獲取省電模式的緩存
PowerManager.invalidatePowerSaveModeCaches();
}
public BatterySaverStateMachine(Object lock,
Context context, BatterySaverController batterySaverController) {
mLock = lock;
mContext = context;
mBatterySaverController = batterySaverController;
mState = STATE_OFF;
// Whether or not battery saver should be "sticky" when manually enabled.
// false
// 注意了,值為 false,表明這個(gè) battery saver sticky 功能是打開(kāi)的
mBatterySaverStickyBehaviourDisabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled);
// Config flag to track default disable threshold for Dynamic power savings enabled battery saver.
// 80
mDynamicPowerSavingsDefaultDisableThreshold = mContext.getResources().getInteger(
com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold);
}BatterySaverController 的構(gòu)造函數(shù),只需要注意一點(diǎn),那就是它監(jiān)聽(tīng)了省電模式策略的改變,因?yàn)檫@個(gè)策略會(huì)影響省電模式。
BatterySaverStateMachine 的構(gòu)造函數(shù),需要注意 mBatterySaverStickyBehaviourDisabled,它表示是否支持 battery saver sticky 功能。注意了,它的值 false,但是表示支持這個(gè)功能,而不是不支持。mDynamicPowerSavingsDefaultDisableThreshold 是與動(dòng)態(tài)省電模式相關(guān),讀者可自行分析。
繼續(xù)看 PowerManagerService 對(duì)省電模式環(huán)境的初始化代碼
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
// ...
mBatterySaverController.systemReady();
mBatterySaverPolicy.systemReady();
// ...
}
}首先看看 BatterySaverController#systemRead()
public void systemReady() {
// 監(jiān)聽(tīng)這些東西,來(lái)控制 battery saver
final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
mContext.registerReceiver(mReceiver, filter);
// 如果 Runtime 重啟,那么讀取 /data/system/battery-saver/default-values.xml 保存的數(shù)據(jù),否則刪除這個(gè)文件。
mFileUpdater.systemReady(LocalServices.getService(ActivityManagerInternal.class)
.isRuntimeRestarted());
// 這里的處理邏輯為空
mHandler.postSystemReady();
}BatterySaverController 會(huì)監(jiān)聽(tīng)屏幕亮滅以及 Doze 模式的廣播。
不過(guò)只有屏幕亮滅,會(huì)實(shí)際地影響省電模式,因?yàn)槠聊坏牧翜鐣?huì)影響交互模式,而省電模式策略會(huì)根據(jù)手機(jī)是否處于交互模式而配置不同的策略。目前,在策略中,只有 CPU 頻率受影響。
再來(lái)看看 BatterySaverPolicy#systemReady()
public void systemReady() {
ConcurrentUtils.wtfIfLockHeld(TAG, mLock);
// 下面兩個(gè)字段,目前沒(méi)有值,但是會(huì)控制省電模式策略,進(jìn)而影響省電模式
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this);
// 無(wú)障礙相關(guān)
final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class);
acm.addAccessibilityStateChangeListener(enabled -> mAccessibilityEnabled.update(enabled));
mAccessibilityEnabled.initialize(acm.isEnabled());
// 汽車相關(guān)
UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);
uiModeManager.addOnProjectionStateChangedListener(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE,
mContext.getMainExecutor(), mOnProjectionStateChangedListener);
mAutomotiveProjectionActive.initialize(
uiModeManager.getActiveProjectionTypes() != UiModeManager.PROJECTION_TYPE_NONE);
// 監(jiān)聽(tīng) SettingProvider 的 config 表中,關(guān)于 battery_saver 命名空間下的所有字段值。
// 目前,這些字段都為空,但是這些字段會(huì)影響省電模式策略,進(jìn)而控制省電模式
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_SAVER,
mContext.getMainExecutor(), this);
mLastDeviceConfigProperties =
DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_SAVER);
onChange(true, null);
}BatterySaverPolicy 本身有一個(gè)默認(rèn)的策略,但是可以通過(guò) SettingsProvider 中的一些字段來(lái)控制策略,從而控制省電模式影響的功能。但是目前,這些字段的值都為空,因此并不影響分析,后面或許我另寫一篇文章,分析如何控制省電模式策略。
繼續(xù)看 PowerManagerService 對(duì)省電模式環(huán)境的初始化代碼
public void onBootPhase(int phase) {
synchronized (mLock) {
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
incrementBootCount();
} else if (phase == PHASE_BOOT_COMPLETED) {
// ...
mBatterySaverStateMachine.onBootCompleted();
// ...
}
}
}BatterySaverStateMachine.onBootCompleted() 代碼如下:
public void onBootCompleted() {
putGlobalSetting(Settings.Global.LOW_POWER_MODE, 0);
runOnBgThread(() -> {
// 監(jiān)聽(tīng)數(shù)據(jù)庫(kù)字段
final ContentResolver cr = mContext.getContentResolver();
// Settings.Global.LOW_POWER_MODE 代表省電模式是否打開(kāi)
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.LOW_POWER_MODE_STICKY 代表 battery saver sticky 功能是否打開(kāi)
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_STICKY),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL 代表觸發(fā)省電模式的電量百分比
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.AUTOMATIC_POWER_SAVE_MODE 代表自動(dòng)省電模式的類型
// 類型有三個(gè),根據(jù)電量百分比觸發(fā),動(dòng)態(tài)省電模式模式,或者none
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.AUTOMATIC_POWER_SAVE_MODE),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED 代表是否打開(kāi)動(dòng)態(tài)省電模式
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD 代表動(dòng)態(tài)省電模式關(guān)閉的閾值
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED 表示是否打開(kāi)了 battery saver sticky auto disable
// 對(duì)應(yīng)于 Settings->Battery->Battery Saver->Turn off when charging
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL 表示 battery saver sticky auto disable 的閾值
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
synchronized (mLock) {
/**
* If 1, battery saver ({@link #LOW_POWER_MODE}) will be re-activated after the device
* is unplugged from a charger or rebooted.
*/
// battery saver sticky 功能是否被打開(kāi)
final boolean lowPowerModeEnabledSticky = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
if (lowPowerModeEnabledSticky) {
mState = STATE_PENDING_STICKY_ON;
}
mBootCompleted = true;
// 讀取數(shù)據(jù)庫(kù)字段,并根據(jù)情況,打開(kāi)/關(guān)閉省電模式
refreshSettingsLocked();
// 自動(dòng)打開(kāi)/關(guān)閉省電模式
doAutoBatterySaverLocked();
}
});
}這里主要是監(jiān)聽(tīng)并讀取與省電模式相關(guān)的數(shù)據(jù)庫(kù)字段,由于現(xiàn)在是分析初始化環(huán)境,因此這里不分析觸發(fā)省電模式的代碼。這些字段值是什么意思,請(qǐng)注意看注釋。
至此,省電模式環(huán)境的初始化代碼已經(jīng)分析完畢,你可能對(duì)代碼中提到的一些概念非常迷惑,我剛開(kāi)啟接觸的時(shí)候也是一樣。為了后面代碼分析的順利進(jìn)行,現(xiàn)在預(yù)備幾個(gè)知識(shí)
- 當(dāng)省電模式開(kāi)啟后,只要插入了充電器,系統(tǒng)會(huì)自動(dòng)關(guān)閉省電模式。
- 當(dāng)處于充電模式,系統(tǒng)是禁止開(kāi)啟省電模式。
- Battery Saver Sticky : 在省電模式開(kāi)啟的情況下,拔掉充電器,或者系統(tǒng)重啟,這個(gè) Battery Saver Sticky 模式就會(huì)起效,它會(huì)再次開(kāi)啟省電模式。
- Battery Saver Sticky Auto Disable : 從字面理解意思,就是自動(dòng)關(guān)閉 Battery Saver Sticky 功能。當(dāng)電量百分比大于某個(gè)閾值,默認(rèn)是90%,在省電模式開(kāi)啟的情況狂下,拔掉充電器或者重啟,那么不會(huì)再次開(kāi)啟省電模式。
結(jié)束
到此這篇關(guān)于初識(shí)Android PowerManagerService省電模式的文章就介紹到這了,更多相關(guān)Andorra PowerManagerService內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)登錄界面的注冊(cè)功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)登錄界面的注冊(cè)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
View觸發(fā)機(jī)制API實(shí)現(xiàn)GestureDetector OverScroller詳解
這篇文章主要為大家介紹了View觸發(fā)機(jī)制API實(shí)現(xiàn)GestureDetector OverScroller詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Flutter實(shí)現(xiàn)增強(qiáng)版的頁(yè)面懸浮按鈕的示例代碼
Flutter?自帶的?FloatingActionButton?為我們提供了一個(gè)懸浮在頂部的按鈕,這個(gè)按鈕始終在最頂層,因此可以做一些快捷的操作。本文就來(lái)和大家詳細(xì)聊聊2023-01-01
基于Flutter制作一個(gè)吃豆人加載動(dòng)畫
這篇文章主要為大家介紹了如何利用Flutter制作出吃豆人加載動(dòng)畫效果,文中的示例代碼講解詳細(xì),快跟隨小編一起動(dòng)手嘗試一下2022-04-04
詳細(xì)分析android的MessageQueue.IdleHandler
這篇文章主要介紹了android的MessageQueue.IdleHandler用法,很有參考價(jià)值,歡迎大家在下方留言區(qū)討論。2017-11-11
Android使用ContentProvider實(shí)現(xiàn)跨進(jìn)程通訊示例詳解
這篇文章主要為大家介紹了Android使用ContentProvider實(shí)現(xiàn)跨進(jìn)程通訊示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android筆記之:CM9源碼下載與編譯的應(yīng)用
本篇文章介紹了,在Android中CM9源碼下載與編譯的應(yīng)用,需要的朋友參考下2013-04-04
FFmpeg?Principle學(xué)習(xí)new_video_stream添加視頻輸出流
這篇文章主要為大家介紹了FFmpeg?Principle學(xué)習(xí)new_video_stream添加視頻輸出流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10

