继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android App应用启动流程(二)

呼唤远方
关注TA
已关注
手记 333
粉丝 82
获赞 367

还回到上一篇结束的地方:

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

    r.getStack().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.versionCode,
                        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);
}

进程存在情况下启动app

看realStartActivityLocked方法

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {    ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global and
        // override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, !andResume,
        mService.isNextTransitionForward(), profilerInfo);    ...

    return true;
}

这个地方调用了一个app.thread.scheduleLaunchActivity,这里其实调用的是ActivityThread的子类ApplicationThread里面的scheduleLaunchActivity方法

// we use token to identify this activity without having to send the// activity itself back to the activity manager. (matters more with ipc)@Overridepublic final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
        CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,        int procState, Bundle state, PersistableBundle persistentState,
        List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

    updateProcessState(procState, false);

    ActivityClientRecord r = new ActivityClientRecord();

    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.referrer = referrer;
    r.voiceInteractor = voiceInteractor;
    r.activityInfo = info;
    r.compatInfo = compatInfo;
    r.state = state;
    r.persistentState = persistentState;

    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;

    r.startsNotResumed = notResumed;
    r.isForward = isForward;

    r.profilerInfo = profilerInfo;

    r.overrideConfig = overrideConfig;
    updatePendingConfiguration(curConfig);

    sendMessage(H.LAUNCH_ACTIVITY, r);
}//下面就到了你最熟悉的Handler通信去启动Activity//--->private void sendMessage(int what, Object obj) {
    sendMessage(what, obj, 0, 0, false);
}//--->private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {    if (DEBUG_MESSAGES) Slog.v(
        TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
        + ": " + arg1 + " / " + obj);
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;    if (async) {
        msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
}

...public void handleMessage(Message msg) {    if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));    switch (msg.what) {        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
...
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {    ...

    // Initialize before creating the activity
    WindowManagerGlobal.initialize();
    //执行启动Activity
    Activity a = performLaunchActivity(r, customIntent);    ...}

这个方法里面你会看到各种关于一个Activity的重要的方法,例如:activity.attach跟当前ActivityThread绑定,activity.setTheme设置主题等等,到这里基本上到Activity的范畴了,下面我们去看另一种情况,新建进程的情况。

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

    ...
    Activity activity = null;

    try {
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
        if (localLOGV) Slog.v(
                TAG, r + ": app=" + app
                + ", appName=" + app.getPackageName()
                + ", pkg=" + r.packageInfo.getPackageName()
                + ", comp=" + r.intent.getComponent().toShortString()
                + ", dir=" + r.packageInfo.getAppDir());

        if (activity != null) {
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (r.overrideConfig != null) {
                config.updateFrom(r.overrideConfig);
            }
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);
            Window window = null;
            if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                window = r.mPendingRemoveWindow;
                r.mPendingRemoveWindow = null;
                r.mPendingRemoveWindowManager = null;
            }
            appContext.setOuterContext(activity);
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.referrer, r.voiceInteractor, window, r.configCallback);

            if (customIntent != null) {
                activity.mIntent = customIntent;
            }
            r.lastNonConfigurationInstances = null;
            checkAndBlockForNetworkAccess();
            activity.mStartedActivity = false;
            int theme = r.activityInfo.getThemeResource();
            if (theme != 0) {
                activity.setTheme(theme);
            }

            activity.mCalled = false;
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            if (!activity.mCalled) {
                throw new SuperNotCalledException(                    "Activity " + r.intent.getComponent().toShortString() +                    " did not call through to super.onCreate()");
            }
            r.activity = activity;
            r.stopped = true;
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }
            if (!r.activity.mFinished) {
                if (r.isPersistable()) {
                    if (r.state != null || r.persistentState != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                r.persistentState);
                    }
                } else if (r.state != null) {
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state,
                            r.persistentState);
                } else {
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(                        "Activity " + r.intent.getComponent().toShortString() +                        " did not call through to super.onPostCreate()");
                }
            }
        }
        r.paused = true;

        mActivities.put(r.token, r);

    } catch (SuperNotCalledException e) {
        throw e;

    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(                "Unable to start activity " + component
                + ": " + e.toString(), e);
        }
    }

    return activity;}

新建进程启动app

0xa

看mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
           “activity”, r.intent.getComponent(), false, false, true);
这里又要回到ActivityManagerService这个类中去,这里有个地方需要注意,在startProcessLocked方法里面又调用了一个startProcessLocked方法,参数不一样,加入一个需要注意的参数叫做entryPoint,并且参数为null

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

    checkTime(startTime, "startProcess: stepping in to startProcess");
    startProcessLocked(
            app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    checkTime(startTime, "startProcess: done starting proc!");    return (app.pid != 0) ? app : null;
}

