關于Android9.0開機黑屏一段時間才加載launcher界面的解決方法[轉載]

原文路徑:關于Android9.0開機黑屏一段時間才加載launcher界面的解決方法

前言

最近做9.0項目,發現開機的時候,會先顯示壁紙一段時間,再去加載launcher,如果壁紙是黑色的,則會導致開機動畫結束后,顯示黑屏一段時間,再看到launcher。

調試抓log

遇到問題,當然就是看開機日志了。一番折騰,找到比較有用的log如下:

20:10:50.453   769  1910 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.example.user.myapplication/.FallbackHome} from uid 0 on display 0

20:10:54.376  2029  2029 D FallbackHome: User unlocked and real home found; let's go!
 
20:10:54.466   769  2207 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.setupwizard/.SetupWizardActivity} from uid 0 on display 0

原來在啟動launcher前,系統先啟動了一個FallbackHome的界面,接著再啟動launcher,這中間差了4秒,這跟現象對上了,即先顯示一段時間的壁紙,再啟動launcher。

FallbackHome

那FallbackHome是什么呢?
FallbackHome是原生setting的一個activity,且配置了DirectBoot mode。launcher啟動的時候會先啟動到這個界面,用戶解鎖后,才會調用finish,結束該界面,從而進入到真正的launcher界面。
若未解鎖就等待ACTION_USER_UNLOCKED廣播后再去啟動Launcher。非DirectBoot模式下的launcher耗時4s就是在等待finishBooting后的系統廣播ACTION_USER_UNLOCKED。
FallbackHome就是應DirectBoot功能而新增的一個頁面,具體DirectBoot功能不在這里贅述,大家可自行了解。

如何解決黑屏

那如何解決掉處于DirectBoot模式下的黑屏呢?
嘗試了多種方案,最終比較完美的方案如下:
通過延長開機動畫,等進入到非DirectBoot模式,再結束開機動畫。
但屏蔽掉關閉開機動畫以及開機動畫服務結束檢測相關代碼:

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java 
private void performEnableScreen()方法:
.....
    /* 這里屏蔽掉一些代碼
        if (!mBootAnimationStopped) {
            Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
            // stop boot animation
            // formerly we would just kill the process, but we now ask it to exit so it
            // can choose where to stop the animation.
            SystemProperties.set("service.bootanim.exit", "1");
            mBootAnimationStopped = true;
        }

        if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) {
            if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: Waiting for anim complete");
            return;
        }

        try {
            IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
            if (surfaceFlinger != null) {
                Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
                Parcel data = Parcel.obtain();
                data.writeInterfaceToken("android.ui.ISurfaceComposer");
                surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
                        data, null, 0);
                data.recycle();
            }
        } catch (RemoteException ex) {
            Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
        }
    */
    ....
}

這里屏蔽了系統結束開機動畫的代碼,那么得找一個地方去結束開機動畫,從而啟動launcher。
FallbackHome具備home屬性,launcher也必帶home屬性。那么我們可以通過判斷系統所啟動的應用為Home應用但又不是FallbackHome時,就可以結束開機動畫了。
在如下地方去結束開機動畫:

frameworks/base/services/core/java/com/android/server/am/ActivityRecord.java 
private void reportLaunchTimeLocked(final long curTime) {
    ....
    //mnq, 20190819, @ {
    //Log.d(TAG, "reportLaunchTimeLocked......" + shortComponentName + " intent" + intent);
    if (isHomeIntent(intent) && shortComponentName != null && !shortComponentName.contains("FallbackHome")) {
        SystemProperties.set("service.bootanim.exit", "1");
        Log.d(TAG, "reportLaunchTimeLocked:real home....." + shortComponentName);
    }
    //mnq, 20190819, @}
}

如此更改后,開機后,發現系統不會有黑屏的現象,且開機動畫結束后就進入到了launcher界面了。
MTK平臺上,也會有此問題,不夠它會在界面上有一個友好的提示:

Phone is starting....

告知用戶,此時機器正在啟動中。
這個其實一樣,也可以用這個辦法去處理。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容