Android6.0 亮屏灭屏流程(DisplayPowerController、WMS)(一)WMS绘制

来源:互联网 发布:淘宝权id 编辑:程序博客网 时间:2024/06/08 10:43

亮屏、灭屏流程整个流程涉及的模块比较多,包括PowerManagerService、DisplayPowerControl、WMS、AMS。因此在分析完WMS之后,我们把这块也分析下。


DisplayPowerControl

我们知道灭屏流程的发起是在PowerManagerService中,会通过updatePowerState函数调用updateDisplayPowerStateLocked函数,再调用DisplayPowerControl的requestPowerState函数,到DisplayPowerControl中。DisplayPowerControl中后面会调用updatePowerState函数,我们也主要从这个函数开始分析:

updatePowerState会根据PowerManagerService传过来的显示状态,然后调用animateScreenStateChange函数。

        animateScreenStateChange(state, performScreenOffTransition);

下面我们先来看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()) {            return;        }        // 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.    ......        } 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.    ......        } 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();//关闭灭屏动画            }        }    }

animateScreenStateChange在亮屏的处理的时候,先会调用setScreenState(Display.STATE_ON),然后根据USE_COLOR_FADE_ON_ANIMATION 判断是否要开启亮屏动画,这里我们是没有设置的。因此直接跳过亮屏动画。灭屏的处理的话,会有一个灭屏动画(也是注册一个VSync信号回调函数处理的,这里我们不分析了),当动画结束后,直接就调用setScreenState(Display.STATE_OFF)结束。

我们再来看看setScreenState函数

    private boolean setScreenState(int state) {        if (mPowerState.getScreenState() != state) {            final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);            mPowerState.setScreenState(state);    ......        }        // 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();//调用PhoneWindowManager的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);//调用PhoneWindowManager的screenTurningOn函数        }        // Return true if the screen isn't blocked.        return mPendingScreenOnUnblocker == null;    }

setScreenState函数,先是调用了DisplayPowerState的setScreenState函数,然后根据屏幕是灭屏还是亮屏调用PhoneWindowManager的相关函数。


PhoneWindowManager的screenTurnedOff和screenTurningOn函数

PhoneWindowManager的screenTurnedOff函数主要是通知kerguard,屏幕灭屏了。

    @Override    public void screenTurnedOff() {        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");        updateScreenOffSleepToken(true);        synchronized (mLock) {            mScreenOnEarly = false;            mScreenOnFully = false;            mKeyguardDrawComplete = false;            mWindowManagerDrawComplete = false;            mScreenOnListener = null;            updateOrientationListenerLp();            if (mKeyguardDelegate != null) {                mKeyguardDelegate.onScreenTurnedOff();            }        }    }

我们再来看PhoneWindowManager的screenTurningOn函数。当有keyguard时,我们会先发一个延时的MSG_KEYGUARD_DRAWN_TIMEOUT信号,并且会调用keyguard的onScreenTurningOn函数,当完成会调用mKeyguardDrawnCallback回调函数。我们这里还要注意下有一个屏幕点亮后的回调。

    @Override    public void screenTurningOn(final ScreenOnListener screenOnListener) {        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");        updateScreenOffSleepToken(false);        synchronized (mLock) {            mScreenOnEarly = true;            mScreenOnFully = false;            mKeyguardDrawComplete = false;            mWindowManagerDrawComplete = false;            mScreenOnListener = screenOnListener;//屏幕点亮后的回调            if (mKeyguardDelegate != null) {                if (DEBUG_WAKEUP) Slog.d(TAG,                        "send delay message MSG_KEYGUARD_DRAWN_TIMEOUT");                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);                mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);            } else {                if (DEBUG_WAKEUP) Slog.d(TAG,                        "null mKeyguardDelegate: setting mKeyguardDrawComplete.");                finishKeyguardDrawn();            }        }    }

我们先看下mKeyguardDrawnCallback 回调,就是发送MSG_KEYGUARD_DRAWN_COMPLETE(keyguard绘制完的消息)

    final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {        @Override        public void onDrawn() {            if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");            mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);        }    };

我们再来看看MSG_KEYGUARD_DRAWN_COMPLETE以及MSG_KEYGUARD_DRAWN_TIMEOUT信号的处理,都会调用finishKeyguardDrawn函数。

                case MSG_KEYGUARD_DRAWN_COMPLETE:                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");                    finishKeyguardDrawn();                    break;                case MSG_KEYGUARD_DRAWN_TIMEOUT:                    Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");                    finishKeyguardDrawn();                    break;
我们再来看看finishKeyguardDrawn函数,会先去除队列中的MSG_KEYGUARD_DRAWN_TIMEOUT消息(因为之前发的MSG_KEYGUARD_DRAWN_TIMEOUT消息,可能keyguard结束发送MSG_KEYGUARD_DRAWN_COMPLETE消息调用的finishKeyguardDrawn就要把MSG_KEYGUARD_DRAWN_TIMEOUT去除了)。然后会调用

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

最后我们再看看WMS的waitForAllWindowsDrawn函数,以及两个参数mWindowManagerDrawCallback和一个WAITING_FOR_DRAWN_TIMEOUT(1秒)。


WMS的waitForAllWindowsDrawn函数

我们先来看看WMS的waitForAllWindowsDrawn函数,会把传进来的回调保存在mWaitingForDrawnCallback 。然后遍历所有的windows,把需要显示或者已经显示的窗口全部加入到mWaitingForDrawn,然后调用requestTraversalLocked这个函数我们之前分析过,就是发送一个消息,重新刷新UI布局。然后我们继续分析这个函数,如果mWaitingForDrawn为空,代表没啥显示的直接调用回调函数,如果mWaitingForDrawn有要显示的窗口,就要会先发送一个WAITING_FOR_DRAWN_TIMEOUT,这个timeout之前传进来的是1秒。然后调用checkDrawnWindowsLocked函数。

        @Override        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {            synchronized (mWindowMap) {                mWaitingForDrawnCallback = callback;//回调保存在mWaitingForDrawnCallback                 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);                    Slog.i(TAG,"In the function waitForAllWindowsDrawn");                    if (win.isVisibleLw()                            && (win.mAppToken != null || isForceHiding)) {                        Slog.i(TAG,"In the function win.isVisibleLw()");                        win.mWinAnimator.mDrawState = WindowStateAnimator.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;                        }                    }                }                requestTraversalLocked();            }            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);            if (mWaitingForDrawn.isEmpty()) {                callback.run();                Slog.i(TAG,"In the function mWaitingForDrawn.isEmpty()");            } else {                mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);                checkDrawnWindowsLocked();                Slog.i(TAG,"In the function checkDrawnWindowsLocked()");            }        }

我们先来看下checkDrawnWindowsLocked函数,这个函数。遍历之前加入的mWaitingForDrawn(要显示的窗口),这个时候我们把已经去除的,不需要显示的,没有surface的窗口从mWaitingForDrawn去除,还有已经绘制好的也去除。然后再当mWaitingForDrawn为空时,就发送ALL_WINDOWS_DRAWN消息。

    void checkDrawnWindowsLocked() {        if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {            return;        }        for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {            WindowState win = mWaitingForDrawn.get(j);            if (win.mRemoved || !win.mHasSurface || !win.mPolicyVisibility) {                // Window has been removed or hidden; no draw will now happen, so stop waiting.                if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);                mWaitingForDrawn.remove(win);            } else if (win.hasDrawnLw()) {                // Window is now drawn (and shown).                if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);                mWaitingForDrawn.remove(win);            }        }        if (mWaitingForDrawn.isEmpty()) {            if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);            mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);        }    }

ALL_WINDOWS_DRAWN消息的处理就是清除mWaitingForDrawnCallback ,然后调用回调。

                case ALL_WINDOWS_DRAWN: {                    Runnable callback;                    synchronized (mWindowMap) {                        callback = mWaitingForDrawnCallback;                        mWaitingForDrawnCallback = null;                    }                    if (callback != null) {                        callback.run();                    }                }

还有当我们调用waitForAllWindowsDrawn一般都是有需要显示的窗口,但是我们直接调用checkDrawnWindowsLocked函数,发现有的窗口还没绘制完成。那么我们就要等,会在刷新的核心函数中performLayoutAndPlaceSurfacesLockedInner有如下代码,这个时候如果之前还没绘制完成的窗口,绘制好了。会再调用checkDrawnWindowsLocked函数,如果mWaitingForDrawn中的窗口绘制好了,会在mWaitingForDrawn中去除这个窗口。然后mWaitingForDrawn为空了,之后会发送ALL_WINDOWS_DRAWN消息,还调用mWaitingForDrawnCallback回调函数。

        if (mWaitingForDrawnCallback != null ||                (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&                        !mInnerFields.mUpdateRotation)) {            checkDrawnWindowsLocked();        }

当然如果我们之前没有把mWaitingForDrawn中的窗口清空,最后在WAITING_FOR_DRAWN_TIMEOUT(这里是1秒)时间到了也会调用回调的。

                case WAITING_FOR_DRAWN_TIMEOUT: {                    Runnable callback = null;                    synchronized (mWindowMap) {                        Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);                        mWaitingForDrawn.clear();                        callback = mWaitingForDrawnCallback;                        mWaitingForDrawnCallback = null;                    }                    if (callback != null) {                        callback.run();                    }                    break;                }



PhoneWindowManager窗口绘制完成的回调函数

那下面我们就要继续看PhoneWindowManager中窗口绘制完成之后的回调函数。代码如下就是发送了一个消息。

    final Runnable mWindowManagerDrawCallback = new Runnable() {        @Override        public void run() {            if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");            mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);        }    };

我们来看这个消息的处理

                case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:                    if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");                    finishWindowsDrawn();                    break;

finishWindowsDrawn就是把mWindowManagerDrawComplete 置为true,然后调用finishScreenTurningOn函数。

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

finishScreenTurningOn函数调用了之前在DisplayPowerControl中调用screenTurningOn传入的回调,然后再调用WMS的enableScreenIfNeeded函数。

    private void finishScreenTurningOn() {        synchronized (mLock) {            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;            ......        }        if (listener != null) {            listener.onScreenOn();        }        if (enableScreen) {            try {                mWindowManager.enableScreenIfNeeded();            } catch (RemoteException unhandled) {            }        }    }

我们先分析下WMS的enableScreenIfNeeded函数,然后再看DisplayPowerControl的回调onScreenOn函数。



WMS的enableScreenIfNeeded函数

WMS的enableScreenIfNeeded函数就是调用了enableScreenIfNeededLocked函数

    @Override    public void enableScreenIfNeeded() {        synchronized (mWindowMap) {            enableScreenIfNeededLocked();        }    }

enableScreenIfNeededLocked这个函数仅仅是保证mDisplayEnabled为true,如果为true直接结束。

    void enableScreenIfNeededLocked() {        if (mDisplayEnabled) {            return;        }        if (!mSystemBooted && !mShowingBootMessages) {            return;        }        mH.sendEmptyMessage(H.ENABLE_SCREEN);    }

mDisplayEnabled不为true,发送ENABLE_SCREEN消息

                case ENABLE_SCREEN: {                    performEnableScreen();                    break;

performEnableScreen函数会让SurfaceFlinger去停止开机动画等,也会把mDisplayEnabled置为true。当然performEnableScreen在开机的时候会AMS中调用WMS的enableScreenAfterBoot函数来调用performEnableScreen函数。这个我们在博客http://blog.csdn.net/kc58236582/article/details/52921978分析过了。

    public void performEnableScreen() {        synchronized(mWindowMap) {            if (mDisplayEnabled) {                return;            }            if (!mSystemBooted && !mShowingBootMessages) {                return;            }            // Don't enable the screen until all existing windows have been drawn.            if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) {                return;            }            if (!mBootAnimationStopped) {                // Do this one time.                try {//停止开机动画                    IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");                    if (surfaceFlinger != null) {                        //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");                        Parcel data = Parcel.obtain();                        data.writeInterfaceToken("android.ui.ISurfaceComposer");                        surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED                                data, null, 0);                        data.recycle();                    }                } catch (RemoteException ex) {                    Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");                }                mBootAnimationStopped = true;            }            if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {                if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: Waiting for anim complete");                return;            }            mDisplayEnabled = true;//置为true            if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");            // Enable input dispatch.            mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled);        }        try {            mActivityManager.bootAnimationComplete();        } catch (RemoteException e) {        }        mPolicy.enableScreenAfterBoot();        // Make sure the last requested orientation has been applied.        updateRotationUnchecked(false, false);    }


窗口绘制完成后调用DisplayPowerControl中的回调

当WMS窗口绘制完成后,会在PhoneWindowManager中的finishScreenTurningOn函数调用DisplayPowerControl的回调函数。最后我们再来看看DisplayPowerControl中的回调的onScreenOn函数。只是发送了一个MSG_SCREEN_ON_UNBLOCKED消息。

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

MSG_SCREEN_ON_UNBLOCKED的处理先是调用了unblockScreenOn函数,然后再调用updatePowerState更新状态。

                case MSG_SCREEN_ON_UNBLOCKED:                    if (mPendingScreenOnUnblocker == msg.obj) {                        unblockScreenOn();                        updatePowerState();                    }                    break;

unblockScreenOn函数,只是打印下从调用screenTurningOn开始,到窗口绘制完成在PhoneWindowManager中回调这个函数的时间差打印。

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


2 0
原创粉丝点击