Android7.0 PowerManagerService亮灭屏分析(三)

本文深入分析了Android 7.0中PowerManagerService的亮屏与灭屏过程。从animateScreenBrightness函数的亮度渐变动画到RampAnimator的实现,再到requestDisplayStateLocked中的runnable机制,详细阐述了亮屏操作。同时,灭屏流程中,从输入事件处理到PhoneWindowManager的角色,再到AMS和WMS的交互,展示了灭屏的独特步骤,包括AMS的comeOutOfSleepIfNeedLocked函数、InputManagerService的屏幕状态记录以及灭屏动画的执行。文章最后总结了亮灭屏的完整流程。

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

在前面两部分已经对绘制windows与设置设备状态进行了详细讲解. 之后接着就该对亮度值进行设置, 实现亮屏动作了.

在DisplayPowerController中的animateScreenBrightness函数通过亮度渐变动画来将亮度设置到目标亮度.

    // Brightness animation ramp rate in brightness units per second.
    private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;     //亮度渐变动画较慢的速率, 每秒变化40个亮度单位 

        mBrightnessRampRateFast = resources.getInteger(
                com.android.internal.R.integer.config_brightness_ramp_rate_fast);   //从配置文件中获取较快的亮度速率

        // Animate the screen brightness when the screen is on or dozing.
        // Skip the animation when the screen is off or suspended.
        if (!mPendingScreenOff) {
            if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
                animateScreenBrightness(brightness,      //当亮屏或doze状态时有亮度渐变动画
                        slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast);
            } else {
                animateScreenBrightness(brightness, 0);   //灭屏时没有亮度渐变动画,直接将亮度设置为0
            }
        }
在animateScreenBrightness函数中调用动画mScreenBrightnessRampAnimator对亮度值处理, 而mScreenBrightnessRampAnimator是在initialize()函数中进行初始化的, 在构造函数中将DisplayPowerState和DisplayPowerState.SCREEN_BRIGHTNESS传输过去.

  private void initialize() {
      //....
        mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(  //泛型为DisplayPowerState
                mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
        mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);
     //...
}

    private void animateScreenBrightness(int target, int rate) {
        if (DEBUG) {
            Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
        }
        if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {    //动画处理亮度值
            try {
                mBatteryStats.noteScreenBrightness(target);
            } catch (RemoteException ex) {
                // same process
            }
        }
    }

在RampAnimator的构造函数中将DisplayPowerState赋值给mObject, DisplayPowerState.SCREEN_BRIGHTNESS赋值给mProperty, 并且创建mChoreographer实例.

    public RampAnimator(T object, IntProperty<T> property) {
        mObject = object;
        mProperty = property;
        mChoreographer = Choreographer.getInstance();
    }

下面重点讲解animateTo函数.

    public boolean animateTo(int target, int rate) {
        // Immediately jump to the target the first time.
        if (mFirstTime || rate <= 0) {   //当第一次调用animateTo, 或者rate小于等于0时直接设置目标亮度.
            if (mFirstTime || target != mCurrentValue) {
                mFirstTime = false;   //之后就不是第一次调用该函数
                mRate = 0;              //设置mRate为0
                mTargetValue = target;   //设置目标亮度为target
                mCurrentValue = target;
                mProperty.setValue(mObject, target);   //调用DisplayPowerState.SCREEN_BRIGHTNESS设置亮度值
                if (mAnimating) {
                    mAnimating = false;
                    cancelAnimationCallback();
                }
                if (mListener != null) {
                    mListener.onAnimationEnd();  //动画结束
                }
                return true;
            }
            return false;
        }

        // Adjust the rate based on the closest target.
        // If a faster rate is specified, then use the new rate so that we converge
        // more rapidly based on the new request.
        // If a slower rate is specified, then use the new rate only if the current
        // value is somewhere in between the new and the old target meaning that
        // we will be ramping in a different direction to get there.
        // Otherwise, continue at the previous rate.
        if (!mAnimating
                || rate > mRate
                || (target <= mCurrentValue && mCurrentValue <= mTargetValue)
                || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
            mRate = rate;   //重新调节亮度速率
        }

        final boolean changed = (mTargetValue != target);  //如果当前亮度值不等于目标亮度值,说明亮度改变了
        mTargetValue = target;    //重新设置mTargetValue

        // Start animating.  开始动画
        if (!mAnimating && target != mCurrentValue) {  
            mAnimating = true;
            mAnimatedValue = mCurrentValue;
            mLastFrameTimeNanos = System.nanoTime();
            postAnimationCallback();
        }

        return changed; 
    }
在postAnimationCallback中调用Choreographer的postCallback函数处理, 调用完成后回调回mAnimationCallback的run函数

    private void postAnimationCallback() {
        mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null)
