Android源码分析 二月 28, 2017 chaossss 2 comments

Android App启动流程

前言

在使用Android手机时,我们总会启动各种各样的App以满足生活的各种需求,你是否想过,我们是怎样启动这些APP的?今天我将带着读者一起探索在Android系统中,一个App是如何被启动的。

在开始分析之前,我们先回想下启动一个App的流程:

Android系统桌面->点击应用图标->启动App

从这个过程来看,只要弄明白:

1. Android系统桌面是什么
2. 点击应用图标后Android系统执行了什么操作

就可以解决我们“App如何被启动”的疑问。

Android系统桌面是什么

如何分析Android系统桌面是什么

在Android系统中,Activity是视图存在的根本,那么我们可以通过命令adb shell dumpsys activity activities判断是哪个Activity为我们呈现桌面视图的。

以我的小米5为例,通过USB连上电脑后,输入命令adb shell dumpsys activity activities得到结果如下:

可以看到,显示桌面视图的Activity是com.miui.home包下的名为Launcher的Activity。

因为虚拟机编译AOSP实在是太慢了,所以我没有编译AOSP得到系统镜像,然后运行模拟器跑AOSP,再通过Ubuntu的Shell跑命令。国内手机厂商虽然会对Android系统进行定制,但是命名和包名都会和原生尽可能保持一致的。

那么我们在IDE中搜索Launcher,看看这个Activity是什么。结果如下:

这里摘选的是Launcher2的Launcher进行分析,虽然新版本Android已经使用Launcher3作为桌面App了,但是我进入源码看了看发现核心的逻辑是没有变化的,所以选取了代码更短的Launcher2的Launcher进行分析。

点击应用图标后Android系统执行了什么操作

既然Launcher是Activity,那就意味着我们点击桌面的事件可以表达为:

呈现Android桌面视图(View)->点击View上某个应用图标->产生点击事件->点击事件被响应->通知Android系统的某个/某些进程->Android系统执行某些操作->启动App

Launcher如何响应由我们产生的点击事件

/**
* Launches the intent referred by the clicked shortcut.
*
* @param v The view representing the clicked shortcut.
*/
public void onClick(View v) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) {
return;
}

if (!mWorkspace.isFinishedSwitchingState()) {
return;
}

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

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) {
if (isAllAppsVisible()) {
showWorkspace(true);
} else {
onClickAllAppsButton(v);
}
}
}
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();
Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
}
return success;
}

从代码来看,产生点击事件后,如果产生点击事件的View的Tag是ShortcutInfo(即启动应用的快捷方式),就会取得ShortcutInfo中保存的Intent(这个Intent指向我们要启动的App),然后执行startActivitySafely(v, intent, tag)方法,而startActivitySafely方法只是对startActivity方法的简单封装。

所以,Launcher响应我们产生的点击事件后,实际上就是启动一个新的Activity。

我们现在回想下App开发时,每个App都需要有一个“MainActivity”,这个Activity必须在AndroidManifest.xml文件中有以下配置:





在配置AndroidManifest.xml文件时,将Activity的Action指定为android.intent.action.MAIN,会使Activity在一个新的Task中启动(Task是一个Activity栈)。将category指定为android.intent.category.LAUNCHER,表示通过Intent启动此Activity时,只接受category为LAUNCHER的Intent。

所以,Launcher将会通过App的快捷方式(ShortcutInfo)得到应用的Intent,并通过这个Intent启动应用的“MainActivity”,从而启动应用。

所以我们研究的问题就从“App启动流程”变为“Activity启动流程”。

Launcher通过Binder通知ActivityManagerService启动Activity

现在我们就进入Launcher的startActivity方法里面探索“Activity启动流程”吧:

boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

try {
// Only launch using the new animation if the shortcut has not opted out (this is a
// private contract between launcher and may be ignored in the future).
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
LauncherApps launcherApps = (LauncherApps)
this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
if (useLaunchAnimation) {
ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
v.getMeasuredWidth(), v.getMeasuredHeight());
if (user == null || user.equals(android.os.Process.myUserHandle())) {
// Could be launching some bookkeeping activity
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) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Launcher does not have the permission to launch " + intent +
". Make sure to create a MAIN intent-filter for the corresponding activity " +
"or use the exported attribute for this activity. "
+ "tag="+ tag + " intent=" + intent, e);
}
return false;
}

在这个方法中,首先,将Intent的Flag设为Intent.FLAG_ACTIVITY_NEW_TASK,使得Android系统将创建一个新的Task来放置即将被打开的新Activity(应用的“MainActivity)。然后获取一个布尔值以用于后续判断是否显示启动App的动画。

然后获取Intent中是否传输了Parcelable格式的用户句柄,并通过Context.LAUNCHER_APPS_SERVICE获取用于在多用户情境下启动App的系统服务。

不管是否显示启动App的动画,最终都会执行startActivity(intent)launcherApps.startMainActivity方法以启动应用的“MainActivity”。而launcherApps.startMainActivity只在用户句柄不为空且用户句柄不等于当前进程句柄时(其他用户的句柄)调用。

为什么用户句柄会影响Activity的启动方式

这一点和Android的多用户安全机制有关。

假设我们有用户A和用户B在使用同一台手机,用户A是无法访问到用户B的文件或者和用户B的App通信的。所以假如我们现在是用户A,但我们想启动用户B的App,是无法直接实现的,因为用户A没有权限访问到用户B的数据,即使我们在代码中强行把user id设为用户B的user id,交给内核执行时也会抛出SecurityException。因此我们需要取得用户A的句柄(和用户A相关的数据),将我们想启动的用户B的App的Intent、用户A的句柄交给内核,让拥有权限的Android系统服务(内核态进程)去访问用户B的数据并执行相关的操作。

假如是单用户情境,就会相对简单了。因为此时只有一个用户,而该用户始终有权限直接访问自己的数据。

startActivity(intent)如何启动Activity

进入Activity类后层层深入就可以看到最终调用的是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());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received.  Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}

cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}

从代码上看,如果Launcher有mParent Activity,就会执行mParent.startActivityFromChild;如果没有,就会执行mInstrumentation.execStartActivity。进入mParent.startActivityFromChild方法会看到最终也是执行了mInstrumentation.execStartActivity。执行完成后,会取得一个ActivityResult对象,用于给调用者Activity传递一些数据,最后在Activity切换时显示Transition动画。

这里有一点需要指出的是:这里的ParentActivity指的是类似TabActivity、ActivityGroup关系的嵌套Activity。之所以要强调parent和child,是要避免混乱的Activity嵌套关系。

我们进入Instrumentation类看看execStartActivity方法吧:

public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) { final ActivityMonitor am = mActivityMonitors.get(i); if (am.match(who, null, intent)) { am.mHits++; if (am.isBlocking()) { return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
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;
}

首先,我们通过参数IBinder contextThread取得一个IApplicationThread类型的对象whoThread,而contextThread是由mMainThread.getApplicationThread()取得的ApplicationThread对象,此时mMainThread指的就是Launcher应用的主线程,所以whoThread指代的自然是Launcher的ApplicationThread。

因为Activity的onProvideReferrer()方法默认返回null,除非该方法被重写,而我们使用的Launcher并没有重写该方法,所以不用管referrer。

然后判断是否有ActivityMonitor,如果有,则即将要打开的Activity是否和ActivityMonitor中保存的IntentFilter匹配,如果匹配则增加ActivityMonitor的计数。大致是用于监控符合匹配规则的Activity的数量的。

最后调用ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);启动Activity,并检查启动是否成功。换句话说,最终负责启动Activity的是ActivityManager,前面得到的ApplicationThread也是在这里使用的。

那么ActivityManager、ApplicationThread、ActivityThread都是什么呢?

ActivityManagerService通过Binder将Launcher切换到pause状态

首先,调用ActivityManagerNative.getDefault()方法实际调用的是asInterface(IBinder obj)方法,也就意味着我们使用的其实是ActivityManagerProxy,而ActivityManagerProxy则是ActivityManagerService的代理,详见下面的代码:

static public IActivityManager getDefault() {
return gDefault.get();
}

private static final Singleton gDefault = new Singleton() {
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 asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}

return new ActivityManagerProxy(obj);
}

那么进入ActivityManagerProxy:

class ActivityManagerProxy implements IActivityManager
{
public ActivityManagerProxy(IBinder remote)
{
mRemote = remote;
}

public IBinder asBinder()
{
return mRemote;
}

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用于传输启动Activity需要的数据,reply用于获取
// 启动Activity操作执行后系统返回的响应
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
// caller 就是Launcher提供的ApplicationThread(也就是前面提到的whoThread)
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
// 记录启动新Activity的应用的包名,也就是Launcher的包名
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
// 将resultTo这个IBinder对象写入data,实际写入的就是前面的参数——IBinder token
// 而这个token是什么,我们暂时不管,后面会给出解释
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;
}
……省略余下代码……
}

将数据都写入后,就通过mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)传输数据并得到响应(写入reply)。

前面已经提到了,ActivityManagerProxy是ActivityManagerService的代理,那么调用mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)实际上就是通过Binder建立Launcher所在的进程与system_server进程(Android Framework层的服务几乎都由system_server进程管理,因此ActivityManagerService运行在system_server进程中)的通信,并把我们写入data的数据通过Binder传递给ActivityManagerService。

ActivityManagerService得到我们用Parcelable封装的data后就会调用startActivity方法为Launcher启动Activity:

@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) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}

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

void enforceNotIsolatedCaller(String caller) {
if (UserHandle.isIsolated(Binder.getCallingUid())) {
throw new SecurityException("Isolated process not allowed to call " + caller);
}
}

enforceNotIsolatedCaller("startActivity");作安全性检查,判断当前用户是否允许启动Activity,然后对之前传入的userId进行转换和安全性检查。最后调用mStackSupervisor.startActivityMayWait。这里的mStackSupervisor是ActivityStackSupervisor对象,前面提到过,Task是以堆栈形式组织Activity的集合,而Task又由ActivityStack管理,ActivityStackSupervisor则是管理ActivityStack的类。

由于代码太长,下面只截取部分关键代码讲解:

首先,通过下面代码段调用PackageManagerService解析Intent(我们想要打开的App的用于启动MainActivity的Intent),将解析的结果保存到ActivityInfo类型的对象里:

// Collect information about the target of the Intent.
ActivityInfo aInfo =
resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

// Method - resolveActivity
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
ProfilerInfo profilerInfo, int userId) {
// 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, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
} catch (RemoteException e) {
aInfo = null;
}

……省略,大致是做一些安全性检查和相关信息的设置……
return aInfo;
}

然后互斥锁锁住ActivityManagerService的实例mService,如果解析的ActivityInfo不为空,且ApplicationInfo有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE标记,意味着调用者App是属于heavy-weight process,如果现在有另一个heavy-weight process正在运行,则需要进行一些额外的处理。然后进入到startActivityLocked方法。

这里通过注释我们可以发现,若App有ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE标记,App就可视为heavy-weight process,该标记可以在AndroidManifest.xml中设置,它是用于声明App是否享受系统提供的Activity状态保存/恢复功能的。但是似乎没有App能成为heavy-weight process,因为PackageParser的parseApplication方法并不会解析该标签。

startActivityLocked方法中,得到Launcher(Activity)的ActivityRecord(Activity相关的信息),并创建我们要启动的Activity的ActivityRecord,最终执行startActivityUncheckedLocked继续启动Activity:


ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) { sourceRecord = isInAnyStackLocked(resultTo); if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord); if (sourceRecord != null) { if (requestCode >= 0 && !sourceRecord.finishing) { resultRecord = sourceRecord; } } } ………… ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null, this, container, options); …… err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);

进入startActivityUncheckedLocked方法,完成一些简单的初始化后,向下执行到这段代码:如果Intent里有Intent.FLAG_ACTIVITY_NEW_DOCUMENT标记(在AndroidManifest.xml中声明),且即将要打开的Activity的启动模式又被声明为SingleInstance或SingleTask,那么Intent中携带的标记和AndroidManifest中声明的标记出现冲突,而AndroidManifest的优先级是高于Intent的,因此将launchFlags的对应位置为0。

然后是对launchFlags一系列的置位,目的是设置启动模式。

