Activity启动流程(五)Activity所在进程启动过程及ActivityThread初始化
发布日期:2021-07-23 22:22:29 浏览次数:2 分类:技术文章

本文共 24728 字,大约阅读时间需要 82 分钟。

参考:

回到之前的startspecificActivityLocked方法

一:从ActivityStackSupervisor到ActivityManagerService

void startSpecificActivityLocked(ActivityRecord r,            boolean andResume, boolean checkConfig) {        // Is this activity's application already running?        ProcessRecord app = mService.getProcessRecordLocked(r.processName,                r.info.applicationInfo.uid, true);        getLaunchTimeTracker().setLaunchTime(r);        if (app != null && app.thread != null) {            try {                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0                        || !"android".equals(r.info.packageName)) {                    // Don't add this if it is a platform component that is marked                    // to run in multiple processes, because this is actually                    // part of the framework so doesn't make sense to track as a                    // separate apk in the process.                    app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,                            mService.mProcessStats);                }                realStartActivityLocked(r, app, andResume, checkConfig);                return;            } catch (RemoteException e) {                Slog.w(TAG, "Exception when starting activity "                        + r.intent.getComponent().flattenToShortString(), e);            }            // If a dead object exception was thrown -- fall through to            // restart the application.        }        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,                "activity", r.intent.getComponent(), false, false, true);    }

此处判断activit所在进程是否已经启动,如果还没有启动的话,则启动之

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,                "activity", r.intent.getComponent(), false, false, true);
@GuardedBy("this")    final ProcessRecord startProcessLocked(String processName,            ApplicationInfo info, boolean knownToBeDead, int intentFlags,            String hostingType, ComponentName hostingName, boolean allowWhileBooting,            boolean isolated, boolean keepIfLarge) {        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,                null /* crashHandler */);    }
@GuardedBy("this")    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,            boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,            boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {        long startTime = SystemClock.elapsedRealtime();        ProcessRecord app;        if (!isolated) {            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);            checkTime(startTime, "startProcess: after getProcessRecord");            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {                // If we are in the background, then check to see if this process                // is bad.  If so, we will just silently fail.                if (mAppErrors.isBadProcessLocked(info)) {                    if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid                            + "/" + info.processName);                    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.                if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid                        + "/" + info.processName);                mAppErrors.resetProcessCrashTimeLocked(info);                if (mAppErrors.isBadProcessLocked(info)) {                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,                            UserHandle.getUserId(info.uid), info.uid,                            info.processName);                    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.        if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName                + " app=" + app + " knownToBeDead=" + knownToBeDead                + " thread=" + (app != null ? app.thread : null)                + " pid=" + (app != null ? app.pid : -1));        if (app != null && app.pid > 0) {            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 (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);                // If this is a new package in the process, add the package to the list                app.addPackage(info.packageName, info.versionCode, mProcessStats);                checkTime(startTime, "startProcess: done, added package to proc");                return app;            }            // An application record is attached to a previous process,            // clean it up now.            if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);            checkTime(startTime, "startProcess: bad proc running, killing");            killProcessGroup(app.uid, app.pid);            handleAppDiedLocked(app, true, true);            checkTime(startTime, "startProcess: done killing old proc");        }        String hostingNameStr = hostingName != null                ? hostingName.flattenToShortString() : null;        if (app == null) {            checkTime(startTime, "startProcess: creating new process record");            app = newProcessRecordLocked(info, processName, isolated, isolatedUid);            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;            checkTime(startTime, "startProcess: done creating new process record");        } else {            // If this is a new package in the process, add the package to the list            app.addPackage(info.packageName, info.versionCode, mProcessStats);            checkTime(startTime, "startProcess: added package to existing proc");        }        // If the system is not ready yet, then hold off on starting this        // process until it is.        if (!mProcessesReady                && !isAllowedWhileBooting(info)                && !allowWhileBooting) {            if (!mProcessesOnHold.contains(app)) {                mProcessesOnHold.add(app);            }            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,                    "System not ready, putting on hold: " + app);            checkTime(startTime, "startProcess: returning with proc on hold");            return app;        }        checkTime(startTime, "startProcess: stepping in to startProcess");        final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);        checkTime(startTime, "startProcess: done starting proc!");        return success ? app : null;    }

下面是多个startProcessLocked 调用

在最后一个startProcessLocked,有这么一句

final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,                            app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,                            requiredAbi, instructionSet, invokeWith, app.startTime);
private ProcessStartResult startProcess(String hostingType, String entryPoint,            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,            String seInfo, String requiredAbi, String instructionSet, String invokeWith,            long startTime) {        try {            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +                    app.processName);            checkTime(startTime, "startProcess: asking zygote to start proc");            final ProcessStartResult startResult;            if (hostingType.equals("webview_service")) {                startResult = startWebView(entryPoint,                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,                        app.info.dataDir, null,                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});            } else {                startResult = Process.start(entryPoint,                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,                        app.info.dataDir, invokeWith,                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});            }            checkTime(startTime, "startProcess: returned from zygote!");            return startResult;        } finally {            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        }    }

