一、AMS进程启动入口
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
拉起空进程时,调用的是AMS的startProcess函数,这个函数比较简单,前后加了Trace追踪(可在systrace中搜索"startProcess:"),然后加AMS锁调用startProcessLocked(以Locked结尾的函数通常是需要加锁使用的意思)。
@VisibleForTesting
public final class LocalService extends ActivityManagerInternal
implements ActivityManagerLocal {
@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
boolean isTop, String hostingType, ComponentName hostingName) {
try {
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
+ processName);
}
synchronized (ActivityManagerService.this) {
// If the process is known as top app, set a hint so when the process is
// started, the top priority can be applied immediately to avoid cpu being
// preempted by other processes before attaching the process of top app.
// 如果该进程被称为top app,设置一个提示,以便当该进程启动时,可以立即应用最高优先级
// 避免 在attach进程到top app之前 cpu被其他进程抢占。
startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
new HostingRecord(hostingType, hostingName, isTop),
ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
false /* isolated */);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
}
startProcessLocked函数中其实就是调用ProcessList的startProcessLocked函数,前面的几个参数都是照搬下来,然后追加了isolatedUid及之后的一些参数。
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
boolean isolated) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,
null /* sdkSandboxClientAppPackage */,
null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
ProcessList中名字为startProcessLocked的有好几个,以ProcessRecord为返回值的startProcessLocked只有一个,继续看二、
1.1 新进程参数:ZYGOTE_POLICY_FLAG
AMS调用startProcessLocked函数时,追加了一个重要的参数“ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE” ZYGOTE_POLICY_FLAG,不多,一共也就4个,分别是空进程、延迟敏感进程、快速连续启动、系统进程。
frameworks/base/core/java/android/os/Process.java
/**
* Value used to indicate that there is no special information about an application launch. App
* launches with this policy will occur through the primary or secondary Zygote with no special
* treatment.
*
* 用于指示没有有关应用程序启动的特殊信息的值。 采用此策略的应用程序启动者将通过主要或辅助 Zygote 进行,无需特殊处理。
* @hide
*/
public static final int ZYGOTE_POLICY_FLAG_EMPTY = 0;
/**
* Flag used to indicate that an application launch is user-visible and latency sensitive. Any
* launch with this policy will use a Unspecialized App Process Pool if the target Zygote
* supports it.
*
* 用于指示应用程序启动是用户可见且延迟敏感的标志。
* 在目标Zygote支持的情况下,任何使用此策略的启动都将使用非专用(Unspecialized)应用程序进程池。
* @hide
*/
public static final int ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE = 1 << 0;
/**
* Flag used to indicate that the launch is one in a series of app launches that will be
* performed in quick succession. For future use.
*
* 用于指示该启动是 快速 连续执行的 一系列 应用程序启动中的一个的标志。 以供将来使用。
* @hide
*/
public static final int ZYGOTE_POLICY_FLAG_BATCH_LAUNCH = 1 << 1;
/**
* Flag used to indicate that the current launch event is for a system process. All system
* processes are equally important, so none of them should be prioritized over the others.
*
* 用于指示当前启动事件是针对 系统进程 的标志。 所有系统进程都同等重要,因此任何一个进程都不应该优先于其他进程。
* @hide
*/
public static final int ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS = 1 << 2;
AMS的startProcess调用startProcessLocked时,默认放的是延迟敏感型的进程flag。
如果需要启动新进程,而又不想启动延迟敏感型的进程,可以加AMS锁调用startProcessLocked,并传入自己需要的ZYGOTE_POLICY_FLAG。
1.2 新进程参数:HostingRecord
frameworks/base/services/core/java/com/android/server/am/HostingRecord.java
/**
* This class describes various information required to start a process.
* 此类描述 启动进程 所需的各种信息。
*
* The {@code mHostingType} field describes the reason why we started a process, and
* is only used for logging and stats.
* 描述了我们启动进程的原因,仅用于 日志记录 和 统计。
*
* The {@code mHostingName} field describes the Component for which we are starting the
* process, and is only used for logging and stats.
* 描述了我们正在启动的进程的组件,并且仅用于 日志记录 和 统计信息。
*
* The {@code mHostingZygote} field describes from which Zygote the new process should be spawned.
*
* 描述了应该从哪个 Zygote 生成新进程。
*
* {@code mDefiningPackageName} contains the packageName of the package that defines the
* component we want to start; this can be different from the packageName and uid in the
* ApplicationInfo that we're creating the process with, in case the service is a
* {@link android.content.Context#BIND_EXTERNAL_SERVICE} service. In that case, the packageName
* and uid in the ApplicationInfo will be set to those of the caller, not of the defining package.
* 包含 定义我们要启动的组件 的 packageName;
* 在服务是 BIND_EXTERNAL_SERVICE 的情况下,这可能与我们创建进程所用的 ApplicationInfo 中的 packageName 和 uid 不同。
* 在这种情况下,ApplicationInfo 中的 packageName 和 uid 将被设置为调用者的 packageName 和 uid,而不是DefiningPackage的 packageName 和 uid。
*
* {@code mDefiningUid} contains the uid of the application that defines the component we want to
* start; this can be different from the packageName and uid in the ApplicationInfo that we're
* creating the process with, in case the service is a
* {@link android.content.Context#BIND_EXTERNAL_SERVICE} service. In that case, the packageName
* and uid in the ApplicationInfo will be set to those of the caller, not of the defining package.
* 同上
*
* {@code mIsTopApp} will be passed to {@link android.os.Process#start}. So Zygote will initialize
* the process with high priority.
* 将被传递到 android.os.Process#start。 所以Zygote会以高优先级初始化进程。
*
* {@code mAction} the broadcast's intent action if the process is started for a broadcast
* receiver.
* 如果是 为了广播接收器启动的进程,mAction是广播的intent action。
*/
public final class HostingRecord {
// ...
}
HostingRecord有几个重要的变量,mHostingType、mHostingName、mHostingZygote、mDefiningPackageName、mDefiningUid、mIsTopApp、mAction
例如mHostingType代表启动新进程的原因,HostingRecord中有一些预定义的String,也可以自己定义,也可以为null。
二、ProcessList#以ProcessRecord为返回值的startProcessLocked
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService")
// 注意这里需要AMS锁
ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
boolean isSdkSandbox, int sdkSandboxUid, String sdkSandboxClientAppPackage,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
startProcessLocked内容比较多,大致可以分为3部分。
2.1 ProcessRecord app的获取
isolated作为参数传进来,标志新进程是否是独立进程
在isolated==false的情况下,通过getProcessRecordLocked获取ProcessRecord;
而如果要启动的是isolated进程,则直接给app赋值null;
long startTime = SystemClock.uptimeMillis();
ProcessRecord app;
if (!isolated) {
// 首先从map里查找是否有已经记录下来的ProcessRecord
app = getProcessRecordLocked(processName, info.uid);
checkSlow(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.
// 如果我们在后台,那么检查一下这个进程是否是bad进程。如果是,我们会静默地失败。
} 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.
// 当用户显式启动一个进程时,请清除其crash计数,
// 为了 在他们再次看到至少一个崩溃对话框之前 我们不会使其变得很糟糕
// 并且如果进程已经是bad进程了,则再次使该进程恢复正常。
}
} else {
// If this is an isolated process, it can't re-use an existing process.
// 如果这是一个孤立的进程,则它无法re-use现有进程。
app = null;
}
// ....
再来看getProcessRecordLocked
首先根据uid判断是否是系统进程,对于普通进程,只需要从mProcessNames根据进程名、uid查询即可。
@GuardedBy("mService")
ProcessRecord getProcessRecordLocked(String processName, int uid) {
if (uid == SYSTEM_UID) {
// The system gets to run in any process. If there are multiple
// processes with the same uid, just pick the first (this
// should never happen).
// 系统可以在任何进程中运行。 如果有多个进程具有相同的 uid,则只需选择第一个(这种情况不应该发生)。
SparseArray<ProcessRecord> procs = mProcessNames.getMap().get(processName);
if (procs == null) return null;
final int procCount = procs.size();
for (int i = 0; i < procCount; i++) {
final int procUid = procs.keyAt(i);
if (!UserHandle.isCore(procUid) || !UserHandle.isSameUser(procUid, uid)) {
// Don't use an app process or different user process for system component.
// 不要对系统组件 使用应用程序进程 或 不同的用户进程。
continue;
}
return procs.valueAt(i);
}
}
return mProcessNames.get(processName, uid);
}
关于ProcessList的mProcessNames:
mProcessNames是ProcessList的一个内部类MyProcessMap,可以先简单理解为一个以进程名为key,以ProcessRecord为value的map
/**
* 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.
* 我们当前运行的所有应用程序 均 按名字组织。
* key是应用程序包名称的字符串(由package manager返回),key是 ApplicationRecord 对象。
*/
@CompositeRWLock({"mService", "mProcLock"})
private final MyProcessMap mProcessNames = new MyProcessMap();
总的来说,第一部分先去查找是否已经有了目标进程的ProcessRecord,有的话给app赋值,没有的话给app赋null。独立进程直接赋null。
2.2 ProcessRecord predecessor的获取
predecessor的含义是“新进程的前身”,如果上面第一步获取到的app不是null,那么分两种情况,
- 一种是进程已经存活或正在启动的过程中,这种情况直接把app返回,该函数结束;
- 另一种情况是进程正在被异步kill,还没有执行完,这种情况下把刚获取的app赋值给predecessor(即前身),然后app赋值null;
而上面第一步获取到的app是null的话,就从mDyingProcesses中找到该目标进程的前身进行赋值。
另外独立进程是不关心predecessor的。
// We don't have to do anything more if:
// (1) There is an existing application record; and
// (2) The caller doesn't think it is dead, OR there is no thread
// object attached to it so we know it couldn't have crashed; and
// (3) There is a pid assigned to it, so it is either starting or
// already running.
// 如果出现以下情况,我们无需执行任何操作(直接返回app):
// (1) 已有application record(看代码这里应该指的是上面获取的ProcessRecord app);并且
// (2) 调用者认为它还存活(knownToBeDead),或者 没有attach任何线程对象,所以我们知道它不可能崩溃;并且
// (3) 有一个分配给它的 pid,因此它 要么正在启动,要么已经在运行。
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
+ " app=" + app + " knownToBeDead=" + knownToBeDead
+ " thread=" + (app != null app.getThread() : null)
+ " pid=" + (app != null app.getPid() : -1));
ProcessRecord predecessor = null;
if (app != null && app.getPid() > 0) {
// 有pid的情况
if ((!knownToBeDead && !app.isKilled()) || app.getThread() == null) {
// app存活 或者 app没有attach线程 的情况
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
// 我们已经让app运行,或者正在等待它出现(我们有 pid,但还没有它的线程),所以保留它。
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
// If this is a new package in the process, add the package to the list
// 如果这是进程中的新package,则将该package添加到列表中
app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
checkSlow(startTime, "startProcess: done, added package to proc");
return app; // 在这里直接return
}
// An application record is attached to a previous process,
// clean it up now.
// 一个application record已经attach到了一个先前的进程,立即清除
// 注意这里是app有pid,但 已知被杀了 且 有线程,即满足:
// (knownToBeDead || app.isKilled()) && app.getThread() != null
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App died: " + app);
checkSlow(startTime, "startProcess: bad proc running, killing");
// 根据注释,这种情况就属于“bad proc”,killProcessGroup是发msg异步执行
ProcessList.killProcessGroup(app.uid, app.getPid());
checkSlow(startTime, "startProcess: done killing old proc");
if (!app.isKilled()) {
// Throw a wtf if it's not killed
Slog.wtf(TAG_PROCESSES, app.toString() + " is attached to a previous process");
} else {
Slog.w(TAG_PROCESSES, app.toString() + " is attached to a previous process");
}
// We are not going to re-use the ProcessRecord, as we haven't dealt with the cleanup
// routine of it yet, but we'd set it as the predecessor of the new process.
// 我们不会re-use ProcessRecord,因为我们还没有处理它的清理程序,但我们将它设置为新进程的前身。
// 这里是刚刚把app对应的进程组kill了,但是并不复用app,因为kill是异步的,并未执行完
predecessor = app;
app = null;
} else if (!isolated) {
// (app为空 或 pid无效) 且非独立进程的情况
// This app may have been removed from process name maps, probably because we killed it
// and did the cleanup before the actual death notification. Check the dying processes.
// 该app可能已从 进程名称map 中删除,可能是因为我们杀死了它并 在实际的死亡通知之前进行了清理。
// 检查mDyingProcesses。
predecessor = mDyingProcesses.get(processName, info.uid);
if (predecessor != null) {
if (app != null) {
// 从mDyingProcesses找出来对应的ProcessRecord,再赋值给app.mPredecessor
// ProcessRecord有两个私有变量mPredecessor、mSuccessor,分别是上一个、下一个实例
app.mPredecessor = predecessor;
predecessor.mSuccessor = app;
}
Slog.w(TAG_PROCESSES, predecessor.toString() + " is attached to a previous process "
+ predecessor.getDyingPid());
}
}
2.3 ProcessRecord操作完成,等待或继续启动
经过上面一步的处理,到这里app可能为null,也有可能非null但pid是0;
在null的情况下创建新的ProcessRecord,非null情况下给app添加新的package信息。
到这里ProcessRecord的处理完成,加入onHold列表 或 调用同名函数startProcessLocked继续启动目标进程。
if (app == null) {
// 到这里app还是null的话,创建新的ProcessRecord
checkSlow(startTime, "startProcess: creating new process record");
app = newProcessRecordLocked(info, processName, isolated, isolatedUid, isSdkSandbox,
sdkSandboxUid, sdkSandboxClientAppPackage, hostingRecord);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
app.mErrorState.setCrashHandler(crashHandler);
app.setIsolatedEntryPoint(entryPoint);
app.setIsolatedEntryPointArgs(entryPointArgs);
if (predecessor != null) {
app.mPredecessor = predecessor;
predecessor.mSuccessor = app;
}
checkSlow(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.longVersionCode, mService.mProcessStats);
checkSlow(startTime, "startProcess: added package to existing proc");
}
// If the system is not ready yet, then hold off on starting this
// process until it is.
// 如果系统没有ready,把app添加到onHold列表里,系统启动完成后再启动进程
if (!mService.mProcessesReady
&& !mService.isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mService.mProcessesOnHold.contains(app)) {
mService.mProcessesOnHold.add(app);
}
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
"System not ready, putting on hold: " + app);
checkSlow(startTime, "startProcess: returning with proc on hold");
return app;
}
// 关于ProcessRecord的一系列操作执行完成,开始启动进程
checkSlow(startTime, "startProcess: stepping in to startProcess");
final boolean success =
startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
checkSlow(startTime, "startProcess: done starting proc!");
return success app : null;
三、ProcessList#以boolean为返回值的startProcessLocked
以boolean为返回值的startProcessLocked有三个,参数数量分别是4个、6个、一堆,依次调用。
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, String abiOverride) {
return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
abiOverride);
}
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
String abiOverride) {
// ...这里内容好多先跳过
try {
// ...
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
// 开始该进程。 它要么成功并返回包含新进程 PID 的结果,要么抛出 RuntimeException。
final String entryPoint = "android.app.ActivityThread";
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
instructionSet, invokeWith, startUptime, startElapsedTime);
} catch (RuntimeException e) {
// ...
return false;
}
}
@GuardedBy("mService")
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startUptime, long startElapsedTime) {
// ...这里内容好多先跳过
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
// 异步执行进程启动
mService.mProcStartHandler.post(() -> handleProcessStart(
app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
requiredAbi, instructionSet, invokeWith, startSeq));
return true;
} else {
// 同步执行进程启动
try {
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
requiredAbi, instructionSet, invokeWith, startUptime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} catch (RuntimeException e) {
// ...
}
return app.getPid() > 0;
}
}
注意第二个函数中将entryPoint直接赋值为"android.app.ActivityThread";
最后根据FLAG_PROCESS_START_ASYNC决定异步或同步进行进程的启动;
在扔给AMS.mProcStartHandler异步执行的handleProcessStart函数里,其实也是调用的startProcess和handleProcessStartedLocked
startProcess看四,handleProcessStartedLocked看五。