0xb

又调用了 void startProcessLocked(ProcessRecord app, String hostingType,
           String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs)

//startProcessLocked方法...//这里由上面0xa处传递的空的entryPoint,到这里赋值给"android.app.ActivityThread"
 //后面要用到这个,通过反射来调用main方法
boolean isActivityProcess = (entryPoint == null);if (entryPoint == null) entryPoint = "android.app.ActivityThread";...startResult = Process.start(entryPoint,
    app.processName, uid, uid, gids, debugFlags, mountExternal,
    app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
    app.info.dataDir, invokeWith, entryPointArgs);...

Process.java

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

每一个app进程都是由Zygote进程fork自身得来的,包括SystemServer进程都是由Zygote fork出来的,下面去看看zygoteProcess的代码,网上分析应用启动流程的结论是app入口是在AcitivtyThread的main方法。那么这个main方法在哪个地方调用,离这里还有多远呢?

ZygoteProcess.java

public final Process.ProcessStartResult start(final String processClass,                                              final String niceName,                                              int uid, int gid, int[] gids,                                              int debugFlags, int mountExternal,                                              int targetSdkVersion,
                                              String seInfo,
                                              String abi,
                                              String instructionSet,
                                              String appDataDir,
                                              String invokeWith,
                                              String[] zygoteArgs) {    try {        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,                "Starting VM process through Zygote failed");        throw new RuntimeException(                "Starting VM process through Zygote failed", ex);
    }
}/**
 * Starts a new process via the zygote mechanism.
 *  通过zygote机制开启一个进程
 */private Process.ProcessStartResult startViaZygote(final String processClass,.....)throws ZygoteStartFailedEx {
    ...    synchronized(mLock) {        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}/**
 *  把参数列表传递给zygote进程,zygote进程返回新进程的pid
 * @throws ZygoteStartFailedEx if process start failed for any reason
 */@GuardedBy("mLock")private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> args)        throws ZygoteStartFailedEx {    try {
        ...        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();        //新建进程启动结果类,把新建的结果例如进程pid等赋值给这个结果类,用来返回
        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);
    }
}

现在拿到了ProcessStartResult,其实这个时候新进程已经被启动了,那么在哪个地方启动的呢?看一下这个方法zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);需要传入一个ZygoteState,这个是ZygoteProcess的一个内部类,包含着与zygote进程的连接状态,一共有两个

/**
 * The state of the connection to the primary zygote.
 */private ZygoteState primaryZygoteState;/**
 * The state of the connection to the secondary zygote.
 */private ZygoteState secondaryZygoteState;

看一下openZygoteSocketIfNeeded方法,尝试与Zygote进程建立socket连接,socket也是一种通信方式,primaryZygoteState为空或者关闭之后,尝试去建立连接,这个ZygoteState匹配直接返回使用,不匹配继续去使用secondaryZygoteState连接,两个都不匹配或者为空,没连接上等等抛异常。总之这里需要一个可以使用的socket连接。拿到这个ZygoteState连接状态后就可以去写操作,而与之建立连接的Zygote进程会读取到这个信息,那么在哪个里读取的呢?继续往下看。

/**
 * 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);
        }
    }    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);
        }
    }    if (secondaryZygoteState.matches(abi)) {        return secondaryZygoteState;
    }    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

zygote在启动之后开启了socket 监听功能,监听需要创建 Process 的请求,关于zygote进程什么时候开启这个socket的需要去看zygote的启动流程。这里我们关心的主要有三个类:
ZygoteInit.java
ZygoteServer.java
ZygoteConnection.java

摘自:https://blog.csdn.net/luoshengyang/article/details/6768304
 我们知道,Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中

Zygote进程启动的时候会调用ZygoteInit的main方法,关于Zygote启动流程我不想多说,感兴趣可以去看一下他的源码,这里我们看到zygoteServer.runSelectLoop(abiList);注释说的是接受socket连接

ZygoteInit.java

public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();    // Zygote goes into its own process group.
    try {
        Os.setpgid(0, 0);
    } catch (ErrnoException ex) {        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }    try {
        ...
        Log.i(TAG, "Accepting command socket connections");
        zygoteServer.runSelectLoop(abiList);
        zygoteServer.closeServerSocket();
    } catch (Zygote.MethodAndArgsCaller caller) {
        caller.run();
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        zygoteServer.closeServerSocket();        throw ex;
    }
}

ZygoteServer.java

/**
 * Runs the zygote process's select loop. Accepts new connections as
 * they happen, and reads commands from connections one spawn-request's
 * worth at a time.
 *
 * @throws Zygote.MethodAndArgsCaller in a child process when a main()
 * should be executed.
 */void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }        try {
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {            throw new RuntimeException("poll failed", ex);
        }        for (int i = pollFds.length - 1; i >= 0; --i) {            if ((pollFds[i].revents & POLLIN) == 0) {                continue;
            }            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {                boolean done = peers.get(i).runOnce(this);                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

下面看看ZygoteConnection类,从socket读取信息,成功的话表示一个子进程被成功fork,失败抛异常。当有新进程连接请求时,唤醒Zygote进程,执行ZygoteConnection的runOnce这个方法。

/**
 * Reads one start command from the command socket. If successful,
 * a child is forked and a {@link Zygote.MethodAndArgsCaller}
 * exception is thrown in that child while in the parent process,
 * the method returns normally. On failure, the child is not
 * spawned and messages are printed to the log and stderr. Returns
 * a boolean status value indicating whether an end-of-file on the command
 * socket has been encountered.
 * 
 * @return false if command socket should continue to be read from, or
 * true if an end-of-file has been encountered.
 * @throws Zygote.MethodAndArgsCaller trampoline to invoke main()
 * method in child process
 */
boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {

    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;    try {        //这里的readArgumentList()就是去获取刚才ZygoteProgress类的BufferedWriter writer = zygoteState.writer        //写入的writer.write(arg);这些参数        //
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        Log.w(TAG, "IOException on command socket " + ex.getMessage());
        closeSocket();        return true;
    }

    ...

    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;    try {
        ...        //获取到被fork出来的新进程的pid
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (ErrnoException ex) {
        logAndPrintError(newStderr, "Exception creating pipe", ex);
    } catch (IllegalArgumentException ex) {
        logAndPrintError(newStderr, "Invalid zygote arguments", ex);
    } catch (ZygoteSecurityException ex) {
        logAndPrintError(newStderr,                "Zygote security policy prevents request: ", ex);
    }    try {        if (pid == 0) {            // 返回的pid为0表示在孵化出来的子进程里面,也就是应用进程里面
            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);            // should never get here, the child is expected to either            // throw Zygote.MethodAndArgsCaller or exec().            return true;
        } else {            // in parent...pid of < 0 means failure
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

继续追踪Zygote.forkAndSpecialize发现最后到了Zygote类的nativeForkAndSpecialize方法,到这调用的就是底层c/c++代码了。这里有一点需要注意:Android也属于Linux系统,所以Android的Zygote进程的fork过程也是Linux系统中的进程fork过程,由于对Linux的进程fork不是太了解,我在这里只能直接说结论,那就是执行完pid = Zygote.forkAndSpecialize这个方法,这里其实就变成了两个进程,也就是一次执行两次返回,两次返回是在两个进程中进行的。一个是在子进程也就是应用进程,一个是原来的Zygote的进程,也就是这里pid = Zygote.forkAndSpecialize往下执行,会执行两次,一次是子进程中,这时候pid=0,表示子进程创建成功;一次是Zygote进程中,pid不为0,不为0的情况还有可能是在异常的情况,但是种异常的情况就先不考虑了。

关于cpp文件的分析,参考这里https://www.2cto.com/kf/201607/527963.html
nativeForkAndSpecialize()方法最终调用的是com_android_internal_os_Zygote.cpp中的 com_android_internal_os_Zygote_nativeForkAndSpecialize()方法,链接在这里https://android.googlesource.com/platform/frameworks/base/+/android-cts-8.0_r8/core/jni/com_android_internal_os_Zygote.cpp

native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,          int[] fdsToIgnore, String instructionSet, String appDataDir);

com_android_internal_os_Zygote.cpp文件

static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring se_name,
        jintArray fdsToClose,
        jintArray fdsToIgnore,
        jstring instructionSet, jstring appDataDir) {    ...
    return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
            rlimits, capabilities, capabilities, mount_external, se_info,
            se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
}

关于进程的fork过程都是jni的cpp文件,这里不再继续深入,感兴趣可以去看看上面的那个链接分析的更多一些。下面继续考虑上面两个进程的返回,都是怎么走的,先考虑在Zygote进程也就是pid不为0情况,可以看到handleParentProc方法就是通过socket把pid返回回去。

//处理Zygote进程后续工作
private boolean handleParentProc(int pid,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {    ...

    try {
        mSocketOutStream.writeInt(pid);
        mSocketOutStream.writeBoolean(usingWrapper);
    } catch (IOException ex) {
        Log.e(TAG, "Error writing to command socket", ex);        return true;
    }    return false;
}

然后看看子进程中做了哪些处理,进入handleChildProc方法,parsedArgs.invokeWith != null执行WrapperInit.execApplication,这个我们要去看看invokeWith传过来的是什么

//处理子进程的设置初始化工作private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)        throws Zygote.MethodAndArgsCaller {    /**
     * By the time we get here, the native code has closed the two actual Zygote
     * socket connections, and substituted /dev/null in their place.  The LocalSocket
     * objects still need to be closed properly.
     */

    closeSocket();    if (descriptors != null) {        try {
            Os.dup2(descriptors[0], STDIN_FILENO);
            Os.dup2(descriptors[1], STDOUT_FILENO);
            Os.dup2(descriptors[2], STDERR_FILENO);            for (FileDescriptor fd: descriptors) {
                IoUtils.closeQuietly(fd);
            }
            newStderr = System.err;
        } catch (ErrnoException ex) {
            Log.e(TAG, "Error reopening stdio", ex);
        }
    }    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }    // End of the postFork event.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd, parsedArgs.remainingArgs);
    } else {
        ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs, null /* classLoader */);
    }
}

在ActivityManagerService的startProcessLocked方法里面,这个invokeWith默认为null,这个应该是Debuggable apps时才会用到的,所以直接考虑ZygoteInit.zygoteInit的情况

String invokeWith = null;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);
    }
}

