Android 8.1 DisplayPowerController(一) 亮灭屏流程

DisplayPowerController (DPC) 在Android系统中控制显示电源状态,处理亮灭屏及背光调节。本文详细分析了DPC的requestPowerState()、updatePowerState()等方法,涉及亮屏、灭屏、亮度调节的决策流程,包括亮灭屏动画和背光设置。DPC作为PMS与DMS之间的中介,确保Display准备就绪。文章通过PMS请求显示的逻辑,深入探讨了DPC中处理显示状态变化的核心方法,以及如何通过DisplayBlanker更新实际屏幕显示状态。
摘要由CSDN通过智能技术生成

概述

DisplayPowerController(以下简称DPC)用于控制显示电源状态,用来处理亮灭屏、背光的调节,包括接近传感器(P-Senser)、光线传感器(L-senser)和亮灭屏动画。它独立于PMS的其余部分,并且不共享任何状态,而是通过DisplayPowerCallbacks接口异步回调进行通信,通知PMS有关Display的改变。当PMS中请求屏幕状态时,会等待它返回一个结果,这个结果表示显示是否准备完成(mDisplayReady)。如果显示未准备就绪,则mDisplayReady为false。

可以将DPC看做是PMS和DMS的之间的一个“中介”,此外由于DPC的功能就是独立于PMS之外,PMS将Display交给它处理,因此在分析DPC时,以Display为切入点进行分析,因此在下面我们从亮屏、灭屏、亮度调节开始进行分析。

在PMS相关文档中已经分析过了PMS部分的亮屏、灭屏了,然而,仅仅是分析了PMS中相关的逻辑,并没有分析之后在DisplayPowerController中的逻辑,分析到updatePowerStateLocked()时就停止了。在PMS的updatePowerStateLocked()方法中,会调用updateDisplayPowerStateLocked()更新显示,而这个方法中更新显示时,是通过DPC完成,接下来我们将以之前的分析过的接口为入口点,开始分析DisplayPowerController中的逻辑。

1.requestPowerState()

这个方法是亮屏、亮度调节的入口方法,PMS中调用该方法从而进入DisplayPowerController并和DisplayManagerService交互。

该方法工作原理是这样的:当亮屏或者亮度调节时,最终都会走PMS中的updatePowerStateLocked()方法,在这个方法中,通过DMS的LocalService传入封装了Display信息的DisplayPowerState对象去请求DMS,之后进入DisplayPowerController中的requsetPowerState()方法中,在这个方法中,首先会判断这次请求的DisplayPowerState是否改变,如果改变,则表示这是一次新的请求,此时在Handler中异步去执行更新操作,同时,返回给PMS的返回值mDisplayReadyLock置为false,表示Display没有更新完成。当异步操作完成后,将mDisplayReadyLock置为true,同时回调DisplayPowerCallback.onStateChanged()方法,PMS重写了这个方法,在这个方法中又调用updatePowerState()方法,因此再此会请求一遍DMS,在这次请求中,由于DisplayPowerState,没有改变,因此直接返回mDisplayReadyLock了。

首先来看PMS中的请求显示的逻辑:

private boolean updateDisplayPowerStateLocked(int dirty) {
   
        mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                mRequestWaitForNegativeProximity);
        mRequestWaitForNegativeProximity = false;
        return mDisplayReady && !oldDisplayReady;
    }                

接下来开始详细分析这个方法,其代码如下:

/**
 * @param request PMS中传入的DisplayPowerState对象,封装了Display信息
 * @param waitForNegativeProximity 如果带有PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY标记,则该值为true,表示在由PSensor灭屏后,当释放PROXIMITY WakeLock时,不会立即亮屏,而是直到等待PSensor收到远离事件后才亮屏
 * @return 如果display改变完成则返回true
 */
public boolean requestPowerState(DisplayPowerRequest request,
        boolean waitForNegativeProximity) {
   
    synchronized (mLock) {
   
        boolean changed = false;
        if (waitForNegativeProximity
                && !mPendingWaitForNegativeProximityLocked) {
   
            mPendingWaitForNegativeProximityLocked = true;
            changed = true;
        }
        //开机后第一次进入
        if (mPendingRequestLocked == null) {
   
            mPendingRequestLocked = new DisplayPowerRequest(request);
            changed = true;
         //如果该次请求和上次请求不同,说明有状态改变,需要更新Display
        } else if (!mPendingRequestLocked.equals(request)) {
   
            mPendingRequestLocked.copyFrom(request);
            changed = true;
        }
        /**
         * changed为true,说明有改变发生,这个改变交给Handler异步去处理,此时说
         * 明显示没有准备好,mDisplayReadyLocked=false
         * 直到改变处理成功,mDisplayReadyLocked将被置为true,
         */
        if (changed) {
   
            mDisplayReadyLocked = false;
        }
        //mPendingRequestChangedLocked:用于标识电源请求状态或者PSensor标签是
        //否改变
        if (changed && !mPendingRequestChangedLocked) {
   
            mPendingRequestChangedLocked = true;
            sendUpdatePowerStateLocked();
        }
        return mDisplayReadyLocked;
    }
}

Changed表示是否需要改变Display。这个方法中就好比一扇门,只有符合条件才能进入到下一个阶段。条件是什么呢?

  • 1.先会对第二个形参进行判断,waitForNegativeProximity如果为true,则表示在释放PSensor相关的WakeLock时,如果PSensor还是靠近事件,则必须等待PSensor远离后才会亮屏,这个值释放wakelock时传入的flag有关,如果在释放wakelock时使用release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY)的形式释放PSensor的WakeLock,则该值为true,大多数场景下为false;
  • 2.如果开机第一次进入该函数,则实例化代表将要请求的DisplayPowerRequest对象。
  • 3.如果本次请求和上次请求不相同,则说明需要更新Display。mPendingRequestChangedLocked用于标识电源请求状态是否要改变,如果changed变为true,则该值会由false变为true,之后又会置为false。

如果满足以上条件,则changed变为true,表示Display需要改变,因此,调用sendUpdatePowerStateLocked()方法获取Handler,并使用Handler进行Display的更新,同时返回值为false,表示Display还没有更新准备完成。

再来看看第二个参数waitForNegativeProximity,这个值来自于PMS中:

private void releaseWakeLockInternal(IBinder lock, int flags) {
   
        if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) {
   
            mRequestWaitForNegativeProximity = true;
        }
    }

因此,在释放WakeLock锁时,如果带有PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY标记,该值就是true,并且在每一次请求完Display之后又会重新置为false,在updateDisplayPowerStateLocked()方法中可以看到。通话过程中,如果由PSensor灭屏并一直保持,然后按Power键,此时系统将执行goToSleep流程,当再次按power键,此时系统将执行Wakeup流程,但是,如果waitForNegativeProximity为true,则系统不会亮屏,直到PSensor接收到远离数据而亮屏。具体的逻辑在updatePowerState()方法中,下面会提到。

再继续分析其异步做了哪些处理,我们接着上一步骤的分析,看看sendUpdatePowerStateLocked()方法:

private void sendUpdatePowerStateLocked() {
   
    if (!mPendingUpdatePowerStateLocked) {
   
        //要打算更新电源状态了
        mPendingUpdatePowerStateLocked = true;
        //异步更新
        Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
        msg.setAsynchronous(true);
        mHandler.sendMessage(msg);
    }
}

这个方法中获取了Handler,并通过异步的方式调用了updatePowerState()方法执行下步处理:

case MSG_UPDATE_POWER_STATE:
    updatePowerState();
    break;

2.updatePowerState()

updatePowerState()方法是一个非常庞大的方法,也是DisplayPowerController中的核心方法,其中处理亮灭屏、调节亮度,都会在这里进行决策处理。该方法的完整代码如下:

private void updatePowerState() {
   
    // Update the power state request.
    //当DisplayPowerController中更新屏幕状态成功后是否必须通知PMS
    final boolean mustNotify;
    //是否要进行初始化
    boolean mustInitialize = false;
    //是否自动调节亮度调节值改变
    boolean autoBrightnessAdjustmentChanged = false;
    synchronized (mLock) {
   
        //该值表示"是否将要更新电源状态",重置该值为false,从而可以被下一次
        //sendUpdatePowerStateLocked()处理该方法
        mPendingUpdatePowerStateLocked = false;
        //表示"将要请求的DisplayPowerRequest对象",当PMS中发起请求后,
        //在requestDisplayPowerState()中会将请求携带的DPS对象赋给该值,
        //或者在系统启动时,通过请求携带的DPS对象实例化该值
        if (mPendingRequestLocked == null) {
   
            return; // wait until first actual power request
        }
        //mPowerRequest表示"当前的电源请求状态",初始值为null,
        //由mPengdingReqestLocked对象拷贝或实例化
        //因此只有系统开机后第一次会进入if中,之后不会进入
        if (mPowerRequest == null) {
   
            mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
            mWaitingForNegativeProximity = 
                  mPendingWaitForNegativeProximityLocked;
            mPendingWaitForNegativeProximityLocked = false;
            mPendingRequestChangedLocked = false;
            mustInitialize = true;
            //标记值,如果请求状态和当前状态不同,则true
        } else if (mPendingRequestChangedLocked) {
   
            //自动调节亮度值是否改变,由"当前电源的请求状态"和"将要请求的电源请求状态"比较
            autoBrightnessAdjustmentChanged = 
                    (mPowerRequest.screenAutoBrightnessAdjustment
                    != mPendingRequestLocked.screenAutoBrightnessAdjustment);
            //复制mPendingRequestLocked给mPowerRequset,
            //即将"将要请求的电源请求状态"赋给"当前电源的请求状态"
            mPowerRequest.copyFrom(mPendingRequestLocked);
            //mWaitingForNegativeProximity表示在亮屏之前是否要等待PSensor接收到远事件值
            //该值由PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY标记在释放锁时决定
            mWaitingForNegativeProximity |= 
                   mPendingWaitForNegativeProximityLocked;
            mPendingWaitForNegativeProximityLocked = false;
            //重置该值为false
            mPendingRequestChangedLocked = false;
            //表示未准备就绪
            mDisplayReadyLocked = false;
        }
        //是否进行通知
        mustNotify = !mDisplayReadyLocked;
    }
    // Initialize things the first time the power state is changed.
    if (mustInitialize) {
   
        //初始化亮灭屏动画、mPowerState等
        initialize();
    }
    int state;
    int brightness = PowerManager.BRIGHTNESS_DEFAULT;
    boolean performScreenOffTransition = false;
    //根据PMS中的请求参数决定屏幕状态和屏幕亮度值
    switch (mPowerRequest.policy) {
   
        //灭屏
        case DisplayPowerRequest.POLICY_OFF:
            state = Display.STATE_OFF;
            performScreenOffTransition = true;
            break;
            //Doze模式
        case DisplayPowerRequest.POLICY_DOZE:
            if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {
   
                state = mPowerRequest.dozeScreenState;
            } else {
   
                state = Display.STATE_DOZE;
            }
            //是否允许在自动调节亮度下配置doze亮度值
            if (!mAllowAutoBrightnessWhileDozingConfig) {
   
                brightness = mPowerRequest.dozeScreenBrightness;
            }
            break;
        //VR模式
        case DisplayPowerRequest.POLICY_VR:
            state = Display.STATE_VR;
            break;
        //DIM和亮屏
        case DisplayPowerRequest.POLICY_DIM:
        case DisplayPowerRequest.POLICY_BRIGHT:
        default:
            state = Display.STATE_ON;
            break;
    }
    assert(state != Display.STATE_UNKNOWN);

    // Apply the proximity sensor.
    //PSensor相关
    /*-------------PSensor设置 beg--------------*/
    if (mProximitySensor != null) {
   
        //如果mPowerRequest.useProximitySensor=true&&Display状态不等于灭屏
        if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
   
            //设置Psensor可用
            setProximitySensorEnabled(true);
            if (!mScreenOffBecauseOfProximity
                    && mProximity == PROXIMITY_POSITIVE) {
   
            //该值表示由PSensor灭屏
                mScreenOffBecauseOfProximity = true;
            //通过DisplayPowerCallback回调PMS
                sendOnProximityPositiveWithWakelock();
            }
        } else if (mWaitingForNegativeProximity //如果该值为true
                && mScreenOffBecauseOfProximity //且由PSensor灭屏
                && mProximity == PROXIMITY_POSITIVE //且当前PSensor靠近
                && state != Display.STATE_OFF) {
   //且Display状态不为灭屏状态
            setProximitySensorEnabled(true);
        } else {
   
            //不满足以上条件,设置PSensor不可用
            setProximitySensorEnabled(false);
            mWaitingForNegativeProximity = false;
        }
        //如果满足说明此时PSensor处理远离事件,重置mScreenOffBecauseOfProximity为false
        if (mScreenOffBecauseOfProximity
                && mProximity != PROXIMITY_POSITIVE) {
   
            mScreenOffBecauseOfProximity = false;
            sendOnProximityNegativeWithWakelock();
        }
    } else {
   
        mWaitingForNegativeProximity = false;
    }
    //由PSensor灭屏为true,则将state置位DISPLAY.STATE_OFF
    if (mScreenOffBecauseOfProximity) {
   
        state = Display.STATE_OFF;
    }
    /*-------------PSensor设置 end--------------*/
    //获取屏幕状态,此时还未设置新的屏幕状态,因此是”旧”的
    final int oldState = mPowerState.getScreenState();
    //在这个方法中会进行屏幕状态、亮度的设置和处理亮灭屏动画
    animateScreenStateChange(state, performScreenOffTransition);
    //获取屏幕状态,此时已经设置新的屏幕状态
    state = mPowerState.getScreenState();

    // Use zero brightness when screen is off.
    //如果屏幕状态为灭屏,设置亮度为0
    if (state == Display.STATE_OFF) {
   
        brightness = PowerManager.BRIGHTNESS_OFF;
    }
    // Configure auto-brightness.
    //自动调节亮度是否可用
    boolean autoBrightnessEnabled = false;
    if (mAutomaticBrightnessController != null) {
   
        //Doze模式下自动调节亮度是否可用
        final boolean autoBrightnessEnabledInDoze = 
             mAllowAutoBrightnessWhileDozingConfig
                 && (state == Display.STATE_DOZE || state == 
            Display.STATE_DOZE_SUSPEND);
        autoBrightnessEnabled = mPowerRequest.useAutoBrightness
                && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
                && brightness < 0;
        final boolean userInitiatedChange = autoBrightnessAdjustmentChanged
                && mPowerRequest.brightnessSetByUser;
        //配置AutomaticBrightnessController
        mAutomaticBrightnessController.configure(autoBrightnessEnabled,
                mPowerRequest.screenAutoBrightnessAdjustment, state != 
                Display.STATE_ON, userInitiatedChange);
    }
    /*----------------------亮度调节值计算 BEG-------------------------------------*/
    //brightnessboost相关
    if (mPowerRequest.boostScreenBrightness
            && brightness != PowerManager.BRIGHTNESS_OFF) {
   
        brightness = PowerManager.BRIGHTNESS_ON;
    }
    // Apply auto-brightness.
    boolean slowChange = false;
    //如果brightness=PowerManager.BRIGHTNESS_DEFAULT=-1,说明请求屏幕状态非Off
    if (brightness < 0) {
   //default = -1
        //如果自动调节亮度可用
        if (autoBrightnessEnabled) {
   
            //从AutomaticBrightnessController中获取自动调节亮度值
            brightness = 
                 mAutomaticBrightnessController.getAutomaticScreenBrightness();
        }
        if (brightness >= 0) {
   //说明使用了自动亮度
            // Use current auto-brightness value and slowly adjust to changes.
            //调整brightness保持在最小值和最大值之间
            //即mScreenBrightnessRangeMinimum <= brightness <= mScreenBrightnessRangeMaximum
            brightness = clampScreenBrightness(brightness);
            if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {
   
                slowChange = true; // slowly adapt to auto-brightness
            }
            mAppliedAutoBrightness = true;//表示使用自动亮度

        } else {
   
            mAppliedAutoBrightness = false;
        }
    } else {
   
        mAppliedAutoBrightness = false;
    }
    //如果PMS中请求的屏幕状态为Doze,则将亮度设置为Doze状态的亮度
    if (brightness < 0 && (state == Display.STATE_DOZE
            || state == Display.STATE_DOZE_SUSPEND)) {
   
        brightness = mScreenBrightnessDozeConfig;
    }
    //如果此时brightness还为-1,说明没有使用自动调节亮度和doze状态亮度,则使用手动设置亮度
    if (brightness < 0) {
   
        //获取screenBrightness并在取值区间进行判断
        brightness = clampScreenBrightness(mPowerRequest.screenBrightness);
    }
    // Apply dimming by at least some minimum amount when user activity
    // timeout is about to expire.
    //如果PMS中请求屏幕状态为Dim状态,则使用dim状态时的亮度,基于手动调节值
    if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
   
        if (brightness > mScreenBrightnessRangeMinimum) {
   
            brightness = Math.max(Math.min(brightness - 
            SCREEN_DIM_MINIMUM_REDUCTION,
                    mScreenBrightnessDimConfig), 
            mScreenBrightnessRangeMinimum);
        }
        if 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值