Android 13 Zygote fork app流程分析

Zygote Fork App流程解析

涉及的源码如下

platform/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java zygote进程启动时,负责创建socket服务端,循环等待来自system server进程(AMS发出)的fork请求

platform/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java socket连接,处理接收到的socket指令

core/java/android/os/ZygoteProcess.java 客户端发送fork app的请求类

services/core/java/com/android/server/wm/ActivityTaskSupervisor.java

services/core/java/com/android/server/wm/TaskFragment.java

ZygoteServer

ZygoteServer.runSelectLoop()

Copy Code

if (pollIndex == 0) {
    // Zygote server socket
    // 客户端发送给zygote socket的请求,会创建一个连接,并且加入监听列表
    ZygoteConnection newPeer = acceptCommandPeer(abiList);
    peers.add(newPeer);
    socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
    // Session socket accepted from the Zygote server socket
    // 处理客户端发送的socket消息
    try {
        ZygoteConnection connection = peers.get(pollIndex);
        boolean multipleForksOK = !isUsapPoolEnabled()
                && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
        // 核心的代码在这里,会执行fork,fork成功,mIsForkChild会置为true并且command != null
        final Runnable command =
                connection.processCommand(this, multipleForksOK);

        // TODO (chriswailes): Is this extra check necessary?
        if (mIsForkChild) {
            // We're in the child. We should always have a command to run at
            // this stage if processCommand hasn't called "exec".
            if (command == null) {
                throw new IllegalStateException("command == null");
            }
            // 对应ZygoteInit.main()的最后一条语句
            return command;
        }

ZygoteConnection

Socket连接封装成ZygoteConnection用于处理客户端发送的相关命令并返回相应的响应信息。

ZygoteConnection.processCommand()

核心的函数,主要为解析参数,执行fork。关键代码如下:

Copy Code

if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
        || !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
    // Continue using old code for now. TODO: Handle these cases in the other path.
    // 这是特殊应用(详见之前的分析文章)进程的fork流程,普通app走不到,暂不分析
    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) {
            // in child
            zygoteServer.setForkChild();

            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;

            return handleChildProc(parsedArgs, childPipeFd,
                    parsedArgs.mStartChildZygote);
        } else {
            // In the parent. A pid < 0 indicates a failure and will be handled in
            // handleParentProc.
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
} else {
    // 普通App的fork
    ZygoteHooks.preFork();
    // childMain -> specializeAppProcess -> ZygoteInit.init()
    Runnable result = Zygote.forkSimpleApps(argBuffer,
            zygoteServer.getZygoteSocketFileDescriptor(),
            peer.getUid(), Zygote.minChildUid(peer), parsedArgs.mNiceName);
    if (result == null) { // 父进程
        // parent; we finished some number of forks. Result is Boolean.
        // We already did the equivalent of handleParentProc().
        ZygoteHooks.postForkCommon();
        // argBuffer contains a command not understood by forksimpleApps.
        continue;
    } else {
        // child; result is a Runnable. 子进程
        zygoteServer.setForkChild();
        Zygote.setAppProcessName(parsedArgs, TAG);  // ??? Necessary?
        return result;
    }
}

对于普通App,关注Zygote.forkSimpleApps及其之后的流程即可。至此服务端的分析结束。客户端的分析与服务端不同,主要使用逆向分析方式,从ZygoteProcess发送socket请求开始,一层一层往上分析。

ZygoteProcess.java

创建了ZygoteServer对应的4个客户端socket连接,调用链为:

start

Copy Code

public final Process.ProcessStartResult start(@NonNull final String processClass,
                                              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>>
                                                      allowlistedDataInfoList,
                                              boolean bindMountAppsData,
                                              boolean bindMountAppStorageDirs,
                                              @Nullable String[] zygoteArgs) {
    // TODO (chriswailes): Is there a better place to check this value?
    if (fetchUsapPoolEnabledPropWithMinInterval()) {
        informZygotesOfUsapPoolStatus();
    }

    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
                pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,
                bindMountAppStorageDirs, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}

startViaZygote

封装参数,调用zygoteSendArgsAndGetResult

zygoteSendArgsAndGetResult

关键代码如下:

Copy Code

// 向服务端发送请求,得到pid
if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
    try {
        // 写入usap socket
        return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
    } catch (IOException ex) {
        // If there was an IOException using the USAP pool we will log the error and
        // attempt to start the process through the Zygote.
        Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
                + ex.getMessage());
    }
}
// 写入zygote socket
return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);

Process.java

内部创建了一个静态的ZygoteProcess实例ZYGOTE_PROCESS。其start()方法,即调用ZygoteProcess的start方法

ProcessList.java

ProcessList.startProcessLocked()

AMS.LocalService

Copy Code

@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.
            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);
    }
}

从上面的代码可知,fork操作其实只能在单线程中执行

AMS及ATMS

ATMS.startProcessAsync

Copy Code

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

ActivityTaskSupervisor.startSpecificActivity

Copy Code

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;
        // Remove the process record so it won't be considered as alive.
        mService.mProcessNames.remove(wpc.mName, wpc.mUid);
        mService.mProcessMap.remove(wpc.getPid());
    }

    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

    final boolean isTop = andResume && r.isTopRunningActivity();
    // 启动进程
    mService.startProcessAsync(r, knownToBeDead, isTop,
            isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
                    : HostingRecord.HOSTING_TYPE_ACTIVITY);
}

前面的调用链:

TaskFragment.resumeTopActivity() <- Task.resumeTopActivityInnerLocked <- Task.resumeTopActivityUncheckedLocked

太深了,方法比较复杂,AMS这块又搞了个ATMS,后面再分析。