Android(安卓)P wakeup 亮屏流程
目录
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 处理上层传递的亮度参数很耗时.
更多相关文章
- 004. Android界面刷新没有调用OnMeasure
- 【攻克Android(安卓)(43)】WebView (网络视图)
- Android-使用OpengGL实现的Canvas进行绘制(简单介绍)
- Android(安卓)文字绘制,多行文字绘制
- Android(安卓)使用AIDL调用外部服务 (转)
- Android(安卓)Audio代码分析10 - audio_track_cblk_t::framesRea
- Bitmap recycle()
- Android的绘制详解(Canvas、Paint、Path等)
- android graphic(3)—surfaceflinger的启动流程