4、PowerManagerService启动流程:SystemServer中的初始化、服务注册、核心成员变量解析

好,咱们今天来聊聊 PMS 的启动流程。说实话,这部分代码我翻过不下二十遍。每次看都有新发现。你想想看,一个系统服务从出生到上岗,中间要经历多少道工序?

PMS 的启动,说白了就三步:创建实例 → 注册服务 → 初始化核心数据。但每一步里面都藏着不少细节。我当年第一次看的时候,差点被那一堆成员变量搞晕。

4.1 SystemServer 中的初始化入口

一切从 SystemServer.java 开始。这是 Android 系统服务的「总指挥部」。PMS 的启动代码就在 startBootstrapServices() 方法里。

// frameworks/base/services/java/com/android/server/SystemServer.java

private void startBootstrapServices() {
    // ... 其他服务启动 ...

    // 启动 PowerManagerService
    mPowerManagerService = mSystemServiceManager.startService(
            PowerManagerService.class);

    // ... 后续操作 ...
}

嗯,这里要注意。PMS 属于引导服务,它必须在很多其他服务之前启动。为什么?因为电池管理、亮屏灭屏这些基础操作,其他服务都要依赖它。

我个人习惯把系统服务的启动顺序画成一张图。PMS 排在第三梯队:

启动顺序 服务名称 启动阶段
1 Installer startBootstrapServices
2 DeviceIdentifiers startBootstrapServices
3 PowerManagerService startBootstrapServices
4 LightsService startBootstrapServices
... ... ...

你可能会问:为什么 LightsService 在 PMS 之后?因为 PMS 需要控制灯光啊。但 LightsService 又需要 PMS 提供电源状态。这其实是个依赖链的问题。Android 团队的处理方式是:先创建 PMS 实例,等 LightsService 启动后再把引用传过去。

4.2 服务注册到 ServiceManager

创建完实例后,下一步就是注册。PMS 把自己注册到 ServiceManager,这样其他进程才能通过 Binder 调用它。

// PowerManagerService.java 的 onStart() 方法

@Override
public void onStart() {
    // 发布到 ServiceManager
    publishBinderService(Context.POWER_SERVICE, mService);
    
    // 发布本地服务
    publishLocalService(PowerManagerInternal.class, mLocalService);
    
    // 跟踪系统服务启动
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}

这里有两个关键点:

  • publishBinderService:对外暴露 Binder 接口。其他 App 通过 getSystemService(Context.POWER_SERVICE) 拿到的就是这个代理。
  • publishLocalService:对内暴露本地接口。只给 SystemServer 内部的其他服务用,不走 Binder,性能更好。

我曾经踩过一个坑:有个第三方 App 频繁调用 PowerManager 的 API,导致 Binder 线程池被打满。后来发现是它没做频率限制。嗯,从那以后我写 PMS 相关的代码,都会特别注意 Binder 调用的开销。

4.3 核心成员变量解析

这部分是重点。PMS 的成员变量非常多,我挑几个最核心的来讲。你想想看,一个电源管理系统要管哪些事?屏幕亮暗、CPU 频率、唤醒锁、充电状态……每个功能都对应一组变量。

4.3.1 电源状态相关

// 当前屏幕状态
private int mScreenState;
// 当前充电状态
private int mBatteryLevel;
// 是否处于交互状态(用户正在操作)
private boolean mUserActivity;
// 是否处于梦境(屏保)状态
private boolean mDreamsEnabled;

这些变量是 PMS 的「眼睛」。系统通过它们感知当前电源状态。比如 mScreenState 的值:

常量 含义
SCREEN_STATE_OFF 0 屏幕关闭
SCREEN_STATE_DIM 1 屏幕变暗(即将关闭)
SCREEN_STATE_BRIGHT 2 屏幕正常亮起
SCREEN_STATE_VR 3 VR 模式

4.3.2 唤醒锁管理

唤醒锁(WakeLock)是 PMS 最核心的机制之一。App 通过它来阻止系统进入休眠。

// 唤醒锁列表
private final ArrayList<WakeLock> mWakeLocks = new ArrayList<>();
// 唤醒锁统计信息
private int mWakeLockCount;
// 是否强制释放所有唤醒锁
private boolean mForceAllWakeLocksReleased;

我记得有一次,某个视频 App 在后台持有一个 PARTIAL_WAKE_LOCK 不放,导致手机一晚上掉电 30%。排查的时候就是通过 mWakeLocks 列表找到的罪魁祸首。

小提示:调试唤醒锁泄漏时,可以用 adb shell dumpsys power 查看当前持有的唤醒锁列表。这个命令我几乎每天都要用。

4.3.3 显示电源相关

// 显示设备(屏幕)的电源状态
private DisplayPowerController mDisplayPowerController;
// 屏幕亮度值(0-255)
private int mScreenBrightness;
// 是否自动调节亮度
private boolean mAutoBrightnessEnabled;
// 屏幕超时时间(毫秒)
private long mScreenOffTimeout;

这里有个细节:mScreenBrightness 虽然是 0-255 的范围,但实际硬件可能只支持 0-100 或者 0-1023。PMS 内部会做映射转换。我建议你在做定制开发时,一定要确认硬件支持的亮度范围。

4.3.4 系统状态监听器

// 电池状态监听
private final BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 更新电池信息
        updateBatteryInfo(intent);
    }
};

// 用户活动监听
private final UserActivityListener mUserActivityListener = 
    new UserActivityListener() {
    @Override
    public void onUserActivity() {
        // 重置屏幕超时计时器
        userActivityNoUpdateLocked();
    }
};

这些监听器是 PMS 的「耳朵」。电池变化、用户触摸、按键事件……PMS 通过它们感知外部世界的变化。

4.4 初始化流程总结

好,咱们把整个流程串起来看:

  1. SystemServer 调用 startService:创建 PMS 实例
  2. PMS 构造函数执行:初始化核心成员变量(大部分是默认值)
  3. onStart() 方法调用:注册 Binder 服务和本地服务
  4. onBootPhase() 阶段回调:在 PHASE_SYSTEM_SERVICES_READY 阶段,PMS 开始监听电池、用户活动等事件
  5. systemReady() 最终就绪:所有依赖服务都准备好了,PMS 开始正常工作
注意:PMS 的 systemReady() 方法执行完后,系统才会真正进入可交互状态。在此之前,屏幕可能一直处于默认亮度,唤醒锁机制也未完全生效。所以如果你在开机阶段遇到电源相关的问题,优先检查 PMS 的启动是否完整。

说实话,PMS 的启动流程看起来简单,但每个环节都环环相扣。我刚开始做 Android 系统开发时,总觉得这些初始化代码没什么好看的。直到有一次遇到一个开机黑屏的 bug,追了两天才发现是 PMS 的 mScreenState 初始化顺序出了问题。

你想想看,一个简单的变量赋值,背后可能牵扯到整个系统的电源管理策略。这就是为什么我建议大家多看源码,多理解这些「看似简单」的初始化逻辑。