Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-08-13: 说说你对app(或进程)启动流程的理解? #11

Open
liyilin-jack opened this issue Aug 13, 2019 · 7 comments
Open

Comments

@liyilin-jack
Copy link

No description provided.

@MicroKibaco MicroKibaco changed the title 2019-08-13: 说说你对app(或进程)启动流程的理解 2019-08-13: 说说你对app(或进程)启动流程的理解? Aug 13, 2019
@MicroKibaco
Copy link
Owner

MicroKibaco commented Aug 13, 2019

App 启动流程

  App启动流程 包括 bootloader , Kernel , init,zygotesystem_server.不过bootloader , Kernel 已经偏操作系统内核和驱动方面了,不做细讲,这里从init开始带大家深入理解App启动流程和顺序.

结构图

  • 借鉴 代码GG|陆晓明流程图

init

  init是Linux用户的第一个进程,进程号是1,说这个主要目的是引入我们话匣子zygote,init是如何创建zygote以及init属性服务是如何工作的呢?

  代码很复杂,我也看不懂,你只要知道是通过init.rc解析,然后执行各个阶段的动作,最后创建zygote就行了,当然还要处理socket属性服务方面的事情,因为涉及很多和Linux系统相关的知识.作为应用开发就没必要太关注这个了.

zygote

  当我上面没说,直接跳到zygote,zygote中文意思是受精卵,他是Android系统牵动Java世界的纽带.而system_server人如其名,系统中重要的server都会驻留在Java中.

  zygotesystem_server这两个进程分别是Java世界的半边天,任何进程的死亡,都会导致Java世界的Crash.

  zygote最初名字是android_process,这个名字是Android.mk文件被指定的,它本身就是个Native程序,和内核和驱动均无关.

  我们不需要深究太多,只要了解一点,Zygote觉的自己工作压力太大,于是通过startSystemServer分裂system_server作为Java的世界服务.zygote被命名为受精卵一点都不过分,如果支持中文编码其实更适合盘古_女娲

  

system_server

   ZygoteInt 调用 startSystemServer 创建 system_server,system_server 通过 hsp 方法完成自己的使命,并抛出异常,最终调用SystemServer 引入 main 方法,main 方法加载 libandroid_server.so 并调用 nativeinit1函数,init1函数通过JNI调用init2函数,init2函数创建一个线程,用于加载各种service,init1函数最终加入Binder通信系统

结构图

  • 借鉴 邓凡平 流程图

参考资源

1. 深入理解 Android
2. App系统启动流程分析
3. App 启动过程(含 Activity 启动过程) | 安卓 offer 收割基

@liu1813565583
Copy link
Contributor

App的启动方式:
冷启动:当启动应用时,后台没有该应用的进程。这是系统会创建一个新的进程分配给该应用。这是app的冷启动。冷启动因为系统会分配一个新的进程给app,此时的app会创建Applocation,然后才回去创建MainActivity,最后显示在界面上。

热启动:当启动应用的时候,后台已经存在该应用的进程了,(列:按back和home应用虽然会退出但是应用的进程仍然在后台运行,可以进入任务列表查看)这个是热启动,因为热启动不会创建进程。所以app不会创建Applocation,只会初始化MainActivity。一个应用从创建到销毁只会执行一次Applocation。

应用的启动步骤:

(1) Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity

(2) ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态

(3) Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行

(4) ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信

(5) ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了

应用启动流程涉及到的类和对象:

(1) Launcher:Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity,实现了点击、长按等回调接口,来接收用户的输入。

(2) ActivityManagerServices:简称AMS,服务端对象,负责系统中所有Activity的生命周期。

(3) ActivityThread:App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作

(4) ApplicationThread:用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。

(5) ApplicationThreadProxy:是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。

(6) Instrumentation:每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。

(7) ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

(8) ActivityRecord:ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。

(9) TaskRecord:AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。

App启动白屏或黑屏的原因:是因为已进入到Activity,但是未加载到布局文件,就先显示来windows窗口的背景。黑屏/白屏就是显示的windows背景(这个就是theme的设置)

App启动白屏或黑屏解决方案:

(1) 为Theme设置背景图(会给人一种快速加载的感觉)

<stylename="Theme.AppStartLoad"parent="android:Theme">

<itemname="android:windowBackground">@drawable/ipod_bg