ZygoteInit.java文件

public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

ZygoteInit.nativeZygoteInit();里面有时c++代码,就是执行进程初始化工作,先不去看了,看看RuntimeInit.applicationInit方法

protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws Zygote.MethodAndArgsCaller {    ...
    // Remaining arguments are passed to the start class's static main
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
/**
 * Invokes a static "main(argv[]) method on class "className".
 * Converts various failing exceptions into RuntimeExceptions, with
 * 根据className去调用它的main方法,那么这个main方法是哪个呢?
 * 其实就是ActivityThead的main方法,我们可以去看看上面
 * 0xa和0xb处的描述,是不传递了这个参数过来
 * @param className Fully-qualified class name
 * @param argv Argument vector for main()
 * @param classLoader the classLoader to load {@className} with
 */private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)        throws Zygote.MethodAndArgsCaller {
    Class<?> cl;    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {        throw new RuntimeException(                "Missing class when invoking static main " + className,
                ex);
    }

    Method m;    try {
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {        throw new RuntimeException(                "Missing static main on " + className, ex);
    } catch (SecurityException ex) {        throw new RuntimeException(                "Problem getting static main on " + className, ex);
    }    int modifiers = m.getModifiers();    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {        throw new RuntimeException(                "Main method is not public and static on " + className);
    }    /*
     * This throw gets caught in ZygoteInit.main(), which responds
     * by invoking the exception's run() method. This arrangement
     * clears up all the stack frames that were required in setting
     * up the process.
     */
    throw new Zygote.MethodAndArgsCaller(m, argv);    //使用MethodAndArgsCaller对象抛异常,然后在这个异常里面执行是个main方法}
public static class MethodAndArgsCaller extends Exception
        implements Runnable {
    /** method to call */
    private final Method mMethod;    /** argument array */
    private final String[] mArgs;    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }    public void run() {        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {            throw new RuntimeException(ex);
        } catch (InvocationTargetException ex) {
            Throwable cause = ex.getCause();            if (cause instanceof RuntimeException) {                throw (RuntimeException) cause;
            } else if (cause instanceof Error) {                throw (Error) cause;
            }            throw new RuntimeException(ex);
        }
    }
}

到此位置我们早到了ActivityThread main方法启动的地方,这个main方法中做了很多app的初始化工作,其中就包括著名的Looper.prepareMainLooper();以及Looper.loop(); 然后后面的事就交给Activity范畴的handler处理了。
ActivityThread.java

public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    SamplingProfilerIntegration.start();    // 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("<pre-initialized>");

    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);    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/luoshengyang/article/details/6747696
https://www.2cto.com/kf/201607/527963.html
https://blog.csdn.net/tfygg/article/details/53563638
http://www.cloudchou.com/android/post-805.html
https://juejin.im/entry/576e42f9128fe1005a27fc11
http://mouxuejie.com/blog/2016-03-12/activity-launch-analysis/

原文出处

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP