从源码角度看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启动过程时序图

非常感谢您的耐心阅读,希望我的文章对您有帮助。欢迎点评、转发或分享给您的朋友或技术群。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部