Android6.0亮屏流程之Keyguard Window繪製
亮滅屏問題一直是Android模組最常見的問題之一。
由於問題出現問題的地方涉及到公司程式碼,我這裡僅僅只作原生程式碼模組的分析
其實在看過另外一篇關於android亮屏流程的文章就會發現,影響亮屏快慢的因素大致有三種:1.設定背光流程出問題了,導致螢幕黑屏,2.window繪製時間過長,導致螢幕block時間過長;3.底層surfacecontroller準備時間過長。
而根據遇到的亮屏慢的問題,基本上都是由於window繪製時間過長,導致螢幕亮屏慢
最近處理的幾個亮屏慢的問題,其中關鍵log資訊基本都是:
10-28 09:02:59.002 1393 1462 I DisplayPowerController: Blocking screen on until initial contents have been drawn.
10-28 09:03:05.020 1393 1462 I DisplayPowerController: Unblocked screen on after 6018 ms
由於在android亮屏流程中大致描述的亮屏所走的流程點,但是僅僅只能作為一個粗略的點做參考,但是看到上面的兩條資訊,我們可以去追溯一下程式碼流程:
在每一次螢幕電源狀態發生改變的都會呼叫的到DisplayPowerController中的updatePowerState方法,在該方法中如果螢幕狀態發生改變的話,會去呼叫到
在DisplayPowerController.java中的setScreenState()方法中,有程式碼:
[java] view plain copy
- if (mPowerState.getColorFadeLevel() ==
- blockScreenOn();
- } else {
- unblockScreenOn();
- }
- mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
- }
- // Return true if the screen isn't blocked.
- return mPendingScreenOnUnblocker == null;
首先會呼叫到 blockScreenOn方法,先看看該方法以及後面要呼叫到的unblockScreenOn的方法
[java] view plain copy
- private void blockScreenOn() {
- if (mPendingScreenOnUnblocker == null) {
- Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
- mPendingScreenOnUnblocker = new ScreenOnUnblocker();
- mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
- Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
- }
- }
- private void unblockScreenOn() {
- if (mPendingScreenOnUnblocke != 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);
- }
- }
在blockScreenOn函式中其實就是建立了一個mPendingScreenOnUnblocker 物件,當該物件為空時,mPendingScreenOnUnblocker == null;返回值才為true。animateScreenStateChange才能繼續往下執行下去。
亮屏過程中繪製window過程是通過mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker); 呼叫到PhoneWindowManager中的screenTurningOn(),
[java] view plain copy
- private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
- @Override
- public void onScreenOn() {
- Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
- }
- }
這裡用一個圖來詳細描述
可以看到 整個過程呼叫的點較為混亂,這裡只能簡單描述一下其呼叫過程當PowerManagerService發出的wakeup請求到DisplayPowerController這邊,在DisplayPowerConrtoller中setScreenState方法中會呼叫到PhoneWindowManager模組的screenTurningOn方法去通過window繪製螢幕。
由於在滅屏之後亮屏首先現實的介面應該是鎖屏介面,所以亮屏首先應該去繪製keyguard,並且keyguard經常會出現超時,當出現keyguard超時時會列印:
WindowManager:Keyguard drawn timeout. Setting mKeyguardDrawComplete
當出現上述列印,便可以確定時keyguard模組繪製鎖屏超時,需要鎖屏的人去確認超時原因。鎖屏超時時間最長也只有2秒時間。因為
[java] view plain copy- if (mKeyguardDelegate != null) {
- mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
- mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
- mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
- } else {
當mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);正常執行完成的情況下會呼叫到finishKeyguardDrawn,當未能正常執行,超過1秒還未完成便會發送訊息MSG_KEYGUARD_DRAWN_TIMEOUT強制執行finishKeyguardDrawn,
在finishKeyguardDrawn完成後會檢查所有的亮屏後所依賴的window是否都繪製完成,在mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,WAITING_FOR_DRAWN_TIMEOUT);//WAITING_FOR_DRAWN_TIMEOUT = 1000 中會去檢查window繪製,如上,當超過1秒後,會自動release等待的window,然後正常亮屏。