Android 8.1 DisplayPowerController(一) 亮灭屏流程

作者:FightFightFight 
来源:CSDN 
原文:https://blog.csdn.net/FightFightFight/article/details/81320519 

概述
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 (!mAppliedDimming) {
            slowChange = false;
        }
        mAppliedDimming = true;//表示采用Dim状态brightness
    } else if (mAppliedDimming) {
        slowChange = false;
        mAppliedDimming = false;
    }
    // If low power mode is enabled, scale brightness by       
    // screenLowPowerBrightnessFactor
    // as long as it is above the minimum threshold.
    //如果开启了低电量模式,则亮度值为brightness*brightnessFactor
    if (mPowerRequest.lowPowerMode) {
        if (brightness > mScreenBrightnessRangeMinimum) {
            final float brightnessFactor =
                    Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
            final int lowPowerBrightness = (int) (brightness * brightnessFactor);
            brightness = Math.max(lowPowerBrightness, 
                        mScreenBrightnessRangeMinimum);
        }
        if (!mAppliedLowPower) {
            slowChange = false;
        }
        mAppliedLowPower = true;//表示采用低电量brightness
    } else if (mAppliedLowPower) {
        slowChange = false;
        mAppliedLowPower = false;
    }
    // Animate the screen brightness when the screen is on or dozing.
    // Skip the animation when the screen is off or suspended or transition to/from VR.
    /*----------------------亮度调节值计算 END-------------------------------------*/
    /*----------------------亮度动画 BEG-------------------------------------*/
    //亮度值计算完毕,下面根据请求屏幕状态决定是否在调节亮度时使用动画
    //当不打算灭屏时,即屏幕状态已经为灭屏或处于其他状态
    if (!mPendingScreenOff) {
        //是否在亮屏时跳过亮度坡度调节,默认false
        if (mSkipScreenOnBrightnessRamp) {
            //如果屏幕状态为亮屏状态
            if (state == Display.STATE_ON) {
                if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
                    mInitialAutoBrightness = brightness;
                    mSkipRampState = RAMP_STATE_SKIP_INITIAL;
                } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
                        && mUseSoftwareAutoBrightnessConfig
                        && brightness != mInitialAutoBrightness) {
                    mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
                } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
                    mSkipRampState = RAMP_STATE_SKIP_NONE;
                }
            } else {
                mSkipRampState = RAMP_STATE_SKIP_NONE;
            }
        }
        //是否处于或将要进入VR状态
        boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
        //如果当前屏幕状态或请求屏幕状态为亮屏
        if ((state == Display.STATE_ON
                && mSkipRampState == RAMP_STATE_SKIP_NONE
                || state == Display.STATE_DOZE 
                && !mBrightnessBucketsInDozeConfig)
                && !wasOrWillBeInVr) {
            //设置亮度,slowChange=true应用于自动调节亮度
            animateScreenBrightness(brightness,
                    slowChange ? mBrightnessRampRateSlow : 
            mBrightnessRampRateFast);
        } else {
            //其他情况下不适用亮度动画,直接设置亮度
            animateScreenBrightness(brightness, 0);
        }
    }
    /*----------------------亮度动画 END-------------------------------------*/
    //ready表示屏幕状态是否准备完成,mPendingScreenOnUnblocker用于亮屏过程中,
    //该值非空表示屏幕目前被阻塞,等待WindowManager回调,回调后将被置为null
    //mColorFadeOnAnimator,mColorFadeOffAnimator表示亮屏和灭屏动画
    final boolean ready = mPendingScreenOnUnblocker == null &&
            (!mColorFadeEnabled ||
                    (!mColorFadeOnAnimator.isStarted() 
            && !mColorFadeOffAnimator.isStarted()))
            && mPowerState.waitUntilClean(mCleanListener);
    //表示屏幕状态准备完成,同时亮度设置也完成
    final boolean finished = ready
            && !mScreenBrightnessRampAnimator.isAnimating();
    // Notify policy about screen turned on.
    if (ready && state != Display.STATE_OFF
            && mReportedScreenStateToPolicy == 
               REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
        //设置屏幕状态报告值,该值表示亮屏完成
        setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
        //通知WindowManager亮屏完成
        mWindowManagerPolicy.screenTurnedOn();
    }
    // Grab a wake lock if we have unfinished business.
    //finish为false,表示屏幕状态或者屏幕背光没有设置完成,需要申请一个Display锁
    if (!finished && !mUnfinishedBusiness) {
        mCallbacks.acquireSuspendBlocker();//申请Display锁
        mUnfinishedBusiness = true;
    }
    // Notify the power manager when ready.
    //当屏幕准备就绪,通知PMS
    if (ready && mustNotify) {
        // Send state change.
        synchronized (mLock) {
            if (!mPendingRequestChangedLocked) {
                //表示屏幕状态准备就绪,就绪和亮度设置完成无关,只和屏幕状态有关
                mDisplayReadyLocked = true;
            }
        }
        //在该方法中回调PMS方法
        sendOnStateChangedWithWakelock();
    }
    // Release the wake lock when we have no unfinished business.
    //完成后释放Display锁
    if (finished && mUnfinishedBusiness) {
        mUnfinishedBusiness = false;
        mCallbacks.releaseSuspendBlocker();
    }
    //mDozing记录状态值
    mDozing = state != Display.STATE_ON;
}
从方法源码来看,这个方法可以拆分为六部分:

第一部分:初始化相关变量;
第二部分:根据PMS请求时携带的DisplayPowerState.policy以及PSensor相关确定要请求的屏幕状态state的值;
第三部分:调用animateScreenState()方法设置屏幕状态(灭屏时还会先设置brightness=0);
第四部分:计算亮度值,即调节亮度时的值;
从代码看,在计算亮度值时,影响亮度值的有:自动调节亮度的亮度值、Doze状态下的亮度值(配置文件中读取)、用户手动设置的亮度值、Dim状态下的亮度值、低电量模式下的亮度值,最终会根据当前的场景来选择亮度值。
第五部分:通过animateScreenBrightness()设置亮度值调节动画;
第六部分:当完成屏幕状态更新和亮度更新后、分别通知WindowManager、PMS进行相应操作。
3.animateScreenStateChange()
这个方法在updatePowerState()中调用,用来设置屏幕状态、屏幕亮度(仅仅设置灭屏亮度0)、执行灭屏动画,同时调用WindowManager中的接口进行window的绘制等。先来看看这个方法:

private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
    //如果mColorFadeEnabled可用且有动画在执行还未结束,说明正在屏幕转换流程中
    if (mColorFadeEnabled &&
            (mColorFadeOnAnimator.isStarted() || mColorFadeOffAnimator.isStarted())) {
        if (target != Display.STATE_ON) {
            //如果目标状态不是亮屏状态,直接返回
            return;
        }
        //将该变量值置为false,该变量用来表示是否打算灭屏
        mPendingScreenOff = false;
    }
    //该值为false,表示在退出doze状态时是否跳过灭屏动画
    if (mDisplayBlanksAfterDozeConfig
            && Display.isDozeState(mPowerState.getScreenState())//当前显示状态为doze状态
            && !Display.isDozeState(target)) {//目标状态非doze
        mPowerState.prepareColorFade(mContext,
                mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
        if (mColorFadeOffAnimator != null) {
            mColorFadeOffAnimator.end();
        }
        setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/);
    }
    //设置显示状态为灭屏状态,mPendingScreenOff表示打算灭屏,在进行灭屏时会设置为true
    if (mPendingScreenOff && target != Display.STATE_OFF) {
        setScreenState(Display.STATE_OFF);
        mPendingScreenOff = false;
        mPowerState.dismissColorFadeResources();
    }
    //目标状态为亮屏,则调用setScreenState()设置,并根据返回值确定是否继续下面的操作
    if (target == Display.STATE_ON) {
        if (!setScreenState(Display.STATE_ON)) {
            return; // screen on blocked
        }
        //亮屏动画
        if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
            // Perform screen on animation.
            if (mPowerState.getColorFadeLevel() == 1.0f) {
                mPowerState.dismissColorFade();
            } else if (mPowerState.prepareColorFade(mContext,
                    mColorFadeFadesConfig ?
                            ColorFade.MODE_FADE :
                            ColorFade.MODE_WARM_UP)) {
                mColorFadeOnAnimator.start();
            } else {
                mColorFadeOnAnimator.end();
            }
        } else {
            // Skip screen on animation.
            mPowerState.setColorFadeLevel(1.0f);
            mPowerState.dismissColorFade();
        }
    } else if (target == Display.STATE_VR) {
        // Wait for brightness animation to complete beforehand when entering VR
        // from screen on to prevent a perceptible jump because brightness may operate
        // differently when the display is configured for dozing.
        if (mScreenBrightnessRampAnimator.isAnimating()
                && mPowerState.getScreenState() == Display.STATE_ON) {
            return;
        }
        // Set screen state.
        if (!setScreenState(Display.STATE_VR)) {
            return; // screen on blocked
        }
        // Dismiss the black surface without fanfare.
        mPowerState.setColorFadeLevel(1.0f);
        mPowerState.dismissColorFade();
    } else if (target == Display.STATE_DOZE) {
        // Want screen dozing.
        // Wait for brightness animation to complete beforehand when entering doze
        // from screen on to prevent a perceptible jump because brightness may operate
        // differently when the display is configured for dozing.
        if (mScreenBrightnessRampAnimator.isAnimating()
                && mPowerState.getScreenState() == Display.STATE_ON) {
            return;
        }

        // Set screen state.
        if (!setScreenState(Display.STATE_DOZE)) {
            return; // screen on blocked
        }

        // Dismiss the black surface without fanfare.
        mPowerState.setColorFadeLevel(1.0f);
        mPowerState.dismissColorFade();
    } else if (target == Display.STATE_DOZE_SUSPEND) {
        if (mScreenBrightnessRampAnimator.isAnimating()
                && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
            return;
        }
        if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
            if (!setScreenState(Display.STATE_DOZE)) {
                return; // screen on blocked
            }
            setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
        }

        // Dismiss the black surface without fanfare.
        mPowerState.setColorFadeLevel(1.0f);
        mPowerState.dismissColorFade();
    } else {//除以上情况外,目标状态就为灭屏状态
        // Want screen off.将mPendingScreenOff置为ture
        mPendingScreenOff = true;
        if (!mColorFadeEnabled) {
            //colorfadelevel和图像显示有关,正常显示时为1,灭屏后就为0了
            mPowerState.setColorFadeLevel(0.0f);
        }
        //如果进入该语句,说明此时灭屏完成
        if (mPowerState.getColorFadeLevel() == 0.0f) {
            // Turn the screen off.
            // A black surface is already hiding the contents of the screen.
            setScreenState(Display.STATE_OFF);
            mPendingScreenOff = false;
            mPowerState.dismissColorFadeResources();
        } else if (performScreenOffTransition  //是否执行灭屏动画
                && mPowerState.prepareColorFade(mContext,
                mColorFadeFadesConfig ?
                        ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN) //colorfade是否准备就绪
                && mPowerState.getScreenState() != Display.STATE_OFF) {
            // Perform the screen off animation.
            mColorFadeOffAnimator.start();  //开始执行灭屏动画
        } else {
            // Skip the screen off animation and add a black surface to hide the
            // contents of the screen.
            mColorFadeOffAnimator.end();//不执行灭屏动画,
        }
    }
}
在这个方法中,一些内容就不再进行分析了,在代码中都有对应的注释,这里我们只分析重点代码。首先,在进入该方法后,变量mPendingScreenOff设置为false,该值意思就是"是否打算将要灭屏?";其次,会根据参数target来进行决策,并调用setScreenState()进行设置对应的屏幕状态,最后,会根据是否需要动画效果而显示动画效果。

现在以灭屏为例,当灭屏时,由updatePowerState()中调用该方法,我们已经分析过了,target为Display.STATE_OFF,进入该方法后,此时只满足最后一个else语句:

} else {
        // Want screen off.
        mPendingScreenOff = true;//设置为true
        //如果colorFadeEnable=false,则直接将ColorFade设置为0.0
        if (!mColorFadeEnabled) {
            mPowerState.setColorFadeLevel(0.0f);
        }
        if (mPowerState.getColorFadeLevel() == 0.0f) {
            // Turn the screen off.
            // A black surface is already hiding the contents of the screen.
            //设置屏幕状态为Display.STATE_OFF
            setScreenState(Display.STATE_OFF);
            mPendingScreenOff = false;
            mPowerState.dismissColorFadeResources();
        } else if (performScreenOffTransition //是否只执行灭屏动画
                && mPowerState.prepareColorFade(mContext,
                mColorFadeFadesConfig ?
                        ColorFade.MODE_FADE : ColorFade.MODE_COOL_DOWN)
                && mPowerState.getScreenState() != Display.STATE_OFF) {
            // Perform the screen off animation.
            mColorFadeOffAnimator.start();//开始执行灭屏动画
        } else {
            // Skip the screen off animation and add a black surface to hide the
            // contents of the screen.
            mColorFadeOffAnimator.end(); //停止灭屏动画
        }
    }
}
在这个else中,首先设置mPendingScreenOff为true,表示打算灭屏了,其次如果mColorFadeEnable为false,表示颜色渲染不可以用,则直接将ColorFadeLevel设置为0。接下来,分三种情况进行分析:

1.如果ColorFadeLevel为0了,就可以设置屏幕状态了,因此直接setScreenState(Display.STATE_OFF),这种情况下,只需执行一遍animateScreenStateChanged()方法,就将屏幕状态值设置;
2.如果可以执行灭屏动画且ColorFade已经准备就绪,则开始执行灭屏动画,在灭屏动画结束后,又将异步回调一次该方法,在这次调用时,由于灭屏动画的执行将ColorFadeLevel设置为0,因此执行条件一,从而完成设置屏幕状态;
mColorFadeOffAnimator = ObjectAnimator.ofFloat(
        mPowerState, DisplayPowerState.COLOR_FADE_LEVEL, 1.0f, 0.0f);
mColorFadeOffAnimator.setDuration(COLOR_FADE_OFF_ANIMATION_DURATION_MILLIS);
mColorFadeOffAnimator.addListener(mAnimatorListener);

private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
    @Override
    public void onAnimationEnd(Animator animation) {
        sendUpdatePowerState();
    }
};
3.如果不满足这两个条件,则调用mColorFadeOffAnimate.end()结束灭屏动画(无论是否执行动画),该方法会将动画结束值设置给相关的属性,也就是设置ColorFadeLevel为0,同时触发动画监听事件,如条件二所述,又会异步回调到animateScreenStateChange()方法。
综上所述,在power键灭屏时,在一般情况下和有灭屏动画时,会在第二次执行该方法时设置屏幕状态,如果执行mColorFadeEnable为false,则第一次执行时就会设置。

分析完灭屏后,再以亮屏为例进行下分析,当亮屏时,在该方法中执行如下这段代码:

if (target == Display.STATE_ON) {
    //直接设置屏幕状态为Display.State_ON,如果返回false,则说明此时处于阻塞状态,Window中还没有回调,所以直接return
    if (!setScreenState(Display.STATE_ON)) {
        return; // screen on blocked
    }
    if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && 
         mPowerRequest.isBrightOrDim()) {
        // Perform screen on animation.
        if (mPowerState.getColorFadeLevel() == 1.0f) {
            mPowerState.dismissColorFade();
        } else if (mPowerState.prepareColorFade(mContext,
                mColorFadeFadesConfig ?
                        ColorFade.MODE_FADE :
                        ColorFade.MODE_WARM_UP)) {
            mColorFadeOnAnimator.start();//开始执行亮屏动画
        } else {
            mColorFadeOnAnimator.end();//结束亮屏动画
        }
    } else {
        //跳过动画,直接将ColorFadeLevel设置为1.0f
        mPowerState.setColorFadeLevel(1.0f);
        mPowerState.dismissColorFade();
    }


在亮屏时,首先会通过setScreenState()设置好屏幕状态,设置完成之后,才会开始执行亮屏动画。至于亮屏设置背光值,则在后面的animateScreenBrightness()结束后。

3.1.1.亮屏动画和灭屏动画
现在分析完了animateScreenStateChange()方法,接下来在分析setScreenState()方法之前,我们先来看看关于设置亮屏、灭屏动画相关的逻辑,这里以灭屏时动画为例,在上面我们分析到了,如果有灭屏动画,则会先执行灭屏动画:

mColorFadeOffAnimator.start();
如果没有灭屏动画,则直接调用如下代码将ColorFadeLevel值设置为0:

mColorFadeOffAnimator.end();
无论是执行灭屏动画还是不执行灭屏动画,最终,ColorFadeLevel的值都会变为0,而当变为0时,动画结束,回调onAnimationEnd()方法,这在前面也分析过了,这里再次说明下:

@Override
public void onAnimationEnd(Animator animation) {
    sendUpdatePowerState();
在onAnimationEnd()中,又会通过sendUpdatePowerState()再次调用updatePowerState().再进入animateScreenStateChange()后,将会更新屏幕状态。

除了回调onAnimationEnd()外,还会在DisplayPowerState.setColorFade()中调用:

public void setColorFadeLevel(float level) {
    if (mColorFadeLevel != level) {
        mColorFadeLevel = level;
        //满足该条件,更新背光,这个逻辑说明如果是灭屏,则先在这里将背光设置为0
        if (mScreenState != Display.STATE_OFF) {
            mScreenReady = false;
            scheduleScreenUpdate(); // update backlight brightness
        }
        if (mColorFadePrepared) {
            mColorFadeReady = false;
            scheduleColorFadeDraw();
        }
    }
}
在setColorFadeLevel()方法中,由于此时还没有设置屏幕状态值,所以State !=Display.STATE_OFF,因此进入该方法,通过scheduleScreenUpdate()方法更新背光值。

因此,对于灭屏,先设置其背光值为0,然后设置其屏幕状态为Display.STATE_OFF.

亮屏动画和灭屏动画类似,当结束后,也会回调onAnimationEnd()方法,再一次进入updatePowerState(),这里就不详细分析了。

4.setScreenState()
分析完了animateScreenStateChange()方法后,紧接着开始分析设置屏幕状态的方法——setScreenState().在这个方法中,会调用进入DisplayPoweState中,以及调用Window中的接口,来通知Window进行屏幕状态设置的一些工作,当WindowManager中处理完成后,又会回调DisplayPowerController中的方法。这个方法也是非常的庞大,重要逻辑已经添加注释,方法源码如下:


private boolean setScreenState(int state, boolean reportOnly) {
//是否要进行灭屏
    final boolean isOff = (state == Display.STATE_OFF);
    if (mPowerState.getScreenState() != state) {//如果当前屏幕状态和将要设置的状态不同,则进入
        // If we are trying to turn screen off, give policy a chance to do something before we
        // actually turn the screen off.
        //灭屏且非PSensor灭屏
        if (isOff && !mScreenOffBecauseOfProximity) {
            //mReportedScreenStateToPolicy是一个报告屏幕状态的值,记录屏幕状态改变过程
            //的状态值,在亮屏完成后,该值为REPORTED_TO_POLICY_SCREEN_ON
            //在灭屏完成后,该值为REPORTED_TO_POLICY_SCREEN_OFF
            if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
                //将方法参数设置为mReportedScreenStateToPolicy值
                setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
                //Window管理策略,在没有灭屏完成时,暂时阻塞屏幕灭屏
                blockScreenOff();
                //通知WindowManager开始灭屏
                mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
                //取消灭屏阻塞
                unblockScreenOff();
            } else if (mPendingScreenOffUnblocker != null) {
                // Abort doing the state change until screen off is unblocked.
                return false;
            }
        }
        if (!reportOnly) {
            //将目标状态设置为屏幕状态,同时进入DisplayPowerState中的逻辑
            mPowerState.setScreenState(state);
            // Tell battery stats about the transition.
            try {
                mBatteryStats.noteScreenState(state);
            } catch (RemoteException ex) {
                // same process
            }
        }
    }
    // Tell the window manager policy when the screen is turned off or on unless it's due
    // to the proximity sensor.  We temporarily block turning the screen on until the
    // window manager is ready by leaving a black surface covering the screen.
    // This surface is essentially the final state of the color fade animation and
    // it is only removed once the window manager tells us that the activity has
    // finished drawing underneath.
    //如果是灭屏且非PSensor灭屏,且屏幕状态报告值为REPORTED_TO_POLICY_SCREEN_OFF,
    //进入该if当中
    //在按power键灭屏,都会进入该if语句中,当PSensor灭屏后,再按power键,也会进入这个语句
    //中,执行灭屏
    if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
            && !mScreenOffBecauseOfProximity) {
        //设置报告屏幕状态的值
        setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
        unblockScreenOn();
        //表示Window屏幕完成
        mWindowManagerPolicy.screenTurnedOff();
    //这种情况说明已经灭屏但是用户改变了(又打算亮屏),这时也应该走完灭屏的流程
    } else if (!isOff
            && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
        // We told policy already that screen was turning off, but now we changed our minds.
        // Complete the full state transition on -> turningOff -> off.
        unblockScreenOff();
        mWindowManagerPolicy.screenTurnedOff();
        setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
    }
    //如果不是灭屏&&屏幕报告值为灭屏(上次是灭屏),则这次为亮屏
    if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
        setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
        if (mPowerState.getColorFadeLevel() == 0.0f) {
            //如果colorFadeLevel为0,说明还没有执行亮屏动画,又由于亮屏动画值设置亮屏状态成
            //功后才开始,所以说明这时mPowerState.setScreenState()设置屏幕状态没有完成,需要暂
            //时进行阻塞
            blockScreenOn();
        } else {//亮屏动画已经完成,所以state=Display.STATE_ON也已设置完成,解除阻塞
            unblockScreenOn();
        }
        //调用WindowManager进行亮屏操作
        mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
        // Return true if the screen isn't blocked.
        //根据返回值来决定是否阻塞
    return mPendingScreenOnUnblocker == null;
}

在这个方法中,mReportedScreenStateToPolicy是一个用来表示报告屏幕状态的全局变量,在灭屏或者亮屏时,每当进行到某一步,会将该值设置成对应的值,如果灭屏完成,则设置为0,亮屏完成设置为2.共有四个值:

private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;//灭屏完成
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;//正在进行亮屏
private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;//亮屏完成
private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;//正在进行灭屏

在这个方法中,首先会判断是否要设置的是灭屏状态且非PSensor灭屏,如果满足条件则会进入if语句中,首先调用 WindManagerPolicy.screenTurningOff()方法,表示让WindowManager中开始灭屏,同时该方法传入的参数是一个WindowManagerPolicy.ScreenOffListener的一个实例,当WindowManagerPolicy中处理完毕后,会通过该接口实例回调到DisplayPowerController中。

接下来,会将state值设置给DisplayPowerState中,关于DisplayPowerState.setState()中的逻辑我们稍后再进行分析,因此不管是何种屏幕状态,都会将状态值设到DisplayPowerState中,对于非PSensor灭屏来说,仅仅是多了一步通知Window开始灭屏的步骤(也就是说,对于PSensor亮灭屏,不会有Window中的处理)。

当屏幕状态值设置后,进入第二个if语句中。对于正常的灭屏流程,肯定会执行进入第二个if中,在这个if中,调用WindowManagerPolicy.screenTurnedOff()方法,给WindowManager通知在DisplayPowerController中的灭屏流程已经结束了,让WindowManager进行收尾工作。所以对于灭屏流程肯定会先后执行WindowManager的screenTurningOff()和screenTurnedOff().

还有一种情况就是,通过PSensor灭屏后,再次点击power键,也会执行第二个if语句流程(因为是GotoSleep嘛)。
接下来,如果isOff为false,说明不是灭屏的流程,此时如果报告屏幕状态的值为灭屏,则会进入最后一个else中,执行亮屏流程,调用WindowManager的screenTurningOn()方法。当然,最终还会在updatePowerState()的结尾处执行一个screenTurnedOn()方法,说明亮屏流程完全完成了。

当以上执行完毕后,根据mPendingScreenOnUnblocker对象是否为空返回true或false,除了屏幕状态设置灭屏外,该方法返回值用于标记屏幕状态是否设置成功,如果返回为false,则将会暂时中断屏幕状态设置时setScreenState()之后的流程。这里举个例子,如在animateScreenStateChange()方法中亮屏时:

if (!setScreenState(Display.STATE_ON)) {
    return; // screen on blocked
}

4.1.block()方法和unblock()方法
现在来看看mPendingScreenOnUnblocker对象的控制方法,我们看到在setScreenState()中调用了多次block和unblock的方法,因此接下来我们要开始分析下blockScreen()和unBlockScreenOn()了。
在DisplayPowerController中共有两对block/unblock方法:

blockScreenOn():暂时阻塞DisplayPowerController中进行亮屏的流程;
unBlockScreenOn():取消亮屏阻塞;
blockScreenOff():暂时阻塞DisplayPowerController中的灭屏流程;
unBlockScreeOff():取消灭屏阻塞。
由于在亮屏时,WindowManager中需要进行亮屏相关操作,如果在Window没有处理完成就先亮屏,用户体验不好,因此,在没有会通过blockScreenOn()来阻塞亮屏过程,那么是如何阻塞的呢?我们先看看该方法:

private void blockScreenOn() {
    if (mPendingScreenOnUnblocker == null) {
        Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
        mPendingScreenOnUnblocker = new ScreenOnUnblocker();
        mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
    }
}
在该方法中,实例化了一个ScreenOnUnblocker类实例,在上面也说过,该类是WindowManagerPolicy.ScreenOnListener的一个子类;然后获取了当前系统时间。

在这里获取的这个mPendingScreenOnUnblocker对象,是不是很眼熟?没错,他就是设置setScreenState()方法返回值时用到的。现在回过头来再看看animateScreenStateChange()方法中设置亮屏时的逻辑:

if (target == Display.STATE_ON) {
    //如果返回值为false,则返回,不再执行剩余流程
    if (!setScreenState(Display.STATE_ON)) {
        return; // screen on blocked
    }
    if (USE_COLOR_FADE_ON_ANIMATION && mColorFadeEnabled && mPowerRequest.isBrightOrDim()) {
    // 亮屏动画
    } else {
        // Skip screen on animation.
        mPowerState.setColorFadeLevel(1.0f);
        mPowerState.dismissColorFade();
    }
如果setScreenState(Display.STATE_ON)返回值为false,也就是mPendingScreenOnUnblocker != null,说明此时WindowManager中没有处理完成,为避免DisplayController中在没有处理完成的情况下先亮,所以临时阻塞流程。
那么什么时候不阻塞呢?当Window中绘制完成后,将会回调ScreenOnUnblocker类的onScreenOn()方法,方法如下:

private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
    @Override
    public void onScreenOn() {
        Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
        msg.setAsynchronous(true);
        mHandler.sendMessage(msg);
    }
}

在这个方法中,通过Handler异步执行消息,最调用unblockScreenOn()方法,在unblockScreenOn()方法中:

private void unblockScreenOn() {
    if (mPendingScreenOnUnblocker != null) {
        mPendingScreenOnUnblocker = null;
        long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
        Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
    }
}

可以看到置空了mPendingScreenOnUnblocker对象,说明取消阻塞,因此再次进入setScreenState(Display.STATE_ON)流程后,由于没有阻塞,从而执行剩余流程。

同样地,blockScreenOff()和unblcokScreenOff()方法也类似,会在灭屏时进行阻塞。

分析完setScreenState()方法后,这里结合animateScreenStateChange()和setScreenState()方法进行一个总结:

对于灭屏(STATE_OFF),首先是设置背光值为0,然后设置屏幕状态,其代码逻辑为:先setColorFadeLevel(0.0f),再setState(Display.STATE_OFF);
对于亮屏(STATE_ON)状态,首先是设置屏幕状态值,然后才会设置背光值,其代码逻辑为:先setState(Display.STATE_ON),再setColorFadeLevel(1.0)。
5.DisplayPowerState.setScreenState()
开始分析下一个方法——在分析setScreenState()方法时,还剩余一个具体设置屏幕状态的方法:

if (!reportOnly) {
        mPowerState.setScreenState(state);
        // Tell battery stats about the transition.
   ......
    }
}

现在我们开始分析DisplayPowerState中的setScreenState()方法,看看它是如何设置屏幕状态的。直接进入DisplayPowerState中看该方法,其源码如下:

/**
 * Sets whether the screen is on, off, or dozing.
 */
public void setScreenState(int state) {
    if (mScreenState != state) {
        mScreenState = state;
        mScreenReady = false;
        scheduleScreenUpdate();
    }
}

最终,在这个方法中将state设置给了mScreenState,然后执行了一个scheduleScreenUpdate()方法:

private void scheduleScreenUpdate() {
    if (!mScreenUpdatePending) {
        mScreenUpdatePending = true;
        postScreenUpdateThreadSafe();
    }
}
在这个方法中又调用了postScreenUpdateThreadSafe(),该方法如下:

private void postScreenUpdateThreadSafe() {
    mHandler.removeCallbacks(mScreenUpdateRunnable);
    mHandler.post(mScreenUpdateRunnable);
}
最终,会在这个方法中通过Handler.post(mScreenUpdateRunnable)进行了处理。这个mScreenUpdateRunnable非常重要,可以测试下如果注释掉它,那么亮屏、灭屏都会失效。好了,现在直接看mScreenUpdateRunnable这个Runnable,其中必要说明已进行了注释:

private final Runnable mScreenUpdateRunnable = new Runnable() {
    @Override
    public void run() {
        //表示是否打算更新屏幕状态,该值在scheduleScreenUpdate()方法中设置为了true
        mScreenUpdatePending = false;
        //获取背光亮度值,如果屏幕状态为State_Off的话就是0,其他屏幕状态下都是设置的背光值
        int brightness = mScreenState != Display.STATE_OFF
                && mColorFadeLevel > 0f ? mScreenBrightness : 0;
        //如果该方法返回false,表示屏幕更新完成,否则表示还没有更新完成
        if (mPhotonicModulator.setState(mScreenState, brightness)) {
            if (DEBUG) {
                Slog.d(TAG, "Screen ready");
            }
            mScreenReady = true;//标记屏幕状态是否更新完成
            invokeCleanListenerIfNeeded();
        } else {
            if (DEBUG) {
                Slog.d(TAG, "Screen not ready");
            }
        }
    }
};

在这个方法中,首先得到背光亮度值brightness,之后将背光亮度值和屏幕状态值传入了mPhotonicModulator.setState()中,并且根据这个方法的返回值来决定是否是屏幕状态更新完成(这里的屏幕状态更新完成是根据方法名直译的,可以理解为屏幕状态是否和其他模块中完成同步,在DisplayPowerState中State已经设置了新的值了)。那么就来看看这个mPhotonicModulator.setState()了。

PhotonicModulator是一个Thread的子类,专门用于更新屏幕和背光亮度值的状态,因此,在DisplayPowerState中,更新屏幕和背光状态是在独立的线程中异步进行的。
现在,先来看看这个线程的setScreen()方法:

public boolean setState(int state, int backlight) {
    synchronized (mLock) {
        //屏幕状态是否改变,和之前的值做比较
        boolean stateChanged = state != mPendingState;
        //背光是否改变
        boolean backlightChanged = backlight != mPendingBacklight;
        //如果有其中之一改变,进入if中
        if (stateChanged || backlightChanged) {
            if (DEBUG) {
                Slog.d(TAG, "Requesting new screen state: state="
                        + Display.stateToString(state) + ", backlight=" + backlight);
            }
            //设置state值
            mPendingState = state;
            mPendingBacklight = backlight;
            //mStateChangeInProgress和mBacklightChangeInProgress分别表示当前屏幕状态和背光值
            //正在更新的过程中,changeInProgress表示其中之一是否正在更新的过程中
            boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
            mStateChangeInProgress = stateChanged || mStateChangeInProgress;
            mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
            //如果为false,则唤醒mPhotonicModulator线程,执行它的run()方法
            if (!changeInProgress) {
                mLock.notifyAll();
            }
        }
        //如果该值为true,说明此时正在进行屏幕状态的改变,没有准备好。因此返回false,反之
        return !mStateChangeInProgress;
    }
}
这个方法中的逻辑容易理解,其中对mLock.notifyAll()这个逻辑再进行下分析,为何当changeInProgress为false的时候需要mLock.notifyAll()呢?这是因为该线程启动后就是一个死循环,可以无线执行,但在死循环中进行了mLock.wait()操作,这里看看它的run()方法,如下:


@Override
public void run() {
    for (;;) {
        // Get pending change.
        final int state;
        final boolean stateChanged;
        final int backlight;
        final boolean backlightChanged;
        synchronized (mLock) {
            //通过全局变量给局部变量赋值
            state = mPendingState;
            //mActualState表示目前实际的状态值
            stateChanged = (state != mActualState);
            backlight = mPendingBacklight;
            //mActualBacklight表示目前实际的亮度值
            backlightChanged = (backlight != mActualBacklight);
            //stateChange为false表示此时屏幕状态已应用为需要设置的值了(已应用),则再次执行一遍
            //postScreenUpdateThreadSafe()方法,这次执行时,PhotonicMudulator.setScreen()将返回
            //true,表示屏幕更新完成
            //-----------------------------------------------------BEG
            if (!stateChanged) {
                // State changed applied, notify outer class.
                postScreenUpdateThreadSafe();
                mStateChangeInProgress = false;//表示更新屏幕已完成
            }
            //说明背光值也已经应用
            if (!backlightChanged) {
                //置为false,表示更新背光已完成,没有正在进行的改变操作
                mBacklightChangeInProgress = false;
            }
            //如果屏幕状态和背光值都应用完成,则让该线程进入等待状态
            if (!stateChanged && !backlightChanged) {
                try {
                    mLock.wait();
                } catch (InterruptedException ex) { }
                continue;
            }
           //-----------------------------------------------------END
           //设置实际状态值和背光值
            mActualState = state;
            mActualBacklight = backlight;
        }
        // Apply pending change.
        if (DEBUG) {
            Slog.d(TAG, "Updating screen state: state="
                    + Display.stateToString(state) + ", backlight=" + backlight);
        }
        //调用DisplayBlanker中去请求Display
        mBlanker.requestDisplayState(state, backlight);
    }
}
在run()方法中,注意我用BEG-END标注的这段,如果在进行状态更新时第一次进入该方法,它肯定不会执行,因为在这段之后才做了mActualState=state等操作,因此,只有在屏幕状态和背光值状态都更新后(应该是在第二次进入后),就会执行到这段代码,从而使得线程进入wait状态。

在这个方法的最后一部分逻辑中,在将mActualState和mActualBacklight赋值之后,调用了mBlanker.requestDisplayState()方法,这个方法非常重要,它直接向DisplayManagerService去请求屏幕状态和亮度值.

Q: screen not ready是指屏幕状态没有设置完成还是屏幕状态+亮度值没有设置完成?
A:在正确流程下,只要state设置后,就会反映出screen ready。

以上DisplayPowerController中的逻辑就到这里结束了,按照流程,我们接下来要分析DisplayBlanker中的相关逻辑了,但由于它是在子线程中进行的,所以我们暂且先不分析DisplayBlanker以及之后的逻辑,而是先看看updatePowerState()方法中剩余的逻辑。

在updatePowerState()中,当执行完毕animateScreenState()后,屏幕状态就设置完成了(如果是灭屏,亮度也已被设置为0),接下来将负责获取亮度值。由于系统中不同场景有不用的亮度值,比如,在用户设置的亮度值、自动调节亮度(LSensor)获取的亮度值、低电量时的亮度值、Dim状态时的亮度值…在这里会做出一个判断具体使用哪个亮度值。这部分代码这里就不贴了,详细的解释已经进行了注释。
当完成亮度值的获取后,开始设置亮度值的设置流程。

6.animateScreenBrightness()
设置背光值用到了animateScreenBrightness()这个方法,这里我们再来看看updatePowerState()中是如何调用该方法的:

if ((state == Display.STATE_ON
        && mSkipRampState == RAMP_STATE_SKIP_NONE
        || state == Display.STATE_DOZE && !mBrightnessBucketsInDozeConfig)
        && !wasOrWillBeInVr) {
    //设置亮度坡度变化,slowChange=true仅应用于自动调节亮度,其他条件时为false
    animateScreenBrightness(brightness,
            slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
} else {
    //其他情况下不使用亮度坡度值,一次性设置为最终亮度值
    animateScreenBrightness(brightness, 0);
}
在这里,如果是state=Display.STATE_ON,说明此时屏幕状态为亮屏,如满足其他条件,则进入if语句中,给animateScreenBrightness()第二个设置参数为一个大于0的固定值,否则,直接给animateScreenBrightness()第二个参数设置为0。这个参数有何作用呢?先来看该方法代码:

private void animateScreenBrightness(int target, int rate) {
    if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
        Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);
        try {
            mBatteryStats.noteScreenBrightness(target);
        } catch (RemoteException ex) {
            // same process
        }
    }
}
在这个方法中,只有调用了一个对象的animateTo()方法,并将其参数传给了animateTo(),其他什么也没有做。在这个方法中,第一个参数是updatePowerState()中获得的最终亮度值,第二个参数则和亮度设置时的动画效果有关系,如果设置为大于0的数,那么会在animateTo()方法中根据这个数逐渐地设置亮度,如果设置为小于等于0,那么则不会有动画效果,直接将亮度值一次性设置。接下来,说说亮度值设置时的动画相关的逻辑。

7.RampAnimator.animateTo()
继续跟着上一段分析,mScreenBrightnessRampAnimator是一个RampAnimator对象,RampAnimator类是一个自定义动画类,专门用于更新亮度,其原理是该类中有一个IntProperty对象作为该类的一个属性:

public RampAnimator(T object, IntProperty<T> property) {
    mObject = object;
    mProperty = property;
    mChoreographer = Choreographer.getInstance();
}
当调用animateTo()时,会调用IntProperty<T>.setValue(Object,int)方法,而在该方法中,将会调用setScreenBrightness()方法将亮度设置,我们先看animateTo()方法:

public boolean animateTo(int target, int rate) {
    // Immediately jump to the target the first time.
    //如果rate>=0,则直接通过mProperty.setValue(mObject, target)设置为目标亮度
    if (mFirstTime || rate <= 0) {
        if (mFirstTime || target != mCurrentValue) {
            mFirstTime = false;
            mRate = 0;
            mTargetValue = target;
            mCurrentValue = target;
            //rate<=0时直接设置
            mProperty.setValue(mObject, target);
            if (mAnimating) {
                mAnimating = false;
                cancelAnimationCallback();
            }
            if (mListener != null) {
                mListener.onAnimationEnd();
            }
            return true;
        }
        return false;
    }
    if (!mAnimating
            || rate > mRate
            || (target <= mCurrentValue && mCurrentValue <= mTargetValue)
            || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
        mRate = rate;
    }
    final boolean changed = (mTargetValue != target);
    mTargetValue = target;
    //通过动画设置为目标亮度
    // Start animating.
    if (!mAnimating && target != mCurrentValue) {
        mAnimating = true;
        mAnimatedValue = mCurrentValue;
        mLastFrameTimeNanos = System.nanoTime();
        postAnimationCallback();
    }

    return changed;
}

这个方法中可以看到,根据传入的第二个参数rate,如果rate<=0,那么直接调用mProperty.setValue(object,target)设置最终的亮度;如果rate>0,那么会进入postAnimationCallback()方法,在这个方法中通过rate计算出每次设置的亮度值进行设置,直到设置到最终亮度为止。

对于postAnimationCallback()方法的代码就不详细说明了。当调用mProperty.setValue(object,target)后,接下来的步骤是哪个呢?我们从该动画对象实例化时就可以知道,其实例化代码如下:

mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
        mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);

因此当执行mProperty.setValue(object,target)时,执行的是DisplayPowerState.SCREEN_BRIGHTNESS的setValue()方法,进入DisplayPowerState中查看该对象:

public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =
        new IntProperty<DisplayPowerState>("screenBrightness") {
    @Override
    public void setValue(DisplayPowerState object, int value) {
        //设置亮度
        object.setScreenBrightness(value);
    }
    @Override
    public Integer get(DisplayPowerState object) {
        return object.getScreenBrightness();
    }
};

在这里可以看出,当调用setValue()方法后,将调用object.setScreenBrightness(),从实例化流程可知,object对象还是DisplayPowerState对象。继续setScreenBrightness()方法:

public void setScreenBrightness(int brightness) {
    if (mScreenBrightness != brightness) {
        mScreenBrightness = brightness;
        //对于屏幕状态为State_OFF,根据上面内容的分析,在设置屏幕状态之间就会设置将背光设置为0,此处不进行处理
        if (mScreenState != Display.STATE_OFF) {
            mScreenReady = false;
            scheduleScreenUpdate();
        }
    }
}

在这个方法中,如果当前屏幕状态不为STATE_OFF,即当前不是处于灭屏状态,则开始调用scheduleScreenUpdate()更新背光,这个方法我们在前面已经分析了,可以查看5小节的分析,最终通过DisplayBlanker.requestPowerState()请求设置到新的亮度值。

还有一点需要注意的是,在setScreenBrightness()方法中,对(mScreenState != Display.STATE_OFF)进行了判断,这是因为我们之前分析过,对于灭屏来说,当设置完ColorFadeLevel值为0后,就开始设置背光了,背光设置为0后才会设置屏幕状态为STATE_OFF,因此是不走这个流程的。而其他状态如亮屏,则是先设置背光,后设置屏幕状态为STATE_ON。

8.ready、finish变量决策收尾工作
现在回到updatePowerState()中,当执行完animateScreenBright()后,接下来的逻辑主要是判断屏幕状态和背光值设置是否成功,这里有两个boolean变量:ready和finish分别表示屏幕状态是否设置成功和屏幕状态、亮度值都设置成功,为了易于理解,这里再复制一下相关代码:

    //ready表示屏幕状态是否准备完成,mPendingScreenOnUnblocker用于亮屏过程中,
    //该值非空表示屏幕目前被阻塞,等待WindowManager回调,回调后将被置为null
    //mColorFadeOnAnimator,mColorFadeOffAnimator表示亮屏和灭屏动画
    final boolean ready = mPendingScreenOnUnblocker == null &&
            (!mColorFadeEnabled ||
                    (!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted()))
            && mPowerState.waitUntilClean(mCleanListener);
    //表示屏幕状态准备完成,同时亮度设置也完成
    final boolean finished = ready
            && !mScreenBrightnessRampAnimator.isAnimating();
    // Notify policy about screen turned on.
    //通知Windows进行亮屏处理亮屏
    if (ready && state != Display.STATE_OFF
            && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
        setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
        //通知WindowManager亮屏完成
        mWindowManagerPolicy.screenTurnedOn();
    }
    //如果未完成,需要申请一个Display锁
    if (!finished && !mUnfinishedBusiness) {
        //申请Display锁
        mCallbacks.acquireSuspendBlocker();
        mUnfinishedBusiness = true;
    }
    // Notify the power manager when ready.
    //当屏幕准备就绪,通知PMS
    if (ready && mustNotify) {
        synchronized (mLock) {
            if (!mPendingRequestChangedLocked) {
                //表示屏幕状态准备就绪,就绪和亮度设置完成无关,只和屏幕状态有关
                mDisplayReadyLocked = true;
            }
        }
        //在该方法中回调PMS方法
        sendOnStateChangedWithWakelock();
    }
    // Release the wake lock when we have no unfinished business.
    //完成后释放Display锁
    if (finished && mUnfinishedBusiness) {
        mUnfinishedBusiness = false;
        mCallbacks.releaseSuspendBlocker();
    }
}

详细说明见注释,从以上代码中看出,当屏幕状态设置完成后,ready为true,因此将mDisplayReadyLock值置为true,然后调用sendOnStateChangedWithWakelock()方法,在这个方法中会通知PMS:Display已经更新完成啦!sendOnStateChangedWithWakelock()方法如下:

private void sendOnStateChangedWithWakelock() {
    mCallbacks.acquireSuspendBlocker();
    mHandler.post(mOnStateChangedRunnable);
}

private final Runnable mOnStateChangedRunnable = new Runnable() {
    @Override
    public void run() {
        mCallbacks.onStateChanged();//回调PMS中的该方法
        mCallbacks.releaseSuspendBlocker();//回调PMS中的该方法,释放Display锁
    }
};

在PMS中,onStateChange()方法如下:

@Override
public void onStateChanged() {
    synchronized (mLock) {
        mDirty |= DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED;
        updatePowerStateLocked();
    }
}

从而使PMS中通过updatePowerStateLocked()方法重新请求状态。

至此,整个updatePowerState()方法以纵向的形式分析完毕了。在分析进入animateScreenStateChange()、DisplayPowerState.setScreenState()时,在DisplayBlanker.requestPowerState()时停止了,因为这是个异步的操作。接下来我们从这里出发,探究一下屏幕状态和背光最后是如何设置的以及设置到哪里去了。

9.DisplayBlanker.requestPowerState()
DisplayBlanker是一个接口,并且只有一个方法,它专门用来更新实际的屏幕显示状态.在DisplayPowerController中,DisplayBlanker由DisplayManagerService在实例化DisplayPowerController时作为参数传入,DisplayPowerController中在实例化DisplayPowerState时又通过构造函数传给了DisplayPowerState,因此,DisplayBlanker的实现还是在DMS中,我们进入DMS中看DisplayBlanker对象:

public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
        SensorManager sensorManager) {
    synchronized (mSyncRoot) {
        DisplayBlanker blanker = new DisplayBlanker() {
            @Override
            public void requestDisplayState(int state, int brightness) {
                // The order of operations is important for legacy reasons.
                //对于灭屏和非灭屏状态,调用callback的顺序不同
                if (state == Display.STATE_OFF) {
                    requestGlobalDisplayStateInternal(state, brightness);
                }
                //PMS中调用native层方法
                callbacks.onDisplayStateChange(state);
                if (state != Display.STATE_OFF) {
                    requestGlobalDisplayStateInternal(state, brightness);
                }
            }
        };
        mDisplayPowerController = new DisplayPowerController(
                mContext, callbacks, handler, sensorManager, blanker);
    }
}

在通过匿名类实例化DisplayBlanker时,重写了requestDisplayState()方法,在这个方法中,callback.OnDisplayStateChange()方法将会回调到PowerManagerService中,用来调用native层方法,从这里可以看到,对于灭屏和其他流程,调用的顺序不同,,如果是灭屏,则会先设置灭屏,再回调PowerManagerService中的onDisplayStateChange()方法,如果是其他操作如亮屏,则会先调用onDisplayStateChange(),然后再调用设置亮屏。我们先进入PMS中看看该方法:


@Override
public void onDisplayStateChange(int state) {
    // This method is only needed to support legacy display blanking behavior
    // where the display's power state is coupled to suspend or to the power HAL.
    // The order of operations matters here.
    synchronized (mLock) {
        if (mDisplayState != state) {
            mDisplayState = state;
            if (state == Display.STATE_OFF) {
                //该配置值表示是否将交互模式与显示状态分离
                if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
                    //调用native层方法,设置交互模式为false
                    setHalInteractiveModeLocked(false);
                }
                //该配置值表示将自动挂起模式与显示状态分离
                if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
                    //调用native层方法,设置自动挂起模式为true
                    setHalAutoSuspendModeLocked(true);
                }
            } else {
                if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
                    setHalAutoSuspendModeLocked(false);
                }
                if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
                    setHalInteractiveModeLocked(true);
                }
            }
        }
    }
}

在上述方法中,调用native层代码进入到了libsuspend中,其中的两个配置值表示是否和Display进行解耦,如果设置为true,则不会调用native方法,默认为false,表示Suspend和Display显示不进行解耦。

回到DisplayBlanker.requestDisplayState()方法中,接下来看看requestGlobalDisplayStateInternal()方法:

private void requestGlobalDisplayStateInternal(int state, int brightness) {
//判断状态和亮度
    if (state == Display.STATE_UNKNOWN) {
        state = Display.STATE_ON;
    }
    if (state == Display.STATE_OFF) {
        brightness = PowerManager.BRIGHTNESS_OFF;
    } else if (brightness < 0) {
        brightness = PowerManager.BRIGHTNESS_DEFAULT;
    } else if (brightness > PowerManager.BRIGHTNESS_ON) {
        brightness = PowerManager.BRIGHTNESS_ON;
    }
   //mTempDisplayStateWorkQueue是一个ArrayList<Runnable>对象,表示显示状态时要执行的延期工
   //作临时列表。仅由requestDisplayState使用
    synchronized (mTempDisplayStateWorkQueue) {
        try {
            // 在mSyncRoot锁内更新屏幕显示状态和亮度
            // mGlobalDisplayState表示全局Display状态,即最终的状态
            synchronized (mSyncRoot) {
                if (mGlobalDisplayState == state
                        && mGlobalDisplayBrightness == brightness) {
                    return; // no change
                }
                //给代表全局屏幕状态和亮度的变量赋值
                mGlobalDisplayState = state;
                mGlobalDisplayBrightness = brightness;
                // 下一步操作
                applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
            }
            //由于设置屏幕状态需要几百毫秒,因此推迟了工作中最昂贵的部分,直到退出临界部分
            //以避免长时间阻塞其他线程。
            for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
                mTempDisplayStateWorkQueue.get(i).run();
            }
        } finally {
            mTempDisplayStateWorkQueue.clear();//清空列表
        }
    }
}

在这个方法中,设置了mGlobalDisplayState和mGlobalDisplayBrightness,这两个全局变量表示整体的显示状态和亮度,然后将这两值传给了下一个方法applyGlobalDisplayStateLocked(),继续分析该方法:

private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
//获取显示设备
    final int count = mDisplayDevices.size();
    for (int i = 0; i < count; i++) {
        DisplayDevice device = mDisplayDevices.get(i);
    //遍历每个显示设备,并更新显示状态
        Runnable runnable = updateDisplayStateLocked(device);
        if (runnable != null) {
            workQueue.add(runnable);
        }
    }
}

在这个方法中,首先会遍历mDisplayDevices,它是表示当前所有显示设备的集合,然后更新每一个显示设备.什么是显示设备呢?目前有三种DisplayDevice:

1.LocalDisplayDevice:手机屏幕就是一个显示设备;
2.WifiDisplayDevice:无线投射,通过wifi将屏幕投射到其他物理屏幕上如TV上.
3.VirtualDisplayDevice:虚拟设备
这里我们暂且不管WifiDisplayDevice和VirtualDisplayDevice,先看看LocalDisplayDevice。
现在进行下一个方法的分析,看看updateDisplayStateLocked()方法:

private Runnable updateDisplayStateLocked(DisplayDevice device) {
    //获取对应显示设备的信息类
    DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
        return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
    }
    return null;
}

在这个方法中,首先根据DisplayDevice对象的getDisplayDeviceInfoLocked()方法获取了DisplayDeviceInfo对象,然后根据DisplayDeviceInfo的flag进行决策,调用下一个方法并返回。DisplayDeviceInfo用于描述显示的物理设备特征,如尺寸、分别率等。

接下来调用了DisplayDevice的requsetDisplayStateLocked()方法,因此我们直接看LocalDisplayDevice中的该方法:

@Override
public Runnable requestDisplayStateLocked(final int state, final int brightness) {
    // Assume that the brightness is off if the display is being turned off.
    assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;
    final boolean stateChanged = (mState != state);
    final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;
    if (stateChanged || brightnessChanged) {
        final int displayId = mBuiltInDisplayId;
        final IBinder token = getDisplayTokenLocked();
        final int oldState = mState;
        if (stateChanged) {
            mState = state;
            updateDeviceInfoLocked();
        }
        if (brightnessChanged) {
            mBrightness = brightness;
        }
        // Defer actually setting the display state until after we have exited
        // the critical section since it can take hundreds of milliseconds
        // to complete.
        //返回该Runnable
        return new Runnable() {
            @Override
            public void run() {
                // Exit a suspended state before making any changes.
                int currentState = oldState;
                if (Display.isSuspendedState(oldState)
                        || oldState == Display.STATE_UNKNOWN) {
                    if (!Display.isSuspendedState(state)) {
                        setDisplayState(state);
                        currentState = state;
                    } else if (state == Display.STATE_DOZE_SUSPEND
                            || oldState == Display.STATE_DOZE_SUSPEND) {
                        setDisplayState(Display.STATE_DOZE);
                        currentState = Display.STATE_DOZE;
                    } else {
                        return; // old state and new state is off
                    }
                }
                // If the state change was from or to VR, then we need to tell the light
                // so that it can apply appropriate VR brightness settings. Also, update the
                // brightness so the state is propogated to light.
                boolean vrModeChange = false;
                if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&
                        currentState != state) {
                    setVrMode(state == Display.STATE_VR);
                    vrModeChange = true;
                }
                // Apply brightness changes given that we are in a non-suspended state.
                if (brightnessChanged || vrModeChange) {
                    setDisplayBrightness(brightness);
                }
                // Enter the final desired state, possibly suspended.
                if (state != currentState) {
                    setDisplayState(state);
                }
            }
            private void setVrMode(boolean isVrEnabled) {
                mBacklight.setVrMode(isVrEnabled);
            }
            //设置屏幕状态
            private void setDisplayState(int state) {
                try {
                    final int mode = getPowerModeForState(state);
                    SurfaceControl.setDisplayPowerMode(token, mode);
                } finally {
                }
            }
            //设置背光
            private void setDisplayBrightness(int brightness) {
                try {
                    mBacklight.setBrightness(brightness);
                } finally {
                }
            }
        };
    }
    return null;
}

最终会在这个方法中设置好屏幕状态和亮度值。

关于后面这一块分析的不是很详细,但这其中涉及到Display中比较多的内容,因此这里仅仅将涉及到亮灭屏过程的部分进行了分析。

以上就是DisplayPowerController中涉及到的亮灭屏流程。灭屏和亮屏时序图如下:

灭屏时序图:


亮屏时序图:

猜你喜欢

转载自blog.csdn.net/sdkdlwk/article/details/88367841
今日推荐