我的应用是什么时候启动的

346 阅读3分钟

前言

本文主要从Android系统开机启动角度解答“我的应用是什么时候启动的”

Android系统开机

我们先看下谷歌官方的图,我们今天的重点就是讲讲怎么应用在开机过程中如何启动的。

androidsystem.png

从AMS说起

我们知道System server 会启动很多系统服务,其中AMS是android系统服务中很重要的一个,我们今天的主角就是它。

下面代码截取自system server的run方法,里面按照重要程度和先后顺序,执行了三个启动系统服务的方法,


// Start services.

try {

traceBeginAndSlog("StartServices");

startBootstrapServices(); // AMS 构造函数在这里执行

startCoreServices();

startOtherServices(); // AMS 的system Ready 在这里执行

SystemServerInitThreadPool.shutdown();

} catch (Throwable ex) {

Slog.e("System", "******************************************");

Slog.e("System", "************ Failure starting system services", ex);

throw ex;

} finally {

traceEnd();

}

我们重点关注的就是AMS的systemReady方法,应用的启动也是从这里开始。

AMS.systemReady

最先启动的应用,AMS的systemReady函数中,systemserver传入的callback中包含2个应用程序的启动,我们看下代码:

if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
    traceBeginAndSlog("StartCarServiceHelperService");
    mSystemServiceManager.startService(CAR_SERVICE_HELPER_SERVICE_CLASS);
    traceEnd();
}

traceBeginAndSlog("StartSystemUI");
try {
    startSystemUi(context, windowManagerF);
} catch (Throwable e) {
    reportWtf("starting System UI", e);
}
traceEnd();

如果是android 车载版本就会启动carservice app,还会启动systemui app,毫无疑问,我们目前看到的这是最早启动的两个应用。 接下来会启动常驻应用,也就是所谓的persistent app,当然在目前这个阶段,并不是所有的常驻应用都会被启动,再没有user unlock之前,我们启动的是包含DIRECT_BOOT_AWARE flag的应用。

// Only start up encryption-aware persistent apps; once user is
// unlocked we'll come back around and start unaware apps
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);

第一个launcher

Android 系统启动的第一个Activity也是第一个桌面是com.android.settings/.FallbackHome,

重点是这个桌面的优先级是-1000,这也为了后面的桌面出现铺平了道路。


<activity android:name=".FallbackHome"

android:excludeFromRecents="true"

android:label=""

android:screenOrientation="nosensor"

android:taskAffinity="com.android.settings.FallbackHome"

android:theme="@style/FallbackHome">

<intent-filter android:priority="-1000">

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.HOME" />

<category android:name="android.intent.category.DEFAULT" />

</intent-filter>

</activity>

启动桌面调用函数如下:

startHomeActivityLocked(currentUserId, "systemReady");

流程简单来说就是在AMS systemReady函数中去启动桌面的时候,这时候还没有user unlcok,在derectboot模式下查询到的是FallbackHome,这时候我们就把他拉起来了,如果开机动画已经结束,这时候桌面上显示的是“android 正在启动”,可以参考下面时序图

boot_fallback_launcher.png

真正的home

真正的home启动其实比较复杂,这里面涉及到复杂的开机流程,FallbackHome是源头,FallbackHome activity启动之后,在FallbackHome的OnResume阶段,会调用到ActivityThread类的handleResumeActivity()方法,handleResumeActivity()方法会往消息队列中增加一个IdelHandler。


Looper.myQueue().addIdleHandler(new Idler());

settings 消息队列空闲时会执行这个idleHandler,最终会调用到AMS端,执行checkFinishBootingLocked函数,触发后续的开机流程。

这个流程比较复杂,会执行关闭开机动画,user unlock,启动桌面,启动非derect boot flag常驻应用,发送开机广播。

这部分比较复杂,直接上图吧:

Home启动流程final.png

启动顺序总结

  • CarService和SystemUI
  • Derect Boot Flag 常驻应用,如settings,android:directBootAware="true",android:persistent="true"
  • FallbackHome,“假桌面”
  • 桌面,非derect boot flag常驻应用,接收开机广播启动的应用

在上面的顺序中,最后一条的内容里面,这些应用启动时间比较相近,启动的也比较多,通常这个阶段系统负载会很高,后续有时间讲一下开机自启动应用治理。