<itemname="android:windowNoTitle">true

</style>

(2) 为Theme设置透明属性(会给人较慢加载出来感觉)

<stylename="Theme.AppStartLoadTranslucent"parent="android:Theme">

<itemname="android:windowIsTranslucent">true

<itemname="android:windowNoTitle">true

</style>

App的启动优化:

(1) Application的创建过程中尽量少的进行耗时操作

(2) 如果用到SharePreference,尽量在异步线程中操作

(3) 减少布局的层次,并且生命周期回调的方法中尽量减少耗时的操作

@chengying1216
Copy link

APP启动在项目中碰到过黑白屏的问题

为什么我的 APP 启动会白屏或者黑屏

有时候我们会发现,我们在启动我们自己的 APP 的时候,总是有那么点时间是白屏(黑屏),经过了白屏(黑屏)后才会进入我们的 APP。那么这是为什么呢?

有很多的初始化放到了 Application 中去完成了,那么这个时候刚打开程序的时候就会有个耗时,就会出现白屏的效果。

所以这里程序加载有个顺序,当打开一个 Activity 的时候,并且这个 Activity 所属的 Application 还没有运行,系统会首先为这个 Activity 创建一个进程,创建进程的时候就会调用 Application 的 onCreate 方法。进程的创建和 onCreate 内部的初始化是需要时间的,如果这个时候过长,没有任何反应的话,那么对于用户来说是不不知道的,用户还以为自己没有点到呢,所以很显然是不可能在原页面等待加载的,那么这个时候就有了 StartingWindow(PerviewWindow)的出现,StartingWindow 出现在应用程序进程创建并且初始化完成之前,是个临时的窗口,对应的 WindowType是 TYPE_APPLICATION_STARTING 作用就是告诉用户,系统已经收到我们的操作了,正在对程序进行初始化,只要初始化完毕后就会移除这个窗口。

所以其实我们看到的白屏或者黑屏就是 StartingWindow,那么为什么是白色或者黑色呢?我们一般都会给我们的 Application 和 Activity 设置 Theme,系统就会根据我们所设置的 Theme 来决定 StartingWindow 的颜色。我们都知道 Window 布局的顶层是 DecorView,而 StaringWindow 显示的是一个空的 DecorView,只是这个 DecorView 会应用我们的这个 Activity 所指定的 Theme。我们默认的 Theme 是 @android:style/Theme.Light 的话,这个时候就会产生白屏了。黑屏就是应用了 @android:style/Theme.Black,好了到这里我们就彻底明白为什么会出现白屏或者黑屏了。

App启动白屏或黑屏解决方案:

(1) 为Theme设置背景图(会给人一种快速加载的感觉)

<stylename="Theme.AppStartLoad"parent="android:Theme">

<itemname="android:windowBackground">@drawable/ipod_bg

<itemname="android:windowNoTitle">true

</style> (2) 为Theme设置透明属性(会给人较慢加载出来感觉)

<stylename="Theme.AppStartLoadTranslucent"parent="android:Theme">

<itemname="android:windowIsTranslucent">true

<itemname="android:windowNoTitle">true

</style> App的启动优化:

(1) Application的创建过程中尽量少的进行耗时操作

(2) 如果用到SharePreference,尽量在异步线程中操作

(3) 减少布局的层次,并且生命周期回调的方法中尽量减少耗时的操作

@pioneerz
Copy link

app的启动流程分析:https://www.jianshu.com/p/28281b54d318

@gys0000
Copy link

gys0000 commented Aug 13, 2019

首先放上我参考的文章,感觉写的不错。Android - Activity 启动过程
我先说一下我理解的一个应用启动的大致流程。
第一步我们点击桌面上一个应用图标,这个时候管理者会向系统服务进程发送一个指令:我要打开一个activity;第二步既然要打开activity,总要有个新的进程装载吧,那么系统服务向最牛的进程,算是系统进程吧,发送创建A进程的请求,这个时候系统主进程会进行创建A进程的工作,先判断要创建的A进程是否存在,然后确定是否要创建A进程;第三步创建好A进程之后,A进程向系统服务进程说,我已经被创建好了,你可以给我发送我运行需要的东西了,然后系统服务进程就会向A进程发送指令,告诉A进程需要创建Applicationactivity等一系列操作。
上面一系列啰嗦的叙述,其中系统服务进程是system_server进程,最牛的系统主进程是Zygote进程,创建进程的操作是fock操作,判断进程的唯一性是查看ActivityManagerService中有没有A进程的ProcessRecord (可以理解为每个进程的uid+process)信息,创建A进程的同时在A进程中创建了ActivityThread;进程A中的ActivityThreadsystem_server进程的ActivityManagerService发送A进程创建好的指令,并把A进程中的ApplicationThread发给ActivityManagerService,然后system_server进程的ActivityManagerService通过ApplicationThreadProxy这个代理与进程中的ApplicationThread沟通,进一步在A进程中创建applicationactivity

