【再出发】Android11源码分析:Activity是怎么启动的?

·  阅读 1610

系列文章索引

并发系列:线程锁事

  1. 篇一:为什么CountDownlatch能保证执行顺序?

  2. 篇二:并发容器为什么能实现高效并发?

  3. 篇三:从ReentrientLock看锁的正确使用姿势

新系列:Android11系统源码解析

  1. Android11源码分析:Mac环境如何下载Android源码?

  2. Android11源码分析:应用是如何启动的?

  3. Android11源码分析:Activity是怎么启动的?

  4. Android11源码分析:Service启动流程分析

  5. Android11源码分析:静态广播是如何收到通知的?

  6. Android11源码分析:binder是如何实现跨进程的?(创作中)

  7. 番外篇 - 插件化探索:插件Activity是如何启动的?

  8. Android11源码分析: UI到底为什么会卡顿?

  9. Android11源码分析:SurfaceFlinger是如何对vsync信号进行分发的?(创作中)

经典系列:Android10系统启动流程

  1. 源码下载及编译

  2. Android系统启动流程纵览

  3. init进程源码解析

  4. zygote进程源码解析

  5. systemServer源码解析

前言

上一篇文章简单介绍了activity的启动流程,但只提及了与进程启动相关的部分,今天我们完整的看一看,activity是怎么被创建出来,又是如何与生命周期相绑定的

在今后的文章中,我们也将从插件化的角度来介绍,如何hook系统服务来达到加载插件activity的功能

Activity启动流程分析

启动activity有两种调用入口

  1. activity.startActivity() 用于在activity对象中启动另一个activity

  2. contxt.startActivity() 用于在任意位置获取Context对象来启动activity

他们的区别在于,activity中的函数会调用startActvityForResult(),可以通过传递bundle值来传递对象(),并能在当前activity中通过onActivityResult拿到回调结果;而ContextImp中是直接调用函数启动activity

这两种方式最终都调用到了InstrumentationexecStartActivity()函数, 通过获取ActiviyTastManagerService(后面简称ATMS)的binderProxy对象,通过binder调用执行到ATMSstartActivity函数

public ActivityResult execStartActivity(...) {
	   //省略无关代码
	   int result = ActivityTaskManager.getService().startActivity(...);
       checkStartActivityResult(result, intent);
    }
复制代码

ATMS是在SystemServer中被启动的系统服务,被ActivityManagerService(后面简称AMS)对象持有,用来处理activiy栈相关的业务逻辑

我们重点需要关注的是ActivityStater对象,在ATMS中执行了starter.excute()函数,内部最终执行到了executeRequest()函数来启动activity

这里涉及到一个重要的类ActivityRecord,用来存储activity相关的信息。我们发现对于各个组件,在系统层的设计中都是用xxxRecord(比如ProcessRecocord,ServiceRecord等)来存储相关的信息,以及根据其是否为null判断其是否启动或存活

executeRequest()中,创建了一个ActivityRecord对象,这里的调用流程比较复杂,我们需要关注几个重要的类,ActivityStackActivityStackSupervisor,经过一系列的流程后,最终调用了ActivityStackSupervisor的函数startSpecificActivity()

如果进程(WindowProcessController wpc)不为空,则直接调用realStartActivityLocked()

这里重点关注scheduleTransaction()函数,可以看到这里持有IApplicationThread的binderProxy对象,通过binder调用与ActivityThread进行通信,到应用层去进一步创建Activity(后面详细分析应用层activity的创建)

/frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java

void scheduleTransaction(@NonNull IApplicationThread client...){
	final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }   
}

复制代码

如果进程为空则直接创建进程

void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
        //...
        final boolean isTop = andResume && r.isTopRunningActivity();
        mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity"); //启动进程
    }
复制代码

这里又调用了ATMS的startProcessAsync()

void startProcessAsync(...) {
			...
            final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                    mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                    isTop, hostingType, activity.intent.getComponent());
            mH.sendMessage(m);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
复制代码

我们看到这里是用来发送消息的,交给handler来处理最终的启动结果,而真正启动ActivityManagerInternal::startProcess作为参数传递,mAmInternal是其实现类LocalService(AMS中的内部类),最终调用到了LocalService的startProcess()函数

com.android.server.am.ActivityManagerService.LocalService

public void startProcess(...) {
	//启动进程
 	startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                            new HostingRecord(hostingType, hostingName, isTop),
                            ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                            false /* isolated */, true /* keepIfLarge */);

}

复制代码

startProcessLocked()最终调用到了ProcessList的函数startProcessLocked(),如果获取到ProcessRecord不为说明进程已经启动,否则去开启进程

ActivityThread到底是什么?

这里不得不提一下困扰我很久的一个问题:ActivityThread是怎么被启动的?

ProcessList中,startProcessLocked()经过了多个重载函数的调用,最终调用到了下面的代码,与Zygote通过socket通信,来fork出新的进程,并调用java层

这里需要关注一个参数entryPoint(原本不在此函数中,这里是为了方便查看),ActivityThread的全类名字符串,用来传递给zygote

boolean startProcessLocked(...) {
           //...
       	   //与Zygote通信fork出子进程
            final String entryPoint = "android.app.ActivityThread"; //process的入口函数
            final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                        entryPoint, app,
                        uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
                        requiredAbi, instructionSet, invokeWith, startTime);
                handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                        startSeq, false);
            return app.pid > 0;
    }
复制代码

zygote在循环中接收到消息后,fork出新的进程,并将其解析为ZygoteArguments,并通过ClassLoader创建出ActivityThreadstatic main函数,封装成Runnable对象向上返回

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
复制代码

最终返回到了ZygoteInit的main函数中

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
		//省略简化无关代码
        ZygoteServer zygoteServer = new ZygoteServer(isPrimaryZygote); //zygote作为服务端创建socket连接
        Runnable caller = zygoteServer.runSelectLoop(abiList);
        if (caller != null) {
            caller.run(); 
        }
    }
复制代码

至此,我们熟悉又陌生的ActvityThread终于被创建并执行了。

但此时Process还不算真正的创建完成,因为还没有完成与AMS的双向绑定。在main函数中,创建了ActivityThread的实例对象,并调用了attach()函数,在这个函数中,通过获取AMS的BinderProxy对象IActivityManager,用来调用AMSattachApplication(applicationThread),完成bpBinder实体对象的函数

AMS通过在attachApplication()中获取并持有ActivityThread中ApplicationThread这个binder对象,来与ActivityThread进行双向通信

小结

ActivityThread的创建是通过hardcode的方式将全类名传递给Zygote,并通过ClassLoader获取到该类的main函数,执行到应用层,并通过binder机制调用attach()完成了与AMS的双向调用

Activity是如何被创建出来的?

现在回到进程已经被创建出来的时候,上面我们已经知道,如果进程(WindowProcessController wpc)不为空,则直接调用realStartActivityLocked(),并最终会调用ClientLifecycleManagerscheduleTransaction(),

通过binder调用执行到ActivityThread中的binder对象ApplicationThread中的scheduleTransaction()函数,最终又指向了ActivityThread的scheduleTransaction()函数

/frameworks/base/core/java/android/app/ActivityThread.java

public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }
复制代码

ActivityThreadClientTransactionHandler的子类对象(这个类目前有且仅有一个子类实现),这里并没有对父类的scheduleTransaction()进行复写,所以调用的是父类中的方法

/frameworks/base/core/java/android/app/ClientTransactionHandler.java

/** Prepare and schedule transaction for execution. */
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
复制代码

这里的sendMessage()为抽象类方法,由ActivityThread实现,发送了一个Tag为ActivityThread.H.EXECUTE_TRANSACTION的消息

/frameworks/base/core/java/android/app/ActivityThread.java

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        Message msg = Message.obtain();
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg); //通过hander发送消息
    }
复制代码

我们都知道,handler是Android中用来处理线程间消息通信的,这里其实也是一样,通过AMS远程调用到ActivityThread中时,是在binder线程中运行的,而不是ActivityThread被创建的线程,因此需要通过handler把消息放到主线程进行处理

在ActivityThread中,用来接收消息的Handler对象是H,我们接着来看handler中是如何处理消息的

public void handleMessage(Message msg) {
	switch (msg.what) {
    		case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);
					//...
                    break;
    }

}
复制代码

这里会把具体的处理交给mTransactionExecutor来处理,主要逻辑是用来执行注册的callback以及相关的生命周期(LifeCycleItem)

/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

public void execute(ClientTransaction transaction) {
        //...
        executeCallbacks(transaction);

        executeLifecycleState(transaction);
    }
复制代码

我们在回来看当时给clientTransaction添加回调和ActivityLifecycleItem的地方,也就是realStartActivityLocked()这个函数

/frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

boolean realStartActivityLocked(...) throws RemoteException {
	// Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(
                        proc.getThread(), r.appToken);
   		clientTransaction.addCallback(LaunchActivityItem.obtain(...); //添加回调
        // Set desired final state.
                final ActivityLifecycleItem lifecycleItem; //添加最终需要执行的生命周期状态
                if (andResume) {
                    lifecycleItem =  ResumeActivityItem.obtain(dc.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.  //binder调用传递clientTransaction
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}

复制代码

小结

ActivityTread其实是用来跟系统服务AMS通信,在应用层接收消息,并post到主线程执行创建application,开启activity,service,等业务流程

在启动Activity的过程中,用来记录activity的数据结构是ActivityRecord,activity的生命周期和栈管理是被ATMS系统服务实现的,并通过binder调用传递到我们实现的各个activity的生命周期回调当中

至于Activity这个类本身的创建,是在ActivityThread这个类的performLaunchActivity()函数中实现的

通过ClassLoader加载对应的类,并将Context对象attach给activity,最终通过mInstrumentation.callActivityOnCreate() 执行到activity实现类的onCreate() 函数当中

后记

关于Context的内容,今后的文章也会进一步探讨,下一篇文章,我们来分析下service是如何开启和绑定的

如果我的文章对你有所启发,请多多点赞支持,我们下期文章再见!

分类:
Android
标签:
分类:
Android
标签: