Android P wakeup 亮屏流程
目錄
?
1. 點(diǎn)亮屏幕的幾種方式:
1.1 應(yīng)用通過PowerManager 的wakeup()接口
1.2 應(yīng)用創(chuàng)建的窗口帶有WindowManager的 FLAG_TURN_SCREEN_ON 的flag
1.3 應(yīng)用申請wakelock時候,添加 ACQUIRE_CAUSES_WAKEUP 的flag
1.4 通話的時候,通過距離感應(yīng)器來點(diǎn)亮屏幕
1.5 調(diào)用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. 點(diǎn)亮屏幕的幾種方式:
1.1 應(yīng)用通過PowerManager 的wakeup()接口
Power鍵喚醒也是通過Input事件調(diào)用到 PhoneWindowManager 中的按鍵事件處理函數(shù)interceptKeyBeforeQueueing中去調(diào)用PowerManager的wakeup接口
PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyDown()->wakeUpFromPowerKey()->wakeUp()
->PowerManager.wakeUp()
1.2 應(yīng)用創(chuàng)建的窗口帶有WindowManager的 FLAG_TURN_SCREEN_ON 的flag
本質(zhì)是調(diào)用到PowerManagerService的WakeUp操作:
PowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),"android.server.wm:TURN_ON")
主要的需要關(guān)注的方法:WindowState.prepareWindowToDisplayDuringRelayout()
FLAG_TURN_SCREEN_ON log堆棧信息
1.3 應(yīng)用申請wakelock時候,添加 ACQUIRE_CAUSES_WAKEUP 的flag
PowerManager.acquireWakeLock()->PowerManagerService.acquireWakeLock()->
?? ?applyWakeLockFlagsOnAcquireLocked()->wakeUpNoUpdateLocked()->?updatePowerStateLocked()
1.4 通話的時候,通過距離感應(yīng)器來點(diǎn)亮屏幕
DisplayPowerController.mProximitySensorListener.onSensorChanged->debounceProximitySensor()
positive =false的時候會給當(dāng)前時間添加一個250ms 的延遲來重新執(zhí)行debounceProximitySensor()
debounceProximitySensor()->updatePowerState()?
updatePowerState是亮屏過程的會多次重復(fù)執(zhí)行的函數(shù),注意其實(shí)通過感應(yīng)器來熄屏的時候,并不是真正的熄屏,
只是把背光置0,其實(shí)本身還是處于亮屏狀態(tài).
這個時候如果用PowerManager 相關(guān)的接口去判斷會發(fā)現(xiàn)還是處于亮屏狀態(tài)。
1.5 調(diào)用PowerManager.userActivity() 保持亮屏
主要調(diào)用流程:
PowerManager.userActivity()->PowerManagerService$BinderService.userActivity()->userActivityInternal()->updatePowerStateLocked()
上面的5種亮屏的情況,這里主要分析一下Power 鍵亮屏的情況,也就是調(diào)用PowerManager 的wakeup()接口的方式,其他的幾種方式都是類似的。
2.wakeup 亮屏的過程:
上面的5種亮屏的情況,這里主要分析一下Power 鍵亮屏的情況,也就是調(diào)用PowerManager 的wakeup()接口的方式,其他的幾種方式都是類似的。
首先整體了解一下wakeup 的大的過程,可以參考下面的一個時序圖,但是這個過程是和實(shí)際有點(diǎn)差別的,下面時序圖的有些過程是異步的,并不是都在同一個線程內(nèi)執(zhí)行,畫在一起是為了先有個整體的概念,后面會就幾個主要的過程再具體分析。
wakeup 亮屏的時序圖:
可以先抓個亮屏的systemtrace 來看一下,從下面的截圖可以看到亮屏的流程大致在304ms。
通過SystemTracek發(fā)現(xiàn)亮屏有以下幾個主要流程:
Screen on blocked/Screen turning on /PhoneWindowManager.mPowerKeyWakeLock /interceptKeyBeforeQueueing
setDisplayState/requestGlobalDisplayState/setDisplayBrightness/setLight
下面會分析各段的主要流程
2.1 Screen on blocked
從log 可以發(fā)現(xiàn)這個過程從 DisplayPowerController 的 setScreenState()->blockScreenOn() 到 unblockScreenOn().
Log:
這2個log 對應(yīng)的是 DisplayPowerController 的 blockScreenOn() 和 unblockScreenOn()的執(zhí)行.
DisplayPowerController.java
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() 會通過一系列的調(diào)用調(diào)用到 SystemUI 的KeyguardServiced.onScreenTurningOn().
其中 MSG_KEYGUARD_DRAWN_TIMEOUT 是5000ms,也就是SystenUI 如果處理任務(wù)超過了5S就會觸發(fā)超時機(jī)制,
直接調(diào)用 finishKeyguardDrawn() 來通知 WindowManagerService 來繼續(xù)完成窗口的繪制.
KeyguardService.java
@Override // Binder interface public void onScreenTurningOn(IKeyguardDrawnCallback callback) {Trace.beginSection("KeyguardService.mBinder#onScreenTurningOn");checkPermission();mKeyguardViewMediator.onScreenTurningOn(callback);mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_ON);Trace.endSection(); }其中主要是 KeyguardViewMediator 和 KeyguardLifecyclesDispatcher 都是使用Handler 發(fā)現(xiàn)message 來處理.
KeyguardViewMediator 最終通過 handleNotifyScreenTurningOn()
KeyguardLifecyclesDispatcher具體任務(wù)是通過ScreenLifecycle的實(shí)現(xiàn)類來完成.
其中 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() 的參數(shù) IKeyguardDrawnCallback callback 很重要,它是 PhoneWindowManager 內(nèi)部的實(shí)現(xiàn)了 DrawnListener 接口的實(shí)體類對象 mKeyguardDrawnCallback
final DrawnListener mKeyguardDrawnCallback = new DrawnListener() {@Overridepublic void onDrawn() {if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn.");mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);}};MSG_KEYGUARD_DRAWN_COMPLETE 會通過Handler 消息機(jī)制調(diào)用 PhoneWindowManager 的 finishKeyguardDrawn(),
finishKeyguardDrawn() 前面已經(jīng)提到過,就是等待 WMS 繼續(xù)處理窗口繪制相關(guān)的工作.
WindowManagerService.java
如果有需要繪制的窗口那么mWaitingForDrawn 的size肯定大于0,就會處理 checkDrawnWindowsLocked().
checkDrawnWindowsLocked()最終就是調(diào)用PhoneWindowManager的finishWindowsDrawn().
同時 WindowManagerService 處理繪制相關(guān)的任務(wù)也有一個超時機(jī)制,用來確保1000ms 后窗口繪制還沒有完成的時候也可以繼續(xù)執(zhí)行正常的流程.
超時機(jī)制的主要流程是:通過Handler的WAITING_FOR_DRAWN_TIMEOUT 消息來控制的,這個時間是1000ms.
當(dāng)窗口都繪制完成或者超過1S之后就會執(zhí)行Handler的ALL_WINDOWS_DRAWN 消息,這個消息會繼續(xù)回調(diào) PhoneWindowManager 的 Runnable mWindowManagerDrawCallback.run()
而這個Runnable 的主要工作就是繼續(xù)執(zhí)行 Handler 的 MSG_WINDOW_MANAGER_DRAWN_COMPLETE 消息來 執(zhí)行 PhoneWindowManager 的 finishWindowsDrawn().
finishWindowsDrawn() 下一步任務(wù)是調(diào)用 finishScreenTurningOn()
WMS 的 checkDrawnWindowsLocked 到 PhoneWindowManager 的finishScreenTurningOn 的流程:
checkDrawnWindowsLocked()->ALL_WINDOWS_DRAWN->PhoneWindowManager.mWindowManagerDrawCallback.run()
->finishScreenTurningOn()
這個ScreenOnListener listener 就是通過 DisplayPowerController 的內(nèi)部類 ScreenOnUnblocker mPendingScreenOnUnblocker.
后續(xù)就是通過 mPendingScreenOnUnblocker.onScreenOn() 發(fā)送 MSG_SCREEN_ON_UNBLOCKED 消息完成 unblockScreenOn()?
總結(jié)一下:
Screen on blocked 的主要過程就是通過DisplayPowerController.java PhoneWindowManager.java WindowManagerService.java 和SystemUI 來完成 screenTurningOn 流程.也就是鎖屏和其他窗口的繪制流程.
想要這個過程具體是卡在那里耗時,就打開 WindowManagerService 的 DEBUG_SCREEN_ON 開關(guān),可以通過 checkDrawnWindowsLocked() 的log看到這段時間主要是繪制那個窗口需要繪制.
WindowManagerService.java
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可以發(fā)現(xiàn)個過程明顯比 Screen on blocked 的158ms 要長的多,而且首尾的2個log表明她們不是在同一個線程里面執(zhí)行的.
這里首尾2個log 對應(yīng)的就是 PowerManagerService.wakeUpNoUpdateLocked()到logScreenOn(),而且要執(zhí)行時間超過200ms 才會打印log.
logScreenOn()主要調(diào)用流程:
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 的時候才能繼續(xù)執(zhí)行下一步的sendOnStateChangedWithWakelock()
2.2.2 PowerManagerService.updatePowerStateLocked() 中的有個for 循環(huán),其中的updateWakefulnessLocked(dirtyPhase1)為false 的時候才能執(zhí)行break 跳出for 循環(huán),繼續(xù)執(zhí)行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 里面對應(yīng)的這段這個比較簡單.
起點(diǎn)就是 PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyDown()-> mPowerKeyWakeLock.acquire().
終點(diǎn)就是: PhoneWindowManager.interceptKeyBeforeQueueing()->interceptPowerKeyUp()->
finishPowerKeyPress()->PowerManager$WakeLock.release()
2.4 requestGlobalDisplayState->setDisplayState?
SystemTrace 里面對應(yīng)的 requestGlobalDisplayState 這段其實(shí)是 DisplayManagerService.requestGlobalDisplayStateInternal()
SystemTrace 里面對應(yīng)的 setDisplayState 這段其實(shí)是 LocalDisplayAdapter$LocalDisplayDevice$1.setDisplayState()
requestGlobalDisplayStateInternal:
通過 SystemTrace 或者log 可以發(fā)現(xiàn) requestGlobalDisplayStateInternal() 是有多次執(zhí)行的.
主要流程是:
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次執(zhí)行requestGlobalDisplayState 后的 setDisplayBrightness和setLight時間主要耗時是setLight_native耗時,
也就是底層lcd 處理上層傳遞的亮度參數(shù)很耗時.
?
總結(jié)
以上是生活随笔為你收集整理的Android P wakeup 亮屏流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【单片机】C51中的定时/计数器介绍
- 下一篇: 纯CSS实现枫叶下落