对于APP的启动,可以分类为两种:冷启动和热启动。
通俗地解释就是,冷启动是内存中不存在这个app进程,需要先初始化该app进程,再启动activity;
热启动是直接启动activity。
对于这两种启动的区别是,内存中是否存在该app进程。
首先附上冷启动app时的流程鸟瞰图:
共有四个步骤:
1.launcher进程通过binder请求ams启动Activity,AMS进程查询内存中是否存在该进程。
2.内存中无相应进程,ams通过socket发送创建进程命令和相关资料到zygote进程。
3.zygote进程收到socket信息后,fork子进程,创建出ActivityThread的进程(目的进程)
4.ActivityThread通过binder把新建的进程信息与AMS进行相关联。
这博文中,我们一起从源码里探究学习(基于Android 9 ),AMS如何判断进程是否存在,和进程如何被实例化。(这里以点击首页launcher的app卡片,进去app作为例子)在本篇中,将介绍步骤1和步骤2.
先看看主要代码调用流程图:
开始从源码看看代码调度流程。
framework\frameworks\base\core\java\android\app\ContextImpl.java
@Override
public void startActivity(Intent intent) {
warnIfCallingFromSystemProcess();
startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, Bundle options) {
...
//mMainThread是ActivityThread类型,用于维护该进程的生命周期
//getInstrumentation返回Instrumentation实例,Instrumentation用于进程生命周期的执行工具类
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity) null, intent, -1, options);
}
frameworks\base\core\java\android\app\Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//得到当前进程的IApplicationThread代理实例 whoThread
IApplicationThread whoThread = (IApplicationThread) contextThread;
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
//调用ActivityManagerService的startActivity,并传入当前进程的IApplicationThread代理实例和目的intent
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
...
}
在AMS中调度到startActivityAsUser(),代码如下:
framework\frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
boolean validateIncomingUser) {
enforceNotIsolatedCaller("startActivity");
...
//mActivityStartController.obtainStarter返回ActivityStartController实例,obtainStarter()返回ActivityStarter实例
//把数据存在ActivityStarter实例,然后调用 execute()进行执行,调用ActivityStarter的startActivityMayWait方法
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
private 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 globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
int userId, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup) {
...
//ResolveInfo 用于描述app的manifest的信息
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
0 /* matchFlags */,
computeResolveFilterUid(
callingUid, realCallingUid, mRequest.filterCallingUid));
...
// 收集关于目标Intent的信息,aInfo
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
...
//新建 outRecord数组,用于activity启动后返回activity对应的 ActivityRecord
final ActivityRecord[] outRecord = new ActivityRecord[1];
//startActivity传入前面的ResolveInfo、ActivityInfo 对象
int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
allowPendingRemoteAnimationRegistryLookup);
...
}
继续跟进startActivity()
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options,
boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
...
ProcessRecord callerApp = null;
//caller是发起StartActivity的进程,这里分析从launcher点击打开。
//所以caller是launcher进程的IApplicationThread
if (caller != null) {
//callerApp得到的是launcher对应的 ProcessRecord
//ProcessRecord是用于存储正在运行的特定进程的信息。
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
//获取当前进程的pid和 uid
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
}
...
//创建即将启动的Activity的描述类 ActivityRecord
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, checkedOptions, sourceRecord);
if (outActivity != null) {
//把 r 赋值给传进来的outActivity数组
outActivity[0] = r;
}
...
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
true /* doResume */, checkedOptions, inTask, outActivity);
}
继续接着调用startActivity
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
//startActivityUnchecked方法主要处理与栈相关的逻辑
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
...
}
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
//初始化ActivityStarter的各个配置, 把 r.intent 赋值给 mIntent
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
//计算出 launcherMode
computeLaunchingTaskFlags();
computeSourceStack();
//mIntent把mLaunchFlags赋值到mIntent.Flags
mIntent.setFlags(mLaunchFlags);
...
int result = START_SUCCESS;
//设置目标任务栈
// mAddingToTask 在computeLaunchingTaskFlags()算出并赋值
// mLaunchFlags 为 FLAG_ACTIVITY_NEW_TASK
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
//创建新的TaskRecord
result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
setTaskToCurrentTopOrCreateNewTask();
}
...
//传入的mDoResume为true
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
...
//调用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked()
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
...
}
frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
...
//获取要启动activity所在栈的栈顶的且不是处于停止状态的ActivityRecord
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || !r.isState(RESUMED)) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
}
...
return false;
}
执行ActivityStack.resumeTopActivityUncheckedLocked时再调用了resumeTopActivityInnerLocked(prev, options);
frameworks\base\services\core\java\com\android\server\am\ActivityStack.java
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
//获取栈顶的activityRecord
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
...
//执行上一个activity的pause
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
....
//热启动
if (next.app != null && next.app.thread != null) {
....
}else {
//冷启动
// Whoops, need to restart this activity!
...
//打开目的activity
mStackSupervisor.startSpecificActivityLocked(next, true, true);
...
}
frameworks\base\services\core\java\com\android\server\am\ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
//调用ams.getProcessRecordLocked()查询进程表内是否有该进程
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
//进程存在
if (app != null && app.thread != null) {
...
}
//进程不存在,调用ams的startProcessLocked进行开启进程
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
...
}
在这里先看看ams怎么实现查询进程表内是否有该进程
rameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
//uid为系统进程,系统进程在开机时被启动
if (uid == SYSTEM_UID) {
...
}
//根据uid,获取ProcessRecord (mProcessNames是ProcessMap类型,存储所有的系统内的进程,key为包名)
ProcessRecord proc = mProcessNames.get(processName, uid);
...
return proc;
}
再来看看,startProcessLocked()如何进行新建进程。在ams中有多个startProcessLocked方法,每个都有着自己的功能。
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
//调用startProcessLocked(参数不一致)
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
在这次startProcessLocked(),主要是为冷启动的app新建ProcessRecord实例
@GuardedBy("this")
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) {
...
ProcessRecord app;
if (!isolated) {
//查看堆栈中是否有启动过该进程
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
...
}
...
//冷启动时,app = null
if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
//新建目的 ProcessRecord对象
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
...
}
...
//调度到startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride)
final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
...
}
在这次startProcessLocked(),主要是为即将发送新建进程的命令传入参数
@GuardedBy("this")
private final boolean startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
//判断进程是否被加入到开启队列
if (app.pendingStart) {
return true;
}
...
//组建发给zygote进程的命令参数,groupid,uid,apk文件路径等
if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopComponent != null
&& app.processName.equals(mTopComponent.getPackageName())) {
uid = 0;
}
if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL
&& (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {
uid = 0;
}
}
...
//把相关必要参数传到startProcessLocked
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
...
}
把具体参数发送到startProcessLocked(),异步触发发送命令到Zygote进程:
@GuardedBy("this")
private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
//pendingStart是加入到开启队列的标识参数
app.pendingStart = true;
...
//异步进行开启进程
if (mConstants.FLAG_PROCESS_START_ASYNC) {
...
//在startProcess方法里进行参数发送
final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
requiredAbi, instructionSet, invokeWith, app.startTime);
...
}
...
}
跟进到startProcess
private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
...
//webview_service开启
if (hostingType.equals("webview_service")) {
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else {
//Process.start实现发送
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
...
}
frameworks\base\core\java\android\os\Process.java
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
跟进到zygoteProcess.start
frameworks\base\core\java\android\os\ZygoteProcess.java
public final Process.ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
zygoteArgs);
...
}
private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
//把参数放入startViaZygote
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("--runtime-flags=" + runtimeFlags);
...
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
synchronized(mLock) {
//zygoteSendArgsAndGetResult()进行把参数发送
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
具体发送由socket实现
@GuardedBy("mLock")
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// Throw early if any of the arguments are malformed. This means we can
// avoid writing a partial response to the zygote.
int sz = args.size();
...
//zygoteState.writer是socket 的输出流,直接往里面写数据即可发送
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
在上面步骤中,介绍了从用户点开app到发送指令给zygote进程请求新建应用进程。
再往下就去到Zygote进程,Zygote接收到初始化进程指令,fork子进程。后面的步骤将在下面一篇博文继续介绍