首页 > 系统相关 >ActivityManagerService 启动进程(3)

ActivityManagerService 启动进程(3)

时间:2024-09-17 19:54:34浏览次数:10  
标签:info null String 启动 int app 进程 ActivityManagerService uid

ActivityManagerService 启动进程

简述

上一节我们介绍了Activity的启动流程,这一节会在上一节的基础上介绍当要启动的Activity所在的进程之前没有启动,这个情况下是怎么样启动一个新的进程,并且继续启动Activity。
我们知道Android是基于linux系统开发的,而linux系统启动一个应用进程都是通过原来的进程fork出来的,Android里面的app都是通过Zygote进程fork启动的。
fork后进程的uid,权限等会继承原来的进程,而app有几种不同的情况,system app,三方app等,所以fork出来的进程还会进行降权。

上一节Activity启动的流程中有两个入口会调用ActivityTaskManagerService.startProcessAsync来启动进程。一个是在resumeTopActivity时,如果发现有Activity需要先pause,再resume新的Activity时会调用,这样可以节约时间,pause的同时去启动新进程;第二个情况就是正常resume的流程中,startSpecificActivity时,发现目标Activity所在的进程还未启动,则会调用startProcessAsync来启动进程。我们就从startProcessAsync开始。

启动Activity 过程中启动app进程

在这里插入图片描述

1.1 ActivityManagerService.startProcessAsync

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
        String hostingType) {
    try {
        // ...
        // 发送一个startProcess消息,详见1.2
        final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                isTop, hostingType, activity.intent.getComponent());
        mH.sendMessage(m);
    } finally {
        // ...
    }
}

1.2 ActivityManagerService.startProcess
加了AMS大锁,调用startProcessLocked

public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
        boolean isTop, String hostingType, ComponentName hostingName) {
    try {
        synchronized (ActivityManagerService.this) {
            // 详见1.3
            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);
    }
}

1.3 ActivityManagerService.startProcessLocked
调用ProcessList.startProcessLocked

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
        boolean isolated) {
    // 详见1.4
    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 */);
}

1.4 ProcessList.startProcessLocked
首先会处理bad app相关的逻辑,一个app如果多次Crash则会标记未bad,我们常看到的xxx app 屡次崩溃的弹框就是bad app的逻辑。
然后会检查是否可以复用之前到进程,或者是否是已经在启动过程中了,如果是则什么都不做直接返回。
否则构建一个新的ProcessRecord,然后调用重载函数startProcessLocked进行进程启动。

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) {
    long startTime = SystemClock.uptimeMillis();
    ProcessRecord app;
    // 不是独立进程则可以考虑复用ProcessRecord
    if (!isolated) {
        app = getProcessRecordLocked(processName, info.uid);
        checkSlow(startTime, "startProcess: after getProcessRecord");

        if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
            // 如果是后台启动,不能启动一个bad app。比如连续多次Crash就会被标记为bad app
            if (mService.mAppErrors.isBadProcess(processName, info.uid)) {
                return null;
            }
        } else {
            // 如果是显示启动,清空bad app的计数。
            mService.mAppErrors.resetProcessCrashTime(processName, info.uid);
            if (mService.mAppErrors.isBadProcess(processName, info.uid)) {
                EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                        UserHandle.getUserId(info.uid), info.uid,
                        info.processName);
                mService.mAppErrors.clearBadProcess(processName, info.uid);
                if (app != null) {
                    app.mErrorState.setBad(false);
                }
            }
        }
    } else {
        // 如果是独立进程,则不能复用ProcessRecord
        app = null;
    }

    // 如果是已经有ProcessRecord,并且有关联pid,并且并没有记录它已经被kill或者死了或者没有关联线程,这种情况不需要做任何事。
    // 这种情况要不就是已经有进程在运行,要不就是已经在启动进程了。
    ProcessRecord predecessor = null;
    if (app != null && app.getPid() > 0) {
        if ((!knownToBeDead && !app.isKilled()) || app.getThread() == null) {
            app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
            checkSlow(startTime, "startProcess: done, added package to proc");
            return app;
        }

        // 否则清理之前关联进程。
        checkSlow(startTime, "startProcess: bad proc running, killing");
        ProcessList.killProcessGroup(app.uid, app.getPid());
        checkSlow(startTime, "startProcess: done killing old proc");

        predecessor = app;
        app = null;
    } else if (!isolated) {
        // 因为app 被kill的情况,检查是否在mDyingProcesses里
        predecessor = mDyingProcesses.get(processName, info.uid);
        if (predecessor != null) {
            if (app != null && app != predecessor) {
                app.mPredecessor = predecessor;
                predecessor.mSuccessor = app;
            } else {
                app = null;
            }
            Slog.w(TAG_PROCESSES, predecessor.toString() + " is attached to a previous process "
                    + predecessor.getDyingPid());
        }
    }

    if (app == null) {
        checkSlow(startTime, "startProcess: creating new process record");
        // 构建新的ProcessRecord
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid, isSdkSandbox,
                sdkSandboxUid, sdkSandboxClientAppPackage, hostingRecord);
        if (app == null) {
            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 {
        app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
        checkSlow(startTime, "startProcess: added package to existing proc");
    }

    // 如果系统服务还没有启动完成,添加到mProcessesOnHold队列中。
    if (!mService.mProcessesReady
            && !mService.isAllowedWhileBooting(info)
            && !allowWhileBooting) {
        if (!mService.mProcessesOnHold.contains(app)) {
            mService.mProcessesOnHold.add(app);
        }
        return app;
    }

    checkSlow(startTime, "startProcess: stepping in to startProcess");
    // 调用重载函数startProcessLocked,详见1.5
    final boolean success =
            startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
    checkSlow(startTime, "startProcess: done starting proc!");
    return success ? app : null;
}

1.5 ProcessList.startProcessLocked
首先清理了ProcessRecord内的变量,然后从PMS中获取进程相关的gids,用户组影响了进程的权限,app启动后需要配置好权限,所以在这里的需要获取gids,且被拒绝的权限需要移除对应的gids。
接下来就是计算RuntimeFlag,主要是一些和debug相关的启动flag。
最终会调用startProcessLocked重载方法,entryPoint作为参数传入,entryPoint被设置为android.app.ActivityThread,新启动的进程java虚拟机会以android.app.ActivityThread的main方法作为入口。

boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
        int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
        String abiOverride) {
    // 防止重入
    if (app.isPendingStart()) {
        return true;
    }
    final long startUptime = SystemClock.uptimeMillis();
    final long startElapsedTime = SystemClock.elapsedRealtime();
    // 清理之前Pid相关记录,以及启动超时的定时器
    if (app.getPid() > 0 && app.getPid() != ActivityManagerService.MY_PID) {
        checkSlow(startUptime, "startProcess: removing from pids map");
        mService.removePidLocked(app.getPid(), app);
        app.setBindMountPending(false);
        mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
        checkSlow(startUptime, "startProcess: done removing from pids map");
        app.setPid(0);
        app.setStartSeq(0);
    }
    // 清理死亡回调监听器
    app.unlinkDeathRecipient();
    app.setDyingPid(0);

    // 从mProcessesOnHold移除,mProcessesOnHold记录的是service没就绪导致需要延迟启动的app
    mService.mProcessesOnHold.remove(app);

    checkSlow(startUptime, "startProcess: starting to update cpu stats");
    // 触发cpu使用记录,anr时候会打印相关信息以便于排查anr
    mService.updateCpuStats();
    checkSlow(startUptime, "startProcess: done updating cpu stats");

    try {
        final int userId = UserHandle.getUserId(app.uid);
        try {
            AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
        }

        int uid = app.uid;
        int[] gids = null;
        int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
        boolean externalStorageAccess = false;
        if (!app.isolated) {
            int[] permGids = null;
            try {
                checkSlow(startUptime, "startProcess: getting gids from package manager");
                final IPackageManager pm = AppGlobals.getPackageManager();
                // 从PMS中获取app相关的gids
                // 后续启动app之后需要配置相关gid以保证权限正常。
                permGids = pm.getPackageGids(app.info.packageName,
                        MATCH_DIRECT_BOOT_AUTO, app.userId);
                StorageManagerInternal storageManagerInternal = LocalServices.getService(
                        StorageManagerInternal.class);
                mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
                        app.info.packageName);
                // sdcard读写权限
                externalStorageAccess = storageManagerInternal.hasExternalStorageAccess(uid,
                        app.info.packageName);
                if (mService.isAppFreezerExemptInstPkg()
                        && pm.checkPermission(Manifest.permission.INSTALL_PACKAGES,
                        app.info.packageName, userId)
                        == PackageManager.PERMISSION_GRANTED) {
                    Slog.i(TAG, app.info.packageName + " is exempt from freezer");
                    app.mOptRecord.setFreezeExempt(true);
                }
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            // 如果该进程特定权限被拒绝,需要去掉相关的gids
            if (app.processInfo != null && app.processInfo.deniedPermissions != null) {
                for (int i = app.processInfo.deniedPermissions.size() - 1; i >= 0; i--) {
                    int[] denyGids = mService.mPackageManagerInt.getPermissionGids(
                            app.processInfo.deniedPermissions.valueAt(i), app.userId);
                    if (denyGids != null) {
                        for (int gid : denyGids) {
                            permGids = ArrayUtils.removeInt(permGids, gid);
                        }
                    }
                }
            }

            gids = computeGidsForProcess(mountExternal, uid, permGids, externalStorageAccess);
        }
        app.setMountMode(mountExternal);
        checkSlow(startUptime, "startProcess: building args");
        if (app.getWindowProcessController().isFactoryTestProcess()) {
            uid = 0;
        }
        int runtimeFlags = 0;

        boolean debuggableFlag = (app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        boolean isProfileableByShell = app.info.isProfileableByShell();
        boolean isProfileable = app.info.isProfileable();

        if (app.isSdkSandbox) {
            ApplicationInfo clientInfo = app.getClientInfoForSdkSandbox();
            if (clientInfo != null) {
                debuggableFlag |= (clientInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
                isProfileableByShell |= clientInfo.isProfileableByShell();
                isProfileable |= clientInfo.isProfileable();
            }
        }

        // ... 配置runtimeFlags,一些和debug相关的启动flag
        // dex2oat flag
        if (app.info.isEmbeddedDexUsed()) {
            runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
        }

        // hide api检查相关的flag

        String useAppImageCache = SystemProperties.get(
                PROPERTY_USE_APP_IMAGE_STARTUP_CACHE, "");
        // Property defaults to true currently.
        if (!TextUtils.isEmpty(useAppImageCache) && !useAppImageCache.equals("false")) {
            runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
        }

        // ...
        // ... abi相关配置

        app.setGids(gids);
        app.setRequiredAbi(requiredAbi);
        app.setInstructionSet(instructionSet);

        ApplicationInfo definingAppInfo;
        if (hostingRecord.getDefiningPackageName() != null) {
            definingAppInfo = new ApplicationInfo(app.info);
            definingAppInfo.packageName = hostingRecord.getDefiningPackageName();
            definingAppInfo.uid = uid;
        } else {
            definingAppInfo = app.info;
        }

        runtimeFlags |= Zygote.getMemorySafetyRuntimeFlags(
                definingAppInfo, app.processInfo, instructionSet, mPlatformCompat);

        // 检查sepolicy 上下文。每个app必须有sepolicy上下文。(sepolicy也是linux的权限检查机制,比用户组权限更加精细)
        if (TextUtils.isEmpty(app.info.seInfoUser)) {
            Slog.wtf(ActivityManagerService.TAG, "SELinux tag not defined",
                    new IllegalStateException("SELinux tag not defined for "
                            + app.info.packageName + " (uid " + app.uid + ")"));
        }

        String seInfo = updateSeInfo(app);

        // 启动入口类
        final String entryPoint = "android.app.ActivityThread";
        // 调用重载,详见1.6
        return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
                instructionSet, invokeWith, startUptime, startElapsedTime);
    } catch (RuntimeException e) {
        mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                false, false, true, false, false, app.userId, "start failure");
        return false;
    }
}

1.6 ProcessList.startProcessLocked
这个方法设置了以些ProcessRecord里面的变量标记,然后根据mService.mConstants.FLAG_PROCESS_START_ASYNC判断是否需要异步调用启动线程,无论是否异步都是通过调用startProcess和handleProcessStartedLocked来启动线程的,所以我们直接来看startProcess

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) {
    // ...配置一些ProcessRecord里的标记

    // 默认这个FLAG_PROCESS_START_ASYNC为ture,其实handleProcessStart和下面的逻辑一样会调用startProcess和handleProcessStartedLocked,只是post了一下
    if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
        // 由于最终还是调用了startProcess和handleProcessStartedLocked,我们直接来看startProcess,详见1.7
        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) {
            app.setPendingStart(false);
            mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                    false, false, true, false, false, app.userId, "start failure");
        }
        return app.getPid() > 0;
    }
}

1.7 ProcessList.startProcess
更新前后台状态,用于后续odj值更新。
判断app进程启动后是否需要执行prepareStorageDirs,来创建app私有目录。
调用appZygote.getProcess().start来启动进程。
根据前面的判断,如果需要则调用prepareStorageDirs。

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) {
    try {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                app.processName);
        checkSlow(startTime, "startProcess: asking zygote to start proc");
        final boolean isTopApp = hostingRecord.isTopApp();
        if (isTopApp) {
            // 更新前后台状态,后续用于更新odj值更新
            app.mState.setHasForegroundActivities(true);
        }

        Map<String, Pair<String, Long>> pkgDataInfoMap;
        Map<String, Pair<String, Long>> allowlistedAppDataInfoMap;
        boolean bindMountAppStorageDirs = false;
        boolean bindMountAppsData = mAppDataIsolationEnabled
                && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid)
                    || app.isSdkSandbox)
                && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);

        final PackageManagerInternal pmInt = mService.getPackageManagerInternal();

        final String[] targetPackagesList;
        if (app.isSdkSandbox) {
            targetPackagesList = new String[]{app.sdkSandboxClientAppPackage};
        } else {
            // 获取所有和该进程共享uid的包名
            final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
                    app.info.packageName, app.userId);
            targetPackagesList = sharedPackages.length == 0
                    ? new String[]{app.info.packageName} : sharedPackages;
        }

        // ...

        int userId = UserHandle.getUserId(uid);
    
        StorageManagerInternal storageManagerInternal = LocalServices.getService(
                StorageManagerInternal.class);
        if (needsStorageDataIsolation(storageManagerInternal, app)) {
            // 将会在Zygote fork app之后调用prepareStorageDirs
            // prepareStorageDirs如果app目录还没有创建,就会创建目录
            if (pkgDataInfoMap != null && storageManagerInternal.isFuseMounted(userId)) {
                bindMountAppStorageDirs = true;
            } else {
                app.setBindMountPending(true);
                bindMountAppStorageDirs = false;
            }
        }

        // ...判断app是否处在后台,设置标识位,将会约束部分能力

        final Process.ProcessStartResult startResult;
        boolean regularZygote = false;
        app.mProcessGroupCreated = false;
        app.mSkipProcessGroupCreation = false;
        // 应用分几种类型,分为通过WebviewZygote来fork,通过Zygote来fork,通过system_server来fork。
        // 一般的app都是通过Zygote来fork,我们来看这个路径。
        if (hostingRecord.usesWebviewZygote()) {
            startResult = startWebView(entryPoint,
                    app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                    app.info.dataDir, null, app.info.packageName,
                    app.getDisabledCompatChanges(),
                    new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
        } else if (hostingRecord.usesAppZygote()) {
            final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

            // 详见1.8
            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()});
            app.mProcessGroupCreated = true;
        }
        // ...
        // 根据前面判断的逻辑决定是否需要调用prepareStorageDirs来创建app的私有目录
        if (bindMountAppStorageDirs) {
            storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
                    app.processName);
        }
        checkSlow(startTime, "startProcess: returned from zygote!");
        return startResult;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

1.8 ZygoteProcess.start
调用startViaZygote

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) {
    //...
    try {
        // 详见1.9
        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);
    }
}

1.9 startViaZygote
收集参数,加入到argsForZygote列表里,包含了所有关键信息,uid,gid,应用包名,sepolicy info等。然后调用zygoteSendArgsAndGetResult

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

    // 添加参数列表,包含了uid,gid等等。
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    argsForZygote.add("--runtime-flags=" + runtimeFlags);
    if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
        argsForZygote.add("--mount-external-default");
    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) {
        argsForZygote.add("--mount-external-installer");
    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_PASS_THROUGH) {
        argsForZygote.add("--mount-external-pass-through");
    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_ANDROID_WRITABLE) {
        argsForZygote.add("--mount-external-android-writable");
    }

    argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

    // --setgroups is a comma-separated list
    if (gids != null && gids.length > 0) {
        final StringBuilder sb = new StringBuilder();
        sb.append("--setgroups=");

        final int sz = gids.length;
        for (int i = 0; i < sz; i++) {
            if (i != 0) {
                sb.append(',');
            }
            sb.append(gids[i]);
        }

        argsForZygote.add(sb.toString());
    }

    if (niceName != null) {
        argsForZygote.add("--nice-name=" + niceName);
    }

    if (seInfo != null) {
        argsForZygote.add("--seinfo=" + seInfo);
    }

    if (instructionSet != null) {
        argsForZygote.add("--instruction-set=" + instructionSet);
    }

    if (appDataDir != null) {
        argsForZygote.add("--app-data-dir=" + appDataDir);
    }

    if (invokeWith != null) {
        argsForZygote.add("--invoke-with");
        argsForZygote.add(invokeWith);
    }

    if (startChildZygote) {
        argsForZygote.add("--start-child-zygote");
    }

    if (packageName != null) {
        argsForZygote.add("--package-name=" + packageName);
    }

    if (isTopApp) {
        argsForZygote.add(Zygote.START_AS_TOP_APP_ARG);
    }
    if (pkgDataInfoMap != null && pkgDataInfoMap.size() > 0) {
        StringBuilder sb = new StringBuilder();
        sb.append(Zygote.PKG_DATA_INFO_MAP);
        sb.append("=");
        boolean started = false;
        for (Map.Entry<String, Pair<String, Long>> entry : pkgDataInfoMap.entrySet()) {
            if (started) {
                sb.append(',');
            }
            started = true;
            sb.append(entry.getKey());
            sb.append(',');
            sb.append(entry.getValue().first);
            sb.append(',');
            sb.append(entry.getValue().second);
        }
        argsForZygote.add(sb.toString());
    }
    if (allowlistedDataInfoList != null && allowlistedDataInfoList.size() > 0) {
        StringBuilder sb = new StringBuilder();
        sb.append(Zygote.ALLOWLISTED_DATA_INFO_MAP);
        sb.append("=");
        boolean started = false;
        for (Map.Entry<String, Pair<String, Long>> entry : allowlistedDataInfoList.entrySet()) {
            if (started) {
                sb.append(',');
            }
            started = true;
            sb.append(entry.getKey());
            sb.append(',');
            sb.append(entry.getValue().first);
            sb.append(',');
            sb.append(entry.getValue().second);
        }
        argsForZygote.add(sb.toString());
    }

    if (bindMountAppStorageDirs) {
        argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
    }

    if (bindMountAppsData) {
        argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
    }

    if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
        StringBuilder sb = new StringBuilder();
        sb.append("--disabled-compat-changes=");

        int sz = disabledCompatChanges.length;
        for (int i = 0; i < sz; i++) {
            if (i != 0) {
                sb.append(',');
            }
            sb.append(disabledCompatChanges[i]);
        }

        argsForZygote.add(sb.toString());
    }

    argsForZygote.add(processClass);

    if (extraArgs != null) {
        Collections.addAll(argsForZygote, extraArgs);
    }

    synchronized(mLock) {
        // 调用zygoteSendArgsAndGetResult,详见1.9
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                          zygotePolicyFlags,
                                          argsForZygote);
    }
}

1.9 zygoteSendArgsAndGetResult
参数检查,然后拼接成一个String,后续调用attemptUsapSendArgsAndGetResult

private Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
        throws ZygoteStartFailedEx {
    // 参数检查,不能有换行符或者\r
    for (String arg : args) {
        if (arg.indexOf('\n') >= 0) {
            throw new ZygoteStartFailedEx("Embedded newlines not allowed");
        } else if (arg.indexOf('\r') >= 0) {
            throw new ZygoteStartFailedEx("Embedded carriage returns not allowed");
        }
    }

    // 参数拼接成一个String
    String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";

    if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
        try {
            // 调用attemptUsapSendArgsAndGetResult,详见1.10
            return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
        } catch (IOException ex) {
            Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
                    + ex.getMessage());
        }
    }

    return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}

1.10 attemptUsapSendArgsAndGetResult
syste_server和Zygote进程是通过LocalSocket进行通信的,这里就是通过LocalSocket将参数指令发送给Zygote。

private Process.ProcessStartResult attemptUsapSendArgsAndGetResult(
        ZygoteState zygoteState, String msgStr)
        throws ZygoteStartFailedEx, IOException {
    try (LocalSocket usapSessionSocket = zygoteState.getUsapSessionSocket()) {
        final BufferedWriter usapWriter =
                new BufferedWriter(
                        new OutputStreamWriter(usapSessionSocket.getOutputStream()),
                        Zygote.SOCKET_BUFFER_SIZE);
        final DataInputStream usapReader =
                new DataInputStream(usapSessionSocket.getInputStream());
        // 通过LocalSocket发送启动指令
        usapWriter.write(msgStr);
        usapWriter.flush();

        Process.ProcessStartResult result = new Process.ProcessStartResult();
        result.pid = usapReader.readInt();
        result.usingWrapper = false;

        if (result.pid >= 0) {
            return result;
        } else {
            throw new ZygoteStartFailedEx("USAP specialization failed");
        }
    }
}

Zygote启动进程

Zygote和app启动都是启动的进程app_process,但是里面走的逻辑不同。
在这里插入图片描述

2.1 app_process.main
这里启动java虚拟机,如果是zygote,入口类是ZygoteInit,否则是RuntimeInit,我们先来看Zygote。