二:从ActivityManagerService到Process

从前面的Process.start方法,最终来到了Process类

public static final ProcessStartResult start(final String processClass,                                  final String niceName,                                  int uid, int gid, int[] gids,                                  int runtimeFlags, int mountExternal,                                  int targetSdkVersion,                                  String seInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  String invokeWith,                                  String[] zygoteArgs) {        return zygoteProcess.start(processClass, niceName, uid, gid, gids,                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);    }

三Process到ZygoteProcess

继续点进去start方法内

/**     * Start a new process.     *     * 

If processes are enabled, a new process is created and the * static main() function of a processClass is executed there. * The process will continue running after this function returns. * *

If processes are not enabled, a new thread in the caller's * process is created and main() of processclass called there. * *

The niceName parameter, if not an empty string, is a custom name to * give to the process instead of using processClass. This allows you to * make easily identifyable processes even if you are using the same base * processClass to start them. * * When invokeWith is not null, the process will be started as a fresh app * and not a zygote fork. Note that this is only allowed for uid 0 or when * runtimeFlags contains DEBUG_ENABLE_DEBUGGER. * * @param processClass The class to use as the process's main entry * point. * @param niceName A more readable name to use for the process. * @param uid The user-id under which the process will run. * @param gid The group-id under which the process will run. * @param gids Additional group-ids associated with the process. * @param runtimeFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param seInfo null-ok SELinux information for the new process. * @param abi non-null the ABI this app should be started with. * @param instructionSet null-ok the instruction set to use. * @param appDataDir null-ok the data directory of the app. * @param invokeWith null-ok the command to invoke with. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure */ public final Process.ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); throw new RuntimeException( "Starting VM process through Zygote failed", ex); } }

startViaZygote方法

/**     * Starts a new process via the zygote mechanism.     *     * @param processClass Class name whose static main() to run     * @param niceName 'nice' process name to appear in ps     * @param uid a POSIX uid that the new process should setuid() to     * @param gid a POSIX gid that the new process shuold setgid() to     * @param gids null-ok; a list of supplementary group IDs that the     * new process should setgroup() to.     * @param runtimeFlags Additional flags for the runtime.     * @param targetSdkVersion The target SDK version for the app.     * @param seInfo null-ok SELinux information for the new process.     * @param abi the ABI the process should use.     * @param instructionSet null-ok the instruction set to use.     * @param appDataDir null-ok the data directory of the app.     * @param startChildZygote Start a sub-zygote. This creates a new zygote process     * that has its state cloned from this zygote process.     * @param extraArgs Additional arguments to supply to the zygote process.     * @return An object that describes the result of the attempt to start the process.     * @throws ZygoteStartFailedEx if process start failed for any reason     */    private Process.ProcessStartResult startViaZygote(final String processClass,                                                      final String niceName,                                                      final int uid, final int gid,                                                      final int[] gids,                                                      int runtimeFlags, int mountExternal,                                                      int targetSdkVersion,                                                      String seInfo,                                                      String abi,                                                      String instructionSet,                                                      String appDataDir,                                                      String invokeWith,                                                      boolean startChildZygote,                                                      String[] extraArgs)                                                      throws ZygoteStartFailedEx {        ArrayList
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_READ) { argsForZygote.add("--mount-external-read"); } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) { argsForZygote.add("--mount-external-write"); } argsForZygote.add("--target-sdk-version=" + targetSdkVersion); // --setgroups is a comma-separated list if (gids != null && gids.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--setgroups="); 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"); } argsForZygote.add(processClass); if (extraArgs != null) { for (String arg : extraArgs) { argsForZygote.add(arg); } } synchronized(mLock) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } }

openZygoteSocketIfNeeded

/**     * Tries to open socket to Zygote process if not already open. If     * already open, does nothing.  May block and retry.  Requires that mLock be held.     */    @GuardedBy("mLock")    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {        Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {            try {                primaryZygoteState = ZygoteState.connect(mSocket);            } catch (IOException ioe) {                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);            }            maybeSetApiBlacklistExemptions(primaryZygoteState, false);            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);        }        if (primaryZygoteState.matches(abi)) {            return primaryZygoteState;        }        // The primary zygote didn't match. Try the secondary.        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {            try {                secondaryZygoteState = ZygoteState.connect(mSecondarySocket);            } catch (IOException ioe) {                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);            }            maybeSetApiBlacklistExemptions(secondaryZygoteState, false);            maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);        }        if (secondaryZygoteState.matches(abi)) {            return secondaryZygoteState;        }        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);    }
/**     * Sends an argument list to the zygote process, which starts a new child     * and returns the child's pid. Please note: the present implementation     * replaces newlines in the argument list with spaces.     *     * @throws ZygoteStartFailedEx if process start failed for any reason     */    @GuardedBy("mLock")    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(            ZygoteState zygoteState, ArrayList
args) throws ZygoteStartFailedEx { try { // Throw early if any of the arguments are malformed. This means we can // avoid writing a partial response to the zygote. int sz = args.size(); for (int i = 0; i < sz; i++) { if (args.get(i).indexOf('\n') >= 0) { throw new ZygoteStartFailedEx("embedded newlines not allowed"); } } /** * See com.android.internal.os.SystemZygoteInit.readArgumentList() * 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. */ final BufferedWriter writer = zygoteState.writer; final DataInputStream inputStream = zygoteState.inputStream; writer.write(Integer.toString(args.size())); writer.newLine(); for (int i = 0; i < sz; i++) { String arg = args.get(i); writer.write(arg); writer.newLine(); } writer.flush(); // Should there be a timeout on this? Process.ProcessStartResult result = new Process.ProcessStartResult(); // Always read the entire result from the input stream to avoid leaving // bytes in the stream for future process starts to accidentally stumble // upon. result.pid = inputStream.readInt(); result.usingWrapper = inputStream.readBoolean(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }

最终是fork出来了一个进程。。

四:ActivityThread

最后是通过反射的方式调用了ActivityThread的main方法

public static void main(String[] args) {        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");        // 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();        // Set the reporter for event logging in libcore        EventLogger.setReporter(new EventLoggingReporter());        // Make sure TrustedCertificateStore looks in the right place for CA certificates        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());        TrustedCertificateStore.setDefaultUserDirectory(configDir);        Process.setArgV0("
"); 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" 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())); } } } ActivityThread thread = new ActivityThread(); 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); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }

 

转载地址:https://blog.csdn.net/perfectnihil/article/details/91044178 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Activity启动流程(六)再次回到ActivityManagerService
下一篇:Activity启动流程(四)从远端回到本地进程到activity的onPause(mClient.scheduleTransaction(this);)

发表评论

最新留言

很好
[***.229.124.182]2024年04月16日 02时32分56秒