if ((launchFlags &amp; Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &amp;&amp;
(launchSingleInstance || launchSingleTask)) {
// We have a conflict between the Intent and the Activity manifest, manifest wins.
Slog.i(TAG, "Ignoring FLAG_ACTIVITY_NEW_DOCUMENT, launchMode is " +
"\"singleInstance\" or \"singleTask\"");
launchFlags &amp;=
~(Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
} else {
switch (r.info.documentLaunchMode) {
case ActivityInfo.DOCUMENT_LAUNCH_NONE:
break;
case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
break;
case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
launchFlags &amp;= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
break;
}
}
}
……

if ((launchFlags &amp; Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &amp;&amp; r.resultTo == null) {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}

// If we are actually going to launch in to a new task, there are some cases where
// we further want to do multiple task.
if ((launchFlags &amp; Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
if (launchTaskBehind
|| r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
}
}

……

if (inTask == null) {
if (sourceRecord == null) {
// This activity is not being started from another...  in this
// case we -always- start a new task.
if ((launchFlags &amp; Intent.FLAG_ACTIVITY_NEW_TASK) == 0 &amp;&amp; inTask == null) {
Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
"Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// The original activity who is starting us is running as a single
// instance...  this new activity it is starting must go on its
// own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
} else if (launchSingleInstance || launchSingleTask) {
// The activity being started is a single instance...  it always
// gets launched into its own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
}

……

// 因为我们是从Launcher启动目的Activity,所以sourceRecord不为null,值为Launcher的ActivityRecord
if (sourceRecord != null) {
if (sourceRecord.finishing) {
// 如果sourceRecord表示的Activity正在结束/被销毁,那么我们不能把该Activity看作启动目的
// Activity的源Activity,因为和源Activity关联的Task现在可能是空的(没有Activity)或者
// 也在结束/被销毁的过程中,所以我们不能盲目地把目的Activity放到该Task中。取而代之的是,
// 我们会为它找到一个可用的Task,但我们要先保存源Activity的Task的信息,使得我们在创建新
// 的可用的Task时能用到里面的一些信息。
if ((launchFlags &amp; Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from finishing " + sourceRecord
+ "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
newTaskInfo = sourceRecord.info;
newTaskIntent = sourceRecord.task.intent;
}
sourceRecord = null;
sourceStack = null;
} else {
sourceStack = sourceRecord.task.stack;
}
} else {
sourceStack = null;
}

……

// 为目的Activity创建新的Task
if (r.resultTo == null &amp;&amp; inTask == null &amp;&amp; !addingToTask
&amp;&amp; (launchFlags &amp; Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
targetStack = computeStackFocus(r, newTask);
targetStack.moveToFront("startingNewTask");

if (reuseTask == null) {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
taskToAffiliate);
if (DEBUG_TASKS) Slog.v(TAG_TASKS,
"Starting new activity " + r + " in new task " + r.task);
} else {
r.setTask(reuseTask, taskToAffiliate);
}
if (isLockTaskModeViolation(r.task)) {
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (!movedHome) {
if ((launchFlags &amp;
(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
// Caller wants to appear on home activity, so before starting
// their own activity we will bring home to the front.
r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
}
}
}

完成上面一系列的处理后,调用ActivityStack的startActivityLocked方法继续执行启动Activity需要的操作,targetStack是通过这行代码targetStack = computeStackFocus(r, newTask)为用户新建的ActivityStack:

mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
intent, r.getUriPermissionsLocked(), r.userId);

if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
}
if (newTask) {
EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
}
ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
targetStack.mLastPausedActivity = null;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
if (!launchTaskBehind) {
// Don't set focus on an activity that's going to the back.
mService.setFocusedActivityLocked(r, "startedActivity");
}
return ActivityManager.START_SUCCESS;

进入到ActivityStack的startActivityLocked方法,首先为目的Activity创建ProcessRecord,然后用WindowManager进行一些切换窗口的操作,最后调用mStackSupervisor.resumeTopActivitiesLocked(this, r, options)

……

if (!isHomeStack() || numActivities() > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
// not currently running.
boolean showStartingIcon = newTask;
ProcessRecord proc = r.app;
if (proc == null) {
proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
}
if (proc == null || proc.thread == null) {
showStartingIcon = true;
}
……调用WindowManager切换窗口……
}

……

if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
}

进入到resumeTopActivitiesLocked方法,调用resumeTopActivityLocked方法将所有ActivityStack(多个显示设备,每个设备对应一个ActivityStack)栈顶的Activity切换到resume状态(生命周期的onResume),而resumeTopActivityLocked方法先避免递归调用,然后调用ActivityStack的resumeTopActivityInnerLocked方法。

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = mFocusedStack;
}
// Do targetStack first.
boolean result = false;
if (isFrontStack(targetStack)) {
result = targetStack.resumeTopActivityLocked(target, targetOptions);
}

for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (stack == targetStack) {
// Already started above.
continue;
}
if (isFrontStack(stack)) {
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}

下面这段代码主要就是做一些前期的检查,避免做多余的工作浪费时间,并且确保目标Activity处于正确的“状态”,使得我们后面能把它切换到resume状态并显示。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

// 判断ActivityManagerService是否已经启动完毕
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
}

// 获取parentActivity,如果parentActivity还未处于resume状态,则不能将stack栈顶的Activity切换为resume状态(Activity的嵌套关系不能弄乱)
ActivityRecord parent = mActivityContainer.mParentActivity;
if ((parent != null && parent.state != ActivityState.RESUMED) ||
!mActivityContainer.isAttachedLocked()) {
// Do not resume this stack if its parent is not resumed.
// TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
return false;
}

// 如果有正在初始化的Activity没有位于ActivityStack的栈顶,且正在执行window的启动和显示,
// 则要将window相关的操作取消。因为这类Activity的窗口有可能被孤立,那么它们有可能永远也不会进入resume状态
cancelInitializingActivities();

// 取得当前ActivityStack栈顶Activity的ActivityRecord
final ActivityRecord next = topRunningActivityLocked(null);

// 记住我们怎样处理pause/resume状态切换,并确保无论何时结束处理都会重置状态
final boolean userLeaving = mStackSupervisor.mUserLeaving;
mStackSupervisor.mUserLeaving = false;

final TaskRecord prevTask = prev != null ? prev.task : null;
if (next == null) {
// next为null表示当前ActivityStack没有要显示的Activity
final String reason = "noMoreActivities";
if (!mFullscreen) {
// 如果当前ActivityStack不是全屏的,将焦点切换到下一个拥有Activity的可见ActivityStack中
final ActivityStack stack = getNextVisibleStackLocked();
if (adjustFocusToNextVisibleStackLocked(stack, reason)) {
return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null);
}
}
// 如果ActivityStack是全屏的,却没有可以显示的Activity,那么就显示桌面(Launcher)
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: No more activities go home");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
}

next.delayedResume = false;

// 如果当前栈顶Activity处于resume状态,且就是我们要打开的Activity,则直接结束
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Top activity resumed " + next);
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}

// 对prevActivity(Launcher)所在的Task进行一些判断,如果prevTask和nextTask相同,那么直接将
// prevTask直接设为栈顶Task;如果prevTask不是当前ActivityStack栈顶的Task,那么它后面的Task
// 都应该放到Launcher的Task后面;后面则是有关是否为桌面的判断和处理了。
final TaskRecord nextTask = next.task;
if (prevTask != null && prevTask.stack == this &&
prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
if (prevTask == nextTask) {
prevTask.setFrontOfTask();
} else if (prevTask != topTask()) {
// This task is going away but it was supposed to return to the home stack.
// Now the task above it has to return to the home task instead.
final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
} else if (!isOnHomeDisplay()) {
return false;
} else if (!isHomeStack()){
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Launching home next");
final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
}
}

// 如果ActivityManagerService处于休眠状态,而且此时没有Activity处于resume状态
// 且栈顶Activity处于pause状态,则中断调度
if (mService.isSleepingOrShuttingDown()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
// Make sure we have executed any pending transitions, since there
// should be nothing left to do at this point.
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Going to sleep and all paused");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}

// Make sure that the user who owns this activity is started.  If not,
// we will just leave it as is because someone should be bringing
// another user's activities to the top of the stack.
if (mService.mStartedUsers.get(next.userId) == null) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.userId + " is stopped");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}

// 确保我们要启动的Activity没有处于stop队列、休眠队列、等待变为可见队列中
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);