int main(int argc, char* const argv[])
{
    // ...

    if (zygote) {
        // 如果是Zygote,java虚拟机入口是ZygoteInit类,详见2.2
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (!className.isEmpty()) {
        // 否者入口是RuntimeInit
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

2.2 ZygoteInit.main
fork出来的子进程会和主进程逻辑一样,从fork的地方继续走代码逻辑,这里runSelectLoop会监听socket命令,Zygote自身会一直在runSelectLoop里面的循环,而fork出来的子进程则会跳出循环,走到caller.run

public static void main(String[] argv) {
    ZygoteServer zygoteServer = null;

    ZygoteHooks.startZygoteNoThreadCreation();

    // zygote需要root权限
    try {
        Os.setpgid(0, 0);
    } catch (ErrnoException ex) {
        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }

    Runnable caller;
    try {
        // ...省略不关心的逻辑
        // 这里会注册LocalSocket
        zygoteServer = new ZygoteServer(isPrimaryZygote);
        // ...如果是SystemServer就启动SystemServer然后直接return

        // runSelectLoop进入循环,监听命令,详见2.3
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with fatal exception", ex);
        throw ex;
    } finally {
        if (zygoteServer != null) {
            // 关闭和SystemServer的socket
            zygoteServer.closeServerSocket();
        }
    }

    // fork出来的子进程会走这里。
    if (caller != null) {
        caller.run();
    }
}

2.3 ZygoteServer.runSelectLoop
通过poll来监听socket的fd
如果fd有事件,通过processCommand来fork子进程
之后Zygote继续循环监听消息,而fork出来的子进程则跳出循环返回。
由2.2可知fork出来的子进程跳出runSelectLoop会执行caller.run(),caller是这里processCommand返回的。

Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
    ArrayList<ZygoteConnection> peers = new ArrayList<>();
    // 这里的Socket是在之前ZygoteServer构造函数里创建的。
    socketFDs.add(mZygoteSocket.getFileDescriptor());
    peers.add(null);

    mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;

    while (true) {
        // ...省略细节逻辑

        int pollReturnValue;
        try {
            // 调用poll在fd上等待,也就是会在socket上等待消息。
            pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }

        if (pollReturnValue == 0) {
            mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
            mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
        } else {
            boolean usapPoolFDRead = false;

            while (--pollIndex >= 0) {
                // 遍历fd,确认是哪个fd的事件
                if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                    continue;
                }

                if (pollIndex == 0) {
                    // Zygote server socket
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor());
                } else if (pollIndex < usapPoolEventFDIndex) {
                    // Session socket accepted from the Zygote server socket

                    try {
                        ZygoteConnection connection = peers.get(pollIndex);
                        boolean multipleForksOK = !isUsapPoolEnabled()
                                && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                        // 调用processCommand做实际的fork操作,详见2.4
                        final Runnable command =
                                connection.processCommand(this, multipleForksOK);

                        // 前面在processCommand已经fork出来子进程了,如果是子进程则直接return command跳出循环
                        // 如果是Zygote进程,做一些后续处理之后,进入下一次循环继续监听消息。
                        if (mIsForkChild) {
                            if (command == null) {
                                throw new IllegalStateException("command == null");
                            }

                            return command;
                        } else {
                            if (command != null) {
                                throw new IllegalStateException("command != null");
                            }

                            if (connection.isClosedByPeer()) {
                                connection.closeSocket();
                                peers.remove(pollIndex);
                                socketFDs.remove(pollIndex);
                            }
                        }
                    } catch (Exception e) {
                        // ...
                    } finally {
                        mIsForkChild = false;
                    }

                } else {
                    // ...
                }
            }
            // ...
        }

        // ...
    }
}

2.4 ZygoteConnection.processCommand
调用Zygote.forkAndSpecialize来fork子进程,该方法会通过jni调用到native层,后续最终通过fork来fork出子进程,fork子进程之后还会调用一些linux的接口让子进程进行一些配置,如配置uid,gid,capability,进程名等等。这里我们就不跟了,感兴趣可以自己去看一下源码。主要逻辑在com_android_internal_os_Zygote_nativeForkAndSpecialize里。
这里顺带提一下capability,了解linux的同学应该知道linux里面有一个root用户,可以拥有非常高的权限。例如可以访问几乎所有文件(不考虑sepolicy的情况下),但是实际上linux并不是因为他的uid为0就可以访问所有用户组的文件,而是因为它的capability对应的位为1,capability是一个掩码,每一个位都代表一个特权,也就是说root用户之所以有那个多权限并不是因为它多uid为0,而是因为它的capability。
fork子进程后,如果返回值是0,则代表当前是子进程,否则就是原来的Zygote进程。Zygote进程后续就会进入下一次循环,我们主要来看子进程。
handleChildProc返回的Runnable后续会执行,实际上这里的Runable就相当于是子进程的入口了,这里的入口是由参数决定的,也就是1.5提到的ActivityThread。

Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
    ZygoteArguments parsedArgs;

    try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
        while (true) {
            try {
                // 解析参数
                parsedArgs = ZygoteArguments.getInstance(argBuffer);
            } catch (IOException ex) {
                throw new IllegalStateException("IOException on command socket", ex);
            }
            if (parsedArgs == null) {
                isEof = true;
                return null;
            }

            // ... 一些参数的处理

            if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
                    || !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
                // 这里会通过jni调用到native层,后续最终通过fork来fork出子进程
                // fork子进程之后还会调用一些linux的接口让子进程进行一些配置,如配置uid,gid,capability,进程名等等,我们就不跟了。
                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 {
                    // 如果forkAndSpecialize返回值是0,则是子进程
                    if (pid == 0) {
                        // in child
                        zygoteServer.setForkChild();

                        zygoteServer.closeServerSocket();
                        IoUtils.closeQuietly(serverPipeFd);
                        serverPipeFd = null;
                        // 子进程则需要调用handleChildProc获取返回值,这个返回值是一个Runnable,子进程后续会执行。
                        // 这里的返回值入口是由参数决定的,也就是我们1.5提到的ActivityThread。详见2.5
                        return handleChildProc(parsedArgs, childPipeFd,
                                parsedArgs.mStartChildZygote);
                    } else {
                        IoUtils.closeQuietly(childPipeFd);
                        childPipeFd = null;
                        // 做一些参数清理的操作
                        handleParentProc(pid, serverPipeFd);
                        return null;
                    }
                } finally {
                    IoUtils.closeQuietly(childPipeFd);
                    IoUtils.closeQuietly(serverPipeFd);
                }
            } else {
                // ...
            }
        }
    }
    // ...
}

