从源码角度看Android系统Launcher在开机时的启动过程
Launcher是Android所有應用的入口,用來顯示系統中已經安裝的應用程序圖標。
Launcher本身也是一個App,一個提供桌面顯示的App,但它與普通App有如下不同:
-
Launcher是所有應用的入口,可以管理應用
-
Launcher是在Android系統啟動后就要顯示給用戶的應用
-
Launcher是頂部App,即任何應用返回后都是到Launcher,不能再繼續返回
Launcher啟動的入口是AMS的systemReady方法。
備注:本文是結合Android8.0的源碼看Android系統Launcher在開機時的啟動過程
1. startBootstrapServices啟動AMS
從前面的《從源碼角度看Android系統SystemServer進程啟動過程》一文中可知:在SystemServer的startBootstrapServices方法中已經啟動ActivityManagerService
代碼路徑:frameworks/base/services/java/com/android/server/SystemServer.java
深入到startBootstrapServices函數中:
private void startBootstrapServices() {...省略...//啟動服務ActivityManagerServicemActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);...省略...}2. startOtherServices中調用AMS的systemReady方法
然后又在SystemServer的startOtherServices方法中調用了AMS的systemReady方法
代碼路徑:frameworks/base/services/java/com/android/server/SystemServer.java
深入到startOtherServices函數中:
private void startOtherServices() {...省略...//調用ActivityManagerService的systemReadymActivityManagerService.systemReady(() -> {Slog.i(TAG, "Making services ready");traceBeginAndSlog("StartActivityManagerReadyPhase");mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);...省略...}3. AMS的systemReady方法
代碼路徑:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
深入到systemReady函數中:
public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {traceLog.traceBegin("PhaseActivityManagerReady");...省略...//啟動HomeActivity,即Launcher應用的桌面ActivitystartHomeActivityLocked(currentUserId, "systemReady");...省略... }4. AMS的startHomeActivityLocked方法
代碼路徑:frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
深入到startHomeActivityLocked函數中:
boolean startHomeActivityLocked(int userId, String reason) {//判斷工廠模式和mTopAction的值if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL&& mTopAction == null) { //注釋1return false;}//創建Launcher啟動所需要的IntentIntent intent = getHomeIntent(); //注釋2ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);if (aInfo != null) {intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));aInfo = new ActivityInfo(aInfo);aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);ProcessRecord app = getProcessRecordLocked(aInfo.processName,aInfo.applicationInfo.uid, true);if (app == null || app.instr == null) { //注釋3intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);final String myReason = reason + ":" + userId + ":" + resolvedUserId;// 啟動LaunchermActivityStarter.startHomeActivityLocked(intent, aInfo, myReason); //注釋4}} else {Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());}return true; }注釋解析:
-
注釋1處的mFactoryTest代表系統的運行模式,系統的運行模式分為三種:工廠模式、低級工廠模式和高級工廠模式。mTopAction用來描述第一個被啟動Activity組件的Action,默認值為Intent.ACTION_MAIN。所以注釋1處的意思就是mFactoryTest 等于FactoryTest.FACTORY_TEST_LOW_LEVEL且mTopAction等于null時,直接返回false
-
注釋2處調用了getHomeIntent方法。具體實現如下:
Intent getHomeIntent() {Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);intent.setComponent(mTopComponent);intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {intent.addCategory(Intent.CATEGORY_HOME);}return intent;}
創建intent對象,并將mTopAction和mTopData傳入,mTopAction的值為Intent.ACTION_MAIN,并且如果系統運行模式不是低級工廠模式,則將intent的Category設置為Intent.CATEGORY_HOME,并返回intent
- 注釋3處判斷如果Action是Intent.ACTION_MAIN,Category是Intent.CATEGORY_HOME的應用程序是否啟動,如果沒有啟動,則走注釋4處的啟動邏輯
這里看下Launcher的AndroidManifest文件:
代碼路徑:packages/apps/Launcher3/AndroidManifest.xml
從上面可以看到intent-filter中設置了android.intent.action.MAIN和android:name="android.intent.category.HOME,這樣com.android.launcher3.Launcher的Activity就成為了主Activity。
- 注釋4處是如果Launcher沒有啟動,就會調用ActivityStarter的startHomeActivityLocked方法來啟動Launcher
5. ActivityStarter的startHomeActivityLocked方法
代碼路徑:frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
深入到startHomeActivityLocked函數中:
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {//將Launcher的堆棧移動到頂部mSupervisor.moveHomeStackTaskToTop(reason); //注釋1mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent, //注釋2null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);if (mSupervisor.inResumeTopActivity) {// If we are in resume section already, home activity will be initialized, but not// resumed (to avoid recursive resume) and will stay that way until something pokes it// again. We need to schedule another resume.mSupervisor.scheduleResumeTopActivities();} }注釋解析:
-
注釋1處將Launcher的堆棧移到頂部,這也是為什么Launcher總是在所有APP頂部的原因
-
注釋2調用startActivityLocked方法啟動Home Activity。startActivityLocked是Android系統啟動所有Activity的入口,后面會專門寫文闡述Activity的啟動過程
最終會進入Launcher的onCreate方法中,到此Launcher就啟動完成。
6. Launcher啟動過程時序圖
非常感謝您的耐心閱讀,希望我的文章對您有幫助。歡迎點評、轉發或分享給您的朋友或技術群。
總結
以上是生活随笔為你收集整理的从源码角度看Android系统Launcher在开机时的启动过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 从源码角度看Android系统Syste
- 下一篇: android sina oauth2.