if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

// If we are currently pausing an activity, then don't do anything
// until that is done.
if (!mStackSupervisor.allPausedActivitiesComplete()) {
if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
"resumeTopActivityLocked: Skip resume: some activity pausing.");
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}

……待续……
}

后面做的工作就是:将Launcher切换到pause状态,用WindowManager将Launcher的窗口隐藏。现在只完成了Activity相关的预处理工作,目标应用的进程和主线程还没有创建,因此后面会进入if的false分支调用mStackSupervisor.startSpecificActivityLocked方法创建应用进程;如果目标Activity的进程和主线程已经创建,则进入if语句的true分支直接将目标Activity切换到resume状态,并显示目标Activity的窗口。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

……续上……

// 步入setLaunchSource方法后可以知道,该方法实际是通过PowerManager的setWorkSource方法
// 设置WakeLock,使得在执行后面的工作时系统不会进入休眠状态
mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

// 现在开始将当前Activity切换到pause状态,使得栈顶Activity可以切换到resume状态
boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
// 将后台ActivityStack的Activity切换到pause状态
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
// 将当前ActivityStack中正在显示Activity切换到pause状态
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}

……

ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next);

// 目标Activity已经可见
mWindowManager.setAppVisibility(next.appToken, true);

next.startLaunchTickingLocked();

ActivityRecord lastResumedActivity =
lastStack == null ? null :lastStack.mResumedActivity;
ActivityState lastState = next.state;

mService.updateCpuStats();

// 目标Activity切换到resume状态
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)");
next.state = ActivityState.RESUMED;
mResumedActivity = next;
next.task.touchActiveTime();
mRecentTasks.addLocked(next.task);
mService.updateLruProcessLocked(next.app, true, null);
updateLRUListLocked(next);
mService.updateOomAdjLocked();

……
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
……
}

ActivityManagerService为即将打开的应用创建进程

进入ActivityStackSupervisor类的startSpecificActivityLocked方法,首先通过应用的包名和uid取得ProcessRecord,判断ProcessRecord是否被创建,若创建,则直接启动Activity;否则调用ActivityManagerService的startProcessLocked方法创建应用进程。

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

r.task.stack.setLaunchTime(r);

if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}

// If a dead object exception was thrown -- fall through to
// restart the application.
}

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}

进入到ActivityManagerService的startProcessLocked方法,首先判断要创建的进程是否为隔离进程(isolated),由于不是隔离进程,则直接进入true分支,然后再次获取ProcessRecord。如果Intent有FLAG_FROM_BACKGROUND标记,则在后台启动badProcess;否则清空进程的崩溃次数,并将进程移出badProcess集合(如果进程存在的话)。然后调用newProcessRecordLocked方法创建ProcessRecord,最后再调用另一个重载的startProcessLocked方法创建进程。

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
checkTime(startTime, "startProcess: after getProcessRecord");

if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
// If we are in the background, then check to see if this process
// is bad.  If so, we will just silently fail.
if (mBadProcesses.get(info.processName, info.uid) != null) {
if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ "/" + info.processName);
return null;
}
} else {
// When the user is explicitly starting a process, then clear its
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ "/" + info.processName);
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mBadProcesses.remove(info.processName, info.uid);
if (app != null) {
app.bad = false;
}
}
}
} else {
// If this is an isolated process, it can't re-use an existing process.
app = null;
}

……

String hostingNameStr = hostingName != null
? hostingName.flattenToShortString() : null;

if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
app.crashHandler = crashHandler;
checkTime(startTime, "startProcess: done creating new process record");
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: added package to existing proc");
}

// 如果系统还没启动完毕,则等待系统启动完毕后再启动进程
if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
"System not ready, putting on hold: " + app);
checkTime(startTime, "startProcess: returning with proc on hold");
return app;
}

checkTime(startTime, "startProcess: stepping in to startProcess");
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
checkTime(startTime, "startProcess: done starting proc!");
return (app.pid != 0) ? app : null;
}

调用newProcessRecordLocked方法根据ApplicationInfo创建ProcessRecord,并让ActivityManagerService管理该ProcessRecord,过程比较简单就不贴代码了,直接看startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs)方法吧。

进入startProcessLocked方法,首先将app的pid初始化,若进程已经存在(pid不等于0),则先清除超时信息,再讲pid置为0,然后确保app不在mProcessesOnHold列表中。

mProcessesOnHold代表在系统启动完毕前尝试启动的进程,这部分进程会先在该列表中待着,等到系统启动完毕再启动。

完成一系列的初始化操作后,调用Process.start方法创建应用进程,然后以进程pid为key,app(ProcessRecord)为value存储到ActivityManagerService的mPidsSelfLocked中。

Process.start方法创建应用进程是通过Zygote进程完成的,设置好参数和创建选项后通过zygoteState.writer将数据交给Zygote进程,它会调用fork()创建进程。在这里要注意一个地方,我们通过if (entryPoint == null) entryPoint = "android.app.ActivityThread"这行代码设置了进程创建完成后的入口点(Process.start的参数注释),因此Zygote进程完成了进程创建的操作后就会执行ActivityThread的main()方法。

private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
if (app.pid > 0 && app.pid != MY_PID) {
checkTime(startTime, "startProcess: removing from pids map");
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
checkTime(startTime, "startProcess: done removing from pids map");
app.setPid(0);
}

if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,
"startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
……

// Start the process.  It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
……
}

进入到ActivityThread的main方法,首先进行一些初始化(包括参数设置、性能安全监控之类的),然后初始化Looper(Looper、Handler消息机制),创建ActivityThread,存储线程的Handler,最后启动Looper监听消息。

ActivityThread通过Binder将ApplicationThread对象传递给ActivityManagerService,并完成启动Activity的后续工作

到这里ActivityThread的初始化就完成了,但是回想一下前面的工作,我们现在将Launcher切换到了pause状态,但由于目标应用进程和线程还没有创建,所以我们还没有把目标应用的MainActivity切换到resume状态。所以就意味着,我们还需要进行应用进程和ActivityManagerService所在的system_server进程的通信,告诉ActivityManagerService我们已经创建好了进程和线程,接下来把MainActivity状态切换到resume中,就能打开应用了。

这一步工作在哪里完成的呢?

thread.attach(false)

final IActivityManager mgr = ActivityManagerNative.getDefault();看到这行代码有没有熟悉的感觉?前面我们就通过ActivityManagerNative.getDefault()取得ActivityManagerService的代理对象,完成了启动MainActivity的前期工作。这里再次取得代理对象,并调用了ActivityManagerService的attachApplication方法。

public static void main(String[] args) {
……

Process.setArgV0("");

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

private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
……
} else {
……
}
……
}

进入到ActivityManagerService的attachApplication方法,前面我们已经存储过目标应用的pid-ProcessRecord键值对了,因此这里的app不为null。然后向下执行,激活ProcessRecord并将ProcessRecord绑定到应用进程。然后通过Binder(thread.bindApplication)将各种应用相关信息传递给应用进程,进行应用进程一些必要的设置。最后调用mStackSupervisor.attachApplicationLocked(app)方法将ApplicationThread对象传递给ActivityManagerService方便后续应用进程与ActivityManagerService的通信(如:将MainActivity切换到resume状态),并完成启动应用的所有工作。

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

private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {

// Find the application record that is being attached...  either via
// the pid if we are running in multiple processes, or just pull the
// next app record if we are emulating process with anonymous threads.
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}

// 此时app不为null,跳过
if (app == null) {
……
}

// 清除ProcessRecord中的信息,以确保没有不相关进程的信息
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}

// Tell the process all about itself.

if (DEBUG_ALL) Slog.v(
TAG, "Binding process pid " + pid + " to record " + app);

// 注册DeathRecipient,确保应用意外关闭时系统进程能收到通知
final String processName = app.processName;
try {
AppDeathRecipient adr = new AppDeathRecipient(
app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {
app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName);
return false;
}

EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);

app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;

mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
……
// 调用ActivityThread的bindApplication方法
try {
……
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
……
}

……

// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}

// Find any services that should be running in this process...
if (!badApp) {
……
}

// Check if a next-broadcast receiver is in this process...
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
……
}

// Check whether the next backup agent is in this process...
if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) {
……
}

……

return true;
}

ActivityManagerService通知ActivityThread启动Activity

回到ActivityThread,先看bindApplication方法,就是将上面传的数据存储在AppBindData中,然后通过Message、Handler发送出去,我们再看看Handler是怎么处理H.BIND_APPLICATION类型的Message的。

