Android源码分析 - Activity启动流程(中)

开篇

本篇以android-11.0.0_r25作为基础解析

上一篇文章 Android源码分析 - Activity启动流程(上) 中,我们分析了Activity启动流程中的一小部分,基本上可以算是Activity启动的前置准备工作,这篇文章我们将会分析App进程启动的主要流程

启动App进程

准备ProcessRecord

上篇文章中我们说过了,如果App尚未启动,则会调用ATMSstartProcessAsync方法去启动App进程

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
        String hostingType) {
    
    
    try {
    
    
        ...
        // 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 {
    
    
        ...
    }
}

这个方法实际上是通过Hander调用了ActivityManagerInternal (AMS.LocalService)startProcess方法

@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
    boolean isTop, String hostingType, ComponentName hostingName) {
    
    
try {
    
    
    ...
    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 */, true /* keepIfLarge */);
    }
} finally {
    
    
    ...
}
}

这里将进程启动的一些信息封装到了HostingRecord类中

final ProcessRecord startProcessLocked(String processName,
    ApplicationInfo info, boolean knownToBeDead, int intentFlags,
    HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
    boolean isolated, boolean keepIfLarge) {
    
    
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
        hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
        keepIfLarge, null /* ABI override */, null /* entryPoint */,
        null /* entryPointArgs */, null /* crashHandler */);
}

AMS将启动进程的任务转交给了ProcessList,这个类的职责是管理进程,包括管理进程优先级(Adj)、进程OOM等

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
        boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
        int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
        boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
        Runnable crashHandler) {
    
    
    long startTime = SystemClock.uptimeMillis();
    ProcessRecord app;
    if (!isolated) {
    
    
        //先通过进程名和uid查找相应App的ProcessRecord
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);

        //如果是由后台进程发起的 startProcess
        //判断启动进程是否为 bad process,如果是,直接启动失败返回
        //这里 bad process 的定义为:短时间内连续崩溃两次以上的进程
        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.
            if (mService.mAppErrors.isBadProcessLocked(info)) {
    
    
                return null;
            }
        } 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.
            //如果是用户显式的要求启动进程,则会清空启动进程的崩溃次数,将启动进程从 bad process 列表中移除
            mService.mAppErrors.resetProcessCrashTimeLocked(info);
            if (mService.mAppErrors.isBadProcessLocked(info)) {
    
    
                EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                        UserHandle.getUserId(info.uid), info.uid,
                        info.processName);
                mService.mAppErrors.clearBadProcessLocked(info);
                if (app != null) {
    
    
                    app.bad = false;
                }
            }
        }
    } else {
    
    
        // If this is an isolated process, it can't re-use an existing process.
        app = null;
    }

    // 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.
    ProcessRecord precedence = null;
    //如果已经存在了对应App的ProcessRecord,并且分配了pid
    if (app != null && app.pid > 0) {
    
    
        //如果进程没有死亡或者进程还未绑定binder线程,说明进程是正常运行状态或正在启动中
        if ((!knownToBeDead && !app.killed) || app.thread == null) {
    
    
            // 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.
            // If this is a new package in the process, add the package to the list
            //将要启动的包信息记录在ProcessRecord中(Android多个App可以运行在同一个进程中)
            app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
            return app;
        }

        // An application record is attached to a previous process,
        // clean it up now.
        //App绑定在之前的一个进程上了,杀死并清理这个进程
        ProcessList.killProcessGroup(app.uid, app.pid);

        Slog.wtf(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 precedence of the new process.
        precedence = app;
        app = null;
    }

    //没有找到对应的ProcessRecord
    if (app == null) {
    
    
        //新创建一个ProcessRecord对象
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);
        if (app == null) {
    
    
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        app.crashHandler = crashHandler;
        app.isolatedEntryPoint = entryPoint;
        app.isolatedEntryPointArgs = entryPointArgs;
        if (precedence != null) {
    
    
            app.mPrecedence = precedence;
            precedence.mSuccessor = app;
        }
    } else {
    
        //存在对应的ProcessRecord,但进程尚未启动或已被清理
        // If this is a new package in the process, add the package to the list
        //将要启动的包信息记录在ProcessRecord中
        app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
    }

    // If the system is not ready yet, then hold off on starting this
    // process until it is.
    //如果系统尚未准备好(开机中或system_server进程崩溃重启中),将其先添加到等待队列中
    if (!mService.mProcessesReady
            && !mService.isAllowedWhileBooting(info)
            && !allowWhileBooting) {
    
    
        if (!mService.mProcessesOnHold.contains(app)) {
    
    
            mService.mProcessesOnHold.add(app);
        }
        return app;
    }

    final boolean success =
            startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
    return success ? app : null;
}

这个方法主要是处理ProcessRecord对象,如果找不到对应的ProcessRecord或对应的ProcessRecord里的信息表明App进程尚未启动,则会调用另一个startProcessLocked重载方法启动进程

final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
        int zygotePolicyFlags, String abiOverride) {
    
    
    return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
            false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
            false /* mountExtStorageFull */, abiOverride);
}

boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
        int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
        boolean mountExtStorageFull, String abiOverride) {
    
    
    //进程正在启动中
    if (app.pendingStart) {
    
    
        return true;
    }
    //从刚才方法中的判断来看,应该不会进入这个case
    if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
    
    
        //将ProcessRecord的pid从PidMap中移除
        mService.removePidLocked(app);
        app.bindMountPending = false;
        //将ProcessRecord的pid重置为0
        app.setPid(0);
        app.startSeq = 0;
    }

    //将ProcessRecord从启动等待队列中移除
    mService.mProcessesOnHold.remove(app);

    mService.updateCpuStats();

    try {
    
    
        try {
    
    
            //检测当前用户是否可以启动这个App
            final int userId = UserHandle.getUserId(app.uid);
            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;
        if (!app.isolated) {
    
    
            int[] permGids = null;
            try {
    
    
                final IPackageManager pm = AppGlobals.getPackageManager();
                //获取GIDS(App申请的权限)
                permGids = pm.getPackageGids(app.info.packageName,
                        MATCH_DIRECT_BOOT_AUTO, app.userId);
                if (StorageManager.hasIsolatedStorage() && mountExtStorageFull) {
    
    
                    //挂载外置存储,允许读写
                    mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
                } else {
    
    
                    StorageManagerInternal storageManagerInternal = LocalServices.getService(
                            StorageManagerInternal.class);
                    //获取App对外置存储的读写权限
                    mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
                            app.info.packageName);
                }
            } catch (RemoteException e) {
    
    
                throw e.rethrowAsRuntimeException();
            }

            // Remove any gids needed if the process has been denied permissions.
            // NOTE: eventually we should probably have the package manager pre-compute
            // this for us?
            //从刚刚过去的App申请权限中剔除进程所被拒绝的权限
            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);
        }
        //设置挂载模式
        app.mountMode = mountExternal;
        //工厂测试进程
        if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
    
    
            uid = 0;
        }
        //进程启动参数(传递到Zygoto)
        int runtimeFlags = 0;
        //如果manifest中设置了android:debuggable
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
    
    
            runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP;
            runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
            // Also turn on CheckJNI for debuggable apps. It's quite
            // awkward to turn on otherwise.
            runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;

            // Check if the developer does not want ART verification
            if (android.provider.Settings.Global.getInt(mService.mContext.getContentResolver(),
                    android.provider.Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE, 1) == 0) {
    
    
                runtimeFlags |= Zygote.DISABLE_VERIFIER;
                Slog.w(TAG_PROCESSES, app + ": ART verification disabled");
            }
        }
        ... //设置各种高进程启动参数

        String invokeWith = null;
        //如果manifest中设置了android:debuggable
        //使用logwrapper工具捕获stdout信息
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
    
    
            // Debuggable apps may include a wrapper script with their library directory.
            String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
    
    
                if (new File(wrapperFileName).exists()) {
    
    
                    invokeWith = "/system/bin/logwrapper " + wrapperFileName;
                }
            } finally {
    
    
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }

        //确定App进程使用的abi(有so库的App会通过so库的架构决定,没有so库的使用系统最优先支持的abi)
        String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
        if (requiredAbi == null) {
    
    
            requiredAbi = Build.SUPPORTED_ABIS[0];
        }

        //将abi转成InstructionSet
        String instructionSet = null;
        if (app.info.primaryCpuAbi != null) {
    
    
            instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
        }

        app.gids = gids;
        app.setRequiredAbi(requiredAbi);
        app.instructionSet = instructionSet;

        ...

        final String seInfo = app.info.seInfo
                + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
        // Start the process.  It will either succeed and return a result containing
        // the PID of the new process, or else throw a RuntimeException.
        //重要:设置进程启动入口
        final String entryPoint = "android.app.ActivityThread";

        //启动进程
        return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
                instructionSet, invokeWith, startTime);
    } catch (RuntimeException e) {
    
    
        ...
        mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                false, false, true, false, false, app.userId, "start failure");
        return false;
    }
}

到这一步位置仍然是在进行准备工作,主要做了以下几件事:

  1. 权限处理:App安装时会检测manifest里申请的权限,并由此生成出一个GIDS数组
  2. 设置挂载模式
  3. 设置进程的各种启动参数
  4. 设置App进程使用的abi
  5. 设置进程启动入口
  6. 继续调用重载方法启动进程
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) {
    
    
    //初始化一些参数
    //标识App进程正在启动
    app.pendingStart = true;
    app.killedByAm = false;
    app.removed = false;
    app.killed = false;
    app.mDisabledCompatChanges = null;
    if (mPlatformCompat != null) {
    
    
        app.mDisabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
    }
    final long startSeq = app.startSeq = ++mProcStartSeqCounter;
    app.setStartParams(uid, hostingRecord, seInfo, startTime);
    app.setUsingWrapper(invokeWith != null
            || Zygote.getWrapProperty(app.processName) != null);
    //将ProcessRecord添加到待启动列表中
    mPendingStarts.put(startSeq, app);

    if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
    
        //异步启动进程
        if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                "Posting procStart msg for " + app.toShortString());
        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);
        } catch (RuntimeException e) {
    
    
            //出错,将pendingStart标志复位并强行停止进程
            app.pendingStart = false;
            mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                    false, false, true, false, false, app.userId, "start failure");
        }
        return app.pid > 0;
    }
}

在异步模式下,程序会等待ProcessRecord.mPrecedence进程结束才会启动进程(这里对应着最开始的startProcessLocked方法中,已经存在了对应App的ProcessRecord,并且分配了pid,但是进程被标记为死亡这种情况)

最终都会进入到startProcesshandleProcessStartedLocked方法中来

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) {
    
    
    try {
    
    
        final boolean isTopApp = hostingRecord.isTopApp();
        if (isTopApp) {
    
    
            // Use has-foreground-activities as a temporary hint so the current scheduling
            // group won't be lost when the process is attaching. The actual state will be
            // refreshed when computing oom-adj.
            app.setHasForegroundActivities(true);
        }

        //处理应用目录隔离机制
        Map<String, Pair<String, Long>> pkgDataInfoMap;
        Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
        boolean bindMountAppStorageDirs = false;
        boolean bindMountAppsData = mAppDataIsolationEnabled
                && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
                && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);

        // Get all packages belongs to the same shared uid. sharedPackages is empty array
        // if it doesn't have shared uid.
        final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
        final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
                app.info.packageName, app.userId);
        final String[] targetPackagesList = sharedPackages.length == 0
                ? new String[]{
    
    app.info.packageName} : sharedPackages;

        pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
        if (pkgDataInfoMap == null) {
    
    
            // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
            // tmp free pass.
            bindMountAppsData = false;
        }

        // Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so
        // it won't be mounted twice.
        final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps);
        for (String pkg : targetPackagesList) {
    
    
            whitelistedApps.remove(pkg);
        }

        whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
                whitelistedApps.toArray(new String[0]), uid);
        if (whitelistedAppDataInfoMap == null) {
    
    
            // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
            // tmp free pass.
            bindMountAppsData = false;
        }

        int userId = UserHandle.getUserId(uid);
        StorageManagerInternal storageManagerInternal = LocalServices.getService(
                StorageManagerInternal.class);
        if (needsStorageDataIsolation(storageManagerInternal, app)) {
    
    
            bindMountAppStorageDirs = true;
            if (pkgDataInfoMap == null ||
                    !storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
                    app.processName)) {
    
    
                // Cannot prepare Android/app and Android/obb directory or inode == 0,
                // so we won't mount it in zygote, but resume the mount after unlocking device.
                app.bindMountPending = true;
                bindMountAppStorageDirs = false;
            }
        }

        // If it's an isolated process, it should not even mount its own app data directories,
        // since it has no access to them anyway.
        if (app.isolated) {
    
    
            pkgDataInfoMap = null;
            whitelistedAppDataInfoMap = null;
        }

        final Process.ProcessStartResult startResult;
        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.mDisabledCompatChanges,
                    new String[]{
    
    PROC_START_SEQ_IDENT + app.startSeq});
        } else if (hostingRecord.usesAppZygote()) {
    
    
            final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

            // We can't isolate app data and storage data as parent zygote already did that.
            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.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
                    false, false,
                    new String[]{
    
    PROC_START_SEQ_IDENT + app.startSeq});
        } else {
    
        //没有特别指定hostingZygote时,进入此case
            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.mDisabledCompatChanges, pkgDataInfoMap,
                    whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                    new String[]{
    
    PROC_START_SEQ_IDENT + app.startSeq});
        }
        return startResult;
    } finally {
    
    
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}

