android Activity启动过程 简析

    xiaoxiao2021-03-26  13

     

    概括

    先简略概括一下Activity的启动过程,以下拿点击Launcher来说。

    1.开始请求执行Activity,Launcher进程发送命令到AMS

    Launcher就是一个App,点击Launcher会隐式启动一个新的应用。所以跑的也是Activity.startActivity的流程。

    接着就是Activity.startActivityForResult()  ——> Instrumentation.execStartActivity()...一系列方法。

     

    2.AMS执行Launcher(栈顶Activity)的onPause方法

    AMS通过Binder执行Launcher的onPause方法

     

    3.启动Activity所属的应用进程

    -从Zygote中fork一个新应用进程出来。里面有负责调度ActivityRecord和Task的代码。

    调度Task的算法涉及的判断很多,和当前回退栈,要启动的activity的启动模式,以及taskAffinity属性,启动Activity时设置的intent的flag等诸多要素相关

    -之后会执行ActivityThread类的main方法。Activity就在这个ActivityThread实例中运行。

     

     

    4.执行启动Activity

    AMS通过代理,请求启动Activity。ApplicationThread通知主线程执行该请求。然后,ActivityThread执行Activity的启动,并执行它的生命周期方法。

    在ApplicationThread中,对应AMS管理Activity生命周期的方法都以scheduleXXXActivity,ApplicationThread在Binder线程中,它会向主线程发送消息,ActivityThread的Handler会调用相应的handleXXXActivity方法,然后会执行performXXXActivity方法,最终调用Activity的onXXX方法。

     

    5.AMS执行Launcher(栈顶Activity)的onStop方法

    AMS通过Binder执行Launcher的onStop方法

     

     

     

     

     

    --------------------------分割线--------------------------

    前置说明:安卓众多应用来回切换,肯定不是两两应用进行通信能协调好的事,所以需要一个总管家的身份。这里就是我们的AMS。它掌管着所有Activity的生命周期。

    已知AMS是运行在SystemServer这个进程上,众多Activity运行在各种应用进程中,那么问题来了...

    重点一:众多Activity怎么与AMS通信的

    先来两张UML图

    一个图是关于ActivityManager,一个是关于ApplicationThread。

    拿ActivityManager这个UML图来分析一下。ApplicationThread跟这个差不多。

    我们知道用android实现IPC,写个XXX.aidl,ide会为我们生成一个同文件名不同后缀的XXX.java文件。这个文件里面的结构就像这张UML图的结构。

    1.这个XXX.java类首先是一个接口,继承IInterface接口。里面一般声明了需要提供的业务方法。在这里就是IActivityManager。

    2.然后XXX.java有一个内部有个抽象类Stub继承Binder实现XXX接口。在这里就是ActivityManagerNative+ActivityManagerProxy。

    3.Stub里面还有内部类Proxy实现了XXX接口。在这里就是ActivityManagerProxy。

    ActivityManagerNative即Stub相当于服务端。ActivityManagerProxy即Proxy相当于客户端。所以ActivityManager设计成这样的aidl结构完成通信。

     

    再具体一点,来看看这个机制怎么完成startActivity方法。

    首先是从Activity.startActivity --> Activity.startActivityForResult() --> Instrumentation.execStartActivity()  

    然后就会调用ActivityManagerNative.getDefault().startActivity()方法

    getDefault会尝试通过ServiceManager.getService("activity")远程服务的Binder对象,然后进行asInterface转换成IActivityManager,其实返回的就是ActivityManagerProxy。

    源码是这个样子的。

    先看getDefault部分,使用了自带的Singleton类实现单例模式,并且声明是静态方法。

     

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

    然后看startActivity部分,类ActivityManagerProxy的startActivity方法

     

     

    class ActivityManagerProxy implements IActivityManager { 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; } }

    里面是对参数使用Parcel序列化,然后调用transact方法,参数是方法名标识,参数,盛放返回值的容器。

     

    这样就会跳转到ActivityManagerService的onTransact方法,ActivityManagerService会调用父类ActivityManagerNative的onTransact方法。

     

    public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { case START_ACTIVITY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder b = data.readStrongBinder(); IApplicationThread app = ApplicationThreadNative.asInterface(b); String callingPackage = data.readString(); Intent intent = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); IBinder resultTo = data.readStrongBinder(); String resultWho = data.readString(); int requestCode = data.readInt(); int startFlags = data.readInt(); ProfilerInfo profilerInfo = data.readInt() != 0 ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle options = data.readInt() != 0 ? Bundle.CREATOR.createFromParcel(data) : null; int result = startActivity(app, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options); reply.writeNoException(); reply.writeInt(result); return true; } } }

    所以客户端调用的方法都要经过onTransact方法转化。所以里面switch判断一下标识,就进入START_ACTIVITY_TRANSACTION的case里面。里面也有一个startActivity方法(注意此时已经位于AMS进程中了),在ActivityManagerNative这个抽象类里没有实现这个方法,所以交给AMS具体实现的方法来处理了。

     

    所以ActivityManagerNative主要是负责Binder机制中,接受参数,转换处理参数这些功能。之后把参数整理好,才会交个AMS,AMS才是具体的处理业务的逻辑。

    之后就是AMS的startActivity方法了,这里面的调用链和处理逻辑就多了。

    比如判断这个新进程是不是已经启动了,不需要再从zygote中fork一个进程出来。。。。。。。。。

     

    ps:所以在我脑里,我觉得这两张UML图附上一点业务逻辑,应该是这样。红色部分的是业务逻辑

     

     

     

     

    重点二:ActivityThread的Main方法干了什么

    从zygote中fork出一个新进程后,就会执行ActivityThread的main方法。

    经典问题,一个App的程序入口到底是什么?回答的就是这个ActivityThread的main方法了

     

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

    1.这里有关于主线程Looper的操作

    我们知道如果主线程像子线程发送消息,需要有Looper.prepare()和Looper.loop()操作。

    在这里就是prepareMainLooper(),因为这是主线程,这名字简直不能更形象了。

    2.这里有new ActivityThread()。

    3.thread.attach(false); 执行ActivityThread的attach方法。看下源码,挑出重点

     

    private void attach(boolean system) { ... if (!system) { ... final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } ... }

    里面依旧ActivityManagerNative.getDefault()获取到ActivityManagerProxy。执行attachApplication方法,传的参数mAppThread类型是ApplicationThread。

     

    这个mAppThread是在new ActivityThread()时做为成员变量同时初始化的。

    然后中间过程同上面之前说的ActivityManager的binder机制调用流程,这里忽略这些流程,直接看AMS的attachApplication方法。

    AMS的attachApplication方法调用attachApplicationLocked方法,里面参数就是当初传过去的ApplicationThread。

    接着在这里面又用了这个ApplicationThread调用了bindApplication方法。

     

    public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) { if (services != null) { // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } setCoreSettings(coreSettings); AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.trackAllocation = trackAllocation; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data); }

    最后一行看到发消息了,其实发到mH这个Handler里面。

     

    点进去handleMessage方法,能看到很多case,比如LAUNCH_ACTIVITY, PAUSE_ACTIVITY, RESUME_ACTIVITY, DESTROY_ACTIVITY这种跟Activity相关的

    还有CREATE_SERVICE, BIND_SERVICE, UNBIND_SERVICE, STOP_SERVICE跟Service相关的。

    大概能猜出,这是AMS管理App的一道关卡。

    我们找到BIND_APPLICATION标识,看到他进入了handleBindApplication方法里面。

     

    private void handleBindApplication(AppBindData data) { ... if (data.instrumentationName != null) { ... mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); ... } else { mInstrumentation = new Instrumentation(); } ... try { ... Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; ... try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { throw new RuntimeException( "Exception thrown in onCreate() of " + data.instrumentationName + ": " + e.toString(), e); } try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { if (!mInstrumentation.onException(app, e)) { throw new RuntimeException( "Unable to create application " + app.getClass().getName() + ": " + e.toString(), e); } } } ... }

    里面有新建Instrumentation的代码,能理解,Activity的生命周期方法都是Instrumentation调用的,当然要先new一个。

     

     

    然后是makeApplication这个方法,这名字+返回值是个Application,很容易猜到是创建应用的Application。进去里面一看,果然是这样。

    这个创建方法需要在LoadedApk中转一手,需要需要这个类是可以读取到xml里面的自定义Application的类名字符串(如果有自定义Application的话,没有会用默认字符串“android.app.Application”)。 然后根据类的全名用反射newInstance出来一个Application。

     

    最后调用callApplicationOnCreate,里面只有一个代码,就是执行application的onCreate方法。

     

    所以其中一个重要流程是,运行应用Application的相关业务。接下来回到ActivityManagerService的attachApplicationLocked方法中,下一步是mStackSupervisor.attachApplicationLocked(app)。

    这个app是ProcessRecord的类型,本来我觉得这是AMS(服务端)保存某一个应用(客户端)信息的实体,心里称它为“应用实体信息类”。后来发现并不能这样想,因为一个进程里面可能有多个应用的Activity,所以还是只能称为“进程实体信息类”。

    attachApplicationLocked方法里面会调用realStartActivityLocked方法,里面有一句代码app.thread.scheduleLaunchActivity。这个thread是实际上是ApplicationThreadProxy类的实体,所以这句话会通过binder机制,调用到ApplicationThread里面的scheduleLaunchActivity方法。

    在这个方法的后一行看到发送一个LAUNCH_ACTIVITY的消息到H这个Hander里面。找到LAUNCH_ACTIVITY这个case,我们看到执行了handleLaunchActivity方法。

     

     

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

    里面有两行重要的代码,重要代码一,执行perforLaunchActivity方法。

     

     

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ... if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } ... if (!r.activity.mFinished) { activity.performStart(); r.stopped = false; } ... return activity; }

    里面有一句mInstrumentation.newActivity方法。点进去只有一句代码,功能就是通过反射创建出一个Activity实体。

    然后下面会有mInstrumentation.callActivityOnCreate方法。里面的调用链是Activity.performCreate()——>Activity.onCreate()这样就执行了我们熟悉的onCreate方法。

    后面又有activity.performStart()。里面的调用链是Instrumentation.callActivityOnStart()——>Activity.onStart()。

     

    然后回到handleLaunchActivity的重要代码二,handleResumeActivity里面的调用链是ActivityThread.performResumeActivity()——>Activity.performResume()——>Instrumentation.callActivityOnResume()——>Activity.onResume().执行了我们熟悉的onResume方法。这样Activity启动的主要流程就跑完了。

     

    总结一下重点二。

    首先想讲一下之前一直没搞清ApplicationThread和ActivityThread这两者的区别。这两个名字实在给我造成了很大的误会。

    看了源码后,才知道。ActivityThread本质是主线程应该处理的代码,它没有继承Thread!!我们常说的UI线程,就是运行在上面的代码。

    ApplicationThread跟Thread没多大关系,它主要是配合ApplicationThreadNative和ApplicationThreadProxy完成Binder进程间通信的。所以为啥元老Android发明者一开始要给定这个名字呢??

    然后想讲其实整个ActivityThread的attach方法,里面涉及的代码,所有方法调用链,随便拿出一个来我感觉细聊的话都可以写篇文章。

    很多细节比如intent的传递,ActivityThread时候时候会新建进程什么时候会寻找已有进程,activity启动是在具体什么时候读取的xml里面该activity标签的自定义属性的等等,都暂时忽略了。

     

    //TODO

    //给上面代码调用画个时序图。。。

     

    转载请注明原文地址: https://ju.6miu.com/read-450180.html

    最新回复(0)