Android 启动的第三阶段是 Launcher 的启动,也就是最终会看到的 Android 桌面的启动。在之前第二阶段 Android启动之Android Framework启动中, Zygote, ServiceManager, ActivityManagerService 和 PackageManagerService 等系统服务已经启动起来,接下来的 Launcher 启动过程就会看到它们的身影。由于 Launcher 也是应用程序,因此其他应用程序的启动过程基本类似。
ActivityManagerService 在完成服务注册等一系列初始化过程后,其 main 方法中会调用 systemReady 方法,开始以下过程:

ActivityStackSupervisor::resumeTopActivitiesLocked()ActivityStackSupervisor::resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions)ActivityStack::resumeTopActivityLocked(ActivityRecord prev, Bundle options)ActivityStackSupervisor::resumeHomeActivity(ActivityRecord prev)ActivityManagerService::startHomeActivityLocked(int userId)

需要注意的是 Launcher 启动过程中, resumeTopActivityLocked 方法会进入两次,第一次由于任务栈中还没有 ActivityRecord,所以会调用 resumeHomeActivity 方法。
经历以上5个方法调用,最后进入 ActivityManagerService 的 startHomeActivityLocked 方法开始 Launcher 启动历程。首先通过 getHomeIntent 方法获得启动 Launcher 的 intent 信息,然后调用 resolveActivityInfo 方法通过 PackageManagerService 获得 Launcher 的 Activity 描述信息 aInfo。如下所示:

代码路径:frameworks/base/services/java/com/android/server/am/ActivityManagerService.javaboolean startHomeActivityLocked(int userId) {    ......    Intent intent = getHomeIntent();    ActivityInfo aInfo =            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);    if (aInfo != null) {        intent.setComponent(new ComponentName(                    aInfo.applicationInfo.packageName, aInfo.name));        // Don't do this if the home app is currently being        // instrumented.        aInfo = new ActivityInfo(aInfo);        aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);        ProcessRecord app = getProcessRecordLocked(aInfo.processName,                    aInfo.applicationInfo.uid, true);        if (app == null || app.instrumentationClass == null) {            intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);            mStackSupervisor.startHomeActivity(intent, aInfo);        }    }    return true;}Intent getHomeIntent() {    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);    intent.setComponent(mTopComponent);    if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {            intent.addCategory(Intent.CATEGORY_HOME);    }    return intent;}

从 getHomeIntent 方法的实现可知,理论上通过在应用程序的 AndroidManifest.xml 文件中添加 Intent.CATEGORY_HOME 的 Category 属性,应用就可以作为 Launcher 来启动。

获得参数 intent 和 aInfo 后,接下来调用 ActivityStackSupervisor 的 startHomeActivity 方法开始以下历程:

ActivityStackSupervisor::startHomeActivity(Intent intent, ActivityInfo aInfo)ActivityStackSupervisor::startActivityLocked(...)ActivityStackSupervisor::startActivityUncheckedLocked(...)ActivityStack::startActivityLocked(...)ActivityStackSupervisor::resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions)ActivityStack::resumeTopActivityLocked(ActivityRecord prev, Bundle options)ActivityStackSupervisor::startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig)

因为在上述步骤2中将会生成 Launcher 的 ActivityRecord 并添加到任务栈中,所以第二次进入 resumeTopActivityLocked 时,会调用 startSpecificActivityLocked 方法来启动 Launcher 的 Activity。由于 Launcher 是第一次运行,因此还没有创建好 Launcher 进程。在启动 Launcher 之前还需要创建一个新的进程,如下所示:

Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",                    app.processName, uid, uid, gids, debugFlags, mountExternal,                    app.info.targetSdkVersion, app.info.seinfo, null);

通过 Process 的 start 方法请求 Zygote 创建进程后,在新进程中开始执行 ActivityThread 的 main 方法。

代码路径:frameworks/base/core/java/android/app/ActivityThread.javapublic static void main(String[] args) {    ......    Looper.prepareMainLooper();    ActivityThread thread = new ActivityThread();    thread.attach(false);    if (sMainThreadHandler == null) {        sMainThreadHandler = thread.getHandler();    }    AsyncTask.init();    if (false) {        Looper.myLooper().setMessageLogging(new                LogPrinter(Log.DEBUG, "ActivityThread"));    }    Looper.loop();    throw new RuntimeException("Main thread loop unexpectedly exited");}

