精华内容
下载资源
问答
  • APP启动流程解析

    万次阅读 多人点赞 2019-04-22 10:07:15
    启动流程简介 首先要知道的是,手机屏幕其实就是一个Activity,我们专业点将其称为Launcher,相信做过车载设备开发的朋友肯定不会陌生,Launcher是手机厂商提供的,不同的手机厂商比拼的就是Launcher的设计。当然...

    前言

    当我们点击手机屏幕上的软件图标时,就可以打开这个软件,看似很简单的过程其实包含了许多的底层交互,看了还不明白,欢迎来打我。

    一 . 启动流程简介

    首先要知道的是,手机屏幕其实就是一个Activity,我们专业点将其称为Launcher,相信做过车载设备开发的朋友肯定不会陌生,Launcher是手机厂商提供的,不同的手机厂商比拼的就是Launcher的设计。当然我们自己也可以去编写Launcher,运行在手机上使用自己的桌面风格,当然这里我们不去讲如何去编写一个Launcher,如果你感兴趣欢迎关注我。

    写过AndroidDemo的朋友肯定都知道,我们必须在AndroidManifest配置文件中配置默认启动的Activity

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
    
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    其实就是告诉Launcher该启动这个App的哪个页面。这样当系统启动的时候,PackageManger-Service就可以从配置文件中读取到该启动哪个Activity。

    其次要知道的是,Launch和其他APP,运行在不同的进程中,所以他们之间的通信是通过Binder去完成的,所以AMS是必不可少的。下面我们以启动微信为例,看看启动流程是怎样的。

                               

                                                 

                                                                 

                                           

                                                                              

                    

                                                                    

              

                                                                 

             

    简单概括启动微信的流程就是:

    1.Launcher通知AMS 要启动微信了,并且告诉AMS要启动的是哪个页面也就是首页是哪个页面

    2.AMS收到消息告诉Launcher知道了,并且把要启动的页面记下来

    3.Launcher进入Paused状态,告诉AMS,你去找微信吧

    上述就是Launcher和AMS的交互过程

    4.AMS检查微信是否已经启动了也就是是否在后台运行,如果是在后台运行就直接启动,如果不是,AMS会在新的进程中创建一个ActivityThread对象,并启动其中的main函数。

    5.微信启动后告诉AMS,启动好了

    6.AMS通过之前的记录找出微信的首页,告诉微信应该启动哪个页面

    7.微信按照AMS通知的页面去启动就启动成功了。

          

    上述阶段是微信和AMS的交互过程。那么接下来我们分析下具体过程

    二  启动流程分析

    1.点击Launcher上的微信图标时,会调用startActivitySafely方法,intent中携带微信的关键信息也就是我们在配置文件中配置的默认启动页信息,其实在微信安装的时候,Launcher已经将启动信息记录下来了,图标只是一个快捷方式的入口。

    startActivitySafely的方法最终还是会调用Activity的startActivity方法

    @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);
        }
    }

    而startActivity方法最终又会回到startActivityForResult方法,这里startActivityForResult的方法中code为-1,表示startActivity并不关心是否启动成功。startActivityForResult部分方法如下所示:

    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());
            }
            if (requestCode >= 0) {

    startActivityForResult方法中又会调用mInstrumentation.execStartActivity方法,我们看到其中有个参数是

    mMainThread.getApplicationThread()

    关于ActivityThread曾在 深入理解Android消息机制https://blog.csdn.net/huangliniqng文章中提到过,ActivityThread是在启动APP的时候创建的,ActivityThread代表应用程序,而我们开发中常用的Application其实是ActivityThread的上下文,在开发中我们经常使用,但在Android系统中其实地位很低的。

                                                             

    Android的main函数就在ActivityThread中

    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();

    再回到上面方法

    mMainThread.getApplicationThread()
    

    得到的是一个Binder对象,代表Launcher所在的App的进程,mToken实际也是一个Binder对象,代表Launcher所在的Activity通过Instrumentation传给AMS,这样AMS就知道是谁发起的请求。

    2.mInstrumentation.execStartActivity

    instrumentation在测试的时候经常用到,instrumentation的官方文档:http://developer.android.com/intl/zh-cn/reference/android/app/Instrumentation.html这里不对instrumentation进行详细介绍了,我们主要接着看mInstrumentation.execStartActivity方法

    public Instrumentation.ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread)contextThread;
        if(this.mActivityMonitors != null) {
            Object e = this.mSync;
            synchronized(this.mSync) {
                int N = this.mActivityMonitors.size();
    
                for(int i = 0; i < N; ++i) {
                    Instrumentation.ActivityMonitor am = (Instrumentation.ActivityMonitor)this.mActivityMonitors.get(i);
                    if(am.match(who, (Activity)null, intent)) {
                        ++am.mHits;
                        if(am.isBlocking()) {
                            return requestCode >= 0?am.getResult():null;
                        }
                        break;
                    }
                }
            }
        }
    
        try {
            intent.setAllowFds(false);
            intent.migrateExtraStreamToClipData();
            int var16 = ActivityManagerNative.getDefault().startActivity(whoThread, intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null?target.mEmbeddedID:null, requestCode, 0, (String)null, (ParcelFileDescriptor)null, options);
            checkStartActivityResult(var16, intent);
        } catch (RemoteException var14) {
            ;
        }
    
        return null;
    }

    其实这个类是一个Binder通信类,相当于IPowerManager.java就是实现了IPowerManager.aidl,我们再来看看getDefault这个函数

    public static IActivityManager getDefault() {
        return (IActivityManager)gDefault.get();
    }

    getDefault方法得到一个IActivityManager,它是一个实现了IInterface的接口,里面定义了四大组件的生命周期,

    public static IActivityManager asInterface(IBinder obj) {
        if(obj == null) {
            return null;
        } else {
            IActivityManager in = (IActivityManager)obj.queryLocalInterface("android.app.IActivityManager");
            return (IActivityManager)(in != null?in:new ActivityManagerProxy(obj));
        }
    }

    最终返回一个ActivityManagerProxy对象也就是AMP,AMP就是AMS的代理对象,说到代理其实就是代理模式,关于什么是代理模式以及动态代理和静态代理的使用可以持续关注我,后面会单独写篇文章进行介绍。

                

    AMP的startActivity方法

    public int startActivity(IApplicationThread caller, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken("android.app.IActivityManager");
        data.writeStrongBinder(caller != null?caller.asBinder():null);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        data.writeString(profileFile);
        if(profileFd != null) {
            data.writeInt(1);
            profileFd.writeToParcel(data, 1);
        } else {
            data.writeInt(0);
        }

    主要就是将数据写入AMS进程,等待AMS的返回结果,这个过程是比较枯燥的,因为我们做插件化的时候只能对客户端Hook,而不能对服务端操作,所以我们只能静静的看着。(温馨提示:如果文章到这儿你已经有点头晕了,那就对了,研究源码主要就是梳理整个流程,千万不要纠结源码细节,那样会无法自拔)。

    3.AMS处理Launcher的信息

    AMS告诉Launcher我知道了,那么AMS如何告诉Launcher呢?

    Binder的通信是平等的,谁发消息谁就是客户端,接收的一方就是服务端,前面已经将Launcher所在的进程传过来了,AMS将其保存为一个ActivityRecord对象,这个对象中有一个ApplicationThreadProxy即Binder的代理对象,AMS通ApplicationTreadProxy发送消息,App通过ApplicationThread来接收这个消息。

    Launcher收到消息后,再告诉AMS,好的我知道了,那我走了,ApplicationThread调用ActivityThread的sendMessage方法给Launcher主线程发送一个消息。这个时候AMS去启动一个新的进程,并且创建ActivityThread,指定main函数入口。

    启动新进程的时候为进程创建了ActivityThread对象,这个就是UI线程,进入main函数后,创建一个Looper,也就是mainLooper,并且创建Application,所以说Application只是对开发人员来说重要而已。创建好后告诉AMS微信启动好了,AMS就记录了这个APP的登记信息,以后AMS通过这个ActivityThread向APP发送消息。

    这个时候AMS根据之前的记录告诉微信应该启动哪个Activity,微信就可以启动了。

    public void handleMessage(Message msg) {
        ActivityThread.ActivityClientRecord data;
        switch(msg.what) {
        case 100:
            Trace.traceBegin(64L, "activityStart");
            data = (ActivityThread.ActivityClientRecord)msg.obj;
            data.packageInfo = ActivityThread.this.getPackageInfoNoCheck(data.activityInfo.applicationInfo, data.compatInfo);
            ActivityThread.this.handleLaunchActivity(data, (Intent)null);
            Trace.traceEnd(64L);
    ActivityThread.ActivityClientRecord

    就是AMS传过来的Activity

    data.activityInfo.applicationInfo

    所得到的属性我们称之为LoadedApk,可以提取到apk中的所有资源,那么APP内部是如何页面跳转的呢,比如我们从ActivityA跳转到ActivityB,我们可以将Activity看作Launcher,唯一不同的就是,在正常情况下ActivityB和ActivityA所在同一进程,所以不会去创建新的进程。

    APP的启动流程就是这样了,欢迎留言探讨,记得持续关注哦。

    展开全文
  • Android APP启动流程

    2019-03-08 14:42:43
    Android APP启动流程 启动过程

    Android APP启动流程

    启动过程

    展开全文
  • 详解APP启动流程

    2018-01-19 10:10:50
    原文链接:app启动流程 一、流程概述 启动流程: ①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求; ②system_server进程接收到请求后,向zygote进程发送创建...

    写在开头

    今天学习了下APP启动流程,从点击桌面开始到我们看到主界面都发生了什么?在此记录,留作学习。
    原文链接: app启动流程


    一、流程概述


    启动流程:

    ①点击桌面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的主界面。

    上面的一些列步骤简单介绍了一个APP启动到主页面显示的过程,可能这些流程中的一些术语看的有些懵,什么是Launcher,什么是zygote,什么是applicationThread…..

    下面我们一一介绍。

    二、理论基础

    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。

    下面介绍下Android系统里面的服务器和客户端的概念。

    其实服务器客户端的概念不仅仅存在于Web开发中,在Android的框架设计中,使用的也是这一种模式。服务器端指的就是所有App共用的系统服务,比如我们这里提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,这些基础的系统服务是被所有的App公用的,当某个App想实现某个操作的时候,要告诉这些系统服务,比如你想打开一个App,那么我们知道了包名和MainActivity类名之后就可以打开

    Intent intent = new Intent(Intent.ACTION_MAIN);  
    intent.addCategory(Intent.CATEGORY_LAUNCHER);              
    ComponentName cn = new ComponentName(packageName, className);              
    intent.setComponent(cn);  
    startActivity(intent);
    

    但是,我们的App通过调用startActivity()并不能直接打开另外一个App,这个方法会通过一系列的调用,最后还是告诉AMS说:“我要打开这个App,我知道他的住址和名字,你帮我打开吧!”所以是AMS来通知zygote进程来fork一个新进程,来开启我们的目标App的。这就像是浏览器想要打开一个超链接一样,浏览器把网页地址发送给服务器,然后还是服务器把需要的资源文件发送给客户端的。

    知道了Android Framework的客户端服务器架构之后,我们还需要了解一件事情,那就是我们的App和AMS(SystemServer进程)还有zygote进程分属于三个独立的进程,他们之间如何通信呢?

    App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。后面具体介绍。

    那么AMS有什么用呢?在前面我们知道了,如果想打开一个App的话,需要AMS去通知zygote进程,除此之外,其实所有的Activity的开启、暂停、关闭都需要AMS来控制,所以我们说,AMS负责系统中所有Activity的生命周期。

    在Android系统中,任何一个Activity的启动都是由AMS和应用程序进程(主要是ActivityThread)相互配合来完成的。AMS服务统一调度系统中所有进程的Activity启动,而每个Activity的启动过程则由其所属的进程具体来完成。

    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的外交工作的。

    6.ApplicationThread

    前面我们已经知道了App的启动以及Activity的显示都需要AMS的控制,那么我们便需要和服务端的沟通,而这个沟通是双向的。

    客户端–>服务端

    而且由于继承了同样的公共接口类,ActivityManagerProxy提供了与ActivityManagerService一样的函数原型,使用户感觉不出Server是运行在本地还是远端,从而可以更加方便的调用这些重要的系统服务。

    服务端–>客户端

    还是通过Binder通信,不过是换了另外一对,换成了ApplicationThread和ApplicationThreadProxy。


    他们也都实现了相同的接口IApplicationThread

      private class ApplicationThread extends ApplicationThreadNative {}
    
      public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}
    
      class ApplicationThreadProxy implements IApplicationThread {}
    

    关于Binder通信,可以参考这两篇文章理解一下:简单理解Binder机制的原理,关于AIDL使用和Binder机制详解,你只需要看这一篇即可

    好了,前面罗里吧嗦的一大堆,介绍了一堆名词,可能不太清楚,没关系,下面结合流程图介绍。

    三、启动流程

    1.创建进程

    ①先从Launcher的startActivity()方法,通过Binder通信,调用ActivityManagerService的startActivity方法。

    ②一系列折腾,最后调用startProcessLocked()方法来创建新的进程。

    ③该方法会通过前面讲到的socket通道传递参数给Zygote进程。Zygote孵化自身。调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid。

    ④调用ActivityThread.main()方法,ActivityThread随后依次调用Looper.prepareLoop()和Looper.loop()来开启消息循环。

    方法调用流程图如下:


    更直白的流程解释:

    ①App发起进程:当从桌面启动应用,则发起进程便是Launcher所在进程;当从某App内启动远程进程,则发送进程便是该App所在进程。发起进程先通过binder发送消息给system_server进程;

    ②system_server进程:调用Process.start()方法,通过socket向zygote进程发送创建新进程的请求;

    ③zygote进程:在执行ZygoteInit.main()后便进入runSelectLoop()循环体内,当有客户端连接时便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程;

    ④新进程:执行handleChildProc方法,最后调用ActivityThread.main()方法。

    2.绑定Application

    上面创建进程后,执行ActivityThread.main()方法,随后调用attach()方法。

    将进程和指定的Application绑定起来。这个是通过上节的ActivityThread对象中调用bindApplication()方法完成的。该方法发送一个BIND_APPLICATION的消息到消息队列中, 最终通过handleBindApplication()方法处理该消息. 然后调用makeApplication()方法来加载App的classes到内存中。

    方法调用流程图如下:


    更直白的流程解释:

    (如果看不懂AMS,ATP等名词,后面有解释)

    3.显示Activity界面

    经过前两个步骤之后, 系统已经拥有了该application的进程。 后面的调用顺序就是普通的从一个已经存在的进程中启动一个新进程的activity了。

    实际调用方法是realStartActivity(), 它会调用application线程对象中的scheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到消息队列中, 通过 handleLaunchActivity()来处理该消息。在 handleLaunchActivity()通过performLaunchActiivty()方法回调Activity的onCreate()方法和onStart()方法,然后通过handleResumeActivity()方法,回调Activity的onResume()方法,最终显示Activity界面。


    更直白的流程解释:

    四、Binder通信

    简称:

    ATP: ApplicationThreadProxy

    AT: ApplicationThread

    AMP: ActivityManagerProxy

    **AMS: **ActivityManagerService

    图解:

    ①system_server进程中调用startProcessLocked方法,该方法最终通过socket方式,将需要创建新进程的消息告知Zygote进程,并阻塞等待Socket返回新创建进程的pid;

    ②Zygote进程接收到system_server发送过来的消息, 则通过fork的方法,将zygote自身进程复制生成新的进程,并将ActivityThread相关的资源加载到新进程app process,这个进程可能是用于承载activity等组件;

    ③ 在新进程app process向servicemanager查询system_server进程中binder服务端AMS, 获取相对应的Client端,也就是AMP. 有了这一对binder c/s对, 那么app process便可以通过binder向跨进程system_server发送请求,即attachApplication()

    ④system_server进程接收到相应binder操作后,经过多次调用,利用ATP向app process发送binder请求, 即bindApplication.
    system_server拥有ATP/AMS, 每一个新创建的进程都会有一个相应的AT/AMP,从而可以跨进程 进行相互通信. 这便是进程创建过程的完整生态链。

    以上大概介绍了一个APP从启动到主页面显示经历的流程,主要从宏观角度介绍了其过程,具体可结合源码理解。

    参考文章:

    startActivity启动过程分析
    理解Android进程创建流程
    [译]Android Application启动流程分析
    【凯子哥带你学Framework】Activity启动过程全解析

    展开全文
  • Android App启动流程详解

    万次阅读 多人点赞 2019-06-26 15:26:19
    前言:在之前的文章中已经写了apk的打包流程、安装流程,今天就是梳理一下apk系列的最后的流程--app启动流程。经过今天的梳理以后咱们就可以对apk包是怎么编译生成的、apk是怎么被安装到安卓手机的、用户点击了桌面...

    前言:在之前的文章中已经写了apk的打包流程、安装流程,今天就是梳理一下apk系列的最后的流程--app启动流程。经过今天的梳理以后咱们就可以对apk包是怎么编译生成的、apk是怎么被安装到安卓手机的、用户点击了桌面icon以后app是怎么启动起来的 整个流程有清晰的认知和了解了。

    下面先附上前面文章的传送门:

    apk打包流程详解

    apk安装流程详解

    在开始分析app启动流程之前,我们先回想下平时是怎么启动一个App的:Android系统桌面->点击应用图标->启动App。

    从这个过程来看,只要弄明白下面两个问题就可以解决我们“App如何被启动”的疑问。

     

    在最开始先将apk启动涉及的“三个进程”,“六个大类”进行介绍一下:

    • Android系统桌面是什么?
    • 点击应用图标后Android系统执行了什么操作?

    三个进程:

    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通信。

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

    先搞清楚Android系统桌面是什么?

    在Android系统中,Activity是视图存在的根本,那么我们可以通过命令 adb shell dumpsys activity activities 判断是哪个Activity为我们呈现桌面视图的。

    以小米为例,通过USB连上电脑后,输入命令 adb shell dumpsys activity activities 得到结果如下:

    在上图可以看到,显示桌面视图的Activity是com.miui.home包下的名为Launcher的Activity。

    下面我copy了一张Launcher的这个Activity:

    再来说说点击App图标后Android系统执行了什么操作?

    既然Launcher是Activity,那就意味着我们点击桌面的事件可以表达为:呈现Android桌面视图(View)->点击View上某个应用图标->产生点击事件->点击事件被响应->通知Android系统的某个/某些进程->Android系统执行某些操作->启动App。

    先看一下Launcher如何响应由我们产生的点击事件的:

    /**
     * Launches the intent referred by the clicked shortcut.
     *
     * @param v The view representing the clicked shortcut.
     */
    public void onClick(View v) {
        // Make sure that rogue clicks don't get through while allapps is launching, or after the
        // view has detached (it's possible for this to happen if the view is removed mid touch).
        if (v.getWindowToken() == null) {
            return;
        }
    
        if (!mWorkspace.isFinishedSwitchingState()) {
            return;
        }
    
        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            // Open shortcut
            final Intent intent = ((ShortcutInfo) tag).intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
    
            boolean success = startActivitySafely(v, intent, tag);
    
            if (success && v instanceof BubbleTextView) {
                mWaitingForResume = (BubbleTextView) v;
                mWaitingForResume.setStayPressed(true);
            }
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                FolderIcon fi = (FolderIcon) v;
                handleFolderClick(fi);
            }
        } else if (v == mAllAppsButton) {
            if (isAllAppsVisible()) {
                showWorkspace(true);
            } else {
                onClickAllAppsButton(v);
            }
        }
    }
    
    boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        try {
            success = startActivity(v, intent, tag);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
        }
        return success;
    }
    

    从上面代码来看,产生点击事件后,如果产生点击事件的View的Tag是ShortcutInfo(即启动应用的快捷方式),就会取得ShortcutInfo中保存的Intent(这个Intent指向我们要启动的App),然后执行startActivitySafely(v, intent, tag)方法,而startActivitySafely方法只是对startActivity方法的简单封装。

    所以,Launcher响应我们产生的点击事件后,实际上就是启动一个新的Activity。

    我们现在回想下在App开发时,每个App都需要有一个“MainActivity”,这个Activity必须在AndroidManifest.xml文件中有以下配置:

    <intent-filter>    
        <action android:name="android.intent.action.MAIN" />    
        <category android:name="android.intent.category.LAUNCHER" />    
    </intent-filter> 
    

    在配置AndroidManifest.xml文件时,将Activity的Action指定为android.intent.action.MAIN,会使Activity在一个新的Task中启动(Task是一个Activity栈)。将category指定为android.intent.category.LAUNCHER,表示通过Intent启动此Activity时,只接受category为LAUNCHER的Intent。

    所以,Launcher将会通过App的快捷方式(ShortcutInfo)得到应用的Intent,并通过这个Intent启动应用的“MainActivity”,从而启动应用。

    到此我们研究的问题就从“App启动流程”变为“Activity启动流程”。

    接下来我们就进入Launcher的startActivity方法里面探索“Activity启动流程”吧:在系统中其实Launcher是通过Binder通知ActivityManagerService启动Activity的。看下面的代码:

    boolean startActivity(View v, Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    
        try {
            // Only launch using the new animation if the shortcut has not opted out (this is a
            // private contract between launcher and may be ignored in the future).
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
            UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
            LauncherApps launcherApps = (LauncherApps)
                    this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
            if (useLaunchAnimation) {
                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
                        v.getMeasuredWidth(), v.getMeasuredHeight());
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    // Could be launching some bookkeeping activity
                    startActivity(intent, opts.toBundle());
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(),
                            opts.toBundle());
                }
            } else {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    startActivity(intent);
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(), null);
                }
            }
            return true;
        } catch (SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
                    "or use the exported attribute for this activity. "
                    + "tag="+ tag + " intent=" + intent, e);
        }
        return false;
    }
    

    在这个方法中,首先,将Intent的Flag设为Intent.FLAG_ACTIVITY_NEW_TASK,使得Android系统将创建一个新的Task来放置即将被打开的新Activity(应用的“MainActivity),然后获取一个布尔值以用于后续判断是否显示启动App的动画。

    再然后获取Intent中是否传输了Parcelable格式的用户句柄,并通过Context.LAUNCHER_APPS_SERVICE获取用于在多用户情境下启动App的系统服务。

    不管是否显示启动App的动画,最终都会执行startActivity(intent)或launcherApps.startMainActivity方法以启动应用的“MainActivity”。而launcherApps.startMainActivity只在用户句柄不为空且用户句柄不等于当前进程句柄时(其他用户的句柄)调用。

    那为什么用户句柄会影响Activity的启动方式呢?

    这一点和Android的多用户安全机制有关。

    假设我们有用户A和用户B在使用同一台手机,用户A是无法访问到用户B的文件或者和用户B的App通信的。所以假如我们现在是用户A,但我们想启动用户B的App,是无法直接实现的,因为用户A没有权限访问到用户B的数据,即使我们在代码中强行把user id设为用户B的user id,交给内核执行时也会抛出SecurityException。因此我们需要取得用户A的句柄(和用户A相关的数据),将我们想启动的用户B的App的Intent、用户A的句柄交给内核,让拥有权限的Android系统服务(内核态进程)去访问用户B的数据并执行相关的操作。

    假如是单用户情境,就会相对简单了。因为此时只有一个用户,而该用户始终有权限直接访问自己的数据。

    接下来继续看startActivity(intent)如何启动Activity,进入Activity类后层层深入就可以看到最终调用的是startActivityForResult方法:

    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            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());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }
    
            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }
    

    从代码上看,如果Launcher有mParent Activity,就会执行mParent.startActivityFromChild;如果没有,就会执行mInstrumentation.execStartActivity。进入mParent.startActivityFromChild方法会看到最终也是执行了mInstrumentation.execStartActivity。执行完成后,会取得一个ActivityResult对象,用于给调用者Activity传递一些数据,最后在Activity切换时显示Transition动画。

    这里有一点需要指出的是:这里的ParentActivity指的是类似TabActivity、ActivityGroup关系的嵌套Activity。之所以要强调parent和child,是要避免混乱的Activity嵌套关系。

    下面我们进入Instrumentation类看看execStartActivity方法:

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .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;
    }
    

    首先,我们通过参数IBinder contextThread取得一个IApplicationThread类型的对象whoThread,而contextThread是由mMainThread.getApplicationThread()取得的ApplicationThread对象,此时mMainThread指的就是Launcher应用的主线程,所以whoThread指代的自然是Launcher的ApplicationThread。

    因为Activity的onProvideReferrer()方法默认返回null,除非该方法被重写,而我们使用的Launcher并没有重写该方法,所以不用管referrer。

    然后判断是否有ActivityMonitor,如果有,则即将要打开的Activity是否和ActivityMonitor中保存的IntentFilter匹配,如果匹配则增加ActivityMonitor的计数。大致是用于监控符合匹配规则的Activity的数量的。

    最后调用ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);启动Activity,并检查启动是否成功。

    换句话说,最终负责启动Activity的是ActivityManager,前面得到的ApplicationThread也是在这里使用的。

    那么ActivityManager、ApplicationThread、ActivityThread都是什么呢?接下来进行解答。

    友情提示:在启动Activity的时候ActivityManagerService会通过Binder将Launcher切换到pause状态。

    接着往下看,首先,调用ActivityManagerNative.getDefault()方法实际调用的是asInterface(IBinder obj)方法,也就意味着我们使用的其实是ActivityManagerProxy,而ActivityManagerProxy则是ActivityManagerService的代理,详见下面的代码:

    static public IActivityManager getDefault() {
            return gDefault.get();
        }
    
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
    
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
    
        return new ActivityManagerProxy(obj);
    }
    

    那么继续进入ActivityManagerProxy看:

    class ActivityManagerProxy implements IActivityManager
    {
        public ActivityManagerProxy(IBinder remote)
        {
            mRemote = remote;
        }
    
        public IBinder asBinder()
        {
            return mRemote;
        }
    
        public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
                String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
            // 创建两个Parcel对象,data用于传输启动Activity需要的数据,reply用于获取
            // 启动Activity操作执行后系统返回的响应
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IActivityManager.descriptor);
            // caller 就是Launcher提供的ApplicationThread(也就是前面提到的whoThread)
            data.writeStrongBinder(caller != null ? caller.asBinder() : null);
            // 记录启动新Activity的应用的包名,也就是Launcher的包名
            data.writeString(callingPackage);
            intent.writeToParcel(data, 0);
            data.writeString(resolvedType);
            // 将resultTo这个IBinder对象写入data,实际写入的就是前面的参数——IBinder token
            // 而这个token是什么,我们暂时不管,后面会给出解释
            data.writeStrongBinder(resultTo);
            data.writeString(resultWho);
            data.writeInt(requestCode);
            data.writeInt(startFlags);
            if (profilerInfo != null) {
                data.writeInt(1);
                profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
            } else {
                data.writeInt(0);
            }
            if (options != null) {
                data.writeInt(1);
                options.writeToParcel(data, 0);
            } else {
                data.writeInt(0);
            }
            mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
            reply.readException();
            int result = reply.readInt();
            reply.recycle();
            data.recycle();
            return result;
        }
    ……省略余下代码……
    }
    

    将数据都写入后,就通过mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)传输数据并得到响应(写入reply)。

    前面已经提到了,ActivityManagerProxy是ActivityManagerService的代理,那么调用mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)实际上就是通过Binder建立Launcher所在的进程与system_server进程(Android Framework层的服务几乎都由system_server进程管理,因此ActivityManagerService运行在system_server进程中)的通信,并把我们写入data的数据通过Binder传递给ActivityManagerService。

    ActivityManagerService得到我们用Parcelable封装的data后就会调用startActivity方法为Launcher启动Activity:

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }
    
    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }
    
    void enforceNotIsolatedCaller(String caller) {
        if (UserHandle.isIsolated(Binder.getCallingUid())) {
            throw new SecurityException("Isolated process not allowed to call " + caller);
        }
    }
    

    enforceNotIsolatedCaller("startActivity");作安全性检查,判断当前用户是否允许启动Activity,然后对之前传入的userId进行转换和安全性检查。最后调用mStackSupervisor.startActivityMayWait。这里的mStackSupervisor是ActivityStackSupervisor对象,前面提到过,Task是以堆栈形式组织Activity的集合,而Task又由ActivityStack管理,ActivityStackSupervisor则是管理ActivityStack的类。

    源码太多,下面截取部分关键代码来说一下:

    首先,通过下面代码段调用PackageManagerService解析Intent(我们想要打开的App的用于启动MainActivity的Intent),将解析的结果保存到ActivityInfo类型的对象里:

    // Collect information about the target of the Intent.
            ActivityInfo aInfo =
                    resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
    
    // Method - resolveActivity
        ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
                ProfilerInfo profilerInfo, int userId) {
            // Collect information about the target of the Intent.
            ActivityInfo aInfo;
            try {
                ResolveInfo rInfo =
                    AppGlobals.getPackageManager().resolveIntent(
                            intent, resolvedType,
                            PackageManager.MATCH_DEFAULT_ONLY
                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
                aInfo = rInfo != null ? rInfo.activityInfo : null;
            } catch (RemoteException e) {
                aInfo = null;
            }
    
    ……省略,大致是做一些安全性检查和相关信息的设置……
            return aInfo;
        }
    

    然后互斥锁锁住ActivityManagerService的实例mService,如果解析的ActivityInfo不为空,且ApplicationInfo有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE标记,意味着调用者App是属于heavy-weight process,如果现在有另一个heavy-weight process正在运行,则需要进行一些额外的处理,然后进入到startActivityLocked方法。

    这里通过注释我们可以发现,若App有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE标记,App就可视为heavy-weight process,该标记可以在AndroidManifest.xml中设置,它是用于声明App是否享受系统提供的Activity状态保存/恢复功能的。但是似乎没有App能成为heavy-weight process,因为PackageParser的parseApplication方法并不会解析该标签。

    之后在startActivityLocked方法中,得到Launcher(Activity)的ActivityRecord(Activity相关的信息),并创建我们要启动的Activity的ActivityRecord,最终执行startActivityUncheckedLocked继续启动Activity:

    ActivityRecord sourceRecord = null;
            ActivityRecord resultRecord = null;
            if (resultTo != null) {
                sourceRecord = isInAnyStackLocked(resultTo);
                if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                        "Will send result to " + resultTo + " " + sourceRecord);
                if (sourceRecord != null) {
                    if (requestCode >= 0 && !sourceRecord.finishing) {
                        resultRecord = sourceRecord;
                    }
                }
            }
    
    …………
    
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                    intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                    requestCode, componentSpecified, voiceSession != null, this, container, options);
    
    ……
    
    err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, true, options, inTask);
    

    进入startActivityUncheckedLocked方法,完成一些简单的初始化后,向下执行到这段代码:如果Intent里有Intent.FLAG_ACTIVITY_NEW_DOCUMENT标记(在AndroidManifest.xml中声明),且即将要打开的Activity的启动模式又被声明为SingleInstance或SingleTask,那么Intent中携带的标记和AndroidManifest中声明的标记出现冲突,而AndroidManifest的优先级是高于Intent的,因此将launchFlags的对应位置为0。

    然后是对launchFlags一系列的置位,目的是设置启动模式。

    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
                (launchSingleInstance || launchSingleTask)) {
        // We have a conflict between the Intent and the Activity manifest, manifest wins.
        Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
                "\"singleInstance\" or \"singleTask\"");
        launchFlags &=
                ~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        } else {
            switch (r.info.documentLaunchMode) {
                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
                    launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
                    break;
            }
        }
    }
    ……
    
    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
        launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
    }
    
    // If we are actually going to launch in to a new task, there are some cases where
    // we further want to do multiple task.
    if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        if (launchTaskBehind
                || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
            launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
        }
    }
    
    ……
    
    if (inTask == null) {
        if (sourceRecord == null) {
            // This activity is not being started from another...  in this
            // case we -always- start a new task.
            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && inTask == null) {
                Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            }
        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
            // The original activity who is starting us is running as a single
            // instance...  this new activity it is starting must go on its
            // own task.
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        } else if (launchSingleInstance || launchSingleTask) {
            // The activity being started is a single instance...  it always
            // gets launched into its own task.
            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
        }
    }
    
    ……
    
    // 因为我们是从Launcher启动目的Activity,所以sourceRecord不为null,值为Launcher的ActivityRecord
    if (sourceRecord != null) {
        if (sourceRecord.finishing) {
            // 如果sourceRecord表示的Activity正在结束/被销毁,那么我们不能把该Activity看作启动目的
            // Activity的源Activity,因为和源Activity关联的Task现在可能是空的(没有Activity)或者
            // 也在结束/被销毁的过程中,所以我们不能盲目地把目的Activity放到该Task中。取而代之的是,
            // 我们会为它找到一个可用的Task,但我们要先保存源Activity的Task的信息,使得我们在创建新
            // 的可用的Task时能用到里面的一些信息。
            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                Slog.w(TAG, "startActivity called from finishing " + sourceRecord
                        + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                newTaskInfo = sourceRecord.info;
                newTaskIntent = sourceRecord.task.intent;
            }
            sourceRecord = null;
            sourceStack = null;
        } else {
            sourceStack = sourceRecord.task.stack;
        }
    } else {
        sourceStack = null;
    }
    
    ……
    
    // 为目的Activity创建新的Task
    if (r.resultTo == null && inTask == null && !addingToTask
            && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
        newTask = true;
        targetStack = computeStackFocus(r, newTask);
        targetStack.moveToFront("startingNewTask");
    
        if (reuseTask == null) {
            r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                    newTaskInfo != null ? newTaskInfo : r.info,
                    newTaskIntent != null ? newTaskIntent : intent,
                    voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
                    taskToAffiliate);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS,
                    "Starting new activity " + r + " in new task " + r.task);
        } else {
            r.setTask(reuseTask, taskToAffiliate);
        }
        if (isLockTaskModeViolation(r.task)) {
            Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
            return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }
        if (!movedHome) {
            if ((launchFlags &
                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
                // Caller wants to appear on home activity, so before starting
                // their own activity we will bring home to the front.
                r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            }
        }
    }
    

    完成上面一系列的处理后,调用ActivityStack的startActivityLocked方法继续执行启动Activity需要的操作,targetStack是通过这行代码targetStack = computeStackFocus(r, newTask)为用户新建的ActivityStack:

    mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
            intent, r.getUriPermissionsLocked(), r.userId);
    
    if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
        r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
    }
    if (newTask) {
        EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
    }
    ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
    targetStack.mLastPausedActivity = null;
    targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    if (!launchTaskBehind) {
        // Don't set focus on an activity that's going to the back.
        mService.setFocusedActivityLocked(r, "startedActivity");
    }
    return ActivityManager.START_SUCCESS;
    

    进入到ActivityStack的startActivityLocked方法,首先为目的Activity创建ProcessRecord,然后用WindowManager进行一些切换窗口的操作,最后调用mStackSupervisor.resumeTopActivitiesLocked(this, r, options):

    if (!isHomeStack() || numActivities() > 0) {
        // We want to show the starting preview window if we are
        // switching to a new task, or the next activity's process is
        // not currently running.
        boolean showStartingIcon = newTask;
        ProcessRecord proc = r.app;
        if (proc == null) {
            proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
        }
        if (proc == null || proc.thread == null) {
            showStartingIcon = true;
        }
        ……调用WindowManager切换窗口……
    }
    
    ……
    
    if (doResume) {
        mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
    }
    

    进入到resumeTopActivitiesLocked方法,调用resumeTopActivityLocked方法将所有ActivityStack(多个显示设备,每个设备对应一个ActivityStack)栈顶的Activity切换到resume状态(生命周期的onResume),而resumeTopActivityLocked方法先避免递归调用,然后调用ActivityStack的resumeTopActivityInnerLocked方法:

    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // Do targetStack first.
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }
    
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // Already started above.
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }
    

    下面resumeTopActivityInnerLocked()这段代码主要就是做一些前期的检查,避免做多余的工作浪费时间,并且确保目标Activity处于正确的“状态”,使得我们后面能把它切换到resume状态并显示:

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    
        // 判断ActivityManagerService是否已经启动完毕
        if (!mService.mBooting && !mService.mBooted) {
            // Not ready yet!
            return false;
        }
    
        // 获取parentActivity,如果parentActivity还未处于resume状态,则不能将stack栈顶的Activity切换为resume状态(Activity的嵌套关系不能弄乱)
        ActivityRecord parent = mActivityContainer.mParentActivity;
        if ((parent != null && parent.state != ActivityState.RESUMED) ||
                !mActivityContainer.isAttachedLocked()) {
            // Do not resume this stack if its parent is not resumed.
            // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
            return false;
        }
    
        // 如果有正在初始化的Activity没有位于ActivityStack的栈顶,且正在执行window的启动和显示,
        // 则要将window相关的操作取消。因为这类Activity的窗口有可能被孤立,那么它们有可能永远也不会进入resume状态
        cancelInitializingActivities();
    
        // 取得当前ActivityStack栈顶Activity的ActivityRecord
        final ActivityRecord next = topRunningActivityLocked(null);
    
        // 记住我们怎样处理pause/resume状态切换,并确保无论何时结束处理都会重置状态
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;
    
        final TaskRecord prevTask = prev != null ? prev.task : null;
        if (next == null) {
            // next为null表示当前ActivityStack没有要显示的Activity
            final String reason = "noMoreActivities";
            if (!mFullscreen) {
                // 如果当前ActivityStack不是全屏的,将焦点切换到下一个拥有Activity的可见ActivityStack中
                final ActivityStack stack = getNextVisibleStackLocked();
                if (adjustFocusToNextVisibleStackLocked(stack, reason)) {
                    return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null);
                }
            }
            // 如果ActivityStack是全屏的,却没有可以显示的Activity,那么就显示桌面(Launcher)
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: No more activities go home");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
            return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
        }
    
        next.delayedResume = false;
    
        // 如果当前栈顶Activity处于resume状态,且就是我们要打开的Activity,则直接结束
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
                    mStackSupervisor.allResumedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Top activity resumed " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }
    
        // 对prevActivity(Launcher)所在的Task进行一些判断,如果prevTask和nextTask相同,那么直接将
        // prevTask直接设为栈顶Task;如果prevTask不是当前ActivityStack栈顶的Task,那么它后面的Task
        // 都应该放到Launcher的Task后面;后面则是有关是否为桌面的判断和处理了。
        final TaskRecord nextTask = next.task;
        if (prevTask != null && prevTask.stack == this &&
                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
            if (prevTask == nextTask) {
                prevTask.setFrontOfTask();
            } else if (prevTask != topTask()) {
                // This task is going away but it was supposed to return to the home stack.
                // Now the task above it has to return to the home task instead.
                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            } else if (!isOnHomeDisplay()) {
                return false;
            } else if (!isHomeStack()){
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                        "resumeTopActivityLocked: Launching home next");
                final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
                        HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
                return isOnHomeDisplay() &&
                        mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
            }
        }
    
        // 如果ActivityManagerService处于休眠状态,而且此时没有Activity处于resume状态
        // 且栈顶Activity处于pause状态,则中断调度
        if (mService.isSleepingOrShuttingDown()
                && mLastPausedActivity == next
                && mStackSupervisor.allPausedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            mWindowManager.executeAppTransition();
            mNoAnimActivities.clear();
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Going to sleep and all paused");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }
    
        // Make sure that the user who owns this activity is started.  If not,
        // we will just leave it as is because someone should be bringing
        // another user's activities to the top of the stack.
        if (mService.mStartedUsers.get(next.userId) == null) {
            Slog.w(TAG, "Skipping resume of top activity " + next
                    + ": user " + next.userId + " is stopped");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }
    
        // 确保我们要启动的Activity没有处于stop队列、休眠队列、等待变为可见队列中
        mStackSupervisor.mStoppingActivities.remove(next);
        mStackSupervisor.mGoingToSleepActivities.remove(next);
        next.sleeping = false;
        mStackSupervisor.mWaitingVisibleActivities.remove(next);
    
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
    
        // If we are currently pausing an activity, then don't do anything
        // until that is done.
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }
    
    ……待续……
    }
    

    紧接上面的代码在后续的工作就是:将Launcher切换到pause状态,用WindowManager将Launcher的窗口隐藏。

    现在只完成了Activity相关的预处理工作,目标应用的进程和主线程还没有创建,因此后面会进入if的false分支调用mStackSupervisor.startSpecificActivityLocked方法创建应用进程;如果目标Activity的进程和主线程已经创建,则进入if语句的true分支直接将目标Activity切换到resume状态,并显示目标Activity的窗口。此流程看下面的代码:(上面的代码后续)

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    
    ……续上……
    
        // 步入setLaunchSource方法后可以知道,该方法实际是通过PowerManager的setWorkSource方法
        // 设置WakeLock,使得在执行后面的工作时系统不会进入休眠状态
        mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
    
        // 现在开始将当前Activity切换到pause状态,使得栈顶Activity可以切换到resume状态
        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
        // 将后台ActivityStack的Activity切换到pause状态
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        // 将当前ActivityStack中正在显示Activity切换到pause状态
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }
        if (pausing) {
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                    "resumeTopActivityLocked: Skip resume: need to start pausing");
            // At this point we want to put the upcoming activity's process
            // at the top of the LRU list, since we know we will be needing it
            // very soon and it would be a waste to let it get killed if it
            // happens to be sitting towards the end.
            if (next.app != null && next.app.thread != null) {
                mService.updateLruProcessLocked(next.app, true, null);
            }
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }
    
    ……
    
        ActivityStack lastStack = mStackSupervisor.getLastStack();
        if (next.app != null && next.app.thread != null) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);
    
            // 目标Activity已经可见
            mWindowManager.setAppVisibility(next.appToken, true);
    
            next.startLaunchTickingLocked();
    
            ActivityRecord lastResumedActivity =
                    lastStack == null ? null :lastStack.mResumedActivity;
            ActivityState lastState = next.state;
    
            mService.updateCpuStats();
    
            // 目标Activity切换到resume状态
            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
            next.state = ActivityState.RESUMED;
            mResumedActivity = next;
            next.task.touchActiveTime();
            mRecentTasks.addLocked(next.task);
            mService.updateLruProcessLocked(next.app, true, null);
            updateLRUListLocked(next);
            mService.updateOomAdjLocked();
    
    ……
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }
    ……
    }
    

    接下来ActivityManagerService就要为即将打开的应用创建进程。

    进入ActivityStackSupervisor类的startSpecificActivityLocked方法,首先通过应用的包名和uid取得ProcessRecord,判断ProcessRecord是否被创建,若创建,则直接启动Activity;否则调用ActivityManagerService的startProcessLocked方法创建应用进程:

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);
    
        r.task.stack.setLaunchTime(r);
    
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
    
            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }
    
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
    

    进入到ActivityManagerService的startProcessLocked方法,首先判断要创建的进程是否为隔离进程(isolated),由于不是隔离进程,则直接进入true分支,然后再次获取ProcessRecord。如果Intent有FLAG_FROM_BACKGROUND标记,则在后台启动badProcess;否则清空进程的崩溃次数,并将进程移出badProcess集合(如果进程存在的话)。然后调用newProcessRecordLocked方法创建ProcessRecord,最后再调用另一个重载的startProcessLocked方法创建进程:

    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        long startTime = SystemClock.elapsedRealtime();
        ProcessRecord app;
        if (!isolated) {
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            checkTime(startTime, "startProcess: after getProcessRecord");
    
            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
                // If we are in the background, then check to see if this process
                // is bad.  If so, we will just silently fail.
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                            + "/" + info.processName);
                    return null;
                }
            } else {
                // When the user is explicitly starting a process, then clear its
                // crash count so that we won't make it bad until they see at
                // least one crash dialog again, and make the process good again
                // if it had been bad.
                if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                        + "/" + info.processName);
                mProcessCrashTimes.remove(info.processName, info.uid);
                if (mBadProcesses.get(info.processName, info.uid) != null) {
                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                            UserHandle.getUserId(info.uid), info.uid,
                            info.processName);
                    mBadProcesses.remove(info.processName, info.uid);
                    if (app != null) {
                        app.bad = false;
                    }
                }
            }
        } else {
            // If this is an isolated process, it can't re-use an existing process.
            app = null;
        }
    
    ……
    
        String hostingNameStr = hostingName != null
                ? hostingName.flattenToShortString() : null;
    
        if (app == null) {
            checkTime(startTime, "startProcess: creating new process record");
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
            if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            app.crashHandler = crashHandler;
            checkTime(startTime, "startProcess: done creating new process record");
        } else {
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: added package to existing proc");
        }
    
        // 如果系统还没启动完毕,则等待系统启动完毕后再启动进程
        if (!mProcessesReady
                && !isAllowedWhileBooting(info)
                && !allowWhileBooting) {
            if (!mProcessesOnHold.contains(app)) {
                mProcessesOnHold.add(app);
            }
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                    "System not ready, putting on hold: " + app);
            checkTime(startTime, "startProcess: returning with proc on hold");
            return app;
        }
    
        checkTime(startTime, "startProcess: stepping in to startProcess");
        startProcessLocked(
                app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
        checkTime(startTime, "startProcess: done starting proc!");
        return (app.pid != 0) ? app : null;
    }
    

    调用newProcessRecordLocked方法根据ApplicationInfo创建ProcessRecord,并让ActivityManagerService管理该ProcessRecord,过程比较简单就不贴代码了,直接看startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs)方法。

    进入startProcessLocked方法,首先将app的pid初始化,若进程已经存在(pid不等于0),则先清除超时信息,再讲pid置为0,然后确保app不在mProcessesOnHold列表中。

    mProcessesOnHold代表在系统启动完毕前尝试启动的进程,这部分进程会先在该列表中待着,等到系统启动完毕再启动。

    完成一系列的初始化操作后,调用Process.start方法创建应用进程,然后以进程pid为key,app(ProcessRecord)为value存储到ActivityManagerService的mPidsSelfLocked中。

    Process.start方法创建应用进程是通过Zygote进程完成的,设置好参数和创建选项后通过zygoteState.writer将数据交给Zygote进程,它会调用fork()创建进程。

    在这里要注意一个地方,我们通过if (entryPoint == null) entryPoint = "android.app.ActivityThread"这行代码设置了进程创建完成后的入口点(Process.start的参数注释),因此Zygote进程完成了进程创建的操作后就会执行ActivityThread的main()方法。

    下面看startProcessLocked的代码:

    private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        long startTime = SystemClock.elapsedRealtime();
        if (app.pid > 0 && app.pid != MY_PID) {
            checkTime(startTime, "startProcess: removing from pids map");
            synchronized (mPidsSelfLocked) {
                mPidsSelfLocked.remove(app.pid);
                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
            }
            checkTime(startTime, "startProcess: done removing from pids map");
            app.setPid(0);
        }
    
        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
                "startProcessLocked removing on hold: " + app);
        mProcessesOnHold.remove(app);
    ……
    
            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
    ……
    }
    

    进入到ActivityThread的main方法以后,首先进行一些初始化(包括参数设置、性能安全监控之类的),然后初始化Looper(Looper、Handler消息机制),创建ActivityThread,存储线程的Handler,最后启动Looper监听消息。

    再之后ActivityThread通过Binder将ApplicationThread对象传递给ActivityManagerService,并完成启动Activity的后续工作。

    到这里ActivityThread的初始化就完成了,但是回想一下前面的工作,我们现在将Launcher切换到了pause状态,但由于目标应用进程和线程还没有创建,所以我们还没有把目标应用的MainActivity切换到resume状态。所以就意味着,我们还需要进行应用进程和ActivityManagerService所在的system_server进程的通信,告诉ActivityManagerService我们已经创建好了进程和线程,接下来把MainActivity状态切换到resume中,就能打开应用了。

    这一步工作在哪里完成的呢:thread.attach(false)

    final IActivityManager mgr = ActivityManagerNative.getDefault();看到这行代码有没有熟悉的感觉?前面我们就通过ActivityManagerNative.getDefault()取得ActivityManagerService的代理对象,完成了启动MainActivity的前期工作。这里再次取得代理对象,并调用了ActivityManagerService的attachApplication方法。

    public static void main(String[] args) {
    ……
    
        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");
    }
    
    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
    ……
        } else {
    ……
        }
    ……
    }
    

    进入到ActivityManagerService的attachApplication方法,前面我们已经存储过目标应用的pid-ProcessRecord键值对了,因此这里的app不为null。然后向下执行,激活ProcessRecord并将ProcessRecord绑定到应用进程。然后通过Binder(thread.bindApplication)将各种应用相关信息传递给应用进程,进行应用进程一些必要的设置。最后调用mStackSupervisor.attachApplicationLocked(app)方法将ApplicationThread对象传递给ActivityManagerService方便后续应用进程与ActivityManagerService的通信(如:将MainActivity切换到resume状态),并完成启动应用的所有工作。

    @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
    
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
    
        // Find the application record that is being attached...  either via
        // the pid if we are running in multiple processes, or just pull the
        // next app record if we are emulating process with anonymous threads.
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }
    
        // 此时app不为null,跳过
        if (app == null) {
    ……
        }
    
        // 清除ProcessRecord中的信息,以确保没有不相关进程的信息
        if (app.thread != null) {
            handleAppDiedLocked(app, true, true);
        }
    
        // Tell the process all about itself.
    
        if (DEBUG_ALL) Slog.v(
                TAG, "Binding process pid " + pid + " to record " + app);
    
        // 注册DeathRecipient,确保应用意外关闭时系统进程能收到通知
        final String processName = app.processName;
        try {
            AppDeathRecipient adr = new AppDeathRecipient(
                    app, pid, thread);
            thread.asBinder().linkToDeath(adr, 0);
            app.deathRecipient = adr;
        } catch (RemoteException e) {
            app.resetPackageList(mProcessStats);
            startProcessLocked(app, "link fail", processName);
            return false;
        }
    
        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
    
        app.makeActive(thread, mProcessStats);
        app.curAdj = app.setAdj = -100;
        app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
        app.forcingToForeground = null;
        updateProcessForegroundLocked(app, false, false);
        app.hasShownUi = false;
        app.debugging = false;
        app.cached = false;
        app.killedByAm = false;
    
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
    ……
        // 调用ActivityThread的bindApplication方法
        try {
    ……
            thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
                    profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            updateLruProcessLocked(app, false, null);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
    ……
        }
    
    ……
    
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
    
        // Find any services that should be running in this process...
        if (!badApp) {
    ……
        }
    
        // Check if a next-broadcast receiver is in this process...
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
    ……
        }
    
        // Check whether the next backup agent is in this process...
        if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
    ……
        }
    
    ……
    
        return true;
    }
    

    后面就是ActivityManagerService通知ActivityThread启动Activity了。

    回到ActivityThread,先看bindApplication方法,就是将上面传的数据存储在AppBindData中,然后通过Message、Handler发送出去,我们再看看Handler是怎么处理H.BIND_APPLICATION类型的Message的。

    public final void bindApplication(String processName, ApplicationInfo appInfo,
            List<ProviderInfo> providers, ComponentName instrumentationName,
            ProfilerInfo profilerInfo, Bundle instrumentationArgs,
            IInstrumentationWatcher instrumentationWatcher,
            IUiAutomationConnection instrumentationUiConnection, int debugMode,
            boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
            Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
            Bundle coreSettings) {
    ……
    
        AppBindData data = new AppBindData();
        data.processName = processName;
        data.appInfo = appInfo;
        data.providers = providers;
        data.instrumentationName = instrumentationName;
        data.instrumentationArgs = instrumentationArgs;
        data.instrumentationWatcher = instrumentationWatcher;
        data.instrumentationUiAutomationConnection = instrumentationUiConnection;
        data.debugMode = debugMode;
        data.enableOpenGlTrace = enableOpenGlTrace;
        data.restrictedBackupMode = isRestrictedBackupMode;
        data.persistent = persistent;
        data.config = config;
        data.compatInfo = compatInfo;
        data.initProfilerInfo = profilerInfo;
        sendMessage(H.BIND_APPLICATION, data);
    }
    
    case BIND_APPLICATION:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
        AppBindData data = (AppBindData)msg.obj;
        handleBindApplication(data);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;
    

    可以看到最终调用了handleBindApplication方法,进入到handleBindApplication方法,首先进行一些初始化操作,然后取出data中存储的进程名,为应用进程设置进程名。然后创建应用的Context,也就是应用的运行上下文,通过Context我们可以访问到应用相关的各种资源文件(图片、布局文件等等)。然后创建进程的Instrumentation对象、Application对象,装载Provider,最终调用mInstrumentation.callApplicationOnCreate(app)方法,也就是调用我们开发App时,Application类(或子类)的onCreate()方法。

    private void handleBindApplication(AppBindData data) {
    ……
    
        // send up app name; do this *before* waiting for debugger
        Process.setArgV0(data.processName);
        android.ddm.DdmHandleAppName.setAppName(data.processName,
                                                UserHandle.myUserId());
    
    ……设置进程运行信息……
    
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    
    ……继续进程的初始化……
    
        if (data.instrumentationName != null) {
            ……
    
        } else {
            mInstrumentation = new Instrumentation();
        }
    
    ……
    
        try {
            // If the app is being launched for full backup or restore, bring it up in
            // a restricted environment with the base application class.
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;
    
            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                List<ProviderInfo> providers = data.providers;
                if (providers != null) {
                    installContentProviders(app, providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }
    
    ……
    
            try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        } finally {
            StrictMode.setThreadPolicy(savedPolicy);
        }
    }
    

    至此应用进程相关的初始化和相关的设置就完成了,接下来只要切换MainActivity的状态就大功告成了。

    进入到ActivityStackSupervisor类的attachApplicationLocked方法,该方法遍历mActivityDisplays列表得到当前所有ActivityStack,然后取得前台ActivityStack栈顶的ActivityRecord,不为空则启动该对该ActivityRecord调用realStartActivityLocked方法。

    boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFrontStack(stack)) {
                    continue;
                }
                ActivityRecord hr = stack.topRunningActivityLocked(null);
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                  + hr.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }
            }
        }
        if (!didSomething) {
            ensureActivitiesVisibleLocked(null, 0);
        }
        return didSomething;
    }
    

    到这里,后面就该ActivityThread调度执行Activity生命周期方法,完成Activity的启动。

    进入到realStartActivityLocked方法,进行一些前期处理后调用ActivityThread的scheduleLaunchActivity方法,将创建ActivityClientRecord存储我们传入的各种应用相关的数据,通过Handler机制发送。当Handler接收到LAUNCH_ACTIVITY类型的消息时,执行handleLaunchActivity方法。

    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                        new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                        task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                        newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
    
    @Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    
        updateProcessState(procState, false);
    
        ActivityClientRecord r = new ActivityClientRecord();
    
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.referrer = referrer;
        r.voiceInteractor = voiceInteractor;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.persistentState = persistentState;
    
        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;
    
        r.startsNotResumed = notResumed;
        r.isForward = isForward;
    
        r.profilerInfo = profilerInfo;
    
        r.overrideConfig = overrideConfig;
        updatePendingConfiguration(curConfig);
    
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
    
    case LAUNCH_ACTIVITY: {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
    
        r.packageInfo = getPackageInfoNoCheck(
                r.activityInfo.applicationInfo, r.compatInfo);
        handleLaunchActivity(r, null);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    } break;
    

    进入到handleLaunchActivity方法,首先进行参数设置,然后调用performLaunchActivity方法得到目标应用的MainActivity并使其分别调用onCreate、onStart方法,然后调用handleResumeActivity方法让MainActivity进入resume状态,完成启动。

    private 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);
    
    ……
        } else {
    ……
        }
    }
    
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // 初始化设置
    ……
    
        // 通过反射获得MainActivity
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }
    
        try {
    ……
    
            if (activity != null) {
                // 为MainActivity创建运行的上下文环境Context,并与Activity绑定
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor);
    
    ……
                // 回调MainActivity生命周期的onCreate方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
    ……
                // 回调MainActivity生命周期的onStart方法
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
    ……
    
        } catch (SuperNotCalledException e) {
            throw e;
    
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to start activity " + component
                    + ": " + e.toString(), e);
            }
        }
    
        return activity;
    }
    
    final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;
    
        // TODO Push resumeArgs into the activity for consideration
        ActivityClientRecord r = performResumeActivity(token, clearHide);
    
    ……
    }
    

    好了,到了这里,apk启动流程的源码分析就算是完成了,咱们已经对apk的启动流程有清晰的认知和理解了。

    最后总结一下app启动步骤:

    (1)启动的起点发生在Launcher活动中,启动一个app说简单点就是启动一个Activity,那么我们说过所有组件的启动,切换,调度都由AMS来负责的,所以第一步就是Launcher响应了用户的点击事件,然后通知AMS;

    (2)AMS得到Launcher的通知,就需要响应这个通知,主要就是新建一个Task去准备启动Activity,并且告诉Launcher你可以休息了(Paused);

    (3)Launcher得到AMS让自己“休息”的消息,那么就直接挂起,并告诉AMS我已经Paused了;

    (4)AMS知道了Launcher已经挂起之后,就可以放心的为新的Activity准备启动工作了,首先,APP肯定需要一个新的进程去进行运行,所以需要创建一个新进程,这个过程是需要Zygote参与的,AMS通过Socket去和Zygote协商,如果需要创建进程,那么就会fork自身,创建一个线程,新的进程会导入ActivityThread类,这就是每一个应用程序都有一个ActivityThread与之对应的原因;

    (5)进程创建好了,通过调用上述的ActivityThread的main方法,这是应用程序的入口,在这里开启消息循环队列,这也是主线程默认绑定Looper的原因;

    (6)这时候,App还没有启动完,要永远记住,四大组建的启动都需要AMS去启动,将上述的应用进程信息注册到AMS中,AMS再在堆栈顶部取得要启动的Activity,通过一系列链式调用去完成App启动;
    最后copy这张图很好的描述了上面的六大步:

     
    

    好了,本文结束了  see  you

    展开全文
  • 简述APP启动流程

    千次阅读 2019-09-27 20:01:11
    AMS启动APP 启动App,通常是启动App的一个Activity,一般是主Activity. 用户从Launcher程序点击应用图标可启动应用的入口Activity,Activity启动时需要多个进程之间的交互 AMS进程实际上是SystemServer进程,因为...
  • 安卓 应用app启动过程.pdf
  • android-App启动过程

    千次阅读 2018-09-24 00:17:04
    APP启动流程涉及的类和调用的方法还是蛮多的,做为android应用开发其实知道整个流程和重要的调用方法就够了。但是在了解整个流程前,得先知道涉及的相关知识,这样才能更好理解后面整个流程。后面源码分析基于...
  • APP启动流程详解

    2018-02-03 18:24:49
    详细的解说了APP启动过程及其核心代码,为学习Android framework框架提供了很好的学习资料
  • Flutter APP 启动过程源码分析.pdf
  • Android应用App启动流程

    千次阅读 2017-07-17 14:44:29
    说来惭愧,开发了2-3年的Android,竟还不知道App启动流程。趁着学习的Binder机制知识,顺便理清当我们点击桌面应用的图标来启动App过程。概述 当Launcher启动一个App,Launcher会通过IPC通知ActivityManager...
  • Android app启动流程 桌面进程收到点击,并进行响应 桌面进程进入onpause状态 System进程通过fork zygote进程复制出app进程 在复制出的进程中创建ActivityThread,病启动main方法,接受消息循环 进程的信息注册...
  • App启动过程:Activity启动过程详解从桌面点击到activity启动的过程1、Launcher线程捕获onclick的点击事件,调用Launcher.startActivitySafely,进一步调用Launcher.startActivity,最后调用父类Activity的start...
  • Android面试题(31)-App启动流程

    千次阅读 多人点赞 2018-03-08 23:43:59
    在看这篇文章之前,希望先看完我的之前的博客 android面试(6)-Binder机制,因为关于App启动流程设计很多Binder通信; 先将“三个进程”,“六个大类”进行介绍: 三个进程: Launcher进程:整个App启动流程的...
  • Android系统应用层App启动过程分析 Android启动App: 1、 先有Lancher启动ActivityThread,ActivityThread负责onPause、onStart等调度所有MainActivity; 2、 ActivityThread为App分配栈内存,使用:...
  • 学习App启动流程的时候,看到这个图。提出两个问题: 1.是否每一个启动的APP都有各独立的一套 ActivityManage,PackageManager,PowerManger等等这些服务? 2.zygote进程有一个监听启动APP的socket。 当有收到...
  • Android APP启动过程

    2017-03-09 11:31:23
    APP启动方式: 冷启动是指应用尚未运行,系统创建进程并初始化应用。 热启动是指应用已经运行但是在后台被挂起,从后台恢复应用。 针对APP的冷启动方式简述APP的一般启动过程,主要使用了启动页、闪屏、引导页...
  • Android App启动流程

    千次阅读 2017-02-28 12:34:51
    前言在使用Android手机时,...在开始分析之前,我们先回想下启动一个App流程:Android系统桌面->点击应用图标->启动App从这个过程来看,只要弄明白: Android系统桌面是什么 点击应用图标后Android系统执行了什么操
  • APP启动流程

    千次阅读 2019-02-20 10:59:11
    关于APP启动以及如何实现界面跳转,我这边简单绘制了一张图。可以辅助了解一下,具体说明要看我的详细博客介绍。
  • Android系统(116)---APP启动过程.pdf
  • H5游戏微端开发(三):app启动流程

    千次阅读 2019-08-02 22:11:18
    App启动流程 个人认为一个H5游戏微端app的启动流程应该是这样的: Created with Raphaël 2.2.0游戏启动页检测联网是否联网?访问游戏主页是否访问成功?进入游戏显示错误页面yesnoyesno 自定义html 在Android ...
  • 本文主要介绍了Android App启动流程和两种启动模式,属于Android UI优化的基础理论知识。
  • iOS的app启动流程原理

    2018-07-26 10:09:28
    APP启动流程 main文件 #import &lt;UIKit/UIKit.h&gt; #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, ...
  • 本文以图文并茂的形式...原地址链接:http://www.jianshu.com/p/a72c5ccbd150一、流程概述启动流程:①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;②system_server进程接
  • 一张图概括App启动流程

    千次阅读 2017-08-25 14:55:48
    参考:http://www.sohu.com/a/130814934_675634 (感谢楼主)三、启动流程:①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;(startActivity()中调用Ac
  • APP启动流程分析(上)

    千次阅读 2020-11-16 20:06:06
    ActivityManagerService的启动流程介绍总体流程涉及的数据结构ProcessRecord(进程)ActivityRecordTaskRecordActivityStackActivityStackSupervisor详细的流程 介绍 这篇文章是讲,从手机桌面(Launcher)点击一个...
  • 前言:项目中被诟病多媒体开机第一次启动很慢,大约3s的黑屏,后续点开启动正常,其中什么原理呢?这就涉及到系统的三种启动模型 ...loding and launching the app displaying a blank window creat...
  • APP启动流程简单描述

    2018-03-02 10:59:27
    启动流程: ①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求; ②system_server进程接收到请求后,向zygote进程发送创建进程的请求; ③Zygote进程fork出新的子进程,即...
  • Android APP启动过程中应用代码的加载

    千次阅读 2017-08-10 16:56:56
    Android APP启动过程中应用代码的加载APP启动过程 zygote->ActivityThread过程略过 ActivityThread main函数 attach->ActivityManagerNative获得AMS代理对象IActivityManager ->AMS attachApplication AMS ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 367,483
精华内容 146,993
关键字:

app启动流程