这过程太复杂了,里边涉及了好多的点。只能大致的说一下,我再继续研究一下,有新的发现和想法再补充上来

@ArtarisCN
Copy link

  1. 点击图标后Launcher进程会通过Binder机制向AMS发起打开Activity的请求【IPC->Binder】
  2. AMS会通过ActivityStarter处理Intent和Flag(启动模式相关的内容),然后通过Socket通知zygote进程【IPC->Socket】
  3. zygote进程会进行孵化(虚拟机和资源的复制),然后fork出新进程
  4. 然后zygote进程会通过invokeDynamicMain()方法调用到ActivityThread的main方法【ActivityThread】
    public static void main(String[] args) {
        // 1. mainLooper
        Looper.prepareMainLooper();
        // 2. 创建ActivityThread,执行attach
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        // 3. Handler
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        // 4. loop()
        Looper.loop();
    }
    
  5. main()中关于Handler相关的工作是:主线程Looper和Handler的创建、开启主线程Looper的消息循环
  6. main()另一工作就是创建ActivityThread对象,执行attach方法。【Application、ContentProvider】
    1. 先通过AMS执行bindApplication方法
    2. 内部会创建属于Application的ContextImpl对象,并且创建Application对象,建立两者的联系
    3. 创建ContentProvider,执行其onCreate()方法,并进行发布相关操作(前提是该app有ContentProvider)
    4. 执行Application的onCreate()方法

  • 进程间通信IPC的Binder机制有哪些应用的场景?
    • Binder 是基于 C/S 架构的
  • IPC中Socket方式有哪些应用场景?
    *
  • Application的Context上下文对象是在哪里初始化的?
    • ActivityThread---handleBindApplication()(初始化)
    • LoadedApk.makeApplication()
    • Instrumentation.newApplication(Class,Context)
      ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
    • Application.attach()
    • Application.attachBaseContext()
  • ContentProvider是在哪里创建、初始化和发布的?
    • ActivityManagerService---attachApplicationLocked()(创建)AppBindData
    • ApplicationThread---bindApplication()
    • ActivityThread---handleBindApplication()(初始化)
    • ActivityThread---installContentProviders()
    • ActivityThread---installProvider()
    • ActivityManagerService---publishContentProviders()(发布)
  • ContentProvider的onCreate()和Application的onCreate()方法哪个先执行?
    • ContentProvider的onCreate()

@TrampcR
Copy link

TrampcR commented Sep 10, 2019

App 启动过程

一、整体了解

1、ActivityManagerService

简称 AMS,服务端对象,负责管理 Activity 生命周期。

2、ActivityThread

App 的入口,启动 App 后,会调用 ActivityThread.main(),开启 Looper、MessageQueue,与 ActivityManagerService 配合完成对 Activity 的管理。

3、ApplicationThread

实现 ActivityManagerService 与 ActivityThread 之间的交互,在 ActivityManagerService 需要管理 Application 中 Activity 的生命周期时,通过 ApplicationThread 代理对象和 ActivityThread 通信。

4、ApplicationThreadProxy

ApplicationThread 在服务端的代理对象,负责和客户端的 ApplicationThread 进行通信。

5、Instrumentation

每个应用程序只有一个 Instrumentation 对象,每个 Activity 内都有一个对该对象的引用,可以理解为应用进程的管家,ActivityThread 需要创建或者暂停某个 Activity 时,都需要通过 Instrumentation 进行操作。

6、ActivityStack

Activity 在 AMS 中的栈管理,用来记录已经启动的 Activity 的先后顺序、状态信息等,通过 ActivityStack 决定是否需要启动新的进程。

7、ActivityRecord