public final void bindApplication(String processName, ApplicationInfo appInfo,
List providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle 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.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}

这里我就直接截出代码段了,最终调用了handleBindApplication方法。

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;

进入到handleBindApplication方法,首先进行一些初始化操作,然后取出data中存储的进程名,为应用进程设置进程名。然后创建应用的Context,也就是应用的运行上下文,通过Context我们可以访问到应用相关的各种资源文件(图片、布局文件等等)。然后创建进程的Instrumentation对象、Application对象,装载Provider,最终调用mInstrumentation.callApplicationOnCreate(app)方法,也就是调用我们开发App时,Application类(或子类)的onCreate()方法。

至此应用进程相关的初始化和相关的设置就完成了,接下来只要切换MainActivity的状态就大功告成了。

private void handleBindApplication(AppBindData data) {
……

// send up app name; do this *before* waiting for debugger
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());

……设置进程运行信息……

final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

……继续进程的初始化……

if (data.instrumentationName != null) {
……

} else {
mInstrumentation = new Instrumentation();
}

……

try {
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;

// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
List providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}

……

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);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}

进入到ActivityStackSupervisor类的attachApplicationLocked方法,该方法遍历mActivityDisplays列表得到当前所有ActivityStack,然后取得前台ActivityStack栈顶的ActivityRecord,不为空则启动该对该ActivityRecord调用realStartActivityLocked方法。

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFrontStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0);
}
return didSomething;
}

ActivityThread调度执行Activity生命周期方法,完成Activity的启动

进入到realStartActivityLocked方法,进行一些前期处理后调用ActivityThread的scheduleLaunchActivity方法,将创建ActivityClientRecord存储我们传入的各种应用相关的数据,通过Handler机制发送。当Handler接收到LAUNCH_ACTIVITY类型的消息时,执行handleLaunchActivity方法。

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

@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 pendingResults, List pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

updateProcessState(procState, false);

ActivityClientRecord r = new ActivityClientRecord();

r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;

r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;

r.startsNotResumed = notResumed;
r.isForward = isForward;

r.profilerInfo = profilerInfo;

r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);

sendMessage(H.LAUNCH_ACTIVITY, r);
}

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);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;

进入到handleLaunchActivity方法,首先进行参数设置,然后调用performLaunchActivity方法得到目标应用的MainActivity并使其分别调用onCreate、onStart方法,然后调用handleResumeActivity方法让MainActivity进入resume状态,完成启动。

private 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,
!r.activity.mFinished && !r.startsNotResumed);

……
} else {
……
}
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 初始化设置
……

// 通过反射获得MainActivity
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) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}

try {
……

if (activity != null) {
// 为MainActivity创建运行的上下文环境Context,并与Activity绑定
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
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);

……
// 回调MainActivity生命周期的onCreate方法
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
……
// 回调MainActivity生命周期的onStart方法
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
……

} catch (SuperNotCalledException e) {
throw e;

} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}

return activity;
}

final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;

// TODO Push resumeArgs into the activity for consideration
ActivityClientRecord r = performResumeActivity(token, clearHide);

……
}

总结

用文字总结App启动流程可以分为以下步骤:

1. Launcher通过Binder建立Launcher所在进程与system_server进程(ActivityManagerService所在进程)的通信,通知ActivityManagerService即将要启动一个Activity
2. ActivityManagerService通过Binder让Launcher进入pause状态
3. Launcher进入pause状态后,通过Binder告知ActivityManagerService,随后ActivityManagerService创建一个进程(将要打开的应用进程)并启动ActivityThread(应用的UI线程)
4. ActivityThread通过Binder将ApplicationThread类型的Binder对象传递给ActivityManagerService,方便ActivityManagerService后续与其的通信
5. 准备工作完成后,ActivityManagerService通知ActivityThread启动Activity
6. ActivityThread调度执行Activity的生命周期方法,完成启动Activity的工作

相关函数调用的时序图:

Android App启动流程》有2个想法

  1. 好长啊,没时间看,只看了大概,Android桌面只是一个app的Activity,上面显示了其它app图标,通过系统ActivityManagerService通信访问…

发表评论