ps:为方便阅读、书写以及和PackageManagerService加以区分,本文后面将统一以PWMS简称PowerManagerService
PWMS是负责管理、协调设备电源管理的系统服务之一,设备常见功能如亮灭屏、亮度调节、低电量模式、唤醒锁等,都会通过PWMS去协调和处理。为了更好地认识android的电源管理机制,我们便从电源管理的大管家——PWMS入手来进行分析。
从前文分析可知,PWMS是在SystemServer的引导阶段开始创建的,不太清楚的读者可以回顾一下下面这篇文章:
Android 10 启动分析之SystemServer篇 (四)
创建语句如下:
mSystemServiceManager.startService(PowerManagerService.class);
SystemServiceManager对应的代码片段如下所示:
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {
final T service;
try {
Constructor<T> constructor = serviceClass.getConstructor(Context.class);
service = constructor.newInstance(mContext);
} catch (InstantiationException ex) {
...
} catch (IllegalAccessException ex) {
...
} catch (NoSuchMethodException ex) {
...
} catch (InvocationTargetException ex) {
...
}
startService(service);
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
public void startService(@NonNull final SystemService service) {
// Register it.
mServices.add(service);
try {
//这个方法里没啥重要的内容,可以忽略
service.onStart();
} catch (RuntimeException ex) {
...
}
}
里面的逻辑很简单,首先通过反射调用了PowerManagerService的构造函数,紧接着调用了它的onStart方法。
PWMS的构造方法里都是些创建对象的动作,但为了让各位读者更加熟悉PWMS依赖的类的作用,我们还是来看一下PWMS的构造函数。
PowerManagerService(Context context, Injector injector) {
super(context);
mContext = context;
//作为IPC的服务端
mBinderService = new BinderService();
//为同进程的其它模块提供支持
mLocalService = new LocalService();
//NativeWrapper是对调用native方法提供的一层包装
mNativeWrapper = injector.createNativeWrapper();
mInjector = injector;
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
mHandlerThread.start();
mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
mConstants = new Constants(mHandler);
//AmbientDisplayConfiguration封装了对配置的读取访问
mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context);
//负责检测用户是否正在关注手机
mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);
//用于统计电池电量消耗率
mBatterySavingStats = new BatterySavingStats(mLock);
//BatterySaverPolic决定是否特定服务打开省电模式。
mBatterySaverPolicy =
mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);
//负责省电模式的逻辑切换
mBatterySaverController = new BatterySaverController(mLock, mContext,
BackgroundThread.get().getLooper(), mBatterySaverPolicy,
mBatterySavingStats);
//决定何时启用/禁用省电模式
mBatterySaverStateMachine = new BatterySaverStateMachine(
mLock, mContext, mBatterySaverController);
synchronized (mLock) {
//锁机制
mWakeLockSuspendBlocker =
mInjector.createSuspendBlocker(this, "PowerManagerService.WakeLocks");
mDisplaySuspendBlocker =
mInjector.createSuspendBlocker(this, "PowerManagerService.Display");
if (mDisplaySuspendBlocker != null) {
mDisplaySuspendBlocker.acquire();
mHoldingDisplaySuspendBlocker = true;
}
mHalAutoSuspendModeEnabled = false;
mHalInteractiveModeEnabled = true;
mWakefulness = WAKEFULNESS_AWAKE;
sQuiescent = SystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
//native方法初始化
mNativeWrapper.nativeInit(this);
//关闭自动休眠
mNativeWrapper.nativeSetAutoSuspend(false);
//保持屏幕点亮
mNativeWrapper.nativeSetInteractive(true);
//禁用双击屏幕唤醒系统的功能
mNativeWrapper.nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
}
}
SystemServer调用PWMS的systemReady方法,标识着PWMS的启动进入了第二个阶段。
systemReady的代码比较长而且琐碎,感兴趣的读者可以自己去翻一下源码,本文就不贴代码了。
简单地概况一下,这个方法里主要做了5件事情:
-
获取各类本地服务、远程服务以及相关联的功能类,如屏保(DreamMangerService)、窗口(PhoneWindowManager)、电池状态监听服务(BatteryService)、屏显服务(DisplayManagerInternal)、背光服务(LightsManager)、无线充电(WirelessChargerDetector)等,用于后续的交互。
-
调用readConfigurationLocked()方法读取配置文件中的默认值,如 插拔USB是否亮屏 、是否支持屏保 、充电和睡眠时屏保是否激活 、是否支持双击唤醒屏幕 等等。
-
调用updateSettingsLocked()方法查询Settings中配置的值,如 是否打开屏保、休眠时是否启用屏保、设备在一段时间不活动后进入休眠或者屏保状态的时间等待。
-
注册SettingsObserver监听,监听Settings中的值的变化。
-
注册广播接收者,监听特定的广播事件,如 电池状态的改变、进入屏保、切换用户、设备物理插槽状态的改变(通常用于监听是否接入了有线充电器)。
SystemServer会在特定的阶段调用startBootPhase方法,最终此方法会调用到PWMS的onBootPhase方法中,在此之前,我们先简单的介绍一下SystemServer的startBootPhase这个重要的方法。
SystemServer在启动所有的系统服务时,定义了七个重要的阶段,不同的服务可能需要关注其中某些时间节点,做一些特定的行为。startBootPhase这个方法,就是在某个阶段被触发时,去通知所有已经启动并缓存的服务,特定的阶段的事件已经被触发了。具体来看,SystemServer定义的七个阶段的事件如下:
PHASE_WAIT_FOR_DEFAULT_DISPLAY 这是一个依赖项,只有DisplayManagerService中进行了对应处理;
PHASE_LOCK_SETTINGS_READY LockSettingsService已准备就绪,DevicePolicyManager需要此前置条件才能初始化。
PHASE_SYSTEM_SERVICES_READY 系统核心服务已准备就绪,这个事件意味着所有服务已经可以安全地调用核心服务了。
PHASE_DEVICE_SPECIFIC_SERVICES_READY 在收到这个阶段事件后,所有服务可以安全地调用设备特殊服务,比如PermissionPolicyService。
PHASE_ACTIVITY_MANAGER_READY 在收到这个阶段事件后,所有服务都可以发送广播了。
PHASE_THIRD_PARTY_APPS_CAN_START 在收到这个阶段事件后,所有服务可以启动第三方应用,第三方应用也可以通过Binder来调用服务。
PHASE_BOOT_COMPLETED 在收到这个阶段事件后,说明所有服务都已经启动完成,这时用户就可以和设备进行交互。一般系统服务更倾向监听此事件,而不是监听ACTION_BOOT_COMPLETED广播,原因是监听此事件比广播更高效。
现在我们再来看看PWMS的onBootPhase方法,
public void onBootPhase(int phase) {
synchronized (mLock) {
if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
//开机启动次数+1,不需要关注
incrementBootCount();
} else if (phase == PHASE_BOOT_COMPLETED) {
final long now = SystemClock.uptimeMillis();
mBootCompleted = true;
mDirty |= DIRTY_BOOT_COMPLETED;
mBatterySaverStateMachine.onBootCompleted();
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
//最后一步,更新电源状态信息
updatePowerStateLocked();
}
}
}
updatePowerStateLocked负责更新电源状态信息,具体来看,它做了以下7项工作:
- 基础状态的更新,比如 是否正在充电,充电时是否保持唤醒、更新屏幕是否保持最大亮度.
- 更新唤醒状态。这一步是个死循环,它会不停地去检查用户未与屏幕交互的时间是否已超过灭屏限制时间,如果是,则进入屏保模式或休眠模式。
- 锁定处于非活动状态的配置文件。
- 异步更新显示电源状态。
- 更新屏保状态,根据配置参数决定是否在界面上显示屏保。
- 通知唤醒状态改变的事件给其他的观察者,比如
WindowManagerPolicy。 - 更新锁状态,根据条件获取或释放唤醒锁。
以上便是PWMS 服务启动的全流程,下一篇文章,我们将关注本篇出现的一个重要的词汇——唤醒锁,看看它有什么作用,又是怎样工作的。