Activity启动流程学习笔记

作者: Mr槑 | 来源:发表于2018-02-27 19:31 被阅读64次

    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启动过程分析

    相关文章

      网友评论

        本文标题:Activity启动流程学习笔记

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