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<T>),这个方法通过反射来启动对应的服务
        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<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    
        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方法函数即可。

这里写图片描述

AMS.attachApplicationLocked() 关联Activity

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

此时的App应用–>
这里写图片描述

因为主线程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<ActivityStack> 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<ResultInfo> pendingResults, List<ReferrerIntent> 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启动过程分析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容