子进程启动

这里我们来到子进程启动。
在这里插入图片描述

3.1 ActivityThread.main
做一些初始化后调用了thread.attach,然后就进入了Looper的消息循环,我们知道app主线程是一直在Looper的消息循环里等待消息,就是这里进去的。
关于Looper的消息队列机制我们这里就不讲了,后面也许会单独写一章,逻辑比较多,但是底层逻辑是比较简单的,通过linux epoll来等待消息通知,消息会通过一个pipe的fd来唤醒线程。

public static void main(String[] args) {
    // 初始化参数,环境的处理

    ActivityThread thread = new ActivityThread();
    // 详见3.2
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    // 进入loop循环
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

3.2 ActivityThread.attach
主要调用了AMS的attachApplication

private void attach(boolean system, long startSeq) {
    sCurrentActivityThread = this;
    mConfigurationController = new ConfigurationController(this);
    mSystemThread = system;
    mStartSeq = startSeq;

    if (!system) {
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                UserHandle.myUserId());
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        final IActivityManager mgr = ActivityManager.getService();
        try {
            // 这里会调用到SystemServer侧 AMS attachApplication
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        // ...
    } else {
        // ...
    }

    // ...
}

3.3 ActivityManagerService.attachApplication
调用attachApplicationLocked

public final void attachApplication(IApplicationThread thread, long startSeq) {
    if (thread == null) {
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

3.4 ActivityManagerService.attachApplicationLocked
更新了一些app状态标志,注册binder死亡回调,然后binder调用回app侧。

private void attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {

    // ...
    // ... 一些进程状态更新,注册binder死亡回调等。

        // ... 调用回app ActivityThread.bindApplication
        if (app.getIsolatedEntryPoint() != null) {
            // This is an isolated process which should just call an entry point instead of
            // being bound to an application.
            thread.runIsolatedEntryPoint(
                    app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
        } else if (instr2 != null) {
            // 详见3.5
            thread.bindApplication(processName, appInfo,
                    app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                    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,
                    app.getStartElapsedTime(), app.getStartUptime());
        } else {
            thread.bindApplication(processName, appInfo,
                    app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
                    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,
                    app.getStartElapsedTime(), app.getStartUptime());
        }
        // ...

}

3.5 Activity.handleBindApplication
中间省略了一个消息post的流程,直接到handleBindApplication
初始化VMRuntime一些参数,以及Applcation到Configuration,包括Local、事件12/24小时制等,创建Context,配置网络代理。
调用Applcation onCreate
回调AMS finishAttachApplication

private void handleBindApplication(AppBindData data) {
    // ... 初始化VMRuntime一些参数,以及Applcation到Configuration,包括Local、事件12/24小时制等。
    // ... 配置是否严格模式


    final InstrumentationInfo ii;
    if (data.instrumentationName != null) {
        ii = prepareInstrumentation(data);
    } else {
        ii = null;
    }

    final IActivityManager mgr = ActivityManager.getService();
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    mConfigurationController.updateLocaleListFromAppContext(appContext);
    // ... 配置网络代理


    try {
        
        try {
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        catch (Exception e) {
            throw new RuntimeException(
                "Exception thrown in onCreate() of "
                + data.instrumentationName + ": " + e.toString(), e);
        }
        try {
            // ...调用Application OnCreate
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            // ...
        }
    } finally {
        // ...
    }

    // ... 获取字体

    try {
        // 回调AMS finishAttachApplication,详见3.6  
        mgr.finishAttachApplication(mStartSeq);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
}

3.6 ActivityManagerService.finishAttachApplication

public final void finishAttachApplication(long startSeq) {
    // ...

    final long origId = Binder.clearCallingIdentity();
    try {
        // 详见3.7
        finishAttachApplicationInner(startSeq, uid, pid);
    } finally {
        Binder.restoreCallingIdentity(origId);
    }
}

3.7 ActivityManagerService.finishAttachApplicationInner
调用ActivityTaskManagerService.attachApplication

private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
    // ...
    synchronized (this) {
        // ...
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                // 详见3.8 
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
    // ...
}

3.8 ActivityTaskManagerService.attachApplication
调用RootWindowContainer.attachApplication

public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    synchronized (mGlobalLockWithoutBoost) {
        try {
            return mRootWindowContainer.attachApplication(wpc);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }
}

3.9 RootWindowContainer.attachApplication
调用AttachApplicationHelper.process

boolean attachApplication(WindowProcessController app) throws RemoteException {
    try {
        // 详见3.10
        return mAttachApplicationHelper.process(app);
    } finally {
        mAttachApplicationHelper.reset();
    }
}

3.10 AttachApplicationHelper.process
用RootWindowContainer.ensureActivitiesVisible,里面会调用每个节点的ensureActivitiesVisible
Task.ensureActivitiesVisible 我们在Activity启动流程1.19中介绍过了,会找到对应ActivityRecord,更新状态和可见性,并且通知app侧。

boolean process(WindowProcessController app) throws RemoteException {
    mApp = app;
    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        getChildAt(displayNdx).forAllRootTasks(this);
        if (mRemoteException != null) {
            throw mRemoteException;
        }
    }
    if (!mHasActivityStarted) {
        // 调用RootWindowContainer.ensureActivitiesVisible,里面会调用每个节点的ensureActivitiesVisible
        // Task.ensureActivitiesVisible 我们在Activity启动流程1.19中介绍过了。
        ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
                false /* preserveWindows */);
    }
    return mHasActivityStarted;
}

小结

本节我们介绍了Activity启动时,当目标进程原本没有启动的情况的流程。
SystemServer会通过Socket来通知Zygote需要启动一个进程。
而Zygote会fork出子进程,以ActivityThread为子进程的入口点。
子进程会调用attach,然后通知AMS bindApplication,AMS再回调回app,App完成Application onCreate后在回调AMS finishAttachApplication。
SystemServer会通过ensureActivitiesVisible来寻找需要resume的Activity,后续的流程和上一节启动的1.19开始的流程就一样了。

AMS的这些流程都看起来很复杂,因为它的调用链很长,但是我们只要知道它核心逻辑是在做什么,还是比较好理解的。需要多看几遍。
下一节会介绍app侧的状态流转。

标签:info,null,String,启动,int,app,进程,ActivityManagerService,uid
From: https://blog.csdn.net/weixin_43833152/article/details/142317877

相关文章

  • 详解IPC(进程间通信)
    进程间通信(IPC,Inter-ProcessCommunication)是指在不同进程之间传递数据或信号的机制。由于进程之间的地址空间是独立的,IPC提供了一种在进程之间进行数据交换的方法。以下是几种常见的IPC机制:1.管道(Pipes)匿名管道匿名管道是单向的通信通道,通常用于具有亲缘关系的进程之间(如......
  • [操作系统]进程通信
    管道在Java中,可以使用管道通过进程间通信。以下是一个简单的例子,展示了如何通过ProcessBuilder创建两个进程,并使用输入和输出流进行通信。示例代码importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.OutputSt......
  • 【Linux进程】Linux Shell编程实战:构建简易脚本示例与技巧详解
    ......
  • 进程之信号
    文章目录进程信号中断的概念信号是异步事件Linux信号信号发生的来源信号的处理方式signal函数示例--使用signal函数对常见的信号进行捕获、执行默认操作、忽略三种方式处理SIGCHLD信号示例--使用SIGCHLD信号来避免子进程退出kill函数raise函数示例--使用kill函数给指定......
  • Linux引导启动程序(boot)
    概述本章主要描述boot/目录中的三个汇编代码文件,见列表6-1所示。正如在前一章中提到的,这三个文件虽然都是汇编程序,但却使用了两种语法格式。bootsect.s和setup.s是实模式下运行的16位代码程序,采用近似于Intel的汇编语言语法并且需要使用Intel8086汇编编译器和连接器as86和ld......
  • C# 以管理员方式启动程序:你需要知道的5个关键步骤
    ......
  • Photoshop启动故障:d3dcompiler_47.dll缺失的应对策略
    面对Photoshop因缺少d3dcompiler_47.dll文件而无法启动的问题,遵循以下细致步骤,逐一排查并修复:1.识别问题根源:•d3dcompiler_47.dll属于Direct3D编译器的一部分,通常与图形处理相关。缺失可能是由于软件更新不完全、系统文件损坏或第三方清理工具误删等原因。2.系统文件检查:......
  • PostgreSQL的walsender和walreceiver进程介绍
    PostgreSQL的walsender和walreceiver进程介绍在PostgreSQL中,WAL(Write-AheadLogging)是一种用于确保数据库事务日志安全可靠的机制。WAL是PostgreSQL进行数据库恢复、复制等操作的基础。walsender和walreceiver是PostgreSQL内部两个非常重要的进程,它们负责主......
  • 小林coding学习笔记(进程调度算法)
    //进程调度算法进程调度算法是CPU通过进程调度算法决定某个时刻去调用哪个进程到CPU上运行的算法1、先来先服务调度算法每次从就绪队列的队头调度到CPU上运行,直到进程退出或被阻塞,才会继续从队列中调度进程运行。特点:对短作业不利,对长作业有利,无法平衡短作业与长作业。2、最......
  • Linux下通过命名管道实现进程间通信
    引入上一篇文章介绍了Linux中通过pipe创建匿名管道,并实现父子进程间通信的功能;当时我就提到了Linux中的另一种管道通信方式——命名管道,下面就来详细介绍一下;命名管道什么是命名管道命名管道(NamedPipe),也叫FIFO(FirstInFirstOut),是一种用于进程间通信(IPC)的机制。与匿名管......