AMS系列
[AMS之进程的启动流程]-本篇
一 概述
在分析完四大进程的启动后,我们就需要开始入手 Android 系统中更加深入一点的服务了,由于是一些底层的服务,所以之前被我们忽视的一些细节,也会开始提起。
就从本篇的进程的启动开始,涉及到的进程会有四个。客户端 Client(一般是桌面的 Launch 进程),Zygote 孵化进程,AMS 进程,被启动的进程 App。
AMS 不是单独进程,它和其他很多服务共用一个 SystemServer 进程,它的底层名是 system_server,这个进程也是用于 binder 通信的中间进程,在 binder 通信中会详细介绍
二 AMS 进程的启动
在之前分析四大组件的启动时,我们应该会经常看到这样一句代码 mService.startProcessXXX,这段代码其实就是调用 AMS 启动进程的函数。
中间的调用链这里就不跟了,我们直接看 AMS 启动进程的逻辑。
2.1 startProcess
[frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java]
@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
boolean isTop, String hostingType, ComponentName hostingName) {
try {
synchronized (ActivityManagerService.this) {
// 如果该进程被称为top app,则设置一个提示,以便当该进程启动时,
// 可以立即应用最高优先级,以避免cpu在附加top app的进程之前被其他进程抢占。
startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
new HostingRecord(hostingType, hostingName, isTop),
ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
false /* isolated */);
}
}
}
在启动进程时会有一个 isTop 的参数,用于标志这个进程是否是 top app,top app 在 CPU 抢占上会有更多的优待。
2.2 startProcessLocked
@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 */,
null /* ABI override */, null /* entryPoint */,
null /* entryPointArgs */, null /* crashHandler */);
}
三 ProcessList
ProcessList 就是进程的列表,Android 启动进程和杀死进程,都需要修改进程,而修改进程的时候自然回需要加锁,
3.1 startProcessLocked
[frameworks/base/services/core/java/com/android/server/am/ProcessList.java]
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 startTime) {
...
// 是同步创建进程,还是异步。
// 其实不管是同步还是异步,最后调用的函数都是相同的
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, startTime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} ...
return app.getPid() > 0;
}
}
在 startProcessLocked 中,会根据一个参数 FLAG_PROCESS_START_ASYNC 来判断是同步还是异步创建进程。不过不管是同步创建,还是异步创建,最后其实都是通过 startProcess 这个函数进行的。
3.2 startProcess
private Process.ProcessStartResult startProcess(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 startTime) {
... // 省略代码
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
false, false,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else {
regularZygote = true;
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
}
在启动进程的 startProcess 函数中也是一样,不管是否使用 AppZygote,最后都会走到 Process.start 函数。
四 Process
4.1 start
[frameworks/base/core/java/android/os/Process.java]
public static ProcessStartResult start(@NonNull final String processClass,
@Nullable final String niceName,
int uid, int gid, @Nullable int[] gids,
int runtimeFlags,
int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
bindMountAppStorageDirs, zygoteArgs);
}
五 ZygoteProcess
5.1 startViaZygote
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
@Nullable final String niceName,
final int uid, final int gid,
@Nullable final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
boolean startChildZygote,
@Nullable String packageName,
int zygotePolicyFlags,
boolean isTopApp,
@Nullable long[] disabledCompatChanges,
@Nullable Map<String, Pair<String, Long>>
pkgDataInfoMap,
@Nullable Map<String, Pair<String, Long>>
allowlistedDataInfoList,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<>();
...// 省略代码,argsForZygote 参数的填充
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
zygotePolicyFlags,
argsForZygote);
}
}
在 startViaZygote 函数中主要做了两件事
- openZygoteSocketIfNeeded:如果需要,则打开 zygote 的 socket
- 发生 socket 请求到 zygote,开始进程的创建
5.2 openZygoteSocketIfNeeded
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
try {
attemptConnectionToPrimaryZygote();
if (primaryZygoteState.matches(abi)) {
return primaryZygoteState;
}
if (mZygoteSecondarySocketAddress != null) {
// The primary zygote didn't match. Try the secondary.
attemptConnectionToSecondaryZygote();
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
}
} ...
}
这里会通过不同的 abi,32 位还是 64 位,来进行不同的 zygote 通信。
5.3 attemptConnectionToPrimaryZygote
private void attemptConnectionToPrimaryZygote() throws IOException {
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
// public static final String PRIMARY_SOCKET_NAME = "zygote";
// 这里其实就算建立一个 socket 连接,socket 的名字是 zygote
primaryZygoteState = ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
...
}
}
5.4 zygoteSendArgsAndGetResult
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
throws ZygoteStartFailedEx {
String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";
// 是否使用 usap 的启动模式创建进程
if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
try {
return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
}
}
// 正常的进程创建流程
return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}
5.5 attemptZygoteSendArgsAndGetResult
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
try {
final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
// 先通过 socket 向 zygote 写数据
zygoteWriter.write(msgStr);
zygoteWriter.flush();
// 然后从 socket 中读数据
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = zygoteInputStream.readInt();
result.usingWrapper = zygoteInputStream.readBoolean();
return result;
} ...
}
通过 zygoteState 获取对应的 socket,然后向其中写数据。
六 ZygoteServer
6.1 构造函数
ZygoteServer 是在 Zygote 进程创建时启动的,Zygote 会通过 runSelectLoop 这个函数开启一个死循环。首先是 ZygoteServer 的构造函数,在这个函数中,会开启一个 socket。
然后,会在 runSelectLoop 函数中,监听这个 socket。
[frameworks/base/core/java/com/android/internal/os/ZygoteServer.java]
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
// 通过 PRIMARY_SOCKET_NAME 构造一个 socket
// PRIMARY_SOCKET_NAME 的值就是 "zygote"
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
mUsapPoolSupported = true;
fetchUsapPoolPolicyProps();
}
6.2 runSelectLoop
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
// 先取出 socket 的文件描述符 FD,索引是 0
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
// 开始一个死循环
while (true) {
// 刷新 Usap 池的参数
fetchUsapPoolPolicyPropsWithMinInterval();
mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
if (mUsapPoolEnabled) {
usapPipeFDs = Zygote.getUsapPipeFDs();
pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
// 先将 socketFD 添加到 pollFDs 中
int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
// 保存 usap 缓存池的数量
final int usapPoolEventFDIndex = pollIndex;
// 如果使用 usap 缓存池,就将 mUsapPoolEventFD 添加到 pollFDs 中
if (mUsapPoolEnabled) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = mUsapPoolEventFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
assert usapPipeFDs != null;
for (int usapPipeFD : usapPipeFDs) {
FileDescriptor managedFd = new FileDescriptor();
managedFd.setInt$(usapPipeFD);
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = managedFd;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
}
int pollTimeoutMs;
if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
pollTimeoutMs = -1;
} else {
long elapsedTimeMs = System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;
if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
// 判断延迟时间
pollTimeoutMs = 0;
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} else if (elapsedTimeMs <= 0) {
// elapsedTimeMs 小于 0 就重置时间
pollTimeoutMs = mUsapPoolRefillDelayMs;
} else {
pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
}
}
int pollReturnValue;
try {
// 调用 Linux 的 poll 函数,开始阻塞
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
if (pollReturnValue == 0) {
// 返回为 0 表示超时,或者 FD 没有准备好
// 需要重新填充参数
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
} else {
boolean usapPoolFDRead = false;
// 开始反向处理文件描述符
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
// 如果索引是 0,就说明是 socket 的 FD
if (pollIndex == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
// 如果 pollIndex 小于 usapPoolEventFDIndex,就说明当初 socket 消息来自 Zygote server
try {
ZygoteConnection connection = peers.get(pollIndex);
boolean multipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
// 执行 fork
final Runnable command =
connection.processCommand(this, multipleForksOK);
if (mIsForkChild) {
return command;
} else {
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
} catch (Exception e) {
if (!mIsForkChild) {
ZygoteConnection conn = peers.remove(pollIndex);
conn.closeSocket();
socketFDs.remove(pollIndex);
} else {
throw e;
}
} finally {
mIsForkChild = false;
}
} else {
// 否则就是 pollIndex 大于 usapPoolEventFDIndex,说明当前使用 USAP 缓存池
long messagePayload;
try {
byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
int readBytes =
Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
DataInputStream inputStream =
new DataInputStream(new ByteArrayInputStream(buffer));
messagePayload = inputStream.readLong();
} else {
continue;
}
} catch (Exception ex) {
continue;
}
if (pollIndex > usapPoolEventFDIndex) {
Zygote.removeUsapTableEntry((int) messagePayload);
}
// 如果是使用 usap 创建进程,就修改标志
usapPoolFDRead = true;
}
}
//
if (usapPoolFDRead) {
int usapPoolCount = Zygote.getUsapPoolCount();
if (usapPoolCount < mUsapPoolSizeMin) {
// Immediate refill
mUsapPoolRefillAction = UsapPoolRefillAction.IMMEDIATE;
} else if (mUsapPoolSizeMax - usapPoolCount >= mUsapPoolRefillThreshold) {
// Delayed refill
mUsapPoolRefillTriggerTimestamp = System.currentTimeMillis();
}
}
}
// 如果使用 usap 缓存池,那么 mUsapPoolRefillAction 的值不会为 NONE
if (mUsapPoolRefillAction != UsapPoolRefillAction.NONE) {
int[] sessionSocketRawFDs =
socketFDs.subList(1, socketFDs.size())
.stream()
.mapToInt(FileDescriptor::getInt$)
.toArray();
final boolean isPriorityRefill =
mUsapPoolRefillAction == UsapPoolRefillAction.IMMEDIATE;
final Runnable command =
fillUsapPool(sessionSocketRawFDs, isPriorityRefill);
if (command != null) {
return command;
} else if (isPriorityRefill) {
// Schedule a delayed refill to finish refilling the pool.
mUsapPoolRefillTriggerTimestamp = System.currentTimeMillis();
}
}
}
}
}
在 runSelectLoop 中 Zygote 会开始进程的创建逻辑,当然,这里 Zygote 做了两种情况的处理,其中一种是 usap 创建进程,这是谷歌弄的一个创建进程的优化,它会预先创建出一批进程,当客户端需要创建进程时,就直接从这个池子里取,还有一种则是正常的进程创建逻辑。即通过 processCommand 函数,调用系统的 fork 方法。
6.3 processCommand
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
ZygoteArguments parsedArgs;
try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
while (true) {
...
if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
|| !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits,
parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName,
fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
parsedArgs.mBindMountAppStorageDirs);
try {
if (pid == 0) {
// 子进程
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 处理子进程
return handleChildProc(parsedArgs, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
} ...
}
调用 Zygote 的 forkAndSpecialize 开始进程的创建。
七 Zygote
7.1 forkAndSpecialize
[frameworks/base/core/jni/com_android_internal_os_Zygote.cpp]
static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList,
boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
ZygoteHooks.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs,
bindMountAppStorageDirs);
...
return pid;
}
7.2 nativeForkAndSpecialize
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags,
jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name,
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list,
jboolean mount_data_dirs, jboolean mount_storage_dirs) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
... // 省略代码
pid_t pid = zygote::ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore,
true);
// 返回 pid 为 0 的时候是子进程
if (pid == 0) {
// 子进程的初始化逻辑
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
mount_storage_dirs == JNI_TRUE);
}
return pid;
}
7.3 zygote::ForkCommon
// Utility routine to fork a process from the zygote.
NO_STACK_PROTECTOR
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
const std::vector<int>& fds_to_close,
const std::vector<int>& fds_to_ignore,
bool is_priority_fork,
bool purge) {
... // 省略代码
pid_t pid = fork();
if (pid == 0) {
if (is_priority_fork) {
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
} else {
setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
}
...
return pid;
}
最后就是调用的 Linux 的 fork 函数进行创建进程。关于进程的概念,我们在之前的 [AMS 的进程管理] 中已经介绍过了,它其实就是一个 task_struct 结构体,所以这里的 fork 创建进程,其实就是复制内存中这个结构体的数据。然后分两次返回,分别是在父进程中返回子进程的 pid,在子进程中返回 0 。
八 ZygoteConnection
说完了进程的启动流程,我们再来说一说启动之后,进程是如何初始化的。回到 [6.3 processCommand] 中,在进程启动会,会调用 handleChildProc 来对子进程进行初始化。
8.1 handleChildProc
[frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java]
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
closeSocket();
Zygote.setAppProcessName(parsedArgs, TAG);
...
} else {
if (!isZygote) {
// isZygote 是否在 Zygote 进程,子进程为 false。
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(
parsedArgs.mRemainingArgs /* classLoader */);
}
}
}
九 ZygoteInit
9.1 zygoteInit
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
...
// 初始化一
RuntimeInit.commonInit();
// 初始化二
ZygoteInit.nativeZygoteInit();
// 初始化三
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
在 zygoteInit 中会做三部分的初始化
- RuntimeInit.commonInit
- ZygoteInit.nativeZygoteInit
- RuntimeInit.applicationInit
9.2 RuntimeInit.commonInit
protected static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
/*
* set handlers; these apply to all threads in the VM. Apps can replace
* the default handler, but not the pre handler.
*/
LoggingHandler loggingHandler = new LoggingHandler();
RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
// 设置未捕获异常的处理
Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
...
}
9.3 uncaughtException
我们可以简单看一下系统默认的未捕获异常的方式,其实就是杀进程。
public void uncaughtException(Thread t, Throwable e) {
try {
...
// 调用 AMS 的 handleApplicationCrash
ActivityManager.getService().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
} catch (Throwable t2) {
...
} finally {
// 杀进程
Process.killProcess(Process.myPid());
System.exit(10);
}
}
然后就是第二步初始化 ZygoteInit.nativeZygoteInit。
9.4 com_android_internal_os_ZygoteInit_nativeZygoteInit
[frameworks/base/core/jni/AndroidRuntime.cpp]
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
9.5 onZygoteInit
[frameworks/base/cmds/app_process/app_main.cpp]
virtual void onZygoteInit()
{
// ProcessState 是进程单例对象,它会打开 binder 驱动
sp<ProcessState> proc = ProcessState::self();
// 然后开启 binder 线程,开始binder 通信
proc->startThreadPool();
}
onZygoteInit 其实就是启动 binder 通信的过程,Android 系统中不论是我们的应用进程,还是系统的进程,都会有这个初始化逻辑。在这步之后,进程的 binder 通信就可以使用了。
9.5 applicationInit
[frameworks/base/core/java/com/android/internal/os/RuntimeInit.java]
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
...
final Arguments args = new Arguments(argv);
// 调用进程的 main 函数
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
9.6 findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
// 反射拿到 ActivityThread 类
cl = Class.forName(className, true, classLoader);
} ...
Method m;
try {
// 调用 ActivityThread 类的 main 函数
m = cl.getMethod("main", new Class[] { String[].class });
} ...
}
最后的 applicationInit 循环,就是调用到我们熟悉的 ActivityThread 的 main 了。
十 ActivityThread
10.1 main
最后再来看看这个 main 方法。
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
...
Process.setArgV0("<pre-initialized>");
// 调用 Looper 的 prepareMainLooper
Looper.prepareMainLooper();
...
// 创建 ActivityThread 对象,并调用 attach 函数
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
...
// 调用 Looper 的 loop
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
main 函数中的逻辑其实比较简单,一个就是调用 attach 函数,这个在之前的进程管理中,我们说到进程启动时,会调用到 AMS 中的 attachApplicationLocked 函数,其实就是这样一步一步调用过去的,然后就是 Handle 的老三样 prepareX 和 loop。
Handler 的原理以后再说,先来说说 attach 这个函数。
现在我们的进程是通过 Zygote 创建和启动的,虽然在初始化的步骤中,已经做好了 binder 的相关工作,我们可以使用 binder 通信了,但是现在我们还没有和 AMS 建立连接,这样 AMS 要如何管理我们这个刚刚创建的进程呢?
于是,attach 这个函数,就是这个建立连接的过程。
10.2 attach
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mConfigurationController = new ConfigurationController(this);
mSystemThread = system;
// 是否是系统进程,我们现在是 false
if (!system) {
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
// 获取 AMS 的 binder 对象
final IActivityManager mgr = ActivityManager.getService();
try {
// 调用 attachApplication 函数
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
注意,这里传入了一个 mAppThread 对象,这个对象是 ActivityThread 的成员变量,
final ApplicationThread mAppThread = new ApplicationThread();
而且,这个 ApplicationThread 类是定义在 ActivityThread 中的内部类,
10.3 ApplicationThread
private class ApplicationThread extends IApplicationThread.Stub {
public final void bindApplication(String processName, ApplicationInfo appInfo,
ProviderInfoList providerList, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
SharedMemory serializedSystemFontMap) {
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
for (Object oname : services.keySet()) {
if (services.get(oname) == null) {
continue; // AM just passed in a null service.
}
String name = (String) oname;
// See b/79378449 about the following exemption.
switch (name) {
case "package":
case Context.WINDOW_SERVICE:
continue;
}
if (ServiceManager.getService(name) == null) {
Log.wtf(TAG, "Service " + name + " should be accessible by this app");
}
}
}
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providerList.getList();
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
data.mSerializedSystemFontMap = serializedSystemFontMap;
sendMessage(H.BIND_APPLICATION, data);
}
}
ApplicationThread 中的函数有很多,我们这里列举一个比较重要的 bindApplication,
十一 ActivityManagerService
接着我们看和 AMS 建立连接的过程,即 attachApplication 函数。
11.1 attachApplication
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
11.2 attachApplicationLocked
接着就是我们之前已经提过的 attachApplicationLocked 的函数,之前在 AMS 的进程管理中,已经说过这个函数,不知道大家还有没有印象,不过这次我们要说的,是这个函数中,另外一个地方,那就是 thread.bindApplication。
thread 我们已经知道了,它是我们之前从 ActivityThread 传入的 ApplicationThread 对象,这个对象应用进程用来和 AMS 通信的,现在 AMS 通过这个 ApplicationThread 的 binder 对象,调用了它的 bindApplication 函数,并且传入了一大堆的参数,这些参数系统进程为就是应用进程分配的一系列的进程信息。
[frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java]
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// 查找正在附加的应用程序记录...
// 如果我们在多个进程中运行,则通过PID,
// 或者如果我们使用匿名线程模拟进程,则仅拉取下一个应用记录。
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
long bindApplicationTimeMillis;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
// 从 mPidsSelfLocked 取出指定进程的进程信息 ProcessRecord
app = mPidsSelfLocked.get(pid);
}
}
// 调用 IApplicationThread 的 bindApplication
if (app.getIsolatedEntryPoint() != null) {
// 这是一个独立的进程,它应该只调用一个入口点,而不是绑定到一个应用程序。
thread.runIsolatedEntryPoint(
app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
} else if (instr2 != null) {
thread.bindApplication(processName, appInfo, providerList,
instr2.mClass,
profilerInfo, instr2.mArguments,
instr2.mWatcher,
instr2.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap);
} else {
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.getCompat(), getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions,
app.getDisabledCompatChanges(), serializedSystemFontMap);
}
// 绑定应用程序后激活应用程序,或者客户端可能正在运行请求(例如启动活动),然后才准备就绪。
synchronized (mProcLock) {
// 将 thread(IApplicationThread)保存到进程信息中。
// 此时处在AMS进程中,所以回将 IApplicationThread 这个 binder 对象,保存到 AMS 中。
app.makeActive(thread, mProcessStats);
}
// 更新进程的 LRU
updateLruProcessLocked(app, false, null);
}
到此,进程的启动流程我们也介绍完毕了。最后还是老规矩,用一幅图还总结一下我们整体的流程吧。