Android 11开始引入了应用目录隔离机制,使得应用仅可以发现和访问自己的储存目录,不可以访问其他应用的储存目录

这里处理完应用目录隔离机制后,调用了Process.start方法启动进程,最终走到ZygoteProcess.startViaZygote方法

向zygoto发送socket请求

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

    // --runtime-args, --setuid=, --setgid=,
    // and --setgroups= must go first
    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) {
    
    
        // The USAP pool can not be used if the application will not use the systems graphics
        // driver.  If that driver is requested use the Zygote application start path.
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                            zygotePolicyFlags,
                                            argsForZygote);
    }
}

这个方法的功能就很简单了,就是将各种参数拼装起来,然后调用zygoteSendArgsAndGetResult方法

我们先看openZygoteSocketIfNeeded这个方法,它返回了一个ZygoteState对象,这个类是对与ZygoteServerSocket建立连接后的封装

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    
    
    try {
    
    
        //尝试连接主ZygoteServerSocket
        attemptConnectionToPrimaryZygote();

        //主zygote进程支持此abi
        if (primaryZygoteState.matches(abi)) {
    
    
            return primaryZygoteState;
        }

        if (mZygoteSecondarySocketAddress != null) {
    
    
            // The primary zygote didn't match. Try the secondary.
            //尝试连接辅ZygoteServerSocket
            attemptConnectionToSecondaryZygote();

            //辅zygote进程支持此abi
            if (secondaryZygoteState.matches(abi)) {
    
    
                return secondaryZygoteState;
            }
        }
    } catch (IOException ioe) {
    
    
        throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
    }

    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

attemptConnectionToxxxZygote方法使用LocalSocket进行连接,并返回一个ZygoteState封装对象

我们之前在 Android源码分析 - Zygote进程 中说过,一般,64位的cpu会启动两个zygoto进程,一个64位(主zygote),一个32位(辅zygote

zygote

接下来我们看zygoteSendArgsAndGetResult方法

private Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
        throws ZygoteStartFailedEx {
    
    

    ...

    /*
        * See com.android.internal.os.ZygoteArguments.parseArgs()
        * Presently the wire format to the zygote process is:
        * a) a count of arguments (argc, in essence)
        * b) a number of newline-separated argument strings equal to count
        *
        * After the zygote process reads these it will write the pid of
        * the child or -1 on failure, followed by boolean to
        * indicate whether a wrapper process was used.
        */
    //构建出符合zygote解析规则的参数(argc + argv)
    String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";

    //USAP机制
    if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
    
    
        try {
    
    
            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());
        }
    }

    return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}

USAP机制我们先跳过,这个方法就做了一件事:拼装参数,然后调用attemptZygoteSendArgsAndGetResult方法

private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
        ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
    
    
    try {
    
    
        final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
        final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

        zygoteWriter.write(msgStr);
        zygoteWriter.flush();

        // Always read the entire result from the input stream to avoid leaving
        // bytes in the stream for future process starts to accidentally stumble
        // upon.
        Process.ProcessStartResult result = new Process.ProcessStartResult();
        result.pid = zygoteInputStream.readInt();
        result.usingWrapper = zygoteInputStream.readBoolean();

        if (result.pid < 0) {
    
    
            throw new ZygoteStartFailedEx("fork() failed");
        }

        return result;
    } catch (IOException ex) {
    
    
        zygoteState.close();
        Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
                + ex.toString());
        throw new ZygoteStartFailedEx(ex);
    }
}

这个方法很明显就能看出来,这是一次socket通信发送 -> 接收

具体zygote进程接收到socket后做了什么可以回顾我之前写的文章 Android源码分析 - Zygote进程

handleProcessStartedLocked

zygote发送完socket请求后,zygote开始forkApp进程,fork完后会将App进程的pidusingWrapper信息再通过socket传回system_server,此时程序会继续执行handleProcessStartedLocked方法

boolean handleProcessStartedLocked(ProcessRecord app, int pid, boolean usingWrapper,
        long expectedStartSeq, boolean procAttached) {
    
    
    //从待启动列表中移除此ProcessRecord
    mPendingStarts.remove(expectedStartSeq);
    final String reason = isProcStartValidLocked(app, expectedStartSeq);
    //未通过进程启动验证,杀死进程
    if (reason != null) {
    
    
        app.pendingStart = false;
        killProcessQuiet(pid);
        Process.killProcessGroup(app.uid, app.pid);
        noteAppKill(app, ApplicationExitInfo.REASON_OTHER,
                ApplicationExitInfo.SUBREASON_INVALID_START, reason);
        return false;
    }
    
    ... //记录进程启动

    //通知看门狗有进程启动
    Watchdog.getInstance().processStarted(app.processName, pid);

    ... //记录进程启动

    //设置ProcessRecord
    app.setPid(pid);
    app.setUsingWrapper(usingWrapper);
    app.pendingStart = false;
    //从PidMap中获取未清理的ProcessRecord
    ProcessRecord oldApp;
    synchronized (mService.mPidsSelfLocked) {
    
    
        oldApp = mService.mPidsSelfLocked.get(pid);
    }
    // If there is already an app occupying that pid that hasn't been cleaned up
    //清理ProcessRecord
    if (oldApp != null && !app.isolated) {
    
    
        mService.cleanUpApplicationRecordLocked(oldApp, false, false, -1,
                true /*replacingPid*/);
    }
    //将ProcessRecord添加到PidMap中
    mService.addPidLocked(app);
    synchronized (mService.mPidsSelfLocked) {
    
    
        //attach超时检测
        if (!procAttached) {
    
    
            Message msg = mService.mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
            msg.obj = app;
            mService.mHandler.sendMessageDelayed(msg, usingWrapper
                    ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
        }
    }
    return true;
}

这个方法将从zygote fork后得到的信息设置到ProcessRecord中,然后将此ProcessRecord添加到PidMap中(AMS.mPidsSelfLocked),后续当attachApplication时会用到它

ActivityThread

zygote进程将App进程fork出来后,便通过反射调用我们之前设置的entryPoint类的main方法,即android.app.ActivityThread.main(String[] args)方法

public static void main(String[] args) {
    
    
    // Install selective syscall interception
    //设置拦截器,拦截部分系统调用自行处理
    AndroidOs.install();

    // CloseGuard defaults to true and can be quite spammy.  We
    // disable it here, but selectively enable it later (via
    // StrictMode) on debug builds, but using DropBox, not logs.
    //资源关闭检测器
    CloseGuard.setEnabled(false);

    //初始化用户环境
    Environment.initForCurrentUser();

    // Make sure TrustedCertificateStore looks in the right place for CA certificates
    //设置CA证书搜索位置
    final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
    TrustedCertificateStore.setDefaultUserDirectory(configDir);

    // Call per-process mainline module initialization.
    //初始化主模块各个注册服务
    initializeMainlineModules();

    //预设进程名
    Process.setArgV0("<pre-initialized>");

    //准备Looper
    Looper.prepareMainLooper();

    // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
    // It will be in the format "seq=114"
    //查找startSeq参数
    long startSeq = 0;
    if (args != null) {
    
    
        for (int i = args.length - 1; i >= 0; --i) {
    
    
            if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
    
    
                startSeq = Long.parseLong(
                        args[i].substring(PROC_START_SEQ_IDENT.length()));
            }
        }
    }
    //创建App进程ActivityThread实例
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    //设置全局Handler
    if (sMainThreadHandler == null) {
    
    
        sMainThreadHandler = thread.getHandler();
    }

    //Looper循环处理消息
    Looper.loop();

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

main方法中主要做了两件事,一是启动Looper,循环处理消息,保证进程不会退出,二是实例化ActivityThread并执行attach方法

private void attach(boolean system, long startSeq) {
    
    
    sCurrentActivityThread = this;
    mConfigurationController = new ConfigurationController(this);
    mSystemThread = system;
    if (!system) {
    
        //非系统ActivityThread
        //预设进程名
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                UserHandle.myUserId());
        //处理一些错误异常需要使用ActivityThread,将其传入
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        //AMS代理binder对象
        final IActivityManager mgr = ActivityManager.getService();
        try {
    
    
            //执行AMS.attachApplication方法
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
    
    
            throw ex.rethrowFromSystemServer();
        }
        // Watch for getting close to heap limit.
        //每次GC时检测内存,如果内存不足则会尝试释放部分不可见的Activity
        BinderInternal.addGcWatcher(new Runnable() {
    
    
            @Override public void run() {
    
    
                if (!mSomeActivitiesChanged) {
    
    
                    return;
                }
                Runtime runtime = Runtime.getRuntime();
                long dalvikMax = runtime.maxMemory();
                long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                if (dalvikUsed > ((3*dalvikMax)/4)) {
    
    
                    if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                            + " total=" + (runtime.totalMemory()/1024)
                            + " used=" + (dalvikUsed/1024));
                    mSomeActivitiesChanged = false;
                    try {
    
    
                        ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
                    } catch (RemoteException e) {
    
    
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
        });
    } else {
    
        //系统ActivityThread
        ...
    }

    //处理ConfigChanged相关逻辑(屏幕旋转之类)
    ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> {
    
    
        synchronized (mResourcesManager) {
    
    
            // We need to apply this change to the resources immediately, because upon returning
            // the view hierarchy will be informed about it.
            if (mResourcesManager.applyConfigurationToResources(globalConfig,
                    null /* compat */)) {
    
    
                mConfigurationController.updateLocaleListFromAppContext(
                        mInitialApplication.getApplicationContext());

                // This actually changed the resources! Tell everyone about it.
                final Configuration updatedConfig =
                        mConfigurationController.updatePendingConfiguration(globalConfig);
                if (updatedConfig != null) {
    
    
                    sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                    mPendingConfiguration = updatedConfig;
                }
            }
        }
    };
    ViewRootImpl.addConfigCallback(configChangedCallback);
}

attach方法最重要的一步又是调用了AMSattachApplication方法

AMS.attachApplication

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

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

    // Find the application record that is being attached...  either via
    // the pid if we are running in multiple processes, or just pull the
    // next app record if we are emulating process with anonymous threads.
    ProcessRecord app;
    long startTime = SystemClock.uptimeMillis();
    long bindApplicationTimeMillis;
    if (pid != MY_PID && pid >= 0) {
    
    
        //通过pid查找PidMap中存在的ProcessRecord
        //对应着handleProcessStartedLocked方法中执行的中的mService.addPidLocked方法
        //在进程同步启动模式下,这里应该是必能取到的
        synchronized (mPidsSelfLocked) {
    
    
            app = mPidsSelfLocked.get(pid);
        }
        //如果此ProcessRecord对不上App的ProcessRecord,则将其清理掉
        if (app != null && (app.startUid != callingUid || app.startSeq != startSeq)) {
    
    
            ...
            // If there is already an app occupying that pid that hasn't been cleaned up
            cleanUpApplicationRecordLocked(app, false, false, -1,
                        true /*replacingPid*/);
            removePidLocked(app);
            app = null;
        }
    } else {
    
    
        app = null;
    }

    // It's possible that process called attachApplication before we got a chance to
    // update the internal state.
    //在进程异步启动模式下,有可能尚未执行到handleProcessStartedLocked方法
    //所以从PidMap中无法取到相应的ProcessRecord
    //这时候从ProcessList.mPendingStarts这个待启动列表中获取ProcessRecord
    if (app == null && startSeq > 0) {
    
    
        final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq);
        if (pending != null && pending.startUid == callingUid && pending.startSeq == startSeq
                && mProcessList.handleProcessStartedLocked(pending, pid, pending
                        .isUsingWrapper(),
                        startSeq, true)) {
    
    
            app = pending;
        }
    }

    //没有找到相应的ProcessRecord,杀死进程
    if (app == null) {
    
    
        if (pid > 0 && pid != MY_PID) {
    
    
            killProcessQuiet(pid);
        } else {
    
    
            try {
    
    
                thread.scheduleExit();
            } catch (Exception e) {
    
    
                // Ignore exceptions.
            }
        }
        return false;
    }

    // If this application record is still attached to a previous
    // process, clean it up now.
    //如果ProcessRecord绑定了其他的ApplicationThread,则需要清理这个进程
    if (app.thread != null) {
    
    
        handleAppDiedLocked(app, true, true);
    }

    final String processName = app.processName;
    try {
    
    
        //注册App进程死亡回调
        AppDeathRecipient adr = new AppDeathRecipient(
                app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);
        app.deathRecipient = adr;
    } catch (RemoteException e) {
    
    
        //如果出现异常则重启进程
        app.resetPackageList(mProcessStats);
        mProcessList.startProcessLocked(app,
                new HostingRecord("link fail", processName),
                ZYGOTE_POLICY_FLAG_EMPTY);
        return false;
    }

    //初始化ProcessRecord各参数
    app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
    mOomAdjuster.setAttachingSchedGroupLocked(app);
    app.forcingToImportant = null;
    updateProcessForegroundLocked(app, false, 0, false);
    app.hasShownUi = false;
    app.setDebugging(false);
    app.setCached(false);
    app.killedByAm = false;
    app.killed = false;


    // We carefully use the same state that PackageManager uses for
    // filtering, since we use this flag to decide if we need to install
    // providers when user is unlocked later
    app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);

    //移除之前在handleProcessStartedLocked中设置的attach超时检测
    mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

    //普通App启动肯定在system_server准备完成后,所以此处为true
    boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
    List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
    //设置ContentProvider启动超时检测
    if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
    
    
        Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
        msg.obj = app;
        mHandler.sendMessageDelayed(msg,
                ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS);
    }

    final BackupRecord backupTarget = mBackupTargets.get(app.userId);
    try {
    
    
        //对应着开发者模式里的 Select debug app 和 Wait for debugger
        int testMode = ApplicationThreadConstants.DEBUG_OFF;
        if (mDebugApp != null && mDebugApp.equals(processName)) {
    
    
            testMode = mWaitForDebugger
                ? ApplicationThreadConstants.DEBUG_WAIT
                : ApplicationThreadConstants.DEBUG_ON;
            app.setDebugging(true);
            if (mDebugTransient) {
    
    
                mDebugApp = mOrigDebugApp;
                mWaitForDebugger = mOrigWaitForDebugger;
            }
        }

        boolean enableTrackAllocation = false;
        if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
    
    
            enableTrackAllocation = true;
            mTrackAllocationApp = null;
        }

        // If the app is being launched for restore or full backup, set it up specially
        boolean isRestrictedBackupMode = false;
        ... //备份相关

        final ActiveInstrumentation instr;
        ... //自动化测试相关

        ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
        app.compat = compatibilityInfoForPackage(appInfo);

        ProfilerInfo profilerInfo = null;
        String preBindAgent = null;
        ... //性能分析相关

        // We deprecated Build.SERIAL and it is not accessible to
        // Instant Apps and target APIs higher than O MR1. Since access to the serial
        // is now behind a permission we push down the value.
        //序列号(Android 8.0后不可再通过Build.SERIAL获取序列号)
        final String buildSerial = (!appInfo.isInstantApp()
                && appInfo.targetSdkVersion < Build.VERSION_CODES.P)
                        ? sTheRealBuildSerial : Build.UNKNOWN;

        
        ... //自动化测试相关
        ... //性能分析相关
        
        //debug模式
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
    
    
            thread.attachStartupAgents(app.info.dataDir);
        }

        ... //自动填充功能(账号密码等)
        ... //内容捕获相关(ContentCaptureManager)

        //自动化测试
        final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
        if (mPlatformCompat != null) {
    
    
            mPlatformCompat.resetReporting(app.info);
        }
        final ProviderInfoList providerList = ProviderInfoList.fromList(providers);
        //调用ApplicationThread.bindApplication方法
        if (app.isolatedEntryPoint != null) {
    
    
            // This is an isolated process which should just call an entry point instead of
            // being bound to an application.
            thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
        } 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.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions,
                    app.mDisabledCompatChanges);
        } else {
    
    
            thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
                    null, null, null, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.isPersistent(),
                    new Configuration(app.getWindowProcessController().getConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, autofillOptions, contentCaptureOptions,
                    app.mDisabledCompatChanges);
        }
        ...

        // Make app active after binding application or client may be running requests (e.g
        // starting activities) before it is ready.
        //ProcessRecord保存ApplicationThread代理对象
        app.makeActive(thread, mProcessStats);
        //更新进程使用情况
        mProcessList.updateLruProcessLocked(app, false, null);
        app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
    } catch (Exception e) {
    
    
        //出现错误,杀死进程
        app.resetPackageList(mProcessStats);
        app.unlinkDeathRecipient();
        app.kill("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
        handleAppDiedLocked(app, false, true);
        return false;
    }

    // Remove this record from the list of starting applications.
    //从persistent启动列表中移除此ProcessRecord
    //persistent是manifest中application标签下的一个属性
    //设置了此属性代表此App会跟随系统启动而启动
    mPersistentStartingProcesses.remove(app);

    boolean badApp = false;
    boolean didSomething = false;

    // See if the top visible activity is waiting to run in this process...
    //检查是否有Activity等待启动
    if (normalMode) {
    
    
        try {
    
    
            didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
        } catch (Exception e) {
    
    
            badApp = true;
        }
    }

    // Find any services that should be running in this process...
    //检查是否有Services等待启动
    if (!badApp) {
    
    
        try {
    
    
            didSomething |= mServices.attachApplicationLocked(app, processName);
        } catch (Exception e) {
    
    
            badApp = true;
        }
    }

    // Check if a next-broadcast receiver is in this process...
    //检查是否有广播接收器需要启动
    if (!badApp && isPendingBroadcastProcessLocked(pid)) {
    
    
        try {
    
    
            didSomething |= sendPendingBroadcastsLocked(app);
        } catch (Exception e) {
    
    
            // If the app died trying to launch the receiver we declare it 'bad'
            badApp = true;
        }
    }

    ... //备份相关

    //以上几步发生异常,杀死App进程
    if (badApp) {
    
    
        app.kill("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true);
        handleAppDiedLocked(app, false, true);
        return false;
    }

    if (!didSomething) {
    
    
        //更新进程OOM等级
        updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
    }

    return true;
}

总结一下这个方法主要做了哪些事,首先获取ProcessRecord,然后对其做一些初始化设置,然后调用ApplicaionThread.bindApplication方法,最后分别检查处理ActivityServiceBroadcastReceiver的启动

获取ProcessRecord

我们看一下这个方法是怎么获取ProcessRecord的,我们先回顾一下之前在startProcessLocked方法的最后,会使用同步或异步的方式启动进程,最终两者都会调用startProcesshandleProcessStartedLocked方法

同步启动进程

我们回顾一下之前讲到的ActivityManagerInternal.startProcess方法,可以发现它内部使用了synchronized (ActivityManagerService.this)加锁,而AMS.attachApplication方法同样也使用了AMS实例对象加了锁,所以在同步启动进程的情况下,必然会先执行handleProcessStartedLocked方法,再执行attachApplication方法,根据之前所分析的,handleProcessStartedLocked方法会将ProcessRecord存到PidMap中,然后attachApplication方法又会从PidMap中去取,此时取出的ProcessRecord必然不为null

异步启动进程

在异步启动进程的情况下,是通过Handler将启动进程的工作插入到任务队列中,这个任务的执行是不在锁的作用域范围内的,在这个任务内没有对startProcess方法加锁,只对handleProcessStartedLocked方法加了锁,所以这里会有两种情况:

  • 先执行handleProcessStartedLocked方法,再执行attachApplication方法

    这种情况和同步启动进程的执行顺序是一样的,ProcessRecord获取方式也相同

  • 先执行attachApplication方法,再执行handleProcessStartedLocked方法

    这种情况下,PidMap中取不到相应的ProcessRecord,此时ProcessList.mPendingStarts中还没有将ProcessRecord移除,所以会从mPendingStarts这个启动列表中取出ProcessRecord,然后再调用handleProcessStartedLocked方法,等到attachApplication方法走完,锁释放后,在进入到外部的handleProcessStartedLocked重载方法,这个方法会先判断mPendingStarts中是否还存在对应的ProcessRecord,如果不存在,便会直接返回,保证handleProcessStartedLocked方法只执行一次

ApplicationThread.bindApplication

接着,我们继续看重点方法ApplicationThread.bindApplication

ApplicationThreadActivityThread的一个内部类

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) {
    
    
    if (services != null) {
    
    
        ...
        // 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;
    sendMessage(H.BIND_APPLICATION, data);
}

这个方法很简单,只是将参数包装成一个AppBindData,然后通过Handler发送消息处理,根据消息的类型,最终会调用ActivityThread.handleBindApplication方法

private void handleBindApplication(AppBindData data) {
    
    
    // Register the UI Thread as a sensitive thread to the runtime.
    //将UI线程注册成JIT敏感线程
    VMRuntime.registerSensitiveThread();
    
    ...

    mProfiler = new Profiler();
    ... //性能分析相关

    // send up app name; do this *before* waiting for debugger
    //设置进程名
    Process.setArgV0(data.processName);
    android.ddm.DdmHandleAppName.setAppName(data.processName,
                                            data.appInfo.packageName,
                                            UserHandle.myUserId());
    VMRuntime.setProcessPackageName(data.appInfo.packageName);

    // Pass data directory path to ART. This is used for caching information and
    // should be set before any application code is loaded.
    //设置进程数据目录
    VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);

    //性能分析相关
    if (mProfiler.profileFd != null) {
    
    
        mProfiler.startProfiling();
    }

    // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
    // implementation to use the pool executor.  Normally, we use the
    // serialized executor as the default. This has to happen in the
    // main thread so the main looper is set right.
    //当App的targetSdkVersion小于等于 3.1 (12) 时,AsyncTask使用线程池实现
    if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
    
    
        AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    // Let the util.*Array classes maintain "undefined" for apps targeting Pie or earlier.
    //当App的targetSdkVersion大于等于 10 (29) 时,针对Android SDK提供的容器(SparseArray等)
    //如果index越界,会主动抛ArrayIndexOutOfBoundsException异常
    //(之前数组越界的行为未被定义)
    UtilConfig.setThrowExceptionForUpperArrayOutOfBounds(
            data.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q);

    //当App的targetSdkVersion大于等于 5.0 (21) 时,回收正在使用的Message会抛出异常
    Message.updateCheckRecycle(data.appInfo.targetSdkVersion);

    // Prior to P, internal calls to decode Bitmaps used BitmapFactory,
    // which may scale up to account for density. In P, we switched to
    // ImageDecoder, which skips the upscale to save memory. ImageDecoder
    // needs to still scale up in older apps, in case they rely on the
    // size of the Bitmap without considering its density.
    ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;

    /*
    * Before spawning a new process, reset the time zone to be the system time zone.
    * This needs to be done because the system time zone could have changed after the
    * the spawning of this process. Without doing this this process would have the incorrect
    * system time zone.
    */
    //设置时区
    TimeZone.setDefault(null);

    /*
    * Set the LocaleList. This may change once we create the App Context.
    */
    LocaleList.setDefault(data.config.getLocales());

    //更新Configuration
    synchronized (mResourcesManager) {
    
    
        /*
        * Update the system configuration since its preloaded and might not
        * reflect configuration changes. The configuration object passed
        * in AppBindData can be safely assumed to be up to date
        */
        mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
        mCurDefaultDisplayDpi = data.config.densityDpi;

        // This calls mResourcesManager so keep it within the synchronized block.
        applyCompatConfiguration(mCurDefaultDisplayDpi);
    }

    //获取LoadedApk
    data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);

    //性能分析器代理JVM(JVMTI)
    if (agent != null) {
    
    
        handleAttachAgent(agent, data.info);
    }

    /**
    * Switch this process to density compatibility mode if needed.
    */
    //在manifest,supports-screens标签中设置了android:anyDensity
    //详见:https://developer.android.com/guide/topics/manifest/supports-screens-element#any
    if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
            == 0) {
    
    
        //指示App包含用于适应任何屏幕密度的资源
        mDensityCompatMode = true;
        Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
    }
    //设置默认密度
    updateDefaultDensity();

    /* 设置 12/24 小时时间制 */
    final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);
    Boolean is24Hr = null;
    if (use24HourSetting != null) {
    
    
        is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;
    }
    // null : use locale default for 12/24 hour formatting,
    // false : use 12 hour format,
    // true : use 24 hour format.
    DateFormat.set24HourTimePref(is24Hr);

    //更新view debug属性sDebugViewAttributes
    //设置了这个属性,View将会保存它本身的属性
    //和Layout Inspector相关
    updateDebugViewAttributeState();

    //初始化默认线程策略
    StrictMode.initThreadDefaults(data.appInfo);
    //初始化默认VM策略
    StrictMode.initVmDefaults(data.appInfo);

    //debug模式
    if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
    
    
        // XXX should have option to change the port.
        Debug.changeDebugPort(8100);
        if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
    
    
            Slog.w(TAG, "Application " + data.info.getPackageName()
                    + " is waiting for the debugger on port 8100...");

            IActivityManager mgr = ActivityManager.getService();
            try {
    
    
                mgr.showWaitingForDebugger(mAppThread, true);
            } catch (RemoteException ex) {
    
    
                throw ex.rethrowFromSystemServer();
            }

            Debug.waitForDebugger();

            try {
    
    
                mgr.showWaitingForDebugger(mAppThread, false);
            } catch (RemoteException ex) {
    
    
                throw ex.rethrowFromSystemServer();
            }

        } else {
    
    
            Slog.w(TAG, "Application " + data.info.getPackageName()
                    + " can be debugged on port 8100...");
        }
    }

    // Allow binder tracing, and application-generated systrace messages if we're profileable.
    //性能分析模式
    boolean isAppProfileable = data.appInfo.isProfileableByShell();
    //允许应用程序跟踪
    Trace.setAppTracingAllowed(isAppProfileable);
    if ((isAppProfileable || Build.IS_DEBUGGABLE) && data.enableBinderTracking) {
    
    
        Binder.enableTracing();
    }

    // Initialize heap profiling.
    //初始化堆分析
    if (isAppProfileable || Build.IS_DEBUGGABLE) {
    
    
        nInitZygoteChildHeapProfiling();
    }

    // Allow renderer debugging features if we're debuggable.
    boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
    //开启硬件加速调试功能
    HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
    HardwareRenderer.setPackageName(data.appInfo.packageName);

    /**
    * Initialize the default http proxy in this process for the reasons we set the time zone.
    */
    //设置默认HTTP代理
    final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
    if (b != null) {
    
    
        // In pre-boot mode (doing initial launch to collect password), not
        // all system is up.  This includes the connectivity service, so don't
        // crash if we can't get it.
        final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
        try {
    
    
            Proxy.setHttpProxySystemProperty(service.getProxyForNetwork(null));
        } catch (RemoteException e) {
    
    
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            throw e.rethrowFromSystemServer();
        }
    }

    // Instrumentation info affects the class loader, so load it before
    // setting up the app context.
    //准备自动化测试信息
    final InstrumentationInfo ii;
    if (data.instrumentationName != null) {
    
    
        try {
    
    
            ii = new ApplicationPackageManager(
                    null, getPackageManager(), getPermissionManager())
                    .getInstrumentationInfo(data.instrumentationName, 0);
        } catch (PackageManager.NameNotFoundException e) {
    
    
            throw new RuntimeException(
                    "Unable to find instrumentation info for: " + data.instrumentationName);
        }

        // Warn of potential ABI mismatches.
        ...

        mInstrumentationPackageName = ii.packageName;
        mInstrumentationAppDir = ii.sourceDir;
        mInstrumentationSplitAppDirs = ii.splitSourceDirs;
        mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
        mInstrumentedAppDir = data.info.getAppDir();
        mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
        mInstrumentedLibDir = data.info.getLibDir();
    } else {
    
    
        ii = null;
    }

    //创建Context
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    //更新区域列表
    updateLocaleListFromAppContext(appContext,
            mResourcesManager.getConfiguration().getLocales());

    if (!Process.isIsolated()) {
    
    
        final int oldMask = StrictMode.allowThreadDiskWritesMask();
        try {
    
    
            setupGraphicsSupport(appContext);
        } finally {
    
    
            StrictMode.setThreadPolicyMask(oldMask);
        }
    } else {
    
    
        HardwareRenderer.setIsolatedProcess(true);
    }

    // Install the Network Security Config Provider. This must happen before the application
    // code is loaded to prevent issues with instances of TLS objects being created before
    // the provider is installed.
    //网络安全设置
    NetworkSecurityConfigProvider.install(appContext);

    // Continue loading instrumentation.
    if (ii != null) {
    
     //如果设置了自动化测试,实例化指定的自动化测试类
        ApplicationInfo instrApp;
        try {
    
    
            instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
                    UserHandle.myUserId());
        } catch (RemoteException e) {
    
    
            instrApp = null;
        }
        if (instrApp == null) {
    
    
            instrApp = new ApplicationInfo();
        }
        ii.copyTo(instrApp);
        instrApp.initForUser(UserHandle.myUserId());
        final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                appContext.getClassLoader(), false, true, false);

        // The test context's op package name == the target app's op package name, because
        // the app ops manager checks the op package name against the real calling UID,
        // which is what the target package name is associated with.
        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
                appContext.getOpPackageName());

        try {
    
    
            final ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation)
                cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } catch (Exception e) {
    
    
            throw new RuntimeException(
                "Unable to instantiate instrumentation "
                + data.instrumentationName + ": " + e.toString(), e);
        }

        final ComponentName component = new ComponentName(ii.packageName, ii.name);
        mInstrumentation.init(this, instrContext, appContext, component,
                data.instrumentationWatcher, data.instrumentationUiAutomationConnection);

        if (mProfiler.profileFile != null && !ii.handleProfiling
                && mProfiler.profileFd == null) {
    
    
            mProfiler.handlingProfiling = true;
            final File file = new File(mProfiler.profileFile);
            file.getParentFile().mkdirs();
            Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
        }
    } else {
    
     //直接实例化Instrumentation
        mInstrumentation = new Instrumentation();
        mInstrumentation.basicInit(this);
    }

    //调整应用可用内存上限
    if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
    
    
        dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
    } else {
    
    
        // Small heap, clamp to the current growth limit and let the heap release
        // pages after the growth limit to the non growth limit capacity. b/18387825
        dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
    }

    // Allow disk access during application and provider setup. This could
    // block processing ordered broadcasts, but later processing would
    // probably end up doing the same disk access.
    Application app;
    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
    final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
    try {
    
    
        // If the app is being launched for full backup or restore, bring it up in
        // a restricted environment with the base application class.
        //创建Application
        app = data.info.makeApplication(data.restrictedBackupMode, null);

        // Propagate autofill compat state
        //设置自动填充功能
        app.setAutofillOptions(data.autofillOptions);

        // Propagate Content Capture options
        //设置内容捕获功能
        app.setContentCaptureOptions(data.contentCaptureOptions);

        mInitialApplication = app;

        // don't bring up providers in restricted mode; they may depend on the
        // app's custom Application class
        //在非受限模式下启动ContentProvider
        if (!data.restrictedBackupMode) {
    
    
            if (!ArrayUtils.isEmpty(data.providers)) {
    
    
                installContentProviders(app, data.providers);
            }
        }

        // Do this after providers, since instrumentation tests generally start their
        // test thread at this point, and we don't want that racing.
        //执行onCreate方法(默认Instrumentation实现为空方法)
        try {
    
    
            mInstrumentation.onCreate(data.instrumentationArgs);
        }
        catch (Exception e) {
    
    
            ...
        }
        //执行Application的onCreate方法
        try {
    
    
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
    
    
            ...
        }
    } finally {
    
    
        // If the app targets < O-MR1, or doesn't change the thread policy
        // during startup, clobber the policy to maintain behavior of b/36951662
        if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
                || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
    
    
            StrictMode.setThreadPolicy(savedPolicy);
        }
    }

    // Preload fonts resources
    //预加载字体资源
    FontsContract.setApplicationContextForResources(appContext);
    if (!Process.isIsolated()) {
    
    
        try {
    
    
            final ApplicationInfo info =
                    getPackageManager().getApplicationInfo(
                            data.appInfo.packageName,
                            PackageManager.GET_META_DATA /*flags*/,
                            UserHandle.myUserId());
            if (info.metaData != null) {
    
    
                final int preloadedFontsResource = info.metaData.getInt(
                        ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
                if (preloadedFontsResource != 0) {
    
    
                    data.info.getResources().preloadFonts(preloadedFontsResource);
                }
            }
        } catch (RemoteException e) {
    
    
            throw e.rethrowFromSystemServer();
        }
    }
}

这个方法很重要,我们先过一下几个重点部分,然后再按着主线继续往下研究:

  • DebugProfilerLayout Inspector

    Android应用开发的同学对这三样肯定不陌生,在Android Studio中我们可以对App进行调试,性能分析和布局检查,在这个方法中,我们可以找到与这三样相关的一些代码

  • 获取LoadedApk

    LoadedApkApk文件在内存中的表示,包含了Apk文件中的代码、资源、组件、manifest等信息

  • 创建Context

    这里通过ActivityThreadLoadedApk创建出了一个ContextImpl

  • 实例化Instrumentation

    这里和自动化测试相关,如果设置了自动化测试,实例化指定的自动化测试类,否则实例化默认的Instrumentation

  • 创建Application

    这里根据LoadedApk创建出相应的Application,需要注意,这里创建的Application并不与上面创建出的ContextImpl绑定,而是在创建Application的过程中,以同样的参数重新创建了一个ContextImpl,然后调用attachBaseContext方法绑定它

  • 设置HTTP代理

    App在启动过程中设置HTTP代理,所以我们在开发过程中使用代理抓包等时候需要注意,设置了代理后需要重启App才会生效

  • 启动ContentProvider

    ContentProvider的启动过程以后会新开文章进行分析,这里只需要知道ContentProvider启动的入口在这就行了

  • 执行ApplicationonCreate方法

    当创建完Application,执行attachBaseContext方法后,便会调用onCreate方法

我们拣重点来看,首先是Application的创建过程

LoadedApk.makeApplication

在上文的方法中,调用了data.info.makeApplication方法创建Application,其中data.infoLoadedApk类型

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    
    
    //如果之前创建过了就可以直接返回
    if (mApplication != null) {
    
    
        return mApplication;
    }

    Application app = null;

    //获取Application类名(App可以自定义Application这个应该所有开发都知道吧)
    //对应AndroidManifest中application标签下的android:name属性
    String appClass = mApplicationInfo.className;
    //没有设置自定义Application或强制使用默认Application的情况下,使用默认Application
    if (forceDefaultAppClass || (appClass == null)) {
    
    
        appClass = "android.app.Application";
    }

    try {
    
    
        //初始化ContextClassLoader
        final java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
    
    
            initializeJavaContextClassLoader();
        }

        // Rewrite the R 'constants' for all library apks.
        //Android共享库资源ID动态映射
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
                false, false);
        for (int i = 0, n = packageIdentifiers.size(); i < n; i++) {
    
    
            final int id = packageIdentifiers.keyAt(i);
            if (id == 0x01 || id == 0x7f) {
    
    
                continue;
            }

            rewriteRValues(cl, packageIdentifiers.valueAt(i), id);
        }

        //创建Context
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        // The network security config needs to be aware of multiple
        // applications in the same process to handle discrepancies
        //网络安全设置
        NetworkSecurityConfigProvider.handleNewApplication(appContext);
        //创建Application
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
    
    
        ...
    }
    //加入Application列表中(多个App可以运行在同一个进程中)
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {
    
    
        //调用Application的OnCreate方法
        try {
    
    
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
    
    
            ...
        }
    }

    return app;
}

这个方法首先尝试取成员变量mApplication,如果不为null,说明曾创建过,直接返回就可以了

然后再去获取Application类名,默认为android.app.Application,开发可以通过设置AndroidManifestapplication标签下的android:name属性来选择创建自定义的Application

然后对共享库资源ID做动态映射,关于这部分感兴趣的同学可以去搜索Android Dynamic Reference

接着创建出ContextImpl作为ApplicationBaseContextApplication继承自ContextWrapper,而ContextWrapper又继承自ContextContextWrapper是对Context的包装,里面有一个mBase成员变量,调用任何方法实际上都是调用mBase这个实例的方法,在Application创建后会调用attachBaseContext将刚刚创建出来的ContextImpl赋值给mBase成员变量,所以调用Application中的任何Context方法,实际上最终都是调用ContextImpl的方法

然后创建Application,并将其设置成ContextImplOuterContext

最后将创建好的Application设置给成员变量mApplication,方便以后获取,然后将其再添加到mActivityThread.mAllApplications列表中,返回

ContextImpl.createAppContext

我们简单看一下ContextImpl的创建,对于不同的组件,创建ContextImpl对象的方法不同,比如说ActivityContext是通过createActivityContext方法创建的,我们这里是通过createAppContext创建ApplicationContext

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    
    
    return createAppContext(mainThread, packageInfo, null);
}

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
        String opPackageName) {
    
    
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    ContextImpl context = new ContextImpl(null, mainThread, packageInfo,
        ContextParams.EMPTY, null, null, null, null, null, 0, null, opPackageName);
    context.setResources(packageInfo.getResources());
    //检查android.permission.STATUS_BAR_SERVICE权限
    context.mContextType = isSystemOrSystemUI(context) ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
            : CONTEXT_TYPE_NON_UI;
    return context;
}

简单看看就好,我们的重点不在这里,这个方法实例化了一个ContextImpl对象,然后通过ResourcesManager获得ApkResource,将其设置到ContextImpl

Instrumentation.newApplication

接着我们来看一下Application是怎么创建的

public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    
    
    Application app = getFactory(context.getPackageName())
            .instantiateApplication(cl, className);
    app.attach(context);
    return app;
}

这里,getFactory方法返回的是一个AppComponentFactory对象,这个类是在Android 9之后加入的,它包括一个实例化ClassLoader的方法,一个实例化Application的方法和四个实例化四大组件的方法

我们可以在AndroidManifest中设置application标签的android:appComponentFactory属性,将其设置成我们自定义的AppComponentFactory,从而进行一些监控或别的操作

我们看一下AppComponentFactory的默认实现是怎样的

public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
        @NonNull String className)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    
    
    return (Application) cl.loadClass(className).newInstance();
}

可以看到非常简单,就是通过className反射实例化出一个Application

接着我们回到newApplication方法中,我们对新创建的Application调用了attach方法去绑定ContextImpl

/* package */ final void attach(Context context) {
    
    
    attachBaseContext(context);
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

这里的attachBaseContext调用的是父类ContextWrapper中的方法

protected void attachBaseContext(Context base) {
    
    
    if (mBase != null) {
    
    
        throw new IllegalStateException("Base context already set");
    }
    mBase = base;
}

可以看到,就是将ContextImpl赋值给ContextWrapper中的mBase赋值,这样后面对Application调用Context的方法,实际上就是代理给这个mBase去执行了

到这一步位置,Application就创建完成了,接下来在ActivityThread.handleBindApplication方法中,还有一步重要操作,就是调用ApplicationonCreate方法

这里是借助了Instrumentation.callApplicationOnCreate方法

public void callApplicationOnCreate(Application app) {
    
    
    app.onCreate();
}

就是简简单单直接调用了ApplicationonCreate方法

结束

到这里为止,整个Application的工作都做完了,接下来还剩检查并启动ActivityServiceBroadcastReceiver,这些内容就放到下一篇再讲吧

话说回来有点惭愧,这篇文章距离上一篇间隔了三个月,最近在忙一些别的项目,这篇文章断断续续写了一个多月才憋出来,感谢大家的支持,在这里我厚着脸皮求点赞求收藏,大家的支持就是我创作的动力

猜你喜欢

转载自blog.csdn.net/qq_34231329/article/details/128150028