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堆棧信息
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:
這2個log 對應的是 DisplayPowerController 的 blockScreenOn() 和 unblockScreenOn()的執行.
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() 會通過一系列的調用調用到 SystemUI 的KeyguardServiced.onScreenTurningOn().
其中 MSG_KEYGUARD_DRAWN_TIMEOUT 是5000ms,也就是SystenUI 如果處理任務超過了5S就會觸發超時機制,
直接調用 finishKeyguardDrawn() 來通知 WindowManagerService 來繼續完成窗口的繪制.
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 發現message 來處理.
KeyguardViewMediator 最終通過 handleNotifyScreenTurningOn()
KeyguardLifecyclesDispatcher具體任務是通過ScreenLifecycle的實現類來完成.
其中 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() {@Overridepublic 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
如果有需要繪制的窗口那么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()
這個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
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()
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 處理上層傳遞的亮度參數很耗時.
?
總結
以上是生活随笔為你收集整理的Android P wakeup 亮屏流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【单片机】C51中的定时/计数器介绍
- 下一篇: Android控制状态栏颜色的两种方式