所有代码均来自Android 11
App的启动流程是AMS 中非常重要的一个环节,也是在面试过程中经常被问到的一个知识点,想要理解并记住就需要对他的整个过程有一个整体的概念,这个整体的概念大致如下
1.任务封装:使用 启动App 其实就是startActivity 的过程 , 在ActivityTaskManagerService 会将这个任务做一个整体的封装,将所有参数封装成一个Request ,
startActivity开始,ContextImpl 使用 ActivityThread 获取到 Instrumentation ,使用Instrumentation 将任务调度给 ActivityTaskManagerService , 这里有一个非常重要的参数,
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;
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getBasePackageName(), who.getAttributionTag(), 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;
}
可以看到这里在一个叫 token 的IBinder 的参数,他有什么用呢,这就需要知道 Activity 的任务管理都是 ActivityTaskManagerService 中完成的,想要收到 ATMS 的处理结果并配合做生命周期动作就需要跨进程通信,那么这个token就是为后期做跨进程通信,那么这个IBinder是谁呢,就是在ActivityThread 的成员变量 ApplicationThread ,他就是一个IInterface.Stub
ATMS startActivityAsUser
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
@Nullable String callingFeatureId, Intent intent, String resolvedType,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
assertPackageMatchesCallingUid(callingPackage);
enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setCallingFeatureId(callingFeatureId)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setUserId(userId)
.execute();
}
这里将上面说的token 放到了caller 的属性上,通过这个caller 就能实现跨进程通信,通过上面代码可以看到 ATMS 通过一个 StartController 将所有请求任务封装成了 ActivityStarter , 并执行了他的 execute 方法,这里也使用到了与MessageQueue 获取消息同样的方法,查看了一下他的代码,实现效果是一致的
在ActiviteStarter 的 execute 方法里面 通过 mRootWindowContainer ,每个window 都会放入到这里, 从后向前遍历找到第一个正在Focused ActivityStack,为他做一个标记,具体方法如下
ActiviteStarter execute
final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
if (stack != null) {
stack.mConfigWillChange = globalConfigWillChange;
}
然后继续执行 将 封装好的 request 放入 execute 中
再接下来有做了很多的判断,被请求的activity 是否在 ActivtyStack 中, 请求这是否有权限,等等的处理,还需要判断启动队列里面是否有正在启动的activity ,如果有他就等待while(正在启动队列是否为空),没有就继续执行来到了 ActivityStarter startActivityInner 的这个方法
ActivityStarter startActivityInner
这个方法中先初始化了启动模式,并计算一下他的启动模式
computeLaunchingTaskFlags();
computeSourceStack();
然后根据lanuchMode 判断是否需要新建task,
如果不是新栈就调用 recycleTask 判断返回状态
是新栈就向RootWindowContainer中添加一个黑白屏 来到 RootWindowContainer 的resumeFocusedStacksTopActivities 方法
RootWindowContainer 的resumeFocusedStacksTopActivities
由于我们刚刚给 RootWindowContainer 添加了一个window,那么这个window在 RootWindowContainer 中是存在的,就来到了
ActivityStarter resumeTopActivityUncheckedLocked 做标记继续向下
ActivityStarter resumeTopActivityUncheckedLocked 在这里判断进程是否存在
if (next.attachedToProcess())
虽然我们启动了黑白屏,但是进程是不存在的接着就来到了 ActivityStackSupervisor startSpecificActivity
ActivityStackSupervisor startSpecificActivity
到了这里终于要创建进程了
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, 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.
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
由于进程不存在,需要通过 ATMS 来调用 startProcessAsync 方法
ATMS startProcessAsync
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
String hostingType) {
try {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
+ activity.processName);
}
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
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);
}
}
看他上面的注释, 发送一个启动进程的消息, 这里需要注意的是 ActivityManagerInternal::startProcess 他是一个函数, 而且还是 AMS 的内部类 LocalService 所持有的,这样启动进程的流程就来到了AMS
AMS LocalService startProcess ---> AMS LocalService startProcessLocked -->
上面都是数据传递
mProcessList.startProcessLocked
这里再说一下 AMS 是如何管理进程的,他与进程是如何通信的 , 在AMS 中 有一个 mProcessList 进程列表,他管理着所有进程,每一个进程都被封装到 ProcessState 当中,这个进程的管理使用的LRU 的方式, 每一个Process 里面都有一个 IApplicationThread thread; 也就是 ApplicationThread ,AMS 就是通过他来与 app 进程通信