<think>我们正在分析Android系统中Power Manager服务(PMS)的流程。根据引用内容,我们可以构建一个从按键事件到幕状态变化的完整流程。以下将结合引用信息逐步分析: ### 1. **按键事件触发** 当用户按下Power键时,Input子系统会捕获该事件并传递给上层。在`PhoneWindowManager`中,会调用`wakeUpFromWakeKey`方法处理请求(引用[5]): ```java private void wakeUpFromWakeKey(KeyEvent event) { // ,原因是WAKE_REASON_WAKE_KEY,details是"android.policy:KEY" if (wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY")) { // ... 可能启动HOME界面 } } ``` 这里通过`wakeUp`方法向PowerManagerService发起请求。 ### 2. **PowerManagerService处理请求** 在PMS中,会计算幕状态、度等参数,并与ActivityManagerService(AMS)、WindowManagerService(WMS)等模块交互(引用[3])。核心流程包括: - 更新电源状态(如从休眠状态切换到状态) - 计算度曲线(考虑自动度、环境光等) - 通知AMS/WMS准备界面绘制 ### 3. **底层LCD控制** PMS最终会通过写入`/sys/power/state`节点控制幕状态(引用[4]): - :调用`autosuspend_disable()`,向节点写入`on` - :写入`mem`(或其他休眠状态字符串) 在写入节点后,会触发LCD的`late_resume`操作(如`sprdfb_dispc_resume`函数),硬件完成幕点。 ### 4. **流程** 流程与类似,但方向相反(引用[1][2]): 1. Power键事件触发`goToSleep`方法 2. PMS计算休眠状态 3. 通知AMS/WMS进入休眠(暂停界面绘制) 4. 写入`/sys/power/state`节点(如`mem`)关闭幕 ### 5. **关键节点总结** | **阶段** | **关键操作** | |----------------|-----------------------------------------------------------------------------| | **按键捕获** | `PhoneWindowManager`处理Power键事件,调用`wakeUp`或`goToSleep` | | **PMS状态计算**| 更新全局电源状态,与AMS/WMS交互,计算度/超时等参数 | | **底层控制** | 通过`/sys/power/state`节点控制LCD电源,调用驱动层`resume/suspend`函数 | > **注意**:不同Android版本或厂商定制可能修改流程细节,但核心框架保持一致。 §§相关问题§§ 1. Power键事件如何从内核传递到Android框架层? 2. PMS与WakeLock机制如何协同工作? 3. 自动度调节在流程中如何生效? 4. 时如何保证应用数据安全?</think>### Android Power Manager 流程分析 Android的电源管理核心是`PowerManagerService`(PMS),流程涉及**输入事件处理、状态计算、跨模块协作、硬件控制**四个关键阶段。以下是基于Android 7.0+的流程解析(兼容至Android 11): --- #### **1. 输入事件捕获** 当用户按下Power键: - **Input子系统**捕获按键事件,通过`InputReader`/`InputDispatcher`传递到上层。 - **`PhoneWindowManager`** 处理事件: ```java // PhoneWindowManager.java private void wakeUpFromWakeKey(KeyEvent event) { if (wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY")) { // 若满足条件(如长按HOME键),启动HOME界面 } } ``` 调用`PowerManager.wakeUp()`触发流程[^5]。 --- #### **2. PMS状态计算与决策** **`PowerManagerService`** 执行核心逻辑: - **状态机切换**:从`OFF`状态切换到`ON`或`DREAM`状态。 - **参数计算**: - 度(结合自动度调节) - 超时时间(根据用户设置、传感器数据) - 电源策略(如是否允许剧院模式唤醒) - **跨模块协作**: - 通知`ActivityManagerService`(AMS)准备应用界面绘制。 - 同步`WindowManagerService`(WMS)更新窗口状态[^3]。 --- #### **3. 底层硬件控制** PMS通过**HAL层**操作显示设备: 1. **禁用自动挂起**: ```c autosuspend_disable(); // 向/sys/power/state写入"on" ``` 2. **唤醒显示控制器**: - 调用`late_resume()`恢复LCD(如`sprdfb_dispc_resume`函数)。 - 硬件初始化时间因设备而异[^4]。 3. **设置度**: - 通过`/sys/class/backlight`节点写入度值。 > 💡 **流程相反**: > 1. PMS计算休眠策略(如`USER_ACTIVITY`超时)。 > 2. 通知AMS/WMS暂停界面。 > 3. 向`/sys/power/state`写入`mem`触发LCD休眠[^1][^2]。 --- #### **4. 关键参与模块** | **模块** | **职责** | |------------------------|---------------------------------------| | `PhoneWindowManager` | 输入事件路由 | | `PowerManagerService` | 电源策略决策、状态管理 | | `DisplayManagerService`| 显示设备控制(度/状态) | | `ActivityManagerService` | 协调应用生命周期 | | 内核驱动 | 操作`/sys/power`节点控制硬件电源状态 | --- ### 流程总结 ```mermaid graph TD A[Power键按下] --> B{Input子系统捕获} B --> C[PhoneWindowManager处理] C --> D[PMS唤醒请求] D --> E[状态计算+跨模块协作] E --> F[写入/sys/power/state] F --> G[内核控制LCD起] ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值