Activity启动流程学习笔记

Zygote是什么?有什么作用?

Android系统底层基于Linux Kernel, 当Kernel启动过程会创建init进程, 该进程是所有用户空间的鼻祖, init进程会启动ServiceManager(Binder服务管家)、 Zygote进程(Java进程的鼻祖)。Zygote进程会创建 system_server进程以及各种App进程。

Zygote进程:是Android系统的首个Java进程,Zygote是所有Java进程的父进程,包括 system_server进程以及所有的App进程都是Zygote的子进程,注意这里说的是子进程,而非子线程。

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

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

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

SystemServer是什么?有什么作用?它与zygote的关系是什么?

首先我要告诉你的是,SystemServer也是一个进程,而且是由zygote进程fork出来的。

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

为什么说SystemServer非常重要呢?因为系统里面重要的服务都是在这个进程里面开启的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看着是不是都挺眼熟的?

那么这些系统服务是怎么开启起来的呢?

在zygote开启的时候,会调用ZygoteInit.main()进行初始化

public static void main(String argv[]) {

     ...ignore some code...

    //在加载首个zygote的时候,会传入初始化参数,使得startSystemServer = true
     boolean startSystemServer = false;
     for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            ...ignore some code...

         //开始fork我们的SystemServer进程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }

     ...ignore some code...

}

ActivityManagerService是什么?什么时候初始化的?有什么作用?

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

ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService。从下面的代码中可以看到

public final class SystemServer {

    //zygote的主入口
    public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }

    private void run() {

        ...ignore some code...

        //加载本地系统服务库,并进行初始化 
        System.loadLibrary("android_servers");
        nativeInit();

        // 创建系统上下文
        createSystemContext();

        //初始化SystemServiceManager对象,下面的系统服务开启都需要调用SystemServiceManager.startService(Class),这个方法通过反射来启动对应的服务
        mSystemServiceManager = new SystemServiceManager(mSystemContext);

        //开启服务
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        ...ignore some code...

    }

    //初始化系统上下文对象mSystemContext,并设置默认的主题,mSystemContext实际上是一个ContextImpl对象。调用ActivityThread.systemMain()的时候,会调用ActivityThread.attach(true),而在attach()里面,则创建了Application对象,并调用了Application.onCreate()。
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

    //在这里开启了几个核心的服务,因为这些服务之间相互依赖,所以都放在了这个方法里面。
    private void startBootstrapServices() {

        ...ignore some code...

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

        //初始化PowerManagerService,因为其他服务需要依赖这个Service,因此需要尽快的初始化
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

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

        // 初始化DisplayManagerService
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    //初始化PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
       mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

    ...ignore some code...

    }

}

经过上面这些步骤,我们的ActivityManagerService对象已经创建好了,并且完成了成员变量初始化。而且在这之前,调用createSystemContext()创建系统上下文的时候,也已经完成了mSystemContext和ActivityThread的创建。注意,这是系统进程开启时的流程,在这之后,会开启系统的Launcher程序,完成系统界面的加载与显示。

你是否会好奇,我为什么说AMS是服务端对象?下面我给你介绍下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的启动过程则由其所属的进程具体来完成。

这样说你可能还是觉得比较抽象,没关系,下面有一部分是专门来介绍AMS与ActivityThread如何一起合作控制Activity的生命周期的。

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 {
                   }1234

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

那么到底是处理的哪个对象的点击事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件呀,是的,我找到了布局文件launcher.xml


为了方便查看,我删除了很多代码,从上面这些我们应该可以看出一些东西来:Launcher大量使用标签来实现界面的复用,而且定义了很多的自定义控件实现界面效果,dock_divider从布局的参数声明上可以猜出,是底部操作栏和上面图标布局的分割线,而paged_view_indicator则是页面指示器,和App首次进入的引导页下面的界面引导是一样的道理。当然,我们最关心的是Workspace这个布局,因为注释里面说在这里面包含了5个屏幕的单元格,想必你也猜到了,这个就是在首页存放我们图标的那五个界面(不同的ROM会做不同的DIY,数量不固定)。

CellLayout确实是继承自ViewGroup。在CellLayout里面,只放了一个子View,那就是ShortcutAndWidgetContainer。从名字也可以看出来,ShortcutAndWidgetContainer这个类就是用来存放快捷图标Widget小部件的,那么里面放的是什么对象呢?

在桌面上的图标,使用的是BubbleTextView对象,这个对象在TextView的基础之上,添加了一些特效,比如你长按移动图标的时候,图标位置会出现一个背景(不同版本的效果不同),所以我们找到BubbleTextView对象的点击事件,就可以找到Launcher如何开启一个App了。

除了在桌面上有图标之外,在程序列表中点击图标,也可以开启对应的程序。这里的图标使用的不是BubbleTextView对象,而是PagedViewIcon对象,我们如果找到它的点击事件,就也可以找到Launcher如何开启一个App。

其实说这么多,和今天的主题隔着十万八千里,上面这些东西,你有兴趣就看,没兴趣就直接跳过,不知道不影响这篇文章阅读。

BubbleTextView的点击事件在哪里呢?我来告诉你:在Launcher.onClick(View v)里面。

public void onClick(View v) {
        ...ignore some code...

        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()));
        //开始开启Activity咯~
            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) {
        ...ignore some code...
        }
    }

从上面的代码我们可以看到,在桌面上点击快捷图标的时候,会调用

startActivitySafely(v, intent, tag);

那么从程序列表界面,点击图标的时候会发生什么呢?实际上,程序列表界面使用的是AppsCustomizePagedView对象,所以我在这个类里面找到了onClick(View v)。

public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
        View.OnClickListener,View.OnKeyListener,DragSource,PagedViewIcon.PressedCallback, 
        PagedViewWidget.ShortPressListener, LauncherTransitionable {

    @Override
    public void onClick(View v) {
        ...
        
        if (v instanceof PagedViewIcon) {
            mLauncher.updateWallpaperVisibility(true);
            mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
        } else if (v instanceof PagedViewWidget) {
                 ...ignore some code..
        }
    }      
}

可以看到,调用的是

mLauncher.startActivitySafely(v, appInfo.intent, appInfo);

和上面一样!这叫什么?这叫殊途同归!

所以咱们现在又明白了一件事情:不管从哪里点击图标,调用的都是Launcher.startActivitySafely()。

  • 下面我们就可以一步步的来看一下Launcher.startActivitySafely()到底做了什么事情。
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();           
    }
    return success;
}

调用了startActivity(v, intent, tag)

boolean startActivity(View v, Intent intent, Object tag) {

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);

            if (useLaunchAnimation) {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    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) {
        ...
        }
        return false;
}

这里会调用Activity.startActivity(intent, opts.toBundle()),这个方法熟悉吗?这就是我们经常用到的Activity.startActivity(Intent)的重载函数。而且由于设置了

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

所以这个Activity会添加到一个新的Task栈中,而且,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);
        }
}

所以我们现在明确了,Launcher中开启一个App,其实和我们在Activity中直接startActivity()基本一样,都是调用了Activity.startActivityForResult()。

Instrumentation是什么?和ActivityThread是什么关系?

还记得前面说过的Instrumentation对象吗?每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象。当startActivityForResult()调用之后,实际上还是调用了mInstrumentation.execStartActivity()

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());
            }
            ...ignore some code...    
        } else {
            if (options != null) {
                 //当现在的Activity有父Activity的时候会调用,但是在startActivityFromChild()内部实际还是调用的mInstrumentation.execStartActivity()
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
         ...ignore some code...    
    }

下面是mInstrumentation.execStartActivity()的实现

 public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...ignore some code...
    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) {
    }
    return null;
}

所以当我们在程序中调用startActivity()的 时候,实际上调用的是Instrumentation的相关的方法。

Instrumentation意为“仪器”,我们先看一下这个类里面包含哪些方法吧


我们可以看到,这个类里面的方法大多数和Application和Activity有关,是的,这个类就是完成对Application和Activity初始化和生命周期的工具类。比如说,我单独挑一个callActivityOnCreate()让你看看

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}

对activity.performCreate(icicle);这一行代码熟悉吗?这一行里面就调用了传说中的Activity的入口函数onCreate(),不信?接着往下看Activity.performCreate()

final void performCreate(Bundle icicle) {
    onCreate(icicle);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

没骗你吧,onCreate在这里调用了吧。但是有一件事情必须说清楚,那就是这个Instrumentation类这么重要,为啥我在开发的过程中,没有发现他的踪迹呢?

是的,Instrumentation这个类很重要,对Activity生命周期方法的调用根本就离不开他,他可以说是一个大管家,但是,这个大管家比较害羞,是一个女的,管内不管外,是老板娘~

那么你可能要问了,老板是谁呀?
老板当然是大名鼎鼎的ActivityThread了

public final class ActivityThread {//没有继承或者实现其他类。

    final ApplicationThread mAppThread = new ApplicationThread();
    
    public ApplicationThread getApplicationThread(){
        return mAppThread;
    }

    //ActivityThread的内部类ApplicationThread 
    private class ApplicationThread extends ApplicationThreadNative {
    ......
    }
}

ApplicationThreadNative就是相当于AIDL通讯中的Stub,也就是服务端,ApplicationThreadProxy即AIDL通讯中的Proxy,也就是客户端。所以ApplicationThread是通讯的具体实现类。

ActivityThread你都没听说过?那你肯定听说过传说中的UI线程吧?是的,这就是UI线程。我们前面说过,App和AMS是通过Binder传递信息的,那么ActivityThread就是专门与AMS的外交工作的

AMS说:“ActivityThread,你给我暂停一个Activity!”
ActivityThread就说:“没问题!”然后转身和Instrumentation说:“老婆,AMS让暂停一个Activity,我这里忙着呢,你快去帮我把这事办了把~”
于是,Instrumentation就去把事儿搞定了。

所以说,AMS是董事会,负责指挥和调度的,ActivityThread是老板,虽然说家里的事自己说了算,但是需要听从AMS的指挥,而Instrumentation则是老板娘,负责家里的大事小事,但是一般不抛头露面,听一家之主ActivityThread的安排

如何理解AMS和ActivityThread之间的Binder通信?

前面我们说到,在调用startActivity()的时候,实际上调用的是

mInstrumentation.execStartActivity()

但是到这里还没完呢!里面又调用了下面的方法

ActivityManagerNative.getDefault().startActivity()

这里的ActivityManagerNative.getDefault返回的就是ActivityManagerService的远程接口,即ActivityManagerProxy

怎么知道的呢?往下看

public abstract class ActivityManagerNative extends Binder implements IActivityManager{

    //从类声明上,可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

    //通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得
    private static final Singleton gDefault = new Singleton() {
    
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            IActivityManager am = asInterface(b);
            return am;
        }
    };

    //最终返回的还是一个ActivityManagerProxy对象
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        
        if (in != null) {
            return in;
        }

     //这里面的Binder类型的obj参数会作为ActivityManagerProxy的成员变量保存为mRemote成员变量,负责进行IPC通信
        return new ActivityManagerProxy(obj);
    }
}
 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 = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        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;
}

再看ActivityManagerProxy.startActivity(),在这里面做的事情就是IPC通信,利用Binder对象,调用transact(),把所有需要的参数封装成Parcel对象,向AMS发送数据进行通信

ActivityManagerProxy经过Binder IPC,进入ActivityManagerNative。接下来程序进入了system_servr进程,开始继续执行。接下来程序进入了system_servr进程,开始继续执行。

transact方法是一个本地方法;它的实现在native层,具体来说在frameworks/base/core/jni/android_util_Binder.cpp文件,里面进行了一系列的函数调用它最终调用到了talkWithDriver函数;看这个函数的名字就知道,通信过程要交给驱动完成了;这个函数最后通过ioctl系统调用,Client进程陷入内核态,Client调用add方法的线程挂起等待返回;驱动完成一系列的操作之后唤醒Server进程,调用了Server进程本地对象的onTransact函数(实际上由Server端线程池完成)。Binder本地对象的onTransact方法(这里就是Stub类里面的此方法)

ActivityManagerService本质就是一个Binder,并且实体在服务端。AMS在远端操作着Activity的生命周期。这个进程由SystemServer进程fork出来。

ActivityThread。大家都知道ActivityThread就是应用的UI线程,main方法就是整个应用的入口。ActivityThread本质并不是一个线程,他只是依附着主线程存在。ActivityThread通过和AMS进行IPC通信来共同管理Activity的生命周期。在后面我准备写一篇关于Handle的续篇,里面还会提到他,因为主线程里面的Looper就是在这里init的。

ApplicationThread。它是ActivityThread的内部类,本质上ActivityThread是通过它来进行和AMS的IPC通信的。它的本质也是一个Binder!只不过这次他的实体放在客户端,AMS通过他的代理类ApplicationThreadProxy来和ApplicationThread通信。

Instrumentation。这个类我在看完第一遍书的时候感觉操作调用链里面的最外层。因为最后一步Activity实例对象的生成和onCreat()方法的调用最终是来自这个类的。其实这个类是ActivityThread想要进行的操作的具体操作类。这个类是全局的,并且每个Acitivity里面都拥有一个它的引用。

对Binder的理解

Binder本质上只是一种底层通信方式,和具体服务没有关系。为了提供具体服务,Server必须提供一套接口函数以便Client通过远程访问使用各种服务。这时通常采用Proxy设计模式:将接口函数定义在一个抽象类中,Server和Client都会以该抽象类为基类实现所有接口函数,所不同的是Server端是真正的功能实现,而Client端是对这些函数远程调用请求的包装

为了更方便的说明客户端和服务器之间的Binder通信,下面以ActivityManagerServices和他在客户端的代理类ActivityManagerProxy为例。

ActivityManagerServices和ActivityManagerProxy都实现了同一个接口——IActivityManager。

ActivityManagerNative.getDefault()就是ActivityManagerService的代理类!AMS和代理类本质上都是IActivityManager的实现类。

class ActivityManagerProxy implements IActivityManager{}

public final class ActivityManagerService extends ActivityManagerNative{}

public abstract class ActivityManagerNative extends Binder implements IActivityManager{}

虽然都实现了同一个接口,但是代理对象ActivityManagerProxy并不会对这些方法进行真正地实现,ActivityManagerProxy只是通过这种方式对方法的参数进行打包(因为都实现了相同接口,所以可以保证同一个方法有相同的参数,即对要传输给服务器的数据进行打包),真正实现的是ActivityManagerService。

但是这个地方并**不是直接由客户端传递给服务器,而是通过Binder驱动进行中转。其实我对Binder驱动并不熟悉,我们就把他当做一个中转站就OK,客户端调用ActivityManagerProxy接口里面的方法,把数据传送给Binder驱动,然后Binder驱动就会把这些东西转发给服务器的ActivityManagerServices,由ActivityManagerServices去真正的实施具体的操作。

但是Binder只能传递数据,并不知道是要调用ActivityManagerServices的哪个方法,所以在数据中会添加方法的唯一标识码,比如前面的startActivity()方法:

public int startActivity() throws RemoteException {
    ...
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
}

上面的START_ACTIVITY_TRANSACTION就是方法标示,data是要传输给Binder驱动的数据,reply则接受操作的返回值。

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

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

但是!这里Binder通信是单方向的,即从ActivityManagerProxy指向ActivityManagerService的,如果AMS想要通知ActivityThread做一些事情,应该咋办呢?

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

客户端:ApplicationThread <=====Binder驱动<===== ApplicationThreadProxy:服务器

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

private class ApplicationThread extends ApplicationThreadNative {}

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}

class ApplicationThreadProxy implements IApplicationThread {}12345

AMS接收到客户端的请求之后,会如何开启一个Activity?

ActivityStack(AMS中)。很好懂,一个Activity栈。但是这个ActivityStack是有两种类型的,一种叫系统ActivityStack(HomeTask),这一类的ActivityStack包含着Launcher(或者有其他我不知道的),还有一种是普通应用的ActivityStack(安卓中Task这个概念的具体实现形式),其实就是一个Task(任务栈)。这个类是由AMS来管理,AMS通过这个数据结构来得知Activity的状态。

ActivityStackSuperisor(AMS中)。加了一个单词,就是Activity栈的管理者。这个类的作用就是管理栈,并且通过ActivityStack来获得要启动的activity的信息。

ActivityRecord。这个就是上面说的服务端的Actiivty信息的载体类。并且也是服务端的类~这个类相当的重要,自始至终都贯穿在调用链里面,在安卓ActivityStack里面存储的并不是activity实例,其实就是这个ActivityRecord的实例。

ActivityClientRecord。这个和上面区别就是这个类是客户端activity信息的载体类。

TaskRecord。同样,这个类就是ActivityTask的信息记录类而已。

至此,点击桌面图标调用startActivity(),终于把数据和要开启Activity的请求发送到了AMS了。说了这么多,其实这些都在一瞬间完成了,下面咱们研究下AMS到底做了什么。

AMS收到startActivity的请求之后,会按照如下的方法链进行调用

注意,从这里开始,调用链会变得很复杂

@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) {
      //调用了startActivityAsUser,caller是我们的ApplicaitonThread
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
}

继续看这个startActivityAsUser()方法:

@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. caller是我们的ApplicaitonThread
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, userId, null, null);
}

startActivityAsUser()方法中调用了ActivityStackSupervisor的startActivityMayWait()方法。这里的目的就是想去通过栈的管理者来通过传进来的数据去改变栈,并且拿到被启动Activity的ActivityRecord实例

startActivityMayWait()里面,主要做了ActivityStack、ActivityInfo、 LaunchMode等等各种信息的初始化工作,然后就又调用了startActivityLocked()方法, 这个方法里面又做了一系列的变量初始化,初始启动的错误判断, UID检查之后,又调用了startActivityUncheckedLocked()方法。这个方法里面根据前面一系列的工作,确定了最终的LanuchMode,这个LaunchMode会在后面的函数被拿来进行判断,构建了一个新的Intent、ActivityInfo、ActivityTask。

ActivityStarter

startActivityMayWait方法根据Intent在系统中找到合适的应用的Activity,如果有多个Activity可选择,
则会弹出ResolverActivity让用户选择合适的应用。再调用startActivityLocked方法

在startActivityLocked方法里,对传过来的参数做一些校验,然后创建ActivityRecord对象,再调用startActivityUnchecked方法启动Activity。

startActivityUnchecked方法负责调度ActivityRecord和Task,理解该方法是理解Actvity启动模式的关键。

startActivityUnchecked方法调度Task的算法非常复杂,和当前回退栈,要启动的acitivity的启动模式以及taskAffinity属性,启动activity时设置的intent的flag等诸多要素相关,intent的flag就有很多种情况,故此算法非常复杂,需要阅读源码并结合特定启动情况才能理解。

ActivityStarter的startActivityUnchecked() 方法调用ActivityStack的startActivityLocked()

//同时调用WindowManager准备App切换相关的工作

//ActivityStarter
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask){

    //ActivityStack的startActivityLocked,同时调用WindowManager准备App切换相关的工作
    mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);

    if (mDoResume) {
     final ActivityRecord topTaskActivity =mStartActivity.task.topRunningActivityLocked();
        
        if (!mTargetStack.isFocusable()|| (topTaskActivity != null &&                               topTaskActivity.mTaskOverlay&& mStartActivity != topTaskActivity)) {
            ...
        } else {
            //最终调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked
            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
            mOptions);
        }
    }
}

ActivityStack

接下来调用ActivityStack的startActivityLocked将ActivityRecord加入到回退栈里。最终调用ActivityStackSupervisorresumeFocusedStackTopActivityLocked()方法。

待启动Activity对应的Task为前台Task时,调用该Task对应ActivityStack的resumeTopActivityUncheckedLocked函数。
接着跟进ActivityStack

//ActivityStack
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    return result;
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev,ActivityOptions options){

    //mResumedActivity指向上一次启动的Activity(Launcher)
    if (mResumedActivity != null) {
        ...
        //通知Launcher进入pause状态
        pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
    }
    
    if (pausing) {//Launcher已经暂停了
        ...
        if (next.app != null && next.app.thread != null) {
            //如果app已经启动过
            //调用淘宝(待启动)Activity所在进程的优先级,保证其不被kill
            mService.updateLruProcessLocked(next.app, true, null);
        }

    } 
    
    ...
    if (next.app != null && next.app.thread != null) {
        //如果Intent不为空,调用NewIntent方法传入Intent
        next.app.thread.scheduleNewIntent(next.newIntents, next.appToken, false);

        //若淘宝已经启动,点击Home键返回到Launcher,再次从Launcher启动淘宝(或者第三方启动已开启的App)
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);
    } else {
        //创建进程,冷启动Activity。或者已启动App,重新启动Activity
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }
    return true;
}

继续看resumeTopActivityInnerLocked(prev, options);这个方法太长了,我分析了一整天,终于所有体会吧。这个方法最终的作用是将启动者Activity的生命周期变成paused,这样之后被启动的Activity的实例创建了之后才能顺利的resumed。

resumeTopActivityInnerLocked函数非常繁琐,但整体来讲应该只有两个比较关键的地方:

  1. 判断是否已有Activity(mResumedActivity)启动(即Launcher,通过Launcher启动淘宝的),有则暂停该Activity
  2. 判断是否需要重新启动目标Activity,即Activity是否已经启动过。(例如保存在后台,应用切换)

2.AMS记录要启动的Activity信息,并且通知Launcher进入pause状态。
3.Launcher进入pause状态后,通知AMS已经paused了,可以启动淘宝了。

最终在函数的末尾会又调用ActivityStackSupervisor的startSpecificActivityLocked(next, true, true);方法。

创建进程

接下来的操作就比较重要了,创建进程,启动Activity。

//ActivityStackSupervisor

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

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {

                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                //目标Activity的App已经启动(存在ActivityThread),则重启Activity
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
               ...
            }
        }

        //如果进程不存在,则通过zygote创建应用进程。
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
}

从上面代码可以了解到startSpecificActivityLocked为启动Activity的两种不同情况

  • 例如从Launcher冷启动淘宝,则需要创建新进程,通过AMS调用Zygote(孕育天地)孵化应用进程。
  • 如果淘宝App已经启动,例如从MainActivity跳转到LoginActivity,则通过realStartActivityLocked启动。

因为我们开头以Launcher启动淘宝为例子,所以我们硬着头皮继续分析AMS创建进程以及Activity的绑定过程。
上面分析到mService.startProcessLocked,到了这里我们直接看启动线程的方法,中间的过程实在是略复杂。

4.淘宝App未开启过,所以AMS启动新的进程,并且在新进程中创建ActivityThread对象,执行其中的main函数方法。

Zygote进程孵化出新的应用进程后,通过反射执行ActivityThread类的main方法。在该方法里会先准备好Looper和消息队列,然后调用attach方法将应用进程绑定到AMS,然后进入loop循环,不断地读取消息队列里的消息,并分发消息

至此,进程创建完毕,并且也有了主线程,剩下的便是启动Activity和关联Context等初始化操作了。

淘宝app主线程启动完毕后通知AMS,并传入applicationThread以便通讯。

//ActivityThread
public static void main(String[] args) {
    ...
    //准备主线程的Looper,下篇博文分析Handler,Looper
    Looper.prepareMainLooper();

    //创建当前进程的ActivityThread
    ActivityThread thread = new ActivityThread();

    //将该进程绑定到AMS
    thread.attach(false);

    if (sMainThreadHandler == null) {
    //保存进程对应的主线程Handler
        sMainThreadHandler = thread.getHandler();
    }

    ...
    //进入主线程的消息循环
    Looper.loop();
    ...
}

