当前位置:网站首页>PowerManagerService(一)— 初始化
PowerManagerService(一)— 初始化
2022-07-05 06:54:00 【ʚ兔子的先森ɞ】
PowerManagerService(一)— 初始化
1. 简介
PowerManagerServcie是android系统电源管理的核心服务,它在Framework层建立起一个策略控制方案,向下决策HAL层以及kernel层来控制设备待机状态,主要功能是控制系统待机状态,屏幕显示,亮度调节,光线/距离传感器的控制等。
除了与应用程序交互之外,还要与系统中其它模块配合,在提供良好的能源管理同时提供友好的用户体验。比如听音乐时持续保持系统唤醒,应用通知来临唤醒手机屏幕等场景
分析一个服务,首先要从它对应用层提供的api PowerManager
入手,观察提供了哪些接口调用;
Wakeup()
:强制系统从睡眠状态唤醒,此接口对应用是不开放的,应用想唤醒系统必须通过设置亮屏标志(后面即将讲到);gotoSleep()
:强制系统进入到睡眠状态,此接口也是应用不开放。userActivity()
:向PowerManagerService报告影响系统休眠的用户活动,重计算灭屏时间,背光亮度等,例如触屏,划屏,power键等用户活动;Wakelock
:wakelock是PowerManager的一个内部类,提供了相关的接口来操作wakelock锁,比如newWakeLock()方法来创建wakelock锁,acquire()和release()方法来申请和释放锁。下面例子有介绍!isDeviceIdleMode()
:返回设备当前的状态,如果处于Idle状态,则返回true,Idle状态是在手机长时间没有被使用以及没有运动的情况下,手机进入到一种Doze低功耗的模式下,这种状态下手机可能会关掉网络数据访问,可以通过监视DEVICE_IDLE_MODE_CHANGED这个广播信息,来监控手机状态的改变
1.1 系统层级图
1.2 电源管理架构
主要分为四个层次:
- 应用接口层:
PowerManager.java
中开放给应用一系列接口,应用可以调用PM的接口申请wakelock,唤醒系统,使系统进入睡眠等操作; - Framework层:
PowerManagerService.java
计算系统中和Power相关的计算,是整个电源管理的决策系; - HAL层:该层只有一个
power.c
文件,该文件通过上层传下来的参数,向/sys/power/wake_lock
或者/sys/power/wake_unlock
文件节点写数据来与kernel进行通信,主要功能是申请/释放锁,维持屏幕亮灭。 - Kernel层:内核层实现电源管理的方案主要包含三个部分:
Kernel/power/
:实现了系统电源管理框架机制。Arch/arm(ormips or powerpc)/mach-XXX/pm.c
:实现对特定板的处理器电源管理。drivers/power
:是设备电源管理的基础框架,为驱动提供了电源管理接口。
2. 初始化
跟其他系统服务一样,PowerManagerService也是继承于SystemService并通过SystemServer启动。
2.1 SystemServer启动PowerManagerService服务
frameworks/base/services/java/com/android/server/SystemServer.java
private void startBootstrapServices() {
......
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
......
}
2.2 PowerManagerService构造
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
public final class PowerManagerService extends SystemService
implements Watchdog.Monitor {
public PowerManagerService(Context context) {
super(context);
mContext = context;
//创建消息处理线程,并启动
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
//创建Hanlder对象处理消息
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
mConstants = new Constants(mHandler);
mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
synchronized (mLock) {
//创建"PowerManagerService.WakeLocks"的SuspendBlocker
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
// 创建"PowerManagerService.Display"的SuspendBlocker
mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
// 请求DisplaySuspendBlocker,禁止系统进入休眠
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
mHalAutoSuspendModeEnabled = false;
mHalInteractiveModeEnabled = true;
// 设置mWakefulness为唤醒状态
mWakefulness = WAKEFULNESS_AWAKE;
sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
// 进入到native层初始化
nativeInit();
nativeSetAutoSuspend(false);
nativeSetInteractive(true);
nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
}
}
......
}
PowerManagerService构造函数中首先创建了处理消息的进程及对应的handler对象以进行消息处理,然后创建SuspendBlocker对象,用于WakeLocks与Display,并设置mWakefulness的初始状态为WAKEFULNESS_AWAKE,最后进入到native层初始化。下面先看一下关于mWakefulness的定义。
frameworks/base/core/java/android/os/PowerManagerInternal.java
/** * 设备处于休眠状态,只能被wakeUp()唤醒. */
public static final int WAKEFULNESS_ASLEEP = 0;
/** * 设备处于正常工作(fully awake)状态. */
public static final int WAKEFULNESS_AWAKE = 1;
/** * 设备处于播放屏保状态. */
public static final int WAKEFULNESS_DREAMING = 2;
/** * 设备处于doze状态,只有低耗电的屏保可以运行,其他应用被挂起. */
public static final int WAKEFULNESS_DOZING = 3;
继续回到PowerManagerService构造函数的native初始化中,首先来看nativeInit的实现。
frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
static void nativeInit(JNIEnv* env, jobject obj) {
// 创建一个全局对象,引用PMS
gPowerManagerServiceObj = env->NewGlobalRef(obj);
// 利用hw_get_module加载power模块
status_t err = hw_get_module(POWER_HARDWARE_MODULE_ID,
(hw_module_t const**)&gPowerModule);
if (!err) {
gPowerModule->init(gPowerModule);
} else {
ALOGE("Couldn't load %s module (%s)", POWER_HARDWARE_MODULE_ID, strerror(-err));
}
}
nativeInit的主要任务时装载power模块,该模块由厂商实现,以高通为例,如下。
device/qcom/common/power/power.c
tatic struct hw_module_methods_t power_module_methods = {
.open = NULL,
};
struct power_module HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = POWER_MODULE_API_VERSION_0_2,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = POWER_HARDWARE_MODULE_ID,
.name = "QCOM Power HAL",
.author = "Qualcomm",
.methods = &power_module_methods,
},
.init = power_init,
.powerHint = power_hint,
.setInteractive = set_interactive,
};
power_module中实现了init,powerHint,setInteractive,nativeInit最终调用到HAL power模块的power_init具体实现中。接着看native初始化nativeSetAutoSuspend的实现。
frameworks/base/services/core/jni/com_android_server_power_PowerManagerService.cpp
static void nativeSetAutoSuspend(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
if (enable) {
ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_enable() while turning screen off");
autosuspend_enable();
} else {
ALOGD_IF_SLOW(100, "Excessive delay in autosuspend_disable() while turning screen on");
autosuspend_disable();
}
}
static void nativeSetInteractive(JNIEnv* /* env */, jclass /* clazz */, jboolean enable) {
if (gPowerModule) {
if (enable) {
ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(true) while turning screen on");
gPowerModule->setInteractive(gPowerModule, true);
} else {
ALOGD_IF_SLOW(20, "Excessive delay in setInteractive(false) while turning screen off");
gPowerModule->setInteractive(gPowerModule, false);
}
}
}
static void nativeSetFeature(JNIEnv *env, jclass clazz, jint featureId, jint data) {
int data_param = data;
if (gPowerModule && gPowerModule->setFeature) {
gPowerModule->setFeature(gPowerModule, (feature_t)featureId, data_param);
}
}
system/core/libsuspend/autosuspend.c
int autosuspend_disable(void)
{
int ret;
ret = autosuspend_init();
if (ret) {
return ret;
}
ALOGV("autosuspend_disable\n");
if (!autosuspend_enabled) {
return 0;
}
ret = autosuspend_ops->disable();
if (ret) {
return ret;
}
autosuspend_enabled = false;
return 0;
}
同nativeInit一样,最终都是调用到HAL power模块的具体实现中。
3. 启动
下面继续看PowerManagerService在系统启动过程中回调onStart(),onBootPhase(),systemReady()的实现。
3.1 启动服务SystemServiceManager.onStart
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
public void onStart() {
publishBinderService(Context.POWER_SERVICE, new BinderService());
publishLocalService(PowerManagerInternal.class, new LocalService());
Watchdog.getInstance().addMonitor(this);
Watchdog.getInstance().addThread(mHandler);
}
private final class BinderService extends IPowerManager.Stub {
......
}
private final class LocalService extends PowerManagerInternal {
......
}
onStart()
中发布了BinderService
,LocalService
分别供其他进程,进程内其他服务调用,并将PowerManagerService
加入到Watchdog
监控中。
3.2 启动服务SystemServiceManager.onBootPhase
public void onBootPhase(int phase) {
synchronized (mLock) {
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
......
} else if (phase == PHASE_BOOT_COMPLETED) {
final long now = SystemClock.uptimeMillis();
// 设置mBootCompleted状态
mBootCompleted = true;
mDirty |= DIRTY_BOOT_COMPLETED;
// 更新userActivity及PowerState,后面分析
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
// 执行mBootCompletedRunnables中的runnable方法
if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
for (Runnable r : mBootCompletedRunnables) {
BackgroundThread.getHandler().post(r);
}
}
mBootCompletedRunnables = null;
}
}
}
onBootPhase()
中主要设置mBootCompleted
状态,更新PowerState
状态,并执行mBootCompletedRunnables
中的runnables
方法(低电量模式会设置)。
3.3 启动服务SystemServiceManager.systemReady
public void systemReady(IAppOpsService appOps) {
synchronized (mLock) {
mSystemReady = true;
// 获取AppOpsService
mAppOps = appOps;
// 获取DreamManager 屏保
mDreamManager = getLocalService(DreamManagerInternal.class);
// 获取DisplayManagerService 屏幕显示
mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
//窗口策略
mPolicy = getLocalService(WindowManagerPolicy.class);
// 获取mBatteryService 电池电量
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
// 获取屏幕默认,最大,最小亮度
mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
// 获取SensorManager
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
mBatteryStats = BatteryStatsService.getService();
// 创建Notifier对象,用于广播power state的变化
mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mPolicy);
// 无线充电检测
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
// 监听设置的变化
mSettingsObserver = new SettingsObserver(mHandler);
mLightsManager = getLocalService(LightsManager.class);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
// Initialize display power management.
mDisplayManagerInternal.initPowerManagement(
mDisplayPowerCallbacks, mHandler, sensorManager);
// Register for settings changes.
final ContentResolver resolver = mContext.getContentResolver();
resolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.SCREENSAVER_ENABLED),
......
IVrManager vrManager =
(IVrManager) getBinderService(VrManagerService.VR_MANAGER_BINDER_SERVICE);
try {
vrManager.registerListener(mVrStateCallbacks);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to register VR mode state listener: " + e);
}
// 读取配置
readConfigurationLocked();
updateSettingsLocked();
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
}
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BatteryReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
mContext.registerReceiver(new DreamReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DOCK_EVENT);
mContext.registerReceiver(new DockReceiver(), filter, null, mHandler);
}
总而言之在SystemReady方法中完成的主要工作如下:
- 1.获取与PowerManagerServcie相关的系统服务以及本地服务;
获取屏幕最大,最小以及默认亮度值; - 2.创建SensorManager 对象,用于和SensorService交互;
- 3.创建Notifier对象,用于通知系统中电源状态的改变;
- 4.创建WirelessChargerDetector对象,用于检测无线充电的传感器(市面上支持的手机较少)
- 5.调用DisplayManagerService的initPowerManagement()方法来初始化Power显示模块。
- 6.注册SettingsObserver监听系统设置的变化
3.4 userActivity
userActivity是定义在PowerManager中的SystemApi,用户向PowerManagerService报告用户活动,以更新PowerManagerService内部时间/状态值,推迟系统休眠的时间。
PowerManager中userActivity请求调用服务端PowerManagerService BinderService的userActivity
,即调用内部方法userActivityNoUpdateLocked
。
private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
// 如果发生时间是上一次休眠或唤醒前,或当前没有开机完成到systemReady,不采取操作直接返回
if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
|| !mBootCompleted || !mSystemReady) {
return false;
}
try {
// 更新mLastInteractivePowerHintTime时间
if (eventTime > mLastInteractivePowerHintTime) {
powerHintInternal(POWER_HINT_INTERACTION, 0);
mLastInteractivePowerHintTime = eventTime;
}
// 通过mNotifier通知BatteryStats UserActivity事件
mNotifier.onUserActivity(event, uid);
if (mUserInactiveOverrideFromWindowManager) {
mUserInactiveOverrideFromWindowManager = false;
mOverriddenTimeout = -1;
}
// 如果系统处于休眠状态,不进行处理
if (mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
return false;
}
// 根据flag是否在已变暗的情况下是否重启活动超时更新mLastUserActivityTimeNoChangeLights或mLastUserActivityTime
// 并且设置mDirty DIRTY_USER_ACTIVITY
if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
if (eventTime > mLastUserActivityTimeNoChangeLights
&& eventTime > mLastUserActivityTime) {
mLastUserActivityTimeNoChangeLights = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
} else {
if (eventTime > mLastUserActivityTime) {
mLastUserActivityTime = eventTime;
mDirty |= DIRTY_USER_ACTIVITY;
return true;
}
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return false;
}
4. 应用场景
例如:长连接需要在后台服务需要持续在线;安卓系统底层优化策略会在系统休眠这段时间调整CPU的运作,我们需要将应用保持CPU一直运转。
mqtt或者websocket等长连接框架就需要如此!
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock w1 = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "MyTag");
w1.acquire();
//在这个过程,屏幕会保持光亮!
//或者网络协议执行心跳包
w1.release();
上述newWakeLock( )的第一个flag标记,这些标记不同程度的影响系统电源.
这些标记都是独占的,并且每次只能指定其中一个。
PARTIAL_WAKE_LOCK
:保持CPU 运转,屏幕和键盘灯有可能是关闭的。SCREEN_DIM_WAKE_LOCK
:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯SCREEN_BRIGHT_WAKE_LOCK
:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯FULL_WAKE_LOCK
:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
5. 控制系统休眠
Android设备的休眠和唤醒主要基于WakeLock机制。WakeLock是一种上锁机制,只要有进程获得了WakeLock锁系统就不会进 入休眠。例如,在下载文件或播放音乐时,即使休眠时间到了,系统也不能进行休眠。WakeLock可以设置超时,超时后会自动解锁,具体关于wake lock的介绍后面会另写一篇,此处仅作简单介绍。
应用使用WakeLock功能前,需要先使用new WakeLock()
接口创建一个WakeLock
类对象,然后调用它的acquire()
方法禁止系统休眠,应用完成工作后调用release()
方法来恢复休眠机制,否则系统将无法休眠,直到耗光所有电量。
WakeLock
类中实现acquire()
和release()
方法实际上是调用了PowerManagerService
的acquireWakeLock()
和releaseWakeLock()
方法。
updatePowerStateLocked()
为PowerManagerService
的核心函数;在执行完申请锁,释放锁,用户事件,强制唤醒/睡眠等操作都需要调用updatePowerStateLocked()
来更新电源状态
5.1 wakelock
Wakelock是android系统上特有的电源管理机制,只要有应用拿着这个锁,系统就不能进入睡眠状态,在上层不同的应用程序可以持有多个不同的wakelock锁,但是反映到底层就只有三种:控制系统休眠PowerManagerService.WakeLock
,控制屏幕显示的PowerManagerService.Display
和控制电源状态改变通知的PowerManagerService.Broadcasts
。
PowerManagerService
有acquire()加锁
和release()解锁
两种状态,加锁有两种方式:
- 第一种是永久的锁住,这样的锁除非显式的放开,否则是不会解锁的,所以这种锁用起来要非常的小心(默认)。
acquire()
:申请wakelock永久锁(默认),需要手动release - 第二种锁是超时锁,这种锁会在锁住后一段时间解锁。
acquire(long timeout)
:申请wakelock超时锁,timeout为设置的超时时间,超时自动release掉该wakelock。
应用程序在使用wakelock前,必须在其manifest.xml
文件中注册android.permission.WAKE_LOCK
权限;
边栏推荐
- Lexin interview process
- 【软件测试】04 -- 软件测试与软件开发
- Ros2 - first acquaintance with ros2 (I)
- Technical conference arrangement
- Error: "mountvolume.setup failed for volume PVC fault handling
- In C language, int a= 'R'
- 三体目标管理笔记
- 基于FPGA的一维卷积神经网络CNN的实现(八)激活层实现
- MySQL setting trigger problem
- Integer to 8-bit binary explanation (including positive and negative numbers) scope of application -127~+127
猜你喜欢
Spinningup drawing curve
Skywalking all
. Net core stepping on the pit practice
Get class files and attributes by reflection
PHY驱动调试之 --- PHY控制器驱动(二)
Ros2 - configuration development environment (V)
.net core踩坑实践
Financial risk control practice -- feature derivation based on time series
ROS2——Service服务(九)
MySQL (UDF authorization)
随机推荐
[Gaode map POI stepping pit] amap Placesearch cannot be used
Ros2 - ros2 vs. ros1 (II)
[tf] Unknown: Failed to get convolution algorithm. This is probably because cuDNN failed to initial
Unity 之 ExecuteAlways正在取代ExecuteInEditMode
Xavier CPU & GPU high load power consumption test
PHY驱动调试之 --- MDIO/MDC接口22号和45号条款(一)
能量守恒和打造能量缺口
How to answer when you encounter a jet on CSDN?
ROS2——node节点(七)
Matlab在线性代数中的应用(四):相似矩阵及二次型
Record of problems in ollvm compilation
Architecture
解读最早的草图-图像翻译工作SketchyGAN
[algorithm post interview] interview questions of a small factory
Cloud native related technology learning
达梦数据库全部
In C language, int a= 'R'
【软件测试】06 -- 软件测试的基本流程
数学分析_笔记_第8章:重积分
Cookie、Session、JWT、token四者间的区别与联系