美文网首页
Android -APP启动流程

Android -APP启动流程

作者: 苍天霸气诀 | 来源:发表于2019-06-22 16:35 被阅读0次

    一、理论基础

    1.zygote

    zygote意为“受精卵“。Android是基于Linux系统的,而在Linux中,所有的进程都是由init进程直接或者是间接fork出来的,zygote进程也不例外。

    在Android系统里面,zygote是一个进程的名字。Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。

    我们都知道,每一个App其实都是

    ● 一个单独的dalvik虚拟机

    ● 一个单独的进程

    所以当系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的。所以说,除了第一个zygote进程,其他应用所在的进程都是zygote的子进程,这下你明白为什么这个进程叫“受精卵”了吧?因为就像是一个受精卵一样,它能快速的分裂,并且产生遗传物质一样的细胞!

    2.system_server

    SystemServer也是一个进程,而且是由zygote进程fork出来的。

    知道了SystemServer的本质,我们对它就不算太陌生了,这个进程是Android Framework里面两大非常重要的进程之一——另外一个进程就是上面的zygote进程。

    为什么说SystemServer非常重要呢?因为系统里面重要的服务都是在这个进程里面开启的,比如

    ActivityManagerService、PackageManagerService、WindowManagerService等等。

    3.ActivityManagerService

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

    ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService。

    4.Launcher

    当我们点击手机桌面上的图标的时候,App就由Launcher开始启动了。但是,你有没有思考过Launcher到底是一个什么东西?

    Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity

    packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
    
    public final class Launcher extends Activity
    
    implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
    
    View.OnTouchListener {
    
    }
    

    Launcher实现了点击、长按等回调接口,来接收用户的输入。既然是普通的App,那么我们的开发经验在这里就仍然适用,比如,我们点击图标的时候,是怎么开启的应用呢?捕捉图标点击事件,然后startActivity()发送对应的Intent请求呗!是的,Launcher也是这么做的,就是这么easy!

    5.Instrumentation和ActivityThread

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

    Instrumentation这个类里面的方法大多数和Application和Activity有关,这个类就是完成对Application和Activity初始化和生命周期的工具类。Instrumentation这个类很重要,对Activity生命周期方法的调用根本就离不开他,他可以说是一个大管家。

    ActivityThread,就是UI线程。App和AMS是通过Binder传递信息的,那么ActivityThread就是专门与AMS的外交工作的。

    二.流程图

    image.png

    先将“三个进程”,“六个大类”进行介绍:

    三个进程:

    Launcher进程:整个App启动流程的起点,负责接收用户点击屏幕事件,它其实就是一个Activity,里面实现了点击事件,长按事件,触摸等事件,可以这么理解,把Launcher想象成一个总的Activity,屏幕上各种App的Icon就是这个Activity的button,当点击Icon时,会从Launcher跳转到其他页面;

    SystemServer进程:这个进程在整个的Android进程中是非常重要的一个,地位和Zygote等同,它是属于Application Framework层的,Android中的所有服务,例如AMS, WindowsManager, PackageManagerService等等都是由这个SystemServer fork出来的。所以它的地位可见一斑。

    App进程:你要启动的App所运行的进程;

    六个大类:

    ActivityManagerService:(AMS)AMS是Android中最核心的服务之一,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,其职责与操作系统中的进程管理和调度模块相类似,因此它在Android中非常重要,它本身也是一个Binder的实现类。

    Instrumentation:监控应用程序和系统的交互;

    ActivityThread:应用的入口类,通过调用main方法,开启消息循环队列。ActivityThread所在的线程被称为主线程;

    ApplicationThread:ApplicationThread提供Binder通讯接口,AMS则通过代理调用此App进程的本地方法

    ActivityManagerProxy:AMS服务在当前进程的代理类,负责与AMS通信。

    ApplicationThreadProxy:ApplicationThread在AMS服务中的代理类,负责与ApplicationThread通信。

    可以说,启动的流程就是通过这六个大类在这三个进程之间不断通信的过程;

    启动流程

    ①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;

    ②system_server进程接收到请求后,向zygote进程发送创建进程的请求;

    ③Zygote进程fork出新的子进程,即App进程;

    ④App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

    ⑤system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

    ⑥App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

    ⑦主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。

    ⑧到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。

    image.png

    (1)Launcher响应用户点击,通知AMS

    Launcher调用startActivity()方法,而startActivity()最终也是调用startActivityForResult();

    
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
       if (options != null) {
           startActivityForResult(intent, -1, options);
       } else {
           // Note we want to go through this call for compatibility with
           // applications that may have overridden the method.
           startActivityForResult(intent, -1);
       }
    }
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
           @Nullable Bundle options) {
       if (mParent == null) {
           options = transferSpringboardActivityOptions(options);
           Instrumentation.ActivityResult ar =
               mInstrumentation.execStartActivity(
                   this, mMainThread.getApplicationThread(), mToken, this,
                   intent, requestCode, options);
           if (ar != null) {
               mMainThread.sendActivityResult(
                   mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                   ar.getResultData());
           }
          ......
    }
    
    

    在其中调用了Instrumentation的execstartActivity方法:

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
            .....
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
    

    这里调用了ActivityManager.getService方法返回的就是ActivityManagerProxy,用于与AMS通信,这样通过这些一系列的方法调用,就把Launcher进程和AMS进程进行通信了一次;

    (2)AMS响应Launcher进程请求

    主要是通过ActivityStackSupervisor:startActivityUncheckedLocked去给Activity申请Task的;此方法经过intent的标志值设置,通过findTaskLocked函数来查找存不存这样的Task,这里返回的结果是null,即intentActivity为null,因此,需要创建一个新的Task来启动这个Activity。现在处理堆栈顶端的Activity是Launcher,与我们即将要启动的MainActivity不是同一个Activity,创建了一个新的Task里面来启动这个Activity。

    经过栈顶检测,则需要将Launcher推入Paused状态,才可以启动新的Activity。后续则调用至ActivityStack:startPausingLocked;此方法里有prev.app.thread是一个ApplicationThread对象的远程接口,通过调用这个远程接口的schedulePauseActivity来通知Launcher进入Paused状态。至此,AMS对Launcher的请求已经响应,这是我们发现又通过Binder通信回调至Launcher进程;

    (3)Launcher进程挂起Launcher,再次通知AMS

    这部分Launcher的ActivityThread处理页面Paused并且再次通过ActivityManagerProxy通知AMS。

    (4)AMS创建新的进程

    创建新进程的时候,AMS会保存一个ProcessRecord信息,如果应用程序中的AndroidManifest.xml配置文件中,我们没有指定Application标签的process属性,系统就会默认使用package的名称。每一个应用程序都有自己的uid,因此,这里uid + process的组合就可以为每一个应用程序创建一个ProcessRecord。

    这里主要是调用Process:start接口来创建一个新的进程,新的进程会导入android.app.ActivityThread类,并且执行它的main函数,这就是每一个应用程序都有一个ActivityThread实例来对应的原因。

    先判断是否有相应的 ProcessRecord,如果不存在,就需要新建进程,这个进程就是相应的应用进程。ActivityManagerService 通过 Socket 通信的方式和 Zygote 进行协商,Zygote 在其监听的 /dev/socket/zygote socket 中发现有需要创建进程的请求后,会 fork 自身,并返回相应的 Process Id。这个 Process 会进行相应的初始化,使得其具备与系统服务进行 IPC 通信的能力;

    (5)应用进程初始化

    我们来看Activity的main函数,这里绑定了主线程的Looper,并进入消息循环,大家应该知道,整个Android系统是消息驱动的,这也是为什么主线程默认绑定Looper的原因:

    public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
    
        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);
    
        Environment.initForCurrentUser();
    
        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());
    
        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
    
        Process.setArgV0("<pre-initialized>");
    
        Looper.prepareMainLooper();
    
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
    
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
    
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
    
        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();
    
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    

    attach函数最终调用了ActivityManagerService的远程接口ActivityManagerProxy的attachApplication函数,传入的参数是mAppThread,这是一个ApplicationThread类型的Binder对象,它的作用是AMS与应用进程进行进程间通信的。

    (6)在AMS中注册应用进程,启动启动栈顶页面

    前面我们提到了AMS负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,通过上一个流程我们知道应用进程创建后通过Binder驱动与AMS产生交互,此时AMS则将应用进程创建后的信息进行了一次注册,如果拿Windows系统程序注册到的注册表来理解这个过程,可能会更形象一些。

    mMainStack.topRunningActivityLocked(null)从堆栈顶端取出要启动的Activity,并在realStartActivityLockedhan函数中通过ApplicationThreadProxy调回App进程启动页面。

    此时在App进程,我们可以看到,经过一些列的调用链最终调用至MainActivity:onCreate函数,之后会调用至onResume,而后会通知AMS该MainActivity已经处于resume状态。至此,整个启动流程告一段落。

    上面讲的是activity的启动流程,下面要说的是,android系统的启动流程,通俗来说,按下电源键,开机的过程系统做了些什么:

    1.当系统引导程序启动Linux内核,内核会加载各种数据结构,和驱动程序,加载完毕之后,Android系统开始启动并加载第一个用户级别的进程:init(system/core/init/Init.c)

    我们来看一看这个Init.c代码,看main函数

    int main(int argc, char **argv)
    {
         ...
        //执行Linux指令
        mkdir("/dev", 0755);
        mkdir("/proc", 0755);
        mkdir("/sys", 0755);
    
        ...
        //解析执行init.rc配置文件
        init_parse_config_file("/init.rc");
        ...
    }
    

    主要创建了一些目录,并且加载执行了一个init.rc的文件,我们来看看这个init.rc

    2.在system\core\rootdir\Init.rc中定义好的指令都会开始执行,其中执行了很多bin指令,启动系统服务

    //启动孵化器进程,此进程是Android系统启动关键服务的一个母进程
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
    
    

    里面启动了一个app_process,我们看看这是什么:

    3.在appprocess文件夹下找到appmain.cpp,查看main函数,发现以下代码

    int main(int argc, const char* const argv[])
    {
        ...
        //启动一个系统服务:ZygoteInit
        runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
        ...
    }
    

    仍然是为启动一个系统服务做准备,我们继续跟下去看看:

    4.在ZygoteInit.java中,查看main方法

     public static void main(String argv[]) {
        ...
        //加载Android系统需要的类
        preloadClasses();
        ...
        if (argv[1].equals("true")) {
            //调用方法启动一个系统服务
            startSystemServer();
        }
        ...
    }
    

    在这里主要是先加载了android系统所需要的类,然后启动系统服务,继续跟下去:

    5.startSystemServer()方法的方法体

    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
        "--capabilities=130104352,130104352",
        "--runtime-init",
        "--nice-name=system_server",
        "com.android.server.SystemServer",
    };
    
    ...
    //分叉启动上面字符串数组定义的服务
     pid = Zygote.forkSystemServer(
     parsedArgs.uid, parsedArgs.gid,
     parsedArgs.gids, debugFlags, null,
     parsedArgs.permittedCapabilities,
     parsedArgs.effectiveCapabilities);
    

    6.SystemServer服务被启动

    public static void main(String[] args) {
        ...
        //加载动态链接库
         System.loadLibrary("android_servers");
        //执行链接库里的init1方法
        init1(args);
        ...
    }
    

    7.动态链接库文件和java类包名相同,找到com_android_server_SystemServer.cpp文件

    在com_android_server_SystemServer.cpp文件中,找到了

    static JNINativeMethod gMethods[] = {
        /* name, signature, funcPtr */
        //给init1方法映射一个指针,调用system_init方法
        { "init1", "([Ljava/lang/String;)V", (void*) android_server_SystemServer_init1 },
    };
    
    

    8.android_server_SystemServer_init1方法体中调用了system_init(),system_init()没有方法体

    在system_init.cpp文件中找到system_init()方法,方法体中 //执行了SystemServer.java的init2方法 runtime->callStatic("com/android/server/SystemServer", "init2");
    
    回到SystemServer.java,在init2的方法体中
    
    //启动一个服务线程
    Thread thr = new ServerThread();
    thr.start();
    

    9.在ServerThread的run方法中

    //准备消息轮询器
    Looper.prepare();
    ...
    //启动大量的系统服务并把其逐一添加至ServiceManager
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    ...
    //调用systemReady,准备创建第一个activity
     ((ActivityManagerService)ActivityManagerNative.getDefault())
            .systemReady(new Runnable(){
            ...
    });
    

    10.在ActivityManagerService.java中,有systemReady方法,方法体里找到

    //检测任务栈中有没有activity,如果没有,创建Launcher
    mMainStack.resumeTopActivityLocked(null);
    

    11.在ActivityStack.java中,方法resumeTopActivityLocked

    // Find the first activity that is not finishing.
    ActivityRecord next = topRunningActivityLocked(null);
    ...
    if (next == null) {
        // There are no more activities!  Let's just start up the
        // Launcher...
        if (mMainStack) {
            return mService.startHomeActivityLocked();
        }
    }
    

    参考:https://blog.csdn.net/pgg_cold/article/details/79491791
    http://www.sohu.com/a/130814934_675634

    相关文章

      网友评论

          本文标题:Android -APP启动流程

          本文链接:https://www.haomeiwen.com/subject/tglvqctx.html