Activity 源码分析

启动一个activity大体可以分为2种情况,比如A启动B,

1,A和B在同一个进程中

2,A和B分属于2个不同的apk,在2个不同的进程中。

以下论述的是第2种情况,即A和B位于不同的进程,那么会涉及到2次跨进程通信,第一次是A进程和AMS服务所在进程进行通信,

第二次是AMS服务所在进程与B进程进行通信。

1, 客户端

客户端启动Activity流程图如下,

当客户端调用startActivity时,会直接调用Activity.java的对应函数

public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

直接调用重载方法,

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);//无结果返回
        }
    }

startActivityForResult方法如下,

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());
            }
            •••
        }
    }

一般启动activity时, mParent都为空,

什么是Instrumentation?Instrumentation是android系统中启动Activity的一个实际操作类,也就是说Activity在应用进程端

(客户端)的启动实际上就是Instrumentation执行的,那么为什么说是在应用进程端的启动呢?实际上acitivty的启动分为应用

进程端的启动和SystemServer服务进程端的启动的,多个应用进程相互配合最终完成了Activity在系统中的启动的,而在应用

进程端的启动实际的操作类就是Intrumentation来执行的。

execStartActivity方法如下,

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        android.util.SeempLog.record_str(377, intent.toString());
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
       •••
        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) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

execStartActivity方法的7个参数如下:

this,为启动Activity的对象;

contextThread,为Binder对象,是主进程的context对象;

token,也是一个Binder对象,指向了服务端一个ActivityRecord对象;

target,为启动的Activity;

intent,启动的Intent对象;

requestCode,请求码;

options,是否返回处理结果的参数;

 

ActivityManagerNative.getDefault()方法最后得到的其实是ActivityManagerNative 的代理类ActivityManagerProxy,

其实就是AMS在客户端的代理,然后通过binder机制进行通信。

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

利用Binder对象,把所有需要的参数封装成Parcel对象,然后调用transact(),向AMS发送数据进行通信。

START_ACTIVITY_TRANSACTION 是一个标记。

需要注意的是这些流程都运行于客户端进程之中。

2, 服务端

通过数据传输之后就会调用SystemServer进程的ActivityManagerService的startActivity方法,

调用流程图如下,


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;
        }
•••
}

这些流程都运行与AMS所在的进程,需要注意的是ActivityManagerService服务继承于ActivityManagerNative,

 onTransact方法是运行于服务进程中,并且startActivity方法是调用子类ActivityManagerService中的startActivity方法。

这样就完成第一次跨进程通信。详细的binder机制在此就不论述了。

AMS的startActivity方法如下,

public final int startActivity(IApplicationThread caller, String callingPackage,
 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
 int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

直接调用了startActivityAsUser方法,

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

StackSupervisorstartActivityMayWait方法如下,

final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            •••

             ActivityInfo aInfo =
                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
             •••
             int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
               realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
               componentSpecified, null, container, inTask);
              •••
}

startActivityMayWait比较长,但是逻辑简单,首先调用resolveActivity方法获取需要启动的Activity信息,resolveActivity方法调用PMS

的resolveIntent方法具体匹配要启动的activity信息。得到activity后,继续调用startActivityLocked方法启动。

startActivityLocked方法检查各种错误,检查调用者的权限以及intent防火墙等等。

ActivityStackSupervisor类从名字就可知道,它管理各种包含activity的栈。

private ActivityStack mHomeStack;  // 系统的第一个栈对象
private ActivityStack mFocusedStack; // 系统前台栈对象
•••

startActivityUncheckedLocked方法也比较长,主要就是判断intent标志和activity属性来确定activity的栈。确定栈之后

就调用其startActivityLocked方法

startActivityLocked方法就是将ActivityRecord对象加入到栈的顶部,同时把该栈放到mHistoryStack的顶部。这里也调

用了WMS方法来处理Activity的显示和切换。

步骤12,13,14就是在ActivityStackSupervisor 和ActivityStack中倒过来到过去而已,就是准备启动activity。直接看

resumeTopActivityInnerLocked方法

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
        next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                        mService.isNextTransitionForward(), resumeAnimOptions);

        mStackSupervisor.startSpecificActivityLocked(next, true, false);
•••
}

这里分2种情况,

1,目标acitivity已经启动,就直接跨进程调用scheduleResumeActivity方法

2,如果acitivity未启动,调用startSpecificActivityLocked方法。

1,scheduleResumeActivity

scheduleResumeActivity方法是通过跨进程通信,从AMS进程到目标activity所在的进程。最后调用目标activity的onResume方法。

2,startSpecificActivityLocked

在startSpecificActivityLocked方法中,又分为2种情况,

如果目标activity所在进程已经启动,则直接调用realStartActivityLocked启动目标activity,调用其oncreate方法;否则,首先启动目标

activity所在进程,然后启动目标activity。

3, 客户端(目标进程)

客户端调用流程图如下,

AMS跨进程一般调用schedule····方法,到ActivityThread的内部类ApplicationThread中,此时代码还运行于Binder线程池中,

然后通过向主线程类(ActivityThread的内部类H)发送消息,跳到目标进程的主线程中执行,最后分别调目标Activity的onResume, oncreate 方法。

 

小结:

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

ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程

或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作。

ActivityManagerServices和 客户端的通信(主要是管理Activity等)

ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理

相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。

ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是

通过该代理与ActivityThread进行通信的。

 

客户端 和 ActivityManagerServices的通信(主要是发送相关请求)

ActivityManagerNative的代理类ActivityManagerProxy,其实就是AMS在客户端的代理,客户端通过ActivityManagerProxy 对AMS发送请求。

 

Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation

可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。

ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。

ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。

其实就是服务器端的Activity对象的映像。

TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用

TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生。

 

启动activity的流程如下,

1,客户端向服务端的AMS发送启动activity的请求。

2,服务端AMS处理该请求,获取目标activity的基本信息等。

3,启动目标activity的进程,然后启动目标activity。

 

这里涉及到2个跨进程通信:

1,从apk到AMS。ActivityManagerProxy是AMS的在客户端的代理。

2,从AMS到apk。ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。

AMS就是通过该代理与ActivityThread进行通信的。ApplicationThread是ActivityThread的内部类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值