網站首頁 編程語言 正文
前言
最近遇到一些關于省電模式、電量消耗、Doze模式,等等相關問題。于是,我決定對它們進行徹底分析,那就先從省電模式開啟。
功能介紹
可以在 Settings->Battery->Battery Saver 界面進行省電模式的操作,如下圖:
界面中有三個開關,它們的意思如下:
- Use Battery Saver : 打開/關閉省電模式。
- Set a Schedule : 設置一個電量百分比閾值,當電量低于這個閾值的時候,就會觸發省電模式。設置閾值的界面如下圖
- Turn off when charging : 這個開關的意思不能按表面意思理解,它真正的意思是,省電模式被打開的情況下,拔掉充電器或者重啟,如果電量百分比大于90%,那么不會再次開啟省電模式。
由于省電模式的功能涉及的代碼比較多,本文只分析省電模式環境的初始化,涉及的文件路徑如下
- 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
環境
省電模式屬于?PowerManagerService?的一部分功能,下面列出與省電模式環境相關的代碼:
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);
// ...
}
與省電模式相關的類有三個,BatterySaverPolicy,?BatterySaverController,?BatterySaverStateMachine。
介紹下三個類的作用:
- BatterySaverPolicy?: 省電模式的策略。
- BatterySaverController?: 控制省電模式的打開/關閉,并根據省電模式策略,控制某些功能,例如控制 CPU 頻率。
- BatterySaverStateMachine?: 一個狀態機,管理著省電模式相關的狀態,并通過?BatterySaverController?控制省電模式的開啟/關閉。
這里創建三個類對象的方式,就是調用構造函數,下面大致看下這幾個構造函數
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;
// 注意,監聽了 policy change
mBatterySaverPolicy.addListener(this);
// FileUpdater 負責向底層文件節點寫值,例如向CPU頻率的節點寫值,控制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,表明這個 battery saver sticky 功能是打開的
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 的構造函數,只需要注意一點,那就是它監聽了省電模式策略的改變,因為這個策略會影響省電模式。
BatterySaverStateMachine 的構造函數,需要注意?mBatterySaverStickyBehaviourDisabled,它表示是否支持?battery saver sticky?功能。注意了,它的值 false,但是表示支持這個功能,而不是不支持。mDynamicPowerSavingsDefaultDisableThreshold?是與動態省電模式相關,讀者可自行分析。
繼續看?PowerManagerService?對省電模式環境的初始化代碼
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
// ...
mBatterySaverController.systemReady();
mBatterySaverPolicy.systemReady();
// ...
}
}
首先看看?BatterySaverController#systemRead()
public void systemReady() {
// 監聽這些東西,來控制 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 保存的數據,否則刪除這個文件。
mFileUpdater.systemReady(LocalServices.getService(ActivityManagerInternal.class)
.isRuntimeRestarted());
// 這里的處理邏輯為空
mHandler.postSystemReady();
}
BatterySaverController?會監聽屏幕亮滅以及 Doze 模式的廣播。
不過只有屏幕亮滅,會實際地影響省電模式,因為屏幕的亮滅會影響交互模式,而省電模式策略會根據手機是否處于交互模式而配置不同的策略。目前,在策略中,只有 CPU 頻率受影響。
再來看看?BatterySaverPolicy#systemReady()
public void systemReady() {
ConcurrentUtils.wtfIfLockHeld(TAG, mLock);
// 下面兩個字段,目前沒有值,但是會控制省電模式策略,進而影響省電模式
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);
// 無障礙相關
final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class);
acm.addAccessibilityStateChangeListener(enabled -> mAccessibilityEnabled.update(enabled));
mAccessibilityEnabled.initialize(acm.isEnabled());
// 汽車相關
UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class);
uiModeManager.addOnProjectionStateChangedListener(UiModeManager.PROJECTION_TYPE_AUTOMOTIVE,
mContext.getMainExecutor(), mOnProjectionStateChangedListener);
mAutomotiveProjectionActive.initialize(
uiModeManager.getActiveProjectionTypes() != UiModeManager.PROJECTION_TYPE_NONE);
// 監聽 SettingProvider 的 config 表中,關于 battery_saver 命名空間下的所有字段值。
// 目前,這些字段都為空,但是這些字段會影響省電模式策略,進而控制省電模式
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_BATTERY_SAVER,
mContext.getMainExecutor(), this);
mLastDeviceConfigProperties =
DeviceConfig.getProperties(DeviceConfig.NAMESPACE_BATTERY_SAVER);
onChange(true, null);
}
BatterySaverPolicy?本身有一個默認的策略,但是可以通過?SettingsProvider?中的一些字段來控制策略,從而控制省電模式影響的功能。但是目前,這些字段的值都為空,因此并不影響分析,后面或許我另寫一篇文章,分析如何控制省電模式策略。
繼續看?PowerManagerService?對省電模式環境的初始化代碼
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(() -> {
// 監聽數據庫字段
final ContentResolver cr = mContext.getContentResolver();
// Settings.Global.LOW_POWER_MODE 代表省電模式是否打開
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.LOW_POWER_MODE_STICKY 代表 battery saver sticky 功能是否打開
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_STICKY),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL 代表觸發省電模式的電量百分比
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.AUTOMATIC_POWER_SAVE_MODE 代表自動省電模式的類型
// 類型有三個,根據電量百分比觸發,動態省電模式模式,或者none
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.AUTOMATIC_POWER_SAVE_MODE),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED 代表是否打開動態省電模式
cr.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED),
false, mSettingsObserver, UserHandle.USER_SYSTEM);
// Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD 代表動態省電模式關閉的閾值
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 表示是否打開了 battery saver sticky auto disable
// 對應于 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 功能是否被打開
final boolean lowPowerModeEnabledSticky = getGlobalSetting(
Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
if (lowPowerModeEnabledSticky) {
mState = STATE_PENDING_STICKY_ON;
}
mBootCompleted = true;
// 讀取數據庫字段,并根據情況,打開/關閉省電模式
refreshSettingsLocked();
// 自動打開/關閉省電模式
doAutoBatterySaverLocked();
}
});
}
這里主要是監聽并讀取與省電模式相關的數據庫字段,由于現在是分析初始化環境,因此這里不分析觸發省電模式的代碼。這些字段值是什么意思,請注意看注釋。
至此,省電模式環境的初始化代碼已經分析完畢,你可能對代碼中提到的一些概念非常迷惑,我剛開啟接觸的時候也是一樣。為了后面代碼分析的順利進行,現在預備幾個知識
- 當省電模式開啟后,只要插入了充電器,系統會自動關閉省電模式。
- 當處于充電模式,系統是禁止開啟省電模式。
- Battery Saver Sticky : 在省電模式開啟的情況下,拔掉充電器,或者系統重啟,這個 Battery Saver Sticky 模式就會起效,它會再次開啟省電模式。
- Battery Saver Sticky Auto Disable : 從字面理解意思,就是自動關閉 Battery Saver Sticky 功能。當電量百分比大于某個閾值,默認是90%,在省電模式開啟的情況狂下,拔掉充電器或者重啟,那么不會再次開啟省電模式。
結束
原文鏈接:https://juejin.cn/post/7133505259720163335
相關推薦
- 2021-12-07 C語言SetConsoleTextAttribute函數使用方法_C 語言
- 2022-05-23 MongoDB數據庫部署環境準備及使用介紹_MongoDB
- 2022-10-31 Kotlin集合List?Set?Map使用介紹詳解_Android
- 2022-05-13 在 Dart 中更好地使用類和 Mixin
- 2023-03-04 Golang中goroutine和channel使用介紹深入分析_Golang
- 2022-04-20 從0編寫區塊鏈之用python解釋區塊鏈最基本原理_python
- 2022-04-18 python用plotly實現繪制局部放大圖_python
- 2022-03-08 C++中的對象初始化操作代碼_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支