日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android P wakeup 亮屏流程

發布時間:2023/12/20 Android 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 來繼續完成窗口的繪制.

@Override public 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 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的實現類來完成.

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() {@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

@Override public 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 處理上層傳遞的亮度參數很耗時.

?

總結

以上是生活随笔為你收集整理的Android P wakeup 亮屏流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。