ActivityStack 管理的对象,每个 Activity 在 AMS 对应一个 ActivityRecord,用来记录 Activity 的状态以及其他管理信息,其实就是服务器端 Activity 对象的映射。

8、TaskRecord

AMS 抽象出来的一个任务的概念,是记录 ActivityRecord 的栈,一个 Task 包含若干个 ActivityRecord,AMS 通过 TaskRecord 确保 Activity 启动和退出的顺序。

二、Zygote

在 Linux 中,所有的进程都是由 init 进程直接或间接 fork 出来的,Zygote 进程也不例外。

手机开机后,Linux 内核加载完成后,会启动一个 init 进程。

每一个 App 其实都是:

  • 一个独立的 Dalvik 虚拟机
  • 一个独立的进程

所以,在系统中的第一个 Zygote 进程启动之后,再打开一个 App,其实就是开启一个新的进程。而为了实现资源共用和更快的启动速度,Android 系统开启新进程的方式是:通过 fork 第一个 Zygote 进程开启新进程,换句话说,其他应用所在的进程都是 Zygote 的子进程。

三、SystemServer

SystemServer 是一个进程,也是由 Zygote 进程 fork 出来的。

系统里比较重要的服务都是从这个进程里开启的,比如 ActivityManagerService、WindowManagerService、PackageManagerService 等。

Zygote 开启的时候会调用 ZygoteInit.main()

public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();

    // 标记 Zygote 开启
    ZygoteHooks.startZygoteNoThreadCreation();

    // Zygote 进入它自己的进程组
    try {
        Os.setpgid(0, 0);
    } catch (ErrnoException ex) {
        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }

    try {
        // 上报 Zygote 开启时间到分裂时间,除非重新启动
        if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
            MetricsLogger.histogram(null, "boot_zygote_init",
                    (int) SystemClock.elapsedRealtime());
        }

        String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
        BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag,
                Trace.TRACE_TAG_DALVIK);
        bootTimingsTraceLog.traceBegin("ZygoteInit");
        RuntimeInit.enableDdms();
        
        // 开始 Zygote 初始化
        SamplingProfilerIntegration.start();

        boolean startSystemServer = false;
        String socketName = "zygote";
        String abiList = null;
        boolean enableLazyPreload = false;
        for (int i = 1; i < argv.length; i++) {
            if ("start-system-server".equals(argv[i])) {
                startSystemServer = true;
            } else if ("--enable-lazy-preload".equals(argv[i])) {
                enableLazyPreload = true;
            } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                abiList = argv[i].substring(ABI_LIST_ARG.length());
            } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                socketName = argv[i].substring(SOCKET_NAME_ARG.length());
            } else {
                throw new RuntimeException("Unknown command line argument: " + argv[i]);
            }
        }

        if (abiList == null) {
            throw new RuntimeException("No ABI list supplied.");
        }

        zygoteServer.registerServerSocket(socketName);
        // 在许多配置中, 避免急切的预加载资源和类文件
        // 在许多事例中, 在第一次 fork 时会预加载一些优先级高的事情
        if (!enableLazyPreload) {
            bootTimingsTraceLog.traceBegin("ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload(bootTimingsTraceLog);
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            bootTimingsTraceLog.traceEnd(); // ZygotePreload
        } else {
            Zygote.resetNicePriority();
        }

        // 完成 Zygote 的初始化
        SamplingProfilerIntegration.writeZygoteSnapshot();

        // 做一个 GC 初始化,在启动之后进行清理
        bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
        gcAndFinalize();
        bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

        bootTimingsTraceLog.traceEnd(); // ZygoteInit
        
        // 禁止跟踪,以至于被 fork 的进程不能继承老的 Zygote
        Trace.setTracingEnabled(false);

        // Zygote 进程卸载根存储空间
        Zygote.nativeUnmountStorageOnInit();

        // 设置 seccomp 策略
        Seccomp.setPolicy();

        ZygoteHooks.stopZygoteNoThreadCreation();

        if (startSystemServer) {
            startSystemServer(abiList, socketName, zygoteServer);
        }

        Log.i(TAG, "Accepting command socket connections");
        zygoteServer.runSelectLoop(abiList);

        zygoteServer.closeServerSocket();
    } catch (Zygote.MethodAndArgsCaller caller) {
        caller.run();
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        zygoteServer.closeServerSocket();
        throw ex;
    }
}

