美文网首页systemui
Android7.0亮屏流程分析

Android7.0亮屏流程分析

作者: Lonelyyy | 来源:发表于2018-01-18 00:55 被阅读0次

    亮屏的本质是改变屏幕的电源状态,经过一系列的调用会来到PowerManagerService中的updatePowerStateLocked()

    1.PowerManagerService到DisplayPowerController

    private void updatePowerStateLocked() {
            if (!mSystemReady || mDirty == 0) {
                return;
            }
            if (!Thread.holdsLock(mLock)) {
                Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
            }
            try {
                // Phase 0: Basic state updates.
                updateIsPoweredLocked(mDirty);
                updateStayOnLocked(mDirty);
                updateScreenBrightnessBoostLocked(mDirty);
                // Phase 1: Update wakefulness.
                // Loop because the wake lock and user activity computations are influenced
                // by changes in wakefulness.
                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;
                    }
                }
                // Phase 2: Update display power state.
                boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);
                // Phase 3: Update dream state (depends on display ready signal).
                updateDreamLocked(dirtyPhase2, displayBecameReady);
                // Phase 4: Send notifications, if needed.
                finishWakefulnessChangeIfNeededLocked();
                // Phase 5: Update suspend blocker.
                // Because we might release the last suspend blocker here, we need to make sure
                // we finished everything else first!
                updateSuspendBlockerLocked();
            } finally {}
        }
    

    然后经过函数updateDisplayPowerStateLocked来到DisplayPowerController的requestPowerState函数

    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;
                } else if (!mPendingRequestLocked.equals(request)) {
                    mPendingRequestLocked.copyFrom(request);
                    changed = true;
                }
                if (changed) {
                    mDisplayReadyLocked = false;
                }
                if (changed && !mPendingRequestChangedLocked) {
                    mPendingRequestChangedLocked = true;
                    sendUpdatePowerStateLocked();
                }
                return mDisplayReadyLocked;
            }
        }
    

    再次经过sendUpdatePowerStateLocked以及handler+meesage的消息,进入如下的switch结构

    private final class DisplayControllerHandler extends Handler {
            public DisplayControllerHandler(Looper looper) {
                super(looper, null, true /*async*/);
            }
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_UPDATE_POWER_STATE:
                        updatePowerState();
                        break;
                    case MSG_PROXIMITY_SENSOR_DEBOUNCED:
                        debounceProximitySensor();
                        break;
                    case MSG_SCREEN_ON_UNBLOCKED:
                        if (mPendingScreenOnUnblocker == msg.obj) {
                            unblockScreenOn();
                            updatePowerState();
                        }
                        break;
                }
            }
        }
    

    2.DisplayPowerController中的block机制

    block的机制的存在是为了保证在屏幕亮时所有工作都已经准备好(如屏幕完成上电以及所有窗口绘制完成),所以前后需要执行两次的updatePowerState()才会使屏幕真正的亮起来,从PMS传递过来的消息会先走到MSG_UPDATE_POWER_STATE执行第一次updatePowerState(),其核心是走到animateScreenStateChange()

    private void animateScreenStateChange(int target, boolean performScreenOffTransition) {
            // If there is already an animation in progress, don't interfere with it.
            if (mColorFadeOnAnimator.isStarted()
                    || mColorFadeOffAnimator.isStarted()) {
                if (target != Display.STATE_ON) {
                    return;
                }
                // If display state changed to on, proceed and stop the color fade and turn screen on.
                mPendingScreenOff = false;
            }
            // If we were in the process of turning off the screen but didn't quite
            // finish.  Then finish up now to prevent a jarring transition back
            // to screen on if we skipped blocking screen on as usual.
            if (mPendingScreenOff && target != Display.STATE_OFF) {
                setScreenState(Display.STATE_OFF);
                mPendingScreenOff = false;
                mPowerState.dismissColorFadeResources();
            }
            if (target == Display.STATE_ON) {
                // Want screen on.  The contents of the screen may not yet
                // be visible if the color fade has not been dismissed because
                // its last frame of animation is solid black.
                if (!setScreenState(Display.STATE_ON)) {
                    return; // screen on blocked
                }
                if (USE_COLOR_FADE_ON_ANIMATION && 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_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) {
                // Want screen dozing and suspended.
                // Wait for brightness animation to complete beforehand unless already
                // suspended because we may not be able to change it after suspension.
                if (mScreenBrightnessRampAnimator.isAnimating()
                        && mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
                    return;
                }
                // If not already suspending, temporarily set the state to doze until the
                // screen on is unblocked, then suspend.
                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 = true;
                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)
                        && 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();
                }
            }
        }
    

    mColorFadeOnAnimator与亮屏动画相关,默认是关闭的,这里不讨论,对于亮屏来说target == Display.STATE_ON为true,接着看函数setScreenState

    private boolean setScreenState(int state) {
            if (mPowerState.getScreenState() != state) {
                final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
                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.
            final boolean isOff = (state == Display.STATE_OFF);
            if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
                    && !mScreenOffBecauseOfProximity) {
                mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
                unblockScreenOn();
                mWindowManagerPolicy.screenTurnedOff();
            } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
                mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
                if (mPowerState.getColorFadeLevel() == 0.0f) {
                    blockScreenOn();
                } else {
                    unblockScreenOn();
                }
                mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
            }
            // Return true if the screen isn't blocked.
            return mPendingScreenOnUnblocker == null;
        }
    

    2.1blockScreenOn

    其中,mPowerState.setScreenState(state)与屏幕上电有关,这个放在本篇后面讲,对于第一次updatePowerState,屏幕还未上电,即mPowerState.getColorFadeLevel() == 0.0f结果为true,执行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();
                Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
            }
        }
    

    blockscreenon的实质是new一个ScreenOnUnblocker对象,这个对象直到unblockscreen才会置为空,以此来实现block机制

    2.2回调WMS

    setScreenState在执行blockScreenOn之后会执行这一段话

    mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
    

    WindowManagerPolicy的实现是PhoneWindowManager,所以继续看相关代码

    @Override
        public void screenTurningOn(final ScreenOnListener screenOnListener) {
            updateScreenOffSleepToken(false);
            synchronized (mLock) {
                mScreenOnEarly = true;
                mScreenOnFully = false;
                mKeyguardDrawComplete = false;
                mWindowManagerDrawComplete = false;
                mScreenOnListener = screenOnListener;
                if (mKeyguardDelegate != null) {
                    mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
                    mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
                    mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
                } else {
                    finishKeyguardDrawn();
                }
            }
        }
    

    其中,mKeyguardDelegate是用来向锁屏传递消息的对象,如果锁屏存在的话,会把mKeyguardDrawnCallback传递到锁屏中去,锁屏中进行相关判断,满足条件则运行callback中的方法,mKeyguardDrawnCallback中的方法最终依然是执行finishKeyguardDrawn(),所以直接看这个函数

    private void finishKeyguardDrawn() {
            synchronized (mLock) {
                if (!mScreenOnEarly || mKeyguardDrawComplete) {
                    return; // We are not awake yet or we have already informed of this event.
                }
                mKeyguardDrawComplete = true;
                if (mKeyguardDelegate != null) {
                    mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
                }
                mWindowManagerDrawComplete = false;
            }
            // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
            // as well as enabling the orientation change logic/sensor.
            mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
                    WAITING_FOR_DRAWN_TIMEOUT);
        }
    

    mKeyguardDrawComplete的存在是为了防止重复调用,不过多讨论,finishKeyguardDrawn最后是走到了WindowManagerInternal里面,WindowManagerInternal的实现类是WindowManagerService

    2.3窗口绘制检查

    public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
                boolean allWindowsDrawn = false;
                synchronized (mWindowMap) {
                    mWaitingForDrawnCallback = callback;
                    final WindowList windows = getDefaultWindowListLocked();
                    for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                        final WindowState win = windows.get(winNdx);
                        final boolean isForceHiding = mPolicy.isForceHiding(win.mAttrs);
                        final boolean keyguard = mPolicy.isKeyguardHostWindow(win.mAttrs);
                        if (win.isVisibleLw()
                                && (win.mAppToken != null || isForceHiding || keyguard)) {
                            win.mWinAnimator.mDrawState = DRAW_PENDING;
                            // Force add to mResizingWindows.
                            win.mLastContentInsets.set(-1, -1, -1, -1);
                            mWaitingForDrawn.add(win);
                            // No need to wait for the windows below Keyguard.
                            if (isForceHiding) {
                                break;
                            }
                        }
                    }
                    mWindowPlacerLocked.requestTraversal();
                    mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
                    if (mWaitingForDrawn.isEmpty()) {
                        allWindowsDrawn = true;
                    } else {
                        mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
                        checkDrawnWindowsLocked();
                    }
                }
                if (allWindowsDrawn) {
                    callback.run();
                }
            }
    

    这个函数会检查所有的窗口是否都绘制完全,同时启动窗口UI刷新流程,等待绘制的窗口放在mWaitingForDrawn里面,如果内容为空则表示窗口绘制完全,否则需要继续等待,并且还会发送一个延时1秒的message,防止窗口绘制超时导致屏幕无法亮起。
    如果窗口都绘制完成,则会进入传过来的callback的run方法,具体看一下这个传过来的callback

    final Runnable mWindowManagerDrawCallback = new Runnable() {
            @Override
            public void run() {
                mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
            }
        };
    

    来到如下函数

    private void finishWindowsDrawn() {
            synchronized (mLock) {
                if (!mScreenOnEarly || mWindowManagerDrawComplete) {
                    return; // Screen is not turned on or we did already handle this case earlier.
                }
                mWindowManagerDrawComplete = true;
            }
            finishScreenTurningOn();
        }
    

    继续看

    private void finishScreenTurningOn() {
            synchronized (mLock) {
                // We have just finished drawing screen content. Since the orientation listener
                // gets only installed when all windows are drawn, we try to install it again.
                updateOrientationListenerLp();
            }
            final ScreenOnListener listener;
            final boolean enableScreen;
            synchronized (mLock) {
                if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
                        || (mAwake && !mKeyguardDrawComplete)) {
                    return; // spurious or not ready yet
                }
                listener = mScreenOnListener;
                mScreenOnListener = null;
                mScreenOnFully = true;
                // Remember the first time we draw the keyguard so we know when we're done with
                // the main part of booting and can enable the screen and hide boot messages.
                if (!mKeyguardDrawnOnce && mAwake) {
                    mKeyguardDrawnOnce = true;
                    enableScreen = true;
                    if (mBootMessageNeedsHiding) {
                        mBootMessageNeedsHiding = false;
                        hideBootMessages();
                    }
                } else {
                    enableScreen = false;
                }
            }
            if (listener != null) {
                listener.onScreenOn();
            }
            if (enableScreen) {
                try {
                    mWindowManager.enableScreenIfNeeded();
                } catch (RemoteException unhandled) {
                }
            }
        }
    

    注意这里的listener,这个listener是一个ScreenOnListener对象,ScreenOnListener类的实现在DisplayPowerController中,所以通过这个listener,phoneWindowManager把窗口绘制完成的消息由传回了DisplayPowerController

    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);
            }
        }
    

    2.4unblockScreenOn

    ScreenOnUnblocker中的onScreenOn方法最终会走到unblockScreenOn方法

    private void unblockScreenOn() {
            if (mPendingScreenOnUnblocker != null) {
                mPendingScreenOnUnblocker = null;
                long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
                Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
                Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
            }
        }
    

    并且,unblockScreenOn之后会再一次updatePowerState(),调用DisplayPowerState中的相关方法设置亮度,屏幕最终亮起来
    通过unblockScreenOn方法中的log也可以得到block的总时间,一般来说,只要blockscreen前后没有过多的消息传递,可以认为block时间就是亮屏时间

    3.屏幕上电

    在屏幕亮起来之前需要改变屏幕的电源状态,即给屏幕上电
    前面说到,在DisplayPowerController设置电源状态的方法开头有这么一段

    private boolean setScreenState(int state) {
            if (mPowerState.getScreenState() != state) {
                final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
                mPowerState.setScreenState(state);
    ...
    

    mPowerState是一个DisplayPowerState对象,继续看具体的实现

    public void setScreenState(int state) {
            if (mScreenState != state) {
                mScreenState = state;
                mScreenReady = false;
                scheduleScreenUpdate();
            }
        }
    

    mScreenState和mScreenReady会用于状态检查,然后通过scheduleScreenUpdate向底层发出给屏幕上电的命令,具体的流程比较长而且复杂,不一一说明,大致的调用流程是
    DisplayPowerState
    -DisplayManagerService
    -LocalDisplayAdapter
    -SurfaceControl
    -HWComposer
    屏幕的上电时间与硬件的时序相关,并且是影响亮屏总时间的一个非常重要的因素,
    查看屏幕的上电时间可以通过搜索trace文件中的setPowerModeInternal查看或者搜索surfaceControl的log,setPowerMode

    相关文章

      网友评论

        本文标题:Android7.0亮屏流程分析

        本文链接:https://www.haomeiwen.com/subject/yazeoxtx.html