笔记:Activity的启动过程

时间:2023-03-09 08:44:40
笔记:Activity的启动过程

Activity的创建特点

作为四大组件之一的Activity,它不像普通java对像那样,可以new出来,然后去使用。而是调用

startActivity()这样的方式启动。那么Android系统是如何创建并启动Activity的呢?本文就来

一探究竟。

NOTE:本文内容就是对老罗《Android系统源代码情景分析》章节的简化笔记。

因为涉及到不同进程间的通信,所以分析流程的过程中会在不同的源代码文件之间跳转,源码为Android 2.3版本,下载系统源码后,可以使用像Everything这样的软件根据类名对文件进行快速查找。

Launcher启动App

任何安装的应用几乎都是点击桌面上的图标被启动。

接下来以Launcher程序启动一个App的过程作为案例。要启动的App的包名为com.idlestar.bot

,其入口Activity为MainActivity。

Task和Back Stack

即便没有了解过Activity的启动过程、ActivityManagerService(简称AMS,它是运行在系统进程SystemServer中的系统关键服务)这些知识点,对任务(Task)和回退栈(Back Stack)的概念、Activity启动模式等多少都回了解。接下来可以在源码级稍微感受到它们的真实表现。

Task

用户完成一个任务时,可能和若干相关的Activity组件进行交互,这些相关的Activity的集合被称作一个Task,由TaskRecord对象表示。Task中所有Activity形成一个stack结构,以它们的启动顺序被添加。

ActivityStack

实际上在系统中,每一个Activity组件实例被使用一个ActivityRecord对像表示,所有的Activity组件都保存在一个ActivityStack对象的字段ArrayList mHistory中。ActivityRecord.task字段表示其所在Task。假设把所有Activities指定编号:a0,a1,a2...an,表示mHistory中从第0,1,2...n个Activity,那么,Task就是从a0到an中连续的一个个“子序列”,一个Task包括1或多个Activity。Task中的Activity的“栈结构”是通过ArrayList间接实现的

命令adb shell dumpsys activity可以查看当前系统中运行的Activities的信息。在启动MainActivity的前后,可以运行命令来查看有关的Activities的信息。

启动MainActivity前,显示Launcher时:

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #1
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
...
ProcessRecord{529e7b24 735:com.android.launcher/u0a8} Running activities (most recent first):
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
Run #0: ActivityRecord{529e66bc u0 com.android.launcher/com.android.launcher2.Launcher t1}
... Recent tasks:
* Recent #0: TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}

上面的信息有点像Json那种格式,缩进表示了信息的分组。

先是Stack #0这种划分,#跟数字表示序号。Stack #0是整个ActivityStack中的第一个Task。

此时,只有一个Task——Stack #0

Task id为#1,即任务id=1。

而Running activities是Task所包含的运行中的Activity的信息,最近使用的排在前面。Run #0显示了正在运行的第一个也是唯一一个ActivityRecord,就是Launcher组件。

点击App图标,打开MainActivity之后:

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #1
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
...
ProcessRecord{529e7b24 735:com.android.launcher/u0a8} Running activities (most recent first):
TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}
Run #0: ActivityRecord{529e66bc u0 com.android.launcher/com.android.launcher2.Launcher t1} Stack #1:
Task id #2
TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
...
ProcessRecord{529704e8 3307:com.idlestar.bot/u0a82}
...
Running activities (most recent first):
TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
Run #0: ActivityRecord{5296eea0 u0 com.idlestar.bot/.MainActivity t2}
... Recent tasks:
* Recent #0: TaskRecord{52a203f8 #2 A=com.idlestar.bot U=0 sz=1}
* Recent #1: TaskRecord{529e7460 #1 A=com.android.launcher U=0 sz=1}

可以看到此时多了一个Task Stack #1,它在是栈顶位置(#序号最大的),它对应的ActivityRecord为MainActivity,正是当前处在前台(foreground)被显示的Activity。

上面启动MainActivity前后,看到Launcher和MainActivity属于不同的Task,因为Launcher为启动的MainActivity指定了NEW_TASK。

启动过程跟踪

自己的App会运行在一个包名对应的进程中,这点常识这里不去解释。

MainActivity是Launcher启动的,而Launcher是通过AMS来启动MainActivity的。它们分别运行在不同的进程中,整个过程中它们之间使用Binder完成跨进程通信。

NOTE:源代码为android系统2.3。

下面是完整的过程,非重要部分会很简单地描述下,保证流程完整性。

阶段1:Launcher通知AMS启动MainActivity。

Launcher向ActivityManagerService发送一个启动MainActivity组件的进程间通信请求。

系统启动时,会启动PackageManagerService服务,简称PMS,通过它安装系统中的应用程序。

第一个启动的就是Launcher,Launcher向PMS查询所有App的AndroidManifest.xml获得所有App

的图标,启动Activity组件(Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_LAUNCHER)的全名。

用户点击桌面App图标后,Launcher根据对应App的信息,创建一个启动它的intent,并调用startActivity()来启动它。

不同android版本中Launcher的代码会稍有差异,但基本过程是类似的。

方法调用过程,对传递调用不加说明,直接继续给出所调用的方法:

step 1:Launcher.startActivitySafely()

void startActivitySafely(Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
...

默认为intent添加了FLAG_ACTIVITY_NEW_TASK标志。

step 2:Activity.startActivity(intent)

step 3:Activity.startActivityForResult(intent, -1)

参数requestCode = -1表示不处理onActivityResult()

// set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
private Instrumentation mInstrumentation; void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
...
}

step 4:Instrumentation.execStartActivity()

public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode) {
...
try {
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, 0, token, target != null ? target.mEmbeddedID : null,
requestCode, false, false);
...
}

ActivityManagerNative.getDefault()获得的是AMS的一个代理对像,类型为IActivityManager。

/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault()
{
if (gDefault != null) {
//if (Config.LOGV) Log.v(
// "ActivityManager", "returning cur default = " + gDefault);
return gDefault;
}
IBinder b = ServiceManager.getService("activity");
if (Config.LOGV) Log.v(
"ActivityManager", "default service binder = " + b);
gDefault = asInterface(b);
if (Config.LOGV) Log.v(
"ActivityManager", "default service = " + gDefault);
return gDefault;
}

asInterface(b):

/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
static public IActivityManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
} return new ActivityManagerProxy(obj);
}

以上2个方法是典型的Binder通信方式,将一个和远程进程通信的IBinder转为通信定义的接口类型。最终getDefault()返回的就是ActivityManagerProxy对像。

step 5:ActivityManagerProxy.startActivity()

public int startActivity(IApplicationThread caller, Intent intent,
String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
IBinder resultTo, String resultWho,
int requestCode, boolean onlyIfNeeded,
boolean debug) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeStrongBinder(resultTo);
...
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}

上面使用IBinder.transact()对系统进程中的AMS执行远程调用:START_ACTIVITY_TRANSACTION。

  • 参数

    caller:指向Launcher组件所在的应用程序进程的ApplicationThread对像。

    intent:包含了要启动的MainActivity组件的信息。

    resultTo:指向AMS内部的一个ActivityRecord对像,它保存了Launcher组件的信息。
/**
* An entry in the history stack, representing an activity.
*/
class ActivityRecord extends IApplicationToken.Stub {
}

NOTE:在多进程交互的环境下,IBinder对像可以是一个进程*其它进程访问的“可远程访问”对像的一个BinderProxy代理。跨进程引用一个对象的作用。

以上step操作发生在Launcher应用中,其方法调用流程图:

笔记:Activity的启动过程

阶段2:AMS保存启动信息,通知caller进入stop

接下来的操作在AMS中进行,处理Launcher发起的START_ACTIVITY_TRANSACTION请求。

AMS首先将要启动的MainActivity组件的信息保存起来,然后再向Launcher组件发送一个进入中止状态的进程间通信请求。

step 6:ActivityManagerService.startActivity()

AMS继承ActivityManagerNative,其onTransact()方法中,对code = START_ACTIVITY_TRANSACTION的处理是调用接口方法IActivityManager.startActivity(),AMS实现了startActivity():

public ActivityStack mMainStack;

public final int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
boolean debug) {
return mMainStack.startActivityMayWait(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, null, null);
}

step 7:ActivityStack.startActivityMayWait()

final int startActivityMayWait(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
boolean debug, WaitResult outResult, Configuration config) { ... // Collect information about the target of the Intent.
ActivityInfo aInfo;
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveIntent(
intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS);
aInfo = rInfo != null ? rInfo.activityInfo : null; ... int res = startActivityLocked(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, aInfo,
resultTo, resultWho, requestCode, callingPid, callingUid,
onlyIfNeeded, componentSpecified);
...
}

方法先通过PackageManager根据启动intent获得关于MainActivity组件的更多信息,保存在变量ActivityInfo aInfo中。继续调用startActivityLocked()。

step 8:ActivityStack.startActivityLocked()

final ActivityManagerService mService;
/**
* The back history of all previous (and possibly still
* running) activities. It contains HistoryRecord objects.
*/
final ArrayList mHistory = new ArrayList();
...
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType,
Uri[] grantedUriPermissions,
int grantedMode, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, boolean onlyIfNeeded,
boolean componentSpecified) {
...
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
... ActivityRecord sourceRecord = null;
...
int index = indexOfTokenLocked(resultTo);
...
sourceRecord = (ActivityRecord)mHistory.get(index); ActivityRecord r = new ActivityRecord(mService, this, callerApp,
callingUid,intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
... return startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded, true);
}

AMS内部使用ProcessRecord对象表示每一个应用程序进程,getRecordForAppLocked获得caller对应的ProcessRecord callerApp,也就是Launcher的进程信息。

mHistory正是用来保存所有已启动的Activity组件,每个Activity组件使用ActivityRecord表示。sourceRecord就是Launcher组件对应的信息,启动操作的源组件。

之后创建一个ActivityRecord r变量,它表示要启动的MainActivity组件的信息,启动操作的目标组件。

step 9:ActivityStack.startActivityUncheckedLocked()

根据启动intent获得launchFlags。

用户是点击Launcher中的图标手动启动,所以Intent.FLAG_ACTIVITY_NO_USER_ACTION不成立,之后会向源Activity Launcher发送一个“用户离开”的事件通知。

标志FLAG_ACTIVITY_NEW_TASK说明需要将要启动的MainActivity放在一个新Task中——就是和当前的Launcher组件不在一个Task中,而在AndroidManifest.xml中可以使用

android:taskAffinity来指定组件所在任务id,所以AMS检查此Task是否存在,不存在就创建它,把MainActivity放到此Task中。每个新创建的Task有一个int id,是AMS维护的一个自增字段。

最后紧接着执行重载的另一个方法

startActivityLocked(r, newTask, doResume);

如果newTask为true,也就是要启动的Activity组件在新Task中,那么它会被放在mHistory栈的顶部。

然后doResume = true,就对mHistory最后的Activity执行resume。

这里就是MainActivity被添加到栈顶,然后会被执行resume。

step 10:ActivityStack.resumeTopActivityLocked()

在启动MainActivity的ActivityRecord之前,会通知MainActivity的上一个prev处在前台的Activity组件——也就是Launcher用户离开。

step 11:ActivityStack.startPausingLocked()

ActivityRecord有一个字段ProcessRecord app,表示其Activity组件所在的进程。ProcessRecord有一个字段ApplicationThreadProxy thread,就是另一个应用程序进程中ApplicationThread的Binder代理对象。

startPausingLocked()会执行代表Launcher组件所在进程的ProcessRecord变量的方法app.thread.schedulePauseActivity()来通知Launcher组件进入pause状态。

ActivityRecord prev = mResumedActivity;
...
prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
prev.configChangeFlags);

上面代码片段中prev就是Launcher对应的组件信息。它是一个IBinder实例,对应Launcher组件。

因为app.thread.schedulePauseActivity()的执行是一个Binder通信,但指定为FLAG_ONEWAY,所以方法调用会立即返回。当前方法中会使用mHandler发送一个PAUSE_TIMEOUT_MSG的消息:

// Schedule a pause timeout in case the app doesn't respond.
// We don't give it much time because this directly impacts the
// responsiveness seen by the user.
Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
msg.obj = prev;
mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);

作为系统进程中的服务,此处AMS没有以同步的Binder通信方式等待Launcher执行pause完成,而是异步地通知Launcher进入pause,然后,它内部使用Handler发送一个延迟消息,在延迟消息收到前若Launcher没有通知AMS已经进入pause,那么AMS做其它处理——认为Launcher未响应。

step 12:ApplicationThreadProxy.schedulePauseActivity()

public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
data.writeInt(finished ? 1 : 0);
data.writeInt(userLeaving ? 1 :0);
data.writeInt(configChanges);
mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}

它执行了一个Binder-IPC操作,发送命令code = SCHEDULE_PAUSE_ACTIVITY_TRANSACTION。

这个进程间操作是FLAG_ONEWAY的,它会立即返回。

参数token就是AMS中Launcher对应的ActivityRecord对象。

注意Binder的通信默认是同步的,更多为什么可以先了解下Binder通信。

以上操作都是在AMS中执行的,AMS在系统进程SystemServer中。所有方法的调用流程图:

笔记:Activity的启动过程

阶段3:Launcher处理SCHEDULE_PAUSE_ACTIVITY_TRANSACTION

接下来地的几步操作在Launcher中进行,执行处理AMS发送的SCHEDULE_PAUSE_ACTIVITY_TRANSACTION通信请求。

方法调用流程如下:

笔记:Activity的启动过程

Step 13:ApplicationThread.schedulePauseActivity()

注意系统源码在Binder通信的设计,如果了解AIDL生成的通信接口的实现类和Proxy内部类等,这些Binder-IPC相关的类型都很容易理解。

类似AMS和ActivityManagerNative等,ApplicationThreadNative在onTransact()中对code = SCHEDULE_PAUSE_ACTIVITY_TRANSACTION的处理是调用接口方法IApplicationThread.schedulePauseActivity()。

case SCHEDULE_PAUSE_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
IBinder b = data.readStrongBinder();
boolean finished = data.readInt() != 0;
boolean userLeaving = data.readInt() != 0;
int configChanges = data.readInt();
schedulePauseActivity(b, finished, userLeaving, configChanges);
return true;
}

变量IBinder b就是AMS中Launcher对应的ActivityRecord对象。

ApplicationThread是ActivityThread的内部类,它继承ApplicationThreadNative,实现了schedulePauseActivity()。

public final class ActivityThread {
...
private final class ApplicationThread extends ApplicationThreadNative {
...
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
queueOrSendMessage(
finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
token,
(userLeaving ? 1 : 0),
configChanges);
}
}
}

可以看到,方法执行queueOrSendMessage()向应用程序Launcher的主线程的消息队列发送一个类型为PAUSE_ACTIVITY的消息。

Step 14:ActivityThread.queueOrSendMessage()

public final class ActivityThread {
...
final H mH = new H();
...
private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
}
}
}

ActivityThread的字段mH是在进程主线程中创建的,用来处理应用程序进程中的主线程消息,类H继承Handler。

因为对Binder方法onTransact()的执行基本是(当跨进程时)在Binder线程池中的线程中执行的,可见这里定义mH就是为了供其它非主线程的操作转到主线程中执行。

TODO:ActivityThread的创建及其相关知识后面会小结下。

Step 15:H.handleMessage()

/**
* This manages the execution of the main thread in an
* application process, scheduling and executing activities,
* broadcasts, and other operations on it as the activity
* manager requests.
*/
public final class ActivityThread {
...
private final class H extends Handler {
...
public static final int PAUSE_ACTIVITY = 101; public void handleMessage(Message msg) {
switch (msg.what) {
...
case PAUSE_ACTIVITY:
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
...
break;
...
}
}
}

msg.obj就是AMS中执行ApplicationThreadProxy.schedulePauseActivity()时传递的代表IBinder的ActivityRecord对象。

Step 16:ActivityThread.handlePauseActivity()

应用程序进程中启动的每一个Activity组件都使用一个ActivityClientRecord对象描述,其对应AMS中的ActivityRecord对象。ActivityThread的字段mActivities就是。

方法中,根据AMS传递的表示Launcher组件的token从mActivities获得Launcher对应的ActivityClientRecord对象,通知它执行onUserLeaveHint(),然后是onPause()。

最后,ActivityManagerNative.getDefault()获得AMS代理对象,通知AMS已经完成对Launcher的pause。

Step 17:ActivityManagerProxy.activityPaused()

public void activityPaused(IBinder token, Bundle state) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
data.writeBundle(state);
mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}

执行Binder通信,通知AMS事件code = ACTIVITY_PAUSED_TRANSACTION。

阶段4 AMS处理ACTIVITY_PAUSED_TRANSACTION

接下来的操作又转到AMS中进行,从响应ACTIVITY_PAUSED_TRANSACTION事件开始。

方法调用时序图:

笔记:Activity的启动过程

Step 18:ActivityManagerService.activityPaused()

在onTransact()中响应ACTIVITY_PAUSED_TRANSACTION执行的方法。

请求转给ActivityStack:

mMainStack.activityPaused(token, icicle, false);

参数token指向Launcher组件对应的ActivityRecord对象。

Step 19:ActivityStack.activityPaused()

根据token从字段mHistory中找到Launcher的ActivityRecord对象,然后设置其为paused。

继续启动MainActivity。

Step 20:ActivityStack.completePauseLocked()

对ActivityRecord prev = mPausingActivity,也就是Launcher的pause完成。

执行resumeTopActivityLocked(prev)。

前面的执行中,mHistory中的topActivity就是MainActivity。

Step 21:ActivityStack.resumeTopActivityLocked()

此时的topActivity就是MainActivity,其ActivityRecord.app字段为null,因为还未为它创建进程。

Step 22:ActivityStack.startSpecificActivityLocked()

在AMS中,每一个Activity组件都有userId和进程名,用户ID是安装该Activity组件的App时由PackageManagerService分配的,进程名由该组件的android:process决定的。

方法中,AMS检查对应用户ID和进程名的进程是否存在,ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid)

若app为null,就先启动一个App进程,然后通知该进程启动MainActivity。

Step 23:AMS.startProcessLocked()

AMS用字段mProcessNames记录已经运行的App进程的信息:

/**
* All of the applications we currently have running organized by name.
* The keys are strings of the application package name (as
* returned by the package manager), and the keys are ApplicationRecord
* objects.
*/
final ProcessMap<ProcessRecord> mProcessNames
= new ProcessMap<ProcessRecord>();

再次检查对应app进程是否存在:

ProcessRecord app = getProcessRecordLocked(processName, info.uid)

如果app为null:

app = newProcessRecordLocked(null, info, processName);
mProcessNames.put(processName, info.uid, app);

最后,方法调用一个重载版本继续完成MainActivity的进程的创建。

startProcessLocked(app, hostingType, hostingNameStr);

方法首先得到要创建的进程的用户ID和用户组ID,然后执行Process.start()静态函数启动一个新的应用程序进程:

int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);

得到的返回值pid是对应启动的App进程的大于0的进程ID。然后将参数app指向的ProcessRecord对象保存在AMS的以pid为key的字典字段mPidsSelfLocked中:

/**
* All of the processes we currently have running organized by pid.
* The keys are the pid running the application.
*
* <p>NOTE: This object is protected by its own lock, NOT the global
* activity manager lock!
*/
final SparseArray<ProcessRecord> mPidsSelfLocked
= new SparseArray<ProcessRecord>();
.... this.mPidsSelfLocked.put(pid, app);

进程的启动还是异步的,所以这里向AMS使用Handler发送延迟消息PROC_START_TIMEOUT_MSG。

如果延迟时间后新启动的App进程未通知AMS它启动完成,否则AMS不再继续处理MainActivity的启动。

阶段5

接下来就是android应用程序进程启动的过程。

AMS中执行的Process.start()方法所启动的新进程的程序入口方法是android.app.ActivityThread的静态成员函数main()。

接下来的方法执行流程如:

笔记:Activity的启动过程

Step 24:ActivityThread.main

public final class ActivityThread {
...
final ApplicationThread mAppThread = new ApplicationThread();
...
private final void attach(boolean system) {
....
mSystemThread = system;
if (!system) {
...
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException e) {
}
}
...
}
... public static final void main(String[] args) {
..
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(this);
...
Looper.loop();
...
}
}

创建一个ActivityThread对象,调用其attach()向AMS发送进程启动完成通知。

开启主线程消息循环。

ApplicationThread是一个Binder本地对象,AMS使用它的代理和当前App进程通信。

attachApplication()向AMS通知进程创建完成。

Step 25:ActivityManagerProxy.attachApplication

public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}

向AMS发送ATTACH_APPLICATION_TRANSACTION事件,IApplicationThread app的Binder代理作为AMS对当前ApplicationThread的标识。

阶段6 AMS响应App进程创建完成通知

接下来是AMS处理ATTACH_APPLICATION_TRANSACTION事件。

方法时序图:

笔记:Activity的启动过程

Step 26:AMS.attachApplication

public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}

callingPid就是为MainActivity创建的新进程的pid。

Step 27:AMS.attachApplicationLocked

根据pid得到mPidsSelfLocked中的ProcessRecord app对象。

得到AMS管理的栈顶topActivity:

ActivityRecord hr = mMainStack.topRunningActivityLocked(null);

将app设置给MainActivity对应的hr。

执行mMainStack.realStartActivityLocked(hr, app, true, true)继续启动MainActivity。

Step 28:ActivityStack.realStartActivityLocked

这时MainActivity的ActivityRecord r的app字段就是设置过的,不为null。

topActivity.app.thread就是所创建MainActivity进程中ApplicationThread mAppThread的Binder代理。

使用topActivity.app.thread.scheduleLaunchActivity()跨进程通知创建的App进程启动MainActivity组件。

Step 29:ApplicationThreadProxy.scheduleLaunchActivity

使用IBinder向MainActivity对应进程的mAppThread发送SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION通知。

消息中记录了要启动的MainActivity的ActivityInfo info。

阶段7 ActivityThread处理启动MainActivity的请求

接下来的操作就在为MainActivity所创建的新的App进程中执行。

前面的ActivityThread.main()的执行使得进程中已经存在mAppThread和创建的ActivityThread thread。

main方法进入Looper循环。

将要执行的方法时序图:

笔记:Activity的启动过程

Step 30:ApplicationThread.scheduleLaunchActivity

ApplicationThreadNative的onTransact()将对SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION的响应转为ApplicationThread.scheduleLaunchActivity()的调用。

方法继续使用queueOrSendMessage()将处理打包为msg传给ActivityThread.mH。

ActivityClientRecord r = new ActivityClientRecord();
...
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);

r就是从AMS端传递过来的MainActivity的信息。

Step 31:ActivityThread.queueOrSendMessage

handleMessage()中对消息LAUNCH_ACTIVITY的处理:

case LAUNCH_ACTIVITY: {
ActivityClientRecord r = (ActivityClientRecord)msg.obj; r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo);
handleLaunchActivity(r, null);

Step 32:ActivityThread.handleLaunchActivity

private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity a = performLaunchActivity(r, customIntent);
...
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward);
...
}

启动MainActivity,然后设置它为resume。

Step 34:ActivityThread.performLaunchActivity

原型:

private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent)

获得关于MainActivity的组件信息:

ComponentName component = r.intent.getComponent();

然后根据component,使用类加载器实例化Activity对象:

Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...

然后创建一个ContextImpl appContext,作为activity的运行上下文环境。

ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo, r.token, this);
appContext.setOuterContext(activity);

使用appContext和参数r对activity执行初始化:

activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstance,
r.lastNonConfigurationChildInstances, config);

然后执行onCreate:

mInstrumentation.callActivityOnCreate(activity, r.state);

callActivityOnCreate()会调用Activity.onCreate(),这时自定义MainActivity中的setContentView()等逻辑就会被调用。

activity创建完毕后,对应记录被添加到ActivityThread中:

mActivities.put(r.token, r);

ActivityClientRecord r是AMS中对应MainActivity的ActivityRecord对象的Binder代理,它们分别是MainActivity在AMS中和App进程ActivityThread中的描述。

总结

经过以上步骤,从Launcher.startActivitySafely()开始到Activity.onCreate()得以执行,可以认为MainActivity组件及其进程已经启动完毕。

启动的各个阶段

  1. Launcher组件向AMS发送启动MainActivity组件的进程间通信。
  2. AMS首先保存要启动的MainActivity的信息,然后向Launcher发送进入pause状态的进车间通信。
  3. Launcher进入中止状态后,向AMS发送已经进入中止状态的进程间通信请求。这样AMS就继续执行启动MainActivity的操作。
  4. AMS检查用来运行MainActivity的进程不存在,创建并启动一个App进程。
  5. 新进程启动完成后,向AMS发送启动完成的进程间通信请求。
  6. AMS将保存的MainActivity组件的信息发送给创建的新进程。
  7. 新进程启动MainActivity。

ActivityThread.mH

ActivityThread的main方法就是整个App进程的入口函数,它执行结束那么App进程就结束了。

main()中开启了Looper消息循环。

ActivityThread.mH把很多Binder操作从Binder线程中转到UI线程中执行。

(本文使用Atom编写)