// 为 fork SystemServer 进程准备参数
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
        throws Zygote.MethodAndArgsCaller, RuntimeException {
    long capabilities = posixCapabilitiesAsBits(
        OsConstants.CAP_IPC_LOCK,
        OsConstants.CAP_KILL,
        OsConstants.CAP_NET_ADMIN,
        OsConstants.CAP_NET_BIND_SERVICE,
        OsConstants.CAP_NET_BROADCAST,
        OsConstants.CAP_NET_RAW,
        OsConstants.CAP_SYS_MODULE,
        OsConstants.CAP_SYS_NICE,
        OsConstants.CAP_SYS_PTRACE,
        OsConstants.CAP_SYS_TIME,
        OsConstants.CAP_SYS_TTY_CONFIG,
        OsConstants.CAP_WAKE_ALARM
    );
    
    // 没有容量的容器运行,避免设置它
    if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
        capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
    }
    
    // 硬编码开启 system server
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        // 请求 fork system server 进程
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    /* For child process */
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }

        zygoteServer.closeServerSocket();
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

四、ActivityManagerService

简称 AMS,服务端对象,负责系统中所有 Activity 生命周期。

初始化时机:SystemServer 进程开启时。

public static void main(String[] args) {
    new SystemServer().run();
}

public SystemServer() {
    mFactoryTestMode = FactoryTest.getMode();
    
    mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}

private void run() {
    try {
        traceBeginAndSlog("InitBeforeStartServices");
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
        if (timezoneProperty == null || timezoneProperty.isEmpty()) {
            Slog.w(TAG, "Timezone not set; setting to GMT.");
            SystemProperties.set("persist.sys.timezone", "GMT");
        }

        if (!SystemProperties.get("persist.sys.language").isEmpty()) {
            final String languageTag = Locale.getDefault().toLanguageTag();

            SystemProperties.set("persist.sys.locale", languageTag);
            SystemProperties.set("persist.sys.language", "");
            SystemProperties.set("persist.sys.country", "");
            SystemProperties.set("persist.sys.localevar", "");
        }

        // system server 不能多线程调用
        Binder.setWarnOnBlocking(true);

        Slog.i(TAG, "Entered the Android system server!");
        int uptimeMillis = (int) SystemClock.elapsedRealtime();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
        if (!mRuntimeRestart) {
            MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
        }

        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

        if (SamplingProfilerIntegration.isEnabled()) {
            SamplingProfilerIntegration.start();
            mProfilerSnapshotTimer = new Timer();
            mProfilerSnapshotTimer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        SamplingProfilerIntegration.writeSnapshot("system_server", null);
                    }
                }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }

        VMRuntime.getRuntime().clearGrowthLimit();

        // system server 会一直运行,所以它需要高效使用其内存
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        Build.ensureFingerprintProperty();

        // 在 system server 中, 在没有显式指定用户的情况下,访问环境路径是会报错的
        Environment.setUserRequired(true);

        // 在 system server 中, 应该对任何输入包进行解压缩,避免抛出 BadParcelableException
        BaseBundle.setShouldDefuse(true);

        // 确保 binder 进行系统调用时能运行在前台
        BinderInternal.disableBackgroundScheduling(true);

        // 增加 system_server 中 binder 线程的数量
        BinderInternal.setMaxThreads(sMaxBinderThreads);

        android.os.Process.setThreadPriority(
            android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();

        // 初始化 native services(本地服务库)
        System.loadLibrary("android_servers");

        // 检查上次我们尝试关闭是否失败
        performPendingShutdown();

        // 初始化 system context
        createSystemContext();

        // 创建 system service manager
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // 准备 thread pool 并行初始化 tasks
        SystemServerInitThreadPool.get();
    } finally {
        traceEnd();  // InitBeforeStartServices
    }

    // 开启服务
    try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
        throw ex;
    } finally {
        traceEnd();
    }

    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        int uptimeMillis = (int) SystemClock.elapsedRealtime();
        MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);
        final int MAX_UPTIME_MILLIS = 60 * 1000;
        if (uptimeMillis > MAX_UPTIME_MILLIS) {
            Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
                    "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
        }
    }

    // 开启 Looper 循环
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

// 初始化上下文对象 mSystemContext
private void createSystemContext() {
    // 创建 ActivityThread 对象,ActivityThread.systemMain() 会调用 ActivityThread.attach(),在 attach 中创建了 Application 对象,并调用了 Application.onCreate()
    ActivityThread activityThread = ActivityThread.systemMain();
    // mSystemContext 实际上是一个 ContextImpl 对象
    mSystemContext = activityThread.getSystemContext();
    // 设置默认主题
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

private void startBootstrapServices() {
    ...

    // 初始化 ActivityManagerService
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);

    // Power manager 需要被提前创建因为其他服务需要它
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

    // 现在电源管理已经开始了,ActivityManagerService 负责电源管理功能
    // 初始化电源管理
    mActivityManagerService.initPowerManagement();

    // 初始化 DisplayManagerService,在 package manager 之前 需要提供 Display manager
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    // 开启 PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    
    ...
}

这是系统进程开启时的流程,在这之后,会开启系统的 Launcher 程序,完成系统界面的加载与显示。

五、Android 系统里面的服务器和客户端

服务器端:所有 App 共用的系统服务,比如 ActivityManagerService、PackageManagerService、WindowManagerService 等,当某个 App 要进行某项操作时,要告诉这些系统服务。

客户端:某个 App。

App A 调用 startActivity 不能直接打开 App B 的某个页面,而是通过一系列调用,告诉 AMS 要打开 App B 的某个页面,AMS 会通知 Zygote 进程 fork 一个新进程,来开启 App B。

App 与 AMS 之间通过 Binder 进行 IPC 通信,AMS 与 Zygote 之间通过 Socket 进行通信。

AMS 的用途:

  • 通知 Zygote 进程进行 fork 新进程
  • 管理系统中所有 Activity 生命周期

六、Launcher

Launcher 本身也是一个应用程序。

七、Instrumentation 和 ActivityThread

每个 Activity 都持有 Instrumentation 对象的一个引用,但整个进程只会存在一个 Instrumentation 对象。

当 startActivityForResult() 调用之后,实际上还是调用了 mInstrumentation.execStartActivity()。

这个类里面的方法大多数和 Application 和 Activity 有关,这个类就是完成对 Application 和 Activity 初始化和生命周期的工具类。

AMS -> ActivityThread -> Instrumentation

八、AMS 与 ActivityThread 之间的 Binder 通信

startActivity()
-> startActivityForResult()
-> Instrumentation.execStartActivity() -> checkStartActivityResult()
-> ActivityManager.getService().startActivity()
-> ActivityManagerService.startActivity() -> startActivityAsUser()
-> ActivityStarter.startActivityMayWait() -> startActivityLocked() -> startActivity() -> startActivityUnchecked() -> resumeTargetStackIfNeeded()
-> ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()
-> ActivityStack.resumeTopActivityUncheckedLocked() -> resumeTopActivityInnerLocked()
-> ActivityStackSupervisor.startSpecificActivityLocked() -> realStartActivityLocked()
-> ActivityThread.ApplicationThread.scheduleLaunchActivity() -> sendMessage() -> handleLaunchActivity() -> performLaunchActivity()
-> Instrumentation.callActivityOnCreate() 
-> Activity.performCreate() -> onCreate()

ActivityManager.getService() 返回的就是 ActivityManagerService 的远程接口。

客户端:ActivityManagerProxy -> Binder驱动 -> ActivityManagerService:服务器

如果 AMS 想要通知 ActivityThread 做一些事情,还是通过 Binder 通信,不过是换成了 ApplicationThread 和 ApplicationThreadProxy。

ApplicationThreadProxy:服务器 -> Binder 驱动 -> 客户端:ApplicationThread

九、问答

1、一个 App 的程序入口到底是什么?

ActivityThread.main()。

2、整个 App 的主线程的消息循环是在哪里创建的?

是在 ActivityThread 初始化的时候,就已经创建消息循环了,所以在主线程里面创建 Handler 不需要指定 Looper,而如果在其他线程使用 Handler,则需要单独使用 Looper.prepare() 和 Looper.loop() 创建消息循环。

3、Application 是在什么时候创建的?onCreate()什么时候调用的?

也是在 ActivityThread.main() 的时候,再具体点,就是在 thread.attach(false) 的时候。

参考:APP启动过程

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants