目录

 

1. 点亮屏幕的几种方式:

1.1 应用通过PowerManager 的wakeup()接口

1.2 应用创建的窗口带有WindowManager的 FLAG_TURN_SCREEN_ON 的flag

1.3 应用申请wakelock时候,添加 ACQUIRE_CAUSES_WAKEUP 的flag

1.4 通话的时候,通过距离感应器来点亮屏幕

1.5 调用PowerManager.userActivity() 保持亮屏

2.wakeup 亮屏的过程:

2.1 Screen on blocked

2.2 Screen turning on

2.3 PhoneWindowManager.mPowerKeyWakeLock -> interceptKeyBeforeQueueing

2.4 requestGlobalDisplayState->setDisplayState 

2.5 requestGlobalDisplayState->setDisplayBrightness->setLight


1. 点亮屏幕的几种方式:

1.1 应用通过PowerManager 的wakeup()接口

Power键唤醒也是通过Input事件调用到 PhoneWindowManager 中的按键事件处理函数interceptKeyBeforeQueueing中去调用PowerManager的wakeup接口
PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyDown()->wakeUpFromPowerKey()->wakeUp()
->PowerManager.wakeUp()

1.2 应用创建的窗口带有WindowManager的 FLAG_TURN_SCREEN_ON 的flag

本质是调用到PowerManagerService的WakeUp操作:
PowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),"android.server.wm:TURN_ON")
主要的需要关注的方法:WindowState.prepareWindowToDisplayDuringRelayout()

FLAG_TURN_SCREEN_ON log堆栈信息

11-10 12:57:17.267 13957 13992 V WindowManager:     at com.android.server.wm.WindowState.prepareWindowToDisplayDuringRelayout(WindowState.java:2405)11-10 12:57:17.267 13957 13992 V WindowManager:     at com.android.server.wm.WindowState.relayoutVisibleWindow(WindowState.java:4520)11-10 12:57:17.267 13957 13992 V WindowManager:     at com.android.server.wm.WindowManagerService.relayoutWindow(WindowManagerService.java:2182)11-10 12:57:17.267 13957 13992 V WindowManager:     at com.android.server.wm.Session.relayout(Session.java:244)11-10 12:57:17.267 13957 13992 V WindowManager:     at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:309)11-10 12:57:17.267 13957 13992 V WindowManager:     at com.android.server.wm.Session.onTransact(Session.java:164)11-10 12:57:17.267 13957 13992 V WindowManager:     at android.os.Binder.execTransact(Binder.java:748)11-10 12:57:17.268 13957 13992 I PowerManagerService: Waking up from sleep (uid=1000 reason=android.server.wm:TURN_ON)...

1.3 应用申请wakelock时候,添加 ACQUIRE_CAUSES_WAKEUP 的flag

PowerManager.acquireWakeLock()->PowerManagerService.acquireWakeLock()->
    applyWakeLockFlagsOnAcquireLocked()->wakeUpNoUpdateLocked()-> updatePowerStateLocked()

1.4 通话的时候,通过距离感应器来点亮屏幕

DisplayPowerController.mProximitySensorListener.onSensorChanged->debounceProximitySensor()
positive =false的时候会给当前时间添加一个250ms 的延迟来重新执行debounceProximitySensor()
debounceProximitySensor()->updatePowerState() 
updatePowerState是亮屏过程的会多次重复执行的函数,注意其实通过感应器来熄屏的时候,并不是真正的熄屏,
只是把背光置0,其实本身还是处于亮屏状态.
这个时候如果用PowerManager 相关的接口去判断会发现还是处于亮屏状态。

1.5 调用PowerManager.userActivity() 保持亮屏

主要调用流程:
PowerManager.userActivity()->PowerManagerService$BinderService.userActivity()->userActivityInternal()->updatePowerStateLocked()

上面的5种亮屏的情况,这里主要分析一下Power 键亮屏的情况,也就是调用PowerManager 的wakeup()接口的方式,其他的几种方式都是类似的。

2.wakeup 亮屏的过程:

上面的5种亮屏的情况,这里主要分析一下Power 键亮屏的情况,也就是调用PowerManager 的wakeup()接口的方式,其他的几种方式都是类似的。
首先整体了解一下wakeup 的大的过程,可以参考下面的一个时序图,但是这个过程是和实际有点差别的,下面时序图的有些过程是异步的,并不是都在同一个线程内执行,画在一起是为了先有个整体的概念,后面会就几个主要的过程再具体分析。

wakeup 亮屏的时序图:

可以先抓个亮屏的systemtrace 来看一下,从下面的截图可以看到亮屏的流程大致在304ms。


通过SystemTracek发现亮屏有以下几个主要流程:
Screen on blocked/Screen turning on /PhoneWindowManager.mPowerKeyWakeLock /interceptKeyBeforeQueueing
setDisplayState/requestGlobalDisplayState/setDisplayBrightness/setLight
下面会分析各段的主要流程

2.1 Screen on blocked

从log 可以发现这个过程从 DisplayPowerController 的 setScreenState()->blockScreenOn() 到 unblockScreenOn().
Log:

12-09 11:39:24.781  1713  1749 I DisplayPowerController: Blocking screen on until initial contents have been drawn.12-09 11:39:24.940  1713  1749 I DisplayPowerController: Unblocked screen on after 158 ms

这2个log 对应的是 DisplayPowerController 的 blockScreenOn() 和 unblockScreenOn()的执行.
DisplayPowerController.java

private boolean setScreenState(int state, boolean reportOnly) {    final boolean isOff = (state == Display.STATE_OFF);    //.....    if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {        setReportedScreenState(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;}

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

其中 mWindowManagerPolicy.screenTurningOn() 会通过一系列的调用调用到 SystemUI 的KeyguardServiced.onScreenTurningOn().
其中 MSG_KEYGUARD_DRAWN_TIMEOUT 是5000ms,也就是SystenUI 如果处理任务超过了5S就会触发超时机制,
直接调用 finishKeyguardDrawn() 来通知 WindowManagerService 来继续完成窗口的绘制.

@Overridepublic void screenTurningOn(final ScreenOnListener screenOnListener) {    //...    mKeyguardDrawComplete = false;    mWindowManagerDrawComplete = false;    mScreenOnListener = screenOnListener;    if (mKeyguardDelegate != null) {        mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);        mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,                getKeyguardDrawnTimeout());        mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);    } else {        if (DEBUG_WAKEUP) Slog.d(TAG,                "null mKeyguardDelegate: setting mKeyguardDrawComplete.");        finishKeyguardDrawn();    }}

KeyguardService.java

@Override // Binder interfacepublic void onScreenTurningOn(IKeyguardDrawnCallback callback) {    Trace.beginSection("KeyguardService.mBinder#onScreenTurningOn");    checkPermission();    mKeyguardViewMediator.onScreenTurningOn(callback);    mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_ON);    Trace.endSection();}

其中主要是 KeyguardViewMediator 和 KeyguardLifecyclesDispatcher 都是使用Handler 发现message 来处理.
KeyguardViewMediator 最终通过 handleNotifyScreenTurningOn()
KeyguardLifecyclesDispatcher具体任务是通过ScreenLifecycle的实现类来完成.

private void handleNotifyScreenTurningOn(IKeyguardDrawnCallback callback) {    Trace.beginSection("KeyguardViewMediator#handleNotifyScreenTurningOn");    synchronized (KeyguardViewMediator.this) {        if (DEBUG) Log.d(TAG, "handleNotifyScreenTurningOn");        mStatusBarKeyguardViewManager.onScreenTurningOn();        if (callback != null) {            if (mWakeAndUnlocking) {                mDrawnCallback = callback;            } else {                notifyDrawn(callback);            }        }    }    Trace.endSection();}

其中 mStatusBarKeyguardViewManager.onScreenTurningOn() 是个空方法,没有具体的操作

private void notifyDrawn(final IKeyguardDrawnCallback callback) {    Trace.beginSection("KeyguardViewMediator#notifyDrawn");    try {        callback.onDrawn();    } catch (RemoteException e) {        Slog.w(TAG, "Exception calling onDrawn():", e);    }    Trace.endSection();}

notifyDrawn() 的参数 IKeyguardDrawnCallback callback 很重要,它是 PhoneWindowManager 内部的实现了 DrawnListener 接口的实体类对象 mKeyguardDrawnCallback

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 会通过Handler 消息机制调用 PhoneWindowManager 的 finishKeyguardDrawn(),
finishKeyguardDrawn() 前面已经提到过,就是等待 WMS 继续处理窗口绘制相关的工作.
WindowManagerService.java

@Overridepublic void waitForAllWindowsDrawn(Runnable callback, long timeout) {    boolean allWindowsDrawn = false;    synchronized (mWindowMap) {        mWaitingForDrawnCallback = callback;        getDefaultDisplayContentLocked().waitForAllWindowsDrawn();        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();    }}

如果有需要绘制的窗口那么mWaitingForDrawn 的size肯定大于0,就会处理 checkDrawnWindowsLocked().
checkDrawnWindowsLocked()最终就是调用PhoneWindowManager的finishWindowsDrawn().
同时 WindowManagerService 处理绘制相关的任务也有一个超时机制,用来确保1000ms 后窗口绘制还没有完成的时候也可以继续执行正常的流程.
超时机制的主要流程是:通过Handler的WAITING_FOR_DRAWN_TIMEOUT 消息来控制的,这个时间是1000ms.
当窗口都绘制完成或者超过1S之后就会执行Handler的ALL_WINDOWS_DRAWN 消息,这个消息会继续回调 PhoneWindowManager 的 Runnable mWindowManagerDrawCallback.run()
而这个Runnable 的主要工作就是继续执行 Handler 的 MSG_WINDOW_MANAGER_DRAWN_COMPLETE 消息来 执行 PhoneWindowManager 的 finishWindowsDrawn().
finishWindowsDrawn() 下一步任务是调用 finishScreenTurningOn()
WMS 的 checkDrawnWindowsLocked 到 PhoneWindowManager 的finishScreenTurningOn 的流程:
checkDrawnWindowsLocked()->ALL_WINDOWS_DRAWN->PhoneWindowManager.mWindowManagerDrawCallback.run()
->finishScreenTurningOn()

private void finishScreenTurningOn() {//..    if (listener != null) {        listener.onScreenOn();    }//...}

这个ScreenOnListener listener 就是通过 DisplayPowerController 的内部类 ScreenOnUnblocker mPendingScreenOnUnblocker.
后续就是通过 mPendingScreenOnUnblocker.onScreenOn() 发送 MSG_SCREEN_ON_UNBLOCKED 消息完成 unblockScreenOn() 

总结一下:

Screen on blocked 的主要过程就是通过DisplayPowerController.java PhoneWindowManager.java WindowManagerService.java 和SystemUI 来完成 screenTurningOn 流程.也就是锁屏和其他窗口的绘制流程.
想要这个过程具体是卡在那里耗时,就打开 WindowManagerService 的 DEBUG_SCREEN_ON 开关,可以通过 checkDrawnWindowsLocked() 的log看到这段时间主要是绘制那个窗口需要绘制.
WindowManagerService.java

void checkDrawnWindowsLocked() {    if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {        return;    }    for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {        WindowState win = mWaitingForDrawn.get(j);        if (DEBUG_SCREEN_ON) Slog.i(TAG_WM, "Waiting for drawn " + win +                ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +                " mHasSurface=" + win.mHasSurface +                " drawState=" + win.mWinAnimator.mDrawState);        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_WM, "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_WM, "Window drawn win=" + win);            mWaitingForDrawn.remove(win);        }    }    if (mWaitingForDrawn.isEmpty()) {        if (DEBUG_SCREEN_ON) Slog.d(TAG_WM, "All windows drawn!");        mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);        mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);    }}

2.2 Screen turning on

SystemTrace 里面的 Screen turning on 这段和前面的 Screen on blocked 的 screenTurningOn 不是一样的.
前者比后者包含的过程更多,时间也更久.
Log:
12-09 11:39:24.776  1713  1823 I PowerManagerService: Waking up from sleep (uid=1000 reason=android.policy:POWER)...
//12-09 11:39:24.781  1713  1749 I DisplayPowerController: Blocking screen on until initial contents have been drawn.
//12-09 11:39:24.940  1713  1749 I DisplayPowerController: Unblocked screen on after 158 ms
12-09 11:39:25.024  1713  1749 W PowerManagerService: Screen on took 266 ms
通过log可以发现个过程明显比 Screen on blocked 的158ms 要长的多,而且首尾的2个log表明她们不是在同一个线程里面执行的.
这里首尾2个log 对应的就是 PowerManagerService.wakeUpNoUpdateLocked()到logScreenOn(),而且要执行时间超过200ms 才会打印log.
logScreenOn()主要调用流程:
DisplayPowerController.updatePowerState()->sendOnStateChangedWithWakelock()->
DisplayPowerController$Runnable:mOnStateChangedRunnable run()->
PowerManagerService$DisplayManagerInternal.DisplayPowerCallbacks:onStateChanged()->
PowerManagerService.updatePowerStateLocked()->finishWakefulnessChangeIfNeededLocked()->
PowerManagerService.logScreenOn()
其中有2个地方需要注意:

2.2.1  DisplayPowerController.updatePowerState()中的ready && mustNotify 这2个变量的满足为true 的时候才能继续执行下一步的sendOnStateChangedWithWakelock()

private void updatePowerState() {    //.....      // Determine whether the display is ready for use in the newly requested state.    // Note that we do not wait for the brightness ramp animation to complete before    // reporting the display is ready because we only need to ensure the screen is in the    // right power state even as it continues to converge on the desired brightness.    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);        mWindowManagerPolicy.screenTurnedOn();    }    // Notify the power manager when ready.    if (ready && mustNotify) {        // Send state change.        synchronized (mLock) {            if (!mPendingRequestChangedLocked) {                mDisplayReadyLocked = true;                if (DEBUG) {                    Slog.d(TAG, "Display ready!");                }            }        }        sendOnStateChangedWithWakelock();    }    //...}

2.2.2 PowerManagerService.updatePowerStateLocked() 中的有个for 循环,其中的updateWakefulnessLocked(dirtyPhase1)为false 的时候才能执行break 跳出for 循环,继续执行finishWakefulnessChangeIfNeededLocked() 和logScreenOn()   

private void updatePowerStateLocked() {        Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");        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: Lock profiles that became inactive/not kept awake.            updateProfilesLocked(now);            // Phase 3: Update display power state.            final boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);            // Phase 4: Update dream state (depends on display ready signal).            updateDreamLocked(dirtyPhase2, displayBecameReady);            // Phase 5: Send notifications, if needed.            finishWakefulnessChangeIfNeededLocked();            // Phase 6: Update suspend blocker.            // Because we might release the last suspend blocker here, we need to make sure            // we finished everything else first!            updateSuspendBlockerLocked();        } finally {            Trace.traceEnd(Trace.TRACE_TAG_POWER);        }    }

2.3 PhoneWindowManager.mPowerKeyWakeLock -> interceptKeyBeforeQueueing

SystemTrace 里面对应的这段这个比较简单.
起点就是 PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyDown()-> mPowerKeyWakeLock.acquire().
终点就是: PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyUp()->
finishPowerKeyPress()->PowerManager$WakeLock.release()

2.4 requestGlobalDisplayState->setDisplayState 

SystemTrace 里面对应的 requestGlobalDisplayState 这段其实是 DisplayManagerService.requestGlobalDisplayStateInternal()
SystemTrace 里面对应的 setDisplayState 这段其实是 LocalDisplayAdapter$LocalDisplayDevice$1.setDisplayState()

requestGlobalDisplayStateInternal:
通过 SystemTrace 或者log 可以发现 requestGlobalDisplayStateInternal() 是有多次执行的.
主要流程是:
DisplayPowerState$PhotonicModulator.run() -> DisplayManagerService$LocalService$1.requestDisplayState()
->DisplayManagerService.requestGlobalDisplayStateInternal()

setDisplayState:
主要流程:
DisplayManagerService.requestGlobalDisplayStateInternal()->applyGlobalDisplayStateLocked()->updateDisplayStateLocked()
->LocalDisplayAdapter$LocalDisplayDevice$1.setDisplayState()

2.5 requestGlobalDisplayState->setDisplayBrightness->setLight

LocalDisplayAdapter.setDisplayBrightness()->LightsService.setBrightness()->setLightLocked()->setLight_native()
通过 SystemTrace 可以看到第2次执行requestGlobalDisplayState 后的 setDisplayBrightness和setLight时间主要耗时是setLight_native耗时,
也就是底层lcd 处理上层传递的亮度参数很耗时.

 

更多相关文章

  1. 004. Android界面刷新没有调用OnMeasure
  2. 【攻克Android(安卓)(43)】WebView (网络视图)
  3. Android-使用OpengGL实现的Canvas进行绘制(简单介绍)
  4. Android(安卓)文字绘制,多行文字绘制
  5. Android(安卓)使用AIDL调用外部服务 (转)
  6. Android(安卓)Audio代码分析10 - audio_track_cblk_t::framesRea
  7. Bitmap recycle()
  8. Android的绘制详解(Canvas、Paint、Path等)
  9. android graphic(3)—surfaceflinger的启动流程

随机推荐

  1. Android 定位地址,获取经纬度,并转换为中文
  2. Android(安卓)1.5: 飞行模式分析
  3. Android中实现下拉刷新
  4. Fragment 和 Activity 全通讯
  5. android 白天模式/夜间模式切换
  6. Android轮播图 banner,图片视频混播banner
  7. Cocos2d-x在win32,android和IOS下的文件读
  8. Android的FastBoot的安装与环境变量设置
  9. 子墨庖丁Android的ActionBar源码分析 (一
  10. Adobe官网曝光Android版Flash网站优化列