//上面说过,ApplicationThread是ActivityThread用来与AMS通讯的中介
final ApplicationThread mAppThread = new ApplicationThread();

private void attach(boolean system) {
    if (!system) {
        final IActivityManager mgr = ActivityManagerNative.getDefault();

        //调用AMS的attachApplication方法,将ApplicationThread对象绑定至ActivityManagerService
        //这样AMS就可以通过ApplicationThread代理对象控制应用进程
        mgr.attachApplication(mAppThread);
    } else {
        ...
    }
}

AMS启动Activity小结

至此通过下图总结一下在AMS启动Activity的大致流程,各个方法函数像一台机器上的不同零件,各尽其责,分工明确。
虽然错综复杂,但是耦合性低,比如说启动模式需要优化,重新完善startActivityUnchecked方法函数即可。

Activity启动流程学习笔记_第1张图片
这里写图片描述

AMS.attachApplicationLocked() 关联Activity

在这个时候,虽然有了App进程和主线程,但是仍是一副空壳。
没有Activity信息,没有关联上下文,这时候就要请出AMS来进行指挥。

此时的App应用–>
Activity启动流程学习笔记_第2张图片
这里写图片描述

因为主线程main入口通过attach方法将 ApplicationThread 发送给 AMS ,所以通过applicationThread这个桥梁来通知ActivityThread创建/关联和启动Activity

//AMS
@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        //获取applicationThread的进程id(也就是淘宝应用进程)
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

通过Binder获取proxy(ApplicationThread )方的进程id,也就是获取目标(淘宝)进程的Pid。

//Binder
public static final native int getCallingPid();

接下来重点分析attachApplicationLocked方法

//AMS
private final boolean attachApplicationLocked(IApplicationThread thread,int pid) {

        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }

        //因为进程由AMS启动,所以在AMS中一定会有ProcessRecord(进程记录)
        //如果没有ProcessRecord,则需要杀死该进程并退出
        if (app == null) {
            ...
            return false;
        }

        // If this application record is still attached to a previous
        // process, clean it up now.
        if (app.thread != null) {
            //如果从ProcessRecord中获取的IApplicationThread不为空,则需要处理该IApplicationThread
            //因为有可能此Pid为复用,旧应用进程刚释放,内部IApplicationThread尚未清空,
            //同时新进程又刚好使用了此Pid
            handleAppDiedLocked(app, true, true);
        }


        //创建死亡代理(进程kill后通知AMS)
        AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);

        //进程注册成功,移除超时通知
        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        ...
        try {
            //绑定Application
            thread.bindApplication(processName, appInfo, providers,     app.instrumentationClass,profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked());

            updateLruProcessLocked(app, false, null);
        } catch (Exception e) {
            ...
            //bindApplication失败后,重启进程
            startProcessLocked(app, "bind fail", processName);
            return false;
        }

        try {
            //启动Activity(启动淘宝MainActivity)
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;//didSomething表示是否有启动四大组件
            }
        } catch (Exception e) {
            badApp = true;
        }

        ...
        //绑定service和Broadcast的Application


        if (badApp) {
            //如果以上组件启动出错,则需要杀死进程并移除记录
            app.kill("error during init", true);
            handleAppDiedLocked(app, false, true);
            return false;
        }

        //如果以上没有启动任何组件,那么didSomething为false
        if (!didSomething) {
            //调整进程的oom_adj值, oom_adj相当于一种优先级
            //如果应用进程没有运行任何组件,那么当内存出现不足时,该进程是最先被系统“杀死”
            updateOomAdjLocked();
        }
        return true;
    }

attachApplicationLocked中有两个比较重要的方法函数:

  1. thread.bindApplication(…) : 绑定Application到ActivityThread
  2. mStackSupervisor.attachApplicationLocked(app) : 启动Activity(Android 7.0前为mMainStack.realStartActivityLocked()

ApplicationThread.bindApplication绑定Application到ActivityThread

在上面我们说道,ActivityThread通过ApplicationThread与AMS进行通讯,所以上面的thread.bindApplication(...)方法,就应该是通过ApplicationThread进行传达。
ActivityThread的内部类ApplicationThread中,我们找到bindApplication方法

//ActivityThread
//内部类ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {

    public final void bindApplication(...一大堆参数...) {
        AppBindData data = new AppBindData();
        //给data设置参数...
        ...
        sendMessage(H.BIND_APPLICATION, data);
    }
}

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    Message msg = Message.obtain();
    //给msg设置参数
    ...
    mH.sendMessage(msg);
}

发送消息是通过HHandler类来完成的。

private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        ...
        public static final int RESUME_ACTIVITY         = 107;

        public static final int DESTROY_ACTIVITY        = 109;
        public static final int BIND_APPLICATION        = 110;
        public static final int EXIT_APPLICATION        = 111;
        
        ...

        public void handleMessage(Message msg) {
            switch (msg.what) {
                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, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

                ... 
                //绑定application
                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;
            }
        }
}

可以看出,这个H类相当于ActivityThreadApplicationThread的中介人,也就是拉皮条的。
ActivityThread通过ApplicationThread与AMS通讯。
ApplicationThread通过HActivityThread通讯,处理Activity事务。

那么既然HApplicationThread都在ActivityThread类里,为何ApplicationThread还要通过Handler来发送消息?

  • 便于集中管理,方便打印Log日志等,H就是这其中的大管家。
  • ActivityThread通过ApplicationThread和AMS进行进程间通信,AMS以进程通讯的方式来完成ActivityThread的请求后调用ApplicationThread中的Binder方法,然后ApplicationThread会向H发送消息,H收到消息后会将ApplicationThread中的逻辑切换到ActivityThread中去执行,即切换到主线程中去执行,这个过程就是主线程的消息循环模型

而且有一点要注意的是,这个ActivityThread并不是一个线程Thread,它是final类并且无继承或者实现其它类,它的作用就是在main方法内消息循环,处理主线程事务。(还需了解Looper及消息机制)

言归正传,上面ApplicationThreadH发送BIND_APPLICATION标识,在H中,通过handleBindApplication处理Application的绑定事务。

//ActivityThread
private void handleBindApplication(AppBindData data) {

           ...
          //根据传递过来的ApplicationInfo创建一个对应的LoadedApk对象
          data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);//获取LoadedApk

          //禁止在主线程使用网络操作
          if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
              StrictMode.enableDeathOnNetwork();
          }
    
           //7.0引入Fileprovide
          if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
              StrictMode.enableDeathOnFileUriExposure();
          }

          ...  
          //创建进程对应的Android运行环境ContextImpl
          final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

          if ((InstrumentationInfo)ii != null) {
               ...
          } else {
               //注意Activity的所有生命周期方法都会被Instrumentation对象所监控,
               //也就说执行Activity的生命周期方法前后一定会调用Instrumentation对象的相关方法
               mInstrumentation = new Instrumentation();
          }

          try {
             ...
             Application app = data.info.makeApplication(data.restrictedBackupMode, null);
             mInitialApplication = app;

             //加载进程对应Package中携带的ContentProvider
             installContentProviders(app, data.providers);

             ...        
             mInstrumentation.onCreate(data.instrumentationArgs);

             try {
                  //这里会调用Application的onCreate方法
                  //故此Applcation对象的onCreate方法会比ActivityThread的main方法后调用
                  //但是会比这个应用的所有activity先调用
                  mInstrumentation.callApplicationOnCreate(app);
              } catch (Exception e) {
                  ...
              }
            } finally {
                StrictMode.setThreadPolicy(savedPolicy);
            }
        }

如上文所述,handleBindApplication的目的是让一个Java进程融入到Android体系中
因此,该函数中的代码主要进行以下工作:

  1. 按照Android的要求,完成对进程基本参数的设置置,包括设置进程名、时区、资源及兼容性配置;
    同时也添加了一些限制,例如主线程不能访问网络等。
  2. 创建进程对应的ContextImpl、LoadedApk、Application等对象,同时加载Application中的ContentProvider,并初始化Application
  3. 使用Instrumentation监控Activity的生命周期。(一个进程对应一个Instrumentation实例)

当完成上述工作后,新建的进程终于加入到了Android体系。

AMS通知淘宝绑定Application并启动MainActivity。

ActivityStackSupervisor.attachApplicationLocked启动Activity

在上述代码AMS的attachApplicationLocked方法中,我们说道:

attachApplicationLocked中有两个比较重要的方法函数,分析到这里我们的文章也要进入尾声了。

  1. thread.bindApplication(…) : 绑定Application到ActivityThread
  2. mStackSupervisor.attachApplicationLocked(app) : 启动Activity

绑定了Application之后,我们就可以启动Activity(淘宝MainActivity)。

//ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    boolean didSomething = false;

    //ActivityStackSupervisor维护着终端中所有ActivityStack
    //此处通过轮询,找出前台栈顶端的待启动Activity
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
        ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
        
        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = stacks.get(stackNdx);
            if (!isFocusedStack(stack)) {
                continue;
            }

            ActivityRecord hr = stack.topRunningActivityLocked();
            if (hr != null) {
                //前台待启动的Activity与当前新建的进程一致时,启动这个Activity
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid &&                             processName.equals(hr.processName)) {
                    try {
                        //realStartActivityLocked进行实际的启动工作
                        if (realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (RemoteException e) {

                    }
                }
            }
        }
    }
    return didSomething;
}

大概系统工程师也觉得这个启动过程贼鸡儿绕了,最终启动的方法命名为realStartActivityLocked,意味着告诉你,大伙儿不要搞晕了,这个就是最后启动Activity的方法了。realStartActivityLocked()方法通过ApplicaitonThread的scheduleLaunchActivity()调用客户端Binder实体的方法,最后我们直捣黄龙,在ActivityStackSupervisor方法中,我们找到如下代码

//ActivityStackSupervisor
//通过ApplicaitonThread调用客户端Binder实体的方法。
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
public final void scheduleResumeActivity(IBinder token, int processState,
boolean isForward, Bundle resumeArgs) {
    updateProcessState(processState, false);
    sendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
}

看到这里想必大伙儿都明白了,AMS最后通过ApplicationThread通知ActivityThread启动Activity,感觉这一切的通讯都像发电报一样,鬼斧神工出神入化,皆出架构师之目营心匠。
那么到这里我们就能推算出接下来的老套路了
ApplicationThread—> H—> ActivityThread—> 最终启动Activity的方法。

ActivityThread

//ActivityThread

//内部类ApplicationThread
private class ApplicationThread extends ApplicationThreadNative {

    @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 pendingResults, List pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

        updateProcessState(procState, false);

        ActivityClientRecord r = new ActivityClientRecord();
        //设置参数
        ...

        //从LAUNCH_ACTIVITY这个标识我们就可以知道,它就是用来启动Activity
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
}

private class H extends Handler {
    ...
    //用Handler发送了一个Message。Handler的处理会最终调用handlerLaunchActivity方法
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                //利用ApplicationInfo等信息得到对应的LoadedApk,保存到ActivityClientRecord
                //ActivityClientRecord包含Activity相关的信息
                r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
                handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            } break;
                ...  
            }
        }
    }
}

//ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        ...
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
        ...
    } 
    ...
}

handleLaunchActivity方法里有有两个重要的函数调用:

  • performLaunchActivity : 会调用Activity的onCreate、onStart、onResotreInstanceState方法
  • handleResumeActivity : 会调用Activity的onResume方法

从上面的源码可以看出,performLaunchActivity方法最终完成了Activity对象的创建和启动过程,并且ActivityThread通过handleResumeActivity方法来调用被启动Activity的onResume这一生命周期方法。

performLaunchActivity

performLaunchActivity这个方法主要完成了如下几件事:

1、从ActivityClientRecord中获取待启动的Activity的组件信息。

//ActivityThread的performLaunchActivity方法

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

2、通过Instrumentation的newActivity方法使用类加载器创建Activity对象。

//ActivityThread的performLaunchActivity方法

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) {
    ...
}

3、通过LoadedApk的makeApplication方法来创建Application对象。

//ActivityThread的performLaunchActivity方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//r.packageInfo为LoadedApk对象

其实在我们上面的bindApplication中,我们就有介绍到通过LoadedApk创建Application,并且创建完毕后,通过InstrumentationcallApplicationOnCreate来调用Application的onCreate方法

Application app = data.info.makeApplication(data.restrictedBackupMode, null);
...
mInstrumentation.callApplicationOnCreate(app);

所以第三步是为了判断Application是否为空,而且我们从makeApplication方法中也能看出如果Application已经被创建过了,那么就不会再重复创建了。

4、创建ContextImpl对象,并通过Activity的attach方法来完成一些重要数据的初始化。

Context appContext = createBaseContextForActivity(r, activity);//创建ContextImpl对象
Window window = null;

if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
    window = r.mPendingRemoveWindow;
    r.mPendingRemoveWindow = null;
    r.mPendingRemoveWindowManager = null;
}

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, window);

ContextImpl是一个很重要的数据结构,它是Context的具体实现,Context中的大部分逻辑都是由ContextImpl来完成的。ContextImpl来完成的。ContextImpl是通过Activity的attach方法来和Activity建立关联的,除此之外,在attach方法中Activity还会完成Window的创建并建立自己和Window的关联,这样当Window接收到外部输入事件后就可以将事件传递给Activity。

5、调用Activity的onCreate方法

mInstrumentation.callActivityOnCreate(activity, r.state);

由于Activity的onCreate已经被调用,这也意味着Activity已经完成了整个启动过程。

6、调用Activity的onStart、onResotreInstanceState方法

mInstrumentation.callActivityOnCreate(activity, r.state);
...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);

public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}

activity.performCreate(icicle);这一行代码熟悉吗?这一行里面就调用了传说中的Activity的入口函数onCreate(),不信?接着往下看Activity.performCreate()

final void performCreate(Bundle icicle) {
    onCreate(icicle);
    mActivityTransitionState.readState(icicle);
    performCreateCommon();
}

没骗你吧,onCreate在这里调用了吧。

参考文章

【凯子哥带你学Framework】Activity启动过程全解析

Android Launcher 启动 Activity 的工作过程

Android系统开篇

startActivity启动过程分析

你可能感兴趣的:(Activity启动流程学习笔记)