PMS服务之updatePowerStateLocked方法分析

updatePowerStateLocked是Android PowerManagerService的核心方法,用于处理电源状态的更新。该方法根据mDirty变量更新电池状态、低电量模式、屏幕亮度、唤醒锁和用户活动。其中涉及的关键步骤包括更新电池信息、屏幕亮度提升、唤醒状态和互动屏保的管理。当电源状态、充电状态或用户活动发生变化时,系统会调用此方法以调整电源管理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

updatePowerStateLocked更新电源的状态,是PowerManagerService的核心方法,当电源状态发生改变最终都会调用到updatePowerStateLocked方法,下面分析这个方法的实现。

private void updatePowerStateLocked() {
        if (!mSystemReady || mDirty == 0) {
            return;
        }
        
        try {
            // 第一步:更新基本状态
            updateIsPoweredLocked(mDirty);
            updateStayOnLocked(mDirty);
            updateScreenBrightnessBoostLocked(mDirty);

            // 第二步: 更新wakelock和用户活动
            final long now = SystemClock.uptimeMillis();
            int dirtyPhase2 = 0;
            for (;;) {
                int dirtyPhase1 = mDirty;
                dirtyPhase2 |= dirtyPhase1;
                mDirty = 0;

                updateWakeLockSummaryLocked(dirtyPhase1);
                updateUserActivitySummaryLocked(now, dirtyPhase1);
                if (!updateWakefulnessLocked(dirtyPhase1)) {
                    break;
                }
            }

            // 第三步:更新display power state
            boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);

            // 第四步:更新dream state
            updateDreamLocked(dirtyPhase2, displayBecameReady);

            // 第五步:发送通知
            finishWakefulnessChangeIfNeededLocked();

            //第六步:更新底层wakeLock
            updateSuspendBlockerLocked();
        }
    }
 

在PowerManagerService服务中有个很重要的变量,就是mDirty,这个变量按位来存贮PowerManagerService中的各种变化状态,每当和PMS相关发生了变化,就会第一时间来更新mDirty的相应的位,将相应的位置为1,mDirty变量按位来存储一些Power相关的标志位,然后该方法根据mDirty变量来更新Power的各个状态。

在SystemReady方法中会更新mDirty这个状态,把mDirty置位为DIRTY_BATTERY_STATE,收BatterySevice发出来的广播,也会设置mDirty这个标志位。这个方法中集中处理了电源状态的更新逻辑,当系统的电源相关发生一些变化的时候都会调用这个方法更新电源状态。

该方法的处理主要分为几个步骤,我们一个一个步骤的来进行分析:

第一步:更新基本的状态信息

updateIsPowerLocked(mDirty)

private void updateIsPoweredLocked(int dirty) {
        if ((dirty & DIRTY_BATTERY_STATE) != 0) {
           //电池状态发生变化
            ……
            mIsPowered = mBatteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
            //充电类型
            mPlugType = mBatteryManagerInternal.getPlugType();
            //当前电量
            mBatteryLevel = mBatteryManagerInternal.getBatteryLevel();
            //当前是否低电量
            mBatteryLevelLow = mBatteryManagerInternal.getBatteryLevelLow();


            if (wasPowered != mIsPowered || oldPlugType != mPlugType) {
                mDirty |= DIRTY_IS_POWERED;

              ……
              //插拔充电器或者USB是否唤醒屏幕
(shouldWakeUpWhenPluggedOrUnpluggedLocked(wasPowered, oldPlugType,
                        dockedOnWirelessCharger)) {
                    //更新唤醒屏幕的信息
                    wakeUpNoUpdateLocked(now, "android.server.power:POWER", Process.SYSTEM_UID,
                            mContext.getOpPackageName(), Process.SYSTEM_UID);
                }
                //触发一次用户活动,修改用户活动事件的时间,重置屏幕灭屏的时间
                userActivityNoUpdateLocked(
                        now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);

                ……
            }
            //如果充电状态或者低电量状态发生变化,调用updateLowPowerLocked 更新电源信息
            if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {
                ……
                updateLowPowerModeLocked();
            }
        }
    }


 

该方法中更新了电池当前的电量,当前是否正常充电,充电的类型,以及batteryLow的电量和mBatteryLevelLow是否是低电量状态

当电源的充电状态或者充电类型发生变化, 根据设置来决定是否唤醒系统

当电源充电状态发生变化或者低电量的值发生变化的时候,调用updateLowPowerModeLocked()更新低电量的状态。

<pre name="code" class="java">void updateLowPowerModeLocked() {
        if (mIsPowered && mLowPowerModeSetting) {
            Settings.Global.putInt(mContext.getContentResolver(),
                    Settings.Global.LOW_POWER_MODE, 0);
            mLowPowerModeSetting = false;
        }
       //是否可以自动进入低电量状态的省电模式
        final boolean autoLowPowerModeEnabled = !mIsPowered && mAutoLowPowerModeConfigured
                && !mAutoLowPowerModeSnoozing && mBatteryLevelLow;
        //当前是否是低电量模式
        final boolean lowPowerModeEnabled = mLowPowerModeSetting || autoLowPowerModeEnabled;

        if (mLowPowerModeEnabled != lowPowerModeEnabled) {
            mLowPowerModeEnabled = lowPowerModeEnabled;
            powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);
            BackgroundThread.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
                            .putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, mLowPowerModeEnabled)
                            .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                   ……intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                    mContext.sendBroadcast(intent);
                }
            });
        }
    }


 

该方法中首先判断手机是否在充电,如果手机在充电,退出LowPowerMode模式,同时把设置中的mLowPowerModeSetting置为false。 autoLowPowerModeEnabled变量表示是否可以自动进入低电量省电模式,需要满足几个条件:

1.未充电 2.设置了可以自动进入低电量省电模式 3.目前处于低电量的状态

mLowPowerModeEnabled变量表示当前是否进入低电量省电模式

当手机的低电量模式发生了变化,就发送ACTION_POWER_SAVE_MODE_CHANGING的通知,回调关于该模式变化的监听,通知相关的服务Power Save Mode发生了变化。

PowerUI接收到低电量省电模式的广播,就会弹出低电量省电模式的提醒界面

updateStayOnLocked(mDirty)

该方法根据当前的充电状态,来判断充电的时候手机是否保持唤醒。


                
<think>我们正在分析息屏指纹解锁过程中涉及的Android系统底层线程和模块的具体作用。根据用户需求,我们将重点分析以下模块在解锁流程中的协作机制: 1. InputDispatcher 2. DisplayPowerController 3. system_server 4. PowerManagerService 5. android.display线程 同时,用户提供了两段引用,其中引用[1]是关于PhoneWindowManager中唤醒屏幕的代码片段,引用[2]是关于buildroot的,与当前问题关联不大,因此我们主要参考引用[1]。 以下是息屏指纹解锁流程中相关模块的详细分析: ### 一、InputDispatcher 处理指纹触摸事件 当用户在息屏状态下触摸指纹传感器时,传感器产生中断,InputReader读取到原始事件并封装成FingerprintEvent(实际上是一个MotionEvent,类型为ACTION_DOWN)。然后InputReader将事件传递给InputDispatcher。 - **InputDispatcher的作用**:负责将输入事件分发给合适的窗口。在息屏状态下,由于没有活动窗口(除了锁屏窗口,但此时锁屏窗口可能处于不可见状态),因此InputDispatcher需要将事件传递给系统服务。 - **onPointerDownOutsideFocus**:当事件发生在当前焦点窗口之外时,会触发这个回调。在息屏状态下,当前焦点窗口可能是锁屏窗口(如果锁屏处于非活动状态则可能没有焦点窗口),因此指纹事件会被视为焦点外事件。 - 此时,InputDispatcher会通过系统调用(如Binder)将事件传递给system_server进程中的WindowManagerService(WMS)处理。 在WMS中,会判断事件类型并触发指纹认证流程。 ### 二、system_server 进程中的协作 system_server是Android系统核心进程,包含多个系统服务,如WindowManagerService (WMS)、PowerManagerService (PMS)、ActivityManagerService (AMS) 等。 1. **WMS 处理指纹事件**: - WMS收到InputDispatcher传来的指纹触摸事件后,会调用BiometricService进行认证。 - 认证请求会通过Binder传递到BiometricService(运行在system_server进程)。 2. **BiometricService 启动认证**: - BiometricService负责协调生物识别认证。它会与运行在TEE(可信执行环境)中的指纹服务进行通信,进行指纹比对。 3. **认证成功后的处理**: - 当指纹认证成功,BiometricService会回调到WMS或直接通知PowerManagerServicePMS)进行唤醒操作。 4. **PowerManagerService 唤醒设备**: - PMS是管理设备电源状态的核心服务。在收到唤醒请求后,它会更新全局的唤醒状态。 - 关键代码(参考引用[1]中的`wakeUpFromPowerKey`方法,类似地,指纹解锁也会调用类似的唤醒方法): ```java // PowerManagerService.java public void wakeUp(long eventTime, int reason, String details, String opPackageName) { ... setWakefulness(Display.DEFAULT_DISPLAY, WAKEFULNESS_AWAKE, reason); ... } ``` - 这里会设置设备的唤醒状态为`WAKEFULNESS_AWAKE`,然后通知其他模块(如DisplayPowerController)。 ### 三、DisplayPowerController 更新电源状态 DisplayPowerController(DPC)是PMS中负责显示电源状态控制的核心类。它运行在`android.display`线程(这个线程是专门用于处理显示相关操作的,避免主线程阻塞)。 1. **updatePowerState 方法**: - 当PMS的唤醒状态改变时,会调用DPC的`updatePowerState`方法。这个方法会重新计算显示设备的电源状态,并执行相应的状态转换。 - 在息屏状态下,显示设备处于低功耗模式(可能是OFF或DOZE状态)。当收到唤醒请求后,DPC会将目标状态设置为ON。 2. **状态转换过程**: - DPC会通过状态机逐步将显示状态从OFF/DOZE切换到ON。这个过程包括: - 申请唤醒锁(确保在状态转换过程中设备不会休眠)。 - 通过HAL层设置显示设备的电源状态(调用DisplayHardwareController的`setDisplayState`方法)。 - 更新背光亮度(从0逐渐增加到用户设定的亮度)。 3. **背光控制**: - DPC会根据当前环境光传感器数据和用户设置计算目标亮度,然后通过HAL层设置背光值。 4. **HWPeripheralDRM PowerOn**: - 在显示状态切换过程中,会涉及到DRM(Display Render Manager)驱动的操作。当需要打开显示时,会调用DRM驱动的`PowerOn`操作,这会通过Kernel驱动打开显示面板和背光。 ### 四、android.display 线程的作用 `android.display`线程是系统创建的一个专用线程,用于处理显示相关的操作,以避免主线程(system_server的主线程)被阻塞。在DPC中,大部分耗时的显示状态更新操作都在这个线程中执行。 具体来说,在DPC的`updatePowerState`方法中,会通过`DisplayPowerState`对象(运行在`android.display`线程)来更新显示状态和背光亮度。这样做可以确保显示操作不会影响其他系统服务的响应性。 ### 五、PowerManagerService 与 DisplayPowerController 的协作 1. PMS调用DPC更新显示状态: - 当PMS的唤醒状态改变(例如从睡眠变为唤醒)时,它会调用DPC的`updatePowerState`方法(通过`updatePowerStateLocked`方法)。 - 这个调用发生在PMS的锁(`mLock`)保护下,但实际的状态转换工作会提交到`android.display`线程执行。 2. 状态同步: - DPC在更新显示状态后,会通过回调通知PMS(例如,当显示设备完全打开后,会释放一些唤醒锁)。 ### 六、整体流程总结 1. **输入事件传递**: InputReader → InputDispatcher → WMS(在system_server中) → BiometricService 2. **认证与唤醒**: BiometricService(认证成功) → PowerManagerService(唤醒设备) → DisplayPowerController(更新显示状态) 3. **显示与背光控制**: DisplayPowerController(在`android.display`线程) → 调用HAL层(HWComposer) → Kernel DRM驱动(打开显示面板,调节背光) ### 流程图 ```mermaid sequenceDiagram participant InputReader participant InputDispatcher participant WMS participant BiometricService participant PowerManagerService participant DisplayPowerController participant android.display participant HAL participant Kernel InputReader->>InputDispatcher: 指纹事件(ACTION_DOWN) InputDispatcher->>WMS: onPointerDownOutsideFocus WMS->>BiometricService: authenticate() BiometricService-->>WMS: 认证成功回调 WMS->>PowerManagerService: wakeUp() PowerManagerService->>DisplayPowerController: updatePowerState() Note over DisplayPowerController,android.display: 状态切换在android.display线程 DisplayPowerController->>android.display: 提交状态更新任务 android.display->>HAL: setDisplayState(ON) HAL->>Kernel: DRM PowerOn Kernel-->>HAL: 操作完成 HAL-->>android.display: 返回 android.display-->>DisplayPowerController: 状态更新完成 DisplayPowerController->>PowerManagerService: 通知状态改变 ``` ### 相关问题 1. 在息屏状态下,InputDispatcher如何确保指纹事件被优先处理? 2. DisplayPowerController在状态转换过程中如何避免屏幕闪烁? 3. 如果指纹认证失败,系统如何保持息屏状态? 4. 在低电量模式下,背光控制策略会有什么变化? 以上分析基于Android系统源码(特别是引用[1]中涉及的PhoneWindowManager和PowerManagerService逻辑)以及常见的系统架构。</think>### 息屏指纹解锁底层线程与模块协作机制分析 #### 1. **InputDispatcher 事件分发** - **作用**:指纹事件的中枢调度器 - **关键流程**: 1. 接收来自 InputReader 的原始指纹触摸事件(`EV_ABS` 类型) 2. 通过 `onPointerDownOutsideFocus` 检测到息屏状态下的焦点外事件 3. 通过 Binder IPC 将 `MotionEvent(ACTION_DOWN)` 发送到 system_server 进程 - **线程模型**:运行在 `system_server` 的 `InputDispatcher` 专用线程 - **特殊处理**:息屏状态下提升事件优先级,绕过常规窗口焦点检查 #### 2. **system_server 系统服务枢纽** - **作用**:跨服务协调的中控系统 - **关键协作**: ```mermaid graph LR A[InputDispatcher] -->|MotionEvent| B(WindowManagerService) B -->|authenticate| C(BiometricService) C -->|认证结果| D(PowerManagerService) D -->|唤醒指令| E(DisplayPowerController) ``` - **线程模型**: - `android.display`:显示控制专用线程 - `ActivityManager`:主服务线程 - `Binder:IPC`:跨进程通信线程池 #### 3. **PowerManagerService 电源控制** - **唤醒流程**: 1. 收到认证成功消息后调用 `wakeUp()` 方法 2. 更新全局电源状态:`PowerManager.WAKE_REASON_FINGERPRINT` 3. 通过 `setWakefulness()` 触发显示状态切换 4. 执行 `wakeUpFromPowerKey()` 类似逻辑[^1]: ```java // PhoneWindowManager.java 伪代码 if (wakeUp(eventTime, true, PowerManager.WAKE_REASON_FINGERPRINT)) { startDockOrHome(); // 触发主屏幕启动 } ``` #### 4. **DisplayPowerController 显示控制** - **核心方法**:`updatePowerState()` - **状态切换流程**: 1. 接收 `PowerManager.STATE_ON` 指令 2. 计算显示状态转换路径: $$ \text{DOZE} \xrightarrow{\text{transition}} \text{ON} $$ 3. 通过 `HWPeripheralDRM` 调用显示驱动 4. 执行背光渐变算法: ```cpp // 伪代码:背光控制逻辑 int target = calculateUnlockBrightness(); mBacklight.setBrightness(target, BRIGHTNESS_RAMP_RATE_UNLOCK); ``` #### 5. **android.display 专用线程** - **作用**:显示控制的实时响应线程 - **关键操作**: - 执行 `call_made setDisplayState(ON)` 硬件指令 - 管理显示状态机的异步转换 - 协调 VSYNC 信号与背光控制的时序 - **实时性保障**:优先级提升至 `RT`(实时线程) #### 6. **HWPeripheralDRM 硬件抽象层** - **作用**:内核驱动的桥梁 - **解锁关键操作**: 1. `PowerOn`:通过 DRM(Direct Rendering Manager)发送显示使能命令 2. 调用 `ioctl(DRM_IOCTL_MODE_SETDISPLAY)` 切换显示状态 3. 通过 `sysfs` 接口设置背光值:`/sys/class/backlight/.../brightness` #### 7. **完整协作时序** ```mermaid sequenceDiagram participant InputDispatcher participant system_server participant PowerManagerService participant DisplayController participant android.display participant HWPeripheralDRM InputDispatcher->>system_server: onPointerDownOutsideFocus() system_server->>PowerManagerService: wakeUp(WAKE_REASON_FINGERPRINT) PowerManagerService->>DisplayController: setDisplayState(ON) DisplayController->>android.display: postUpdatePowerState() android.display->>HWPeripheralDRM: call_made setDisplayState(ON) HWPeripheralDRM-->>android.display: DRM_MODE_SETDISPLAY success android.display->>HWPeripheralDRM: setBrightness(target) HWPeripheralDRM-->>Kernel: backlight write sysfs ``` #### 8. **功耗优化机制** - **动态刷新率**:`REFRESH_RATE_OVERRIDE` 跳过中间帧 - **背光分级控制**: $$ \text{Brightness} = \begin{cases} 0 & \text{DOZE} \\ \min(B_{\text{user}}, B_{\text{ambient}}) & \text{解锁瞬间} \\ B_{\text{user}} & \text{稳定状态} \end{cases} $$ - **TEE 安全通道**:指纹处理全程在 TrustZone 完成,避免主 CPU 唤醒 --- ### 相关问题 1. 当指纹认证失败时,`DisplayPowerController` 如何保持息屏状态? 2. `HWPeripheralDRM` 如何通过 DRM 接口实现屏幕状态的原子切换? 3. 在低电量模式下,`PowerManagerService` 如何限制背光亮度? 4. 多传感器(如接近传感器)如何影响指纹解锁的背光控制策略? [^1]: 唤醒逻辑参考 PhoneWindowManager 的电源键唤醒实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值