main 方法中有很多值得说的知识点,但和 Launcher 启动有关的是执行 ActivityThread 的 attach 方法,该方法会调用代理类 ActivityManagerProxy 的 attachApplication 方法通知 ActivityManagerService 新进程已经启动成功,可以开始执行应用程序。传入的参数 mAppThread 是一个 ApplicationThread 类的 Binder 对象,用于之后进程间的通信。

Launcher 运行在新创建的进程,而 ActivityManagerService 运行在 system_server 进程,它们之间需要使用 Binder 来进行通信。

通过 Binder 进程间通信机制,ActivityManagerService 收到消息后,其 attachApplication 方法会被调用,接下来执行以下流程:

ActivityManagerService::attachApplicationLocked(IApplicationThread thread, int pid)ApplicationThreadProxy::bindApplication(...)

通过之前传过来的 mAppThread 对象,调用代理类 ApplicationThreadProxy 的 bindApplication 方法。通过 Binder 通信,在 Launcher 进程中加载 Application 类并执行 onCreate 方法。这也说明,每个虚拟机进程中都会有一个 Application 实例。
接下来继续启动 Activity:

ActivityStackSupervisor::attachApplicationLocked(ProcessRecord app, boolean headless)ActivityStackSupervisor::realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig)ApplicationThreadProxy::scheduleLaunchActivity(...)

通过之前传过来的 mAppThread 对象,调用代理类 ApplicationThreadProxy 的 scheduleLaunchActivity 方法。通过 Binder 通信,最终会执行 ActivityThread 中的 handleLaunchActivity 方法,如下所示:

代码路径:frameworks/base/core/java/android/app/ActivityThread.javaprivate void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {    ......    Activity a = performLaunchActivity(r, customIntent);    if (a != null) {        r.createdConfig = new Configuration(mConfiguration);        Bundle oldState = r.state;        handleResumeActivity(r.token, false, r.isForward,                !r.activity.mFinished && !r.startsNotResumed);        ......    }}

handleLaunchActivity 中会加载 Launcher 应用程序的 class 文件,并调用 Activity 的 onCreate, onStart, onResume 等生命周期回调方法。
Launcher Activity 的 onCreate 方法中会初始化一个 Load 线程,用于加载所有的 workspace 数据以及应用程序图标。过程如下所示:

LauncherModel::startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags)LoaderTask::run()LauncherModel::loadAndBindWorkspace()LauncherModel::loadAndBindAllApps()

loadAndBindWorkspace 主要可分为 load 和 bind 两个阶段,load 阶段由 loadWorkspace 方法完成,主要是遍历数据库,生成 FolderInfo, LauncherAppWidgetInfo, ShortcutInfo 对象。bind 阶段由 bindWorkspace 方法完成,主要将之前得到的对象与 workspace 进行绑定。
loadAndBindAllApps 也分为 load 和 bind 两个阶段,load 阶段主要通过 PackageManagerService 提供的服务查询所有应用程序的 AppInfo 数据,bind 阶段则根据 AppInfo 在桌面显示应用程序。
至此,Android 启动流程梳理完毕。由于篇幅原因,中间有些内容点到为止,后续文章再继续完善。

参考资料:
1. Android系统默认Home应用程序(Launcher)的启动过程源代码分析
2. Launcher3的启动流程(一)
3. Launcher3的启动流程(二)

更多相关文章

  1. [原创] Android(安卓)Activity onNewIntent() 详解
  2. 源码解析Android中AsyncTask的工作原理
  3. Android(安卓)UI线程和非UI线程
  4. Android(安卓)NDK开发实例教程
  5. 转:Android(安卓)AsyncTask
  6. Android开机启动流程
  7. Android(安卓)LineaerLayout中layout_margin失效不起作用的解决
  8. Android(安卓)LayoutInflater
  9. android移动数据上网的开关的实现

随机推荐

  1. Android(安卓)INSTALL_FAILED_INSUFFICIE
  2. Android(安卓)emoji表情处理
  3. Android(安卓)ProgressBar设置转圈样式
  4. Android简单实现Socket通信,客户端连接服
  5. Android(安卓)RatingBar:评价条控件
  6. Android(安卓)Studio 1.5.1 JNI 编程
  7. WindowInsets 在View下的的分发(一)
  8. Android开发之自定义相机设定照片和预览
  9. Retrofit2 使用FastJson作为Converter
  10. Android的开发之&强大的adb命令和adb she