Launcher啟動應(yīng)用程序流程分析(基于25的Android源碼)

step 1:

當(dāng)我們在LaucherActivity點擊了界面上的圖標(biāo)疾捍,是會執(zhí)行 Activity.startActivity方法來啟動一個新的應(yīng)用程序柑司,那么它執(zhí)行了什么流程了踊餐?
答:慎用singleTask的原因:看下這段方法上面的注釋

Note that this method should only be used with Intent protocols that are defined to return a result.  In other protocols (such as {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may not get the result when you expect.  For example, if the activity you are launching uses the singleTask launch mode, it will not run in your task and thus you will immediately receive a cancel result.

底層是調(diào)用startActivityForResult(),我們來看看其源碼:

if (mParent == null) {
    options = transferSpringboardActivityOptions(options);
    Instrumentation.ActivityResult ar =
        mInstrumentation.execStartActivity(
            this, mMainThread(描述應(yīng)用程序進程).getApplicationThread(), mToken(Binder代理對象藕漱,指向遠(yuǎn)程進程的Binder的本地對象), this,
            intent, requestCode, options);
    if (ar != null) {
        mMainThread.sendActivityResult(
            mToken, mEmbeddedID, requestCode, ar.getResultCode(),
            ar.getResultData());
    }
    if (requestCode >= 0) {
        mStartedActivity = true;
    }

    cancelInputsAndStartExitTransition(options);
    // TODO Consider clearing/flushing other event sources and events for child windows.
} else {
    if (options != null) {
        mParent.startActivityFromChild(this, intent, requestCode, options);
    } else {
        // Note we want to go through this method for compatibility with
        // existing applications that may have overridden it.
        mParent.startActivityFromChild(this, intent, requestCode);
    }
}

我們看到一個parent的判斷欲侮,那么這個mParent是用來干嘛的呢?mParent是Return the parent activity if this view is an embedded child Instead肋联;這里我們指Activity是一個獨立非嵌套的威蕉,所以mParent都是為null的。

step 2:

上面的方法會調(diào)用Instrumentation實例對象的execStartActivity(Context who(被啟動的activity的來源context), IBinder contextThread(被啟動的activity的context的主線程), IBinder token(定義哪個sytem啟動activity), Activity target(執(zhí)行啟動activity操作的activity橄仍,執(zhí)行者),Intent intent, int requestCode, Bundle options)方法韧涨,細(xì)讀源碼:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
}

step 3:

launcher應(yīng)用運行的進程和SystemServer進程是兩個不同的進程,調(diào)用ActivityManagerNative.getDefault().startActivity()方法侮繁,實際是ActivityManagerProxy.startActivity方法:

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
        String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    data.writeString(callingPackage);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo);
    data.writeString(resultWho);
    data.writeInt(requestCode);
    data.writeInt(startFlags);
    if (profilerInfo != null) {
        data.writeInt(1);
        profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        data.writeInt(0);
    }
    if (options != null) {
        data.writeInt(1);
        options.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);//發(fā)送一個START_ACTIVITY_TRANSACTION的指令虑粥,mRemote指向就是ActivityManagerService
    reply.readException();
    int result = reply.readInt();
    reply.recycle();
    data.recycle();
    return result;
}

step 4:

前面的3步都是在launcher進程中執(zhí)行的,當(dāng)Lauchner進程發(fā)出START_ACTIVITY_TRANSACTION的Binder通信請求時宪哩,系統(tǒng)進程(SystemServer)接收到這個這個請求的時候娩贷,會執(zhí)行 ActivityManagerService的onTransact(int code, Parcel data, Parcel reply, int flags)方法:

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    if (code == SYSPROPS_TRANSACTION) {
      ......
    }
    try {
        return super.onTransact(code, data, reply, flags);
    } catch (RuntimeException e) {
        if (!(e instanceof SecurityException)) {
            Slog.wtf(TAG, "Activity Manager Crash", e);
        }
        throw e;
    }
}

因為code是START_ACTIVITY_TRANSACTION,所以直接執(zhí)行父類ActivityManagerNative的onTransact方法斋射,

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {
    case START_ACTIVITY_TRANSACTION:
    {
        data.enforceInterface(IActivityManager.descriptor);
        IBinder b = data.readStrongBinder();
        IApplicationThread app = ApplicationThreadNative.asInterface(b);
        String callingPackage = data.readString();
        Intent intent = Intent.CREATOR.createFromParcel(data);
        String resolvedType = data.readString();
        IBinder resultTo = data.readStrongBinder();
        String resultWho = data.readString();
        int requestCode = data.readInt();
        int startFlags = data.readInt();
        ProfilerInfo profilerInfo = data.readInt() != 0
                ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
        Bundle options = data.readInt() != 0
                ? Bundle.CREATOR.createFromParcel(data) : null;
        int result = startActivity(app, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
        reply.writeNoException();
        reply.writeInt(result);
        return true;
    }
   ....
}

我們可以看到育勺,在這里會調(diào)用ActivityMangerService的startActivity方法

step 5:

ActivityManagerService.startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId())

step 6:

ActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,profilerInfo, null, null, bOptions, false, userId, null, null)

step 7:

ActivityStarter.startActivityLocked()

step 8:

ActivityStarter.startActivityUnchecked()

step 9:

ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

step 10:

ActivityStack.resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options)

step 11:

ActivityStack.resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)

step 12:

ActivityStackSupervisor.startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig)方法:

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.task.stack.setLaunchTime(r);

    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                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);
        }
    }

    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

前面有個判斷,如果啟動的activity的進程已經(jīng)起來了罗岖,那么接下來涧至,直接調(diào)用realStartActivityLocked方法,進行activity的啟動就可以了桑包,因為現(xiàn)在是launcher上第一次點擊圖標(biāo)南蓬,所以進程是沒有開啟的,接下來我們看看ActivityManagerService.startProcessLocked方法。

step 13:

因為在上面的時候赘方,實際調(diào)用了

startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */)

這個時候傳入的entryPoint是null的

ActivityManagerService.startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs){
            ......
            boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread";
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
            checkTime(startTime, "startProcess: asking zygote to start proc");
            Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
            ......
}

所以在調(diào)用上面方法的時候這里因為entryPoint傳過來的是null的烧颖,所以我們的entryPoint是為android.app.ActivityThread的值,這個時候我們通過Process.start()傳入的第一個參數(shù)是android.app.ActivityThread窄陡,這個參數(shù)在我們進程啟動完成之后炕淮,來決定后續(xù)代碼的執(zhí)行 。

step 14:

我們知道Android中的進程是通過Zygote進行孵化的跳夭,而ActivityManagerService是運行在System進程涂圆,Zygote是運行在Zygote進程中的。Process.start方法的實現(xiàn)是在zygoteSendArgsAndGetResult函數(shù)最終實現(xiàn)的,是向socket服務(wù)端寫數(shù)據(jù),把創(chuàng)建進程的請求通過socket通訊方式來讓zygote的管理進程創(chuàng)建新進程币叹。在向zygote進程發(fā)送的通信請求時润歉,需要組裝數(shù)據(jù),具體實在是在

private static ProcessStartResult startViaZygote(final String processClass,
                                  final String niceName,
                                  final int uid, final int gid,
                                  final int[] gids,
                                  int debugFlags, int mountExternal,
                                  int targetSdkVersion,
                                  String seInfo,
                                  String abi,
                                  String instructionSet,
                                  String appDataDir,
                                  String[] extraArgs)
                                  throws ZygoteStartFailedEx {
        synchronized(Process.class) {
            ArrayList<String> argsForZygote = new ArrayList<String>();

            // --runtime-args, --setuid=, --setgid=,
            // and --setgroups= must go first
            argsForZygote.add("--runtime-args");
            argsForZygote.add("--setuid=" + uid);
            argsForZygote.add("--setgid=" + gid);
            ......//1

            argsForZygote.add(processClass);
            ......//2
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }

省略號的1和2是執(zhí)行數(shù)據(jù)的封裝颈抚,從中我們也可以看到processClass也會添加到對應(yīng)的列表當(dāng)中踩衩。

private static ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList<String> 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");
            }
        }
        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?
        ProcessStartResult result = new 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);
    }
}

通過客戶端發(fā)送一個進程創(chuàng)建的請求給zygote。

step 15:

我們知道看到Android系統(tǒng)在啟動的時候贩汉,會執(zhí)行zygoteInit的main方法驱富,在執(zhí)行的時候,會調(diào)用runSelectLoop方法匹舞,

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

    fds.add(sServerSocket.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();
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

當(dāng)前方法會開啟一個死循環(huán)萌朱,當(dāng)客戶端發(fā)送數(shù)據(jù)的時候,會進行讀取策菜,并執(zhí)行ZygoteConnection.runOnce()方法晶疼。

step 16:

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    ......
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, 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) {
            // in child
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

            // should never get here, the child is expected to either
            // throw ZygoteInit.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()方法,創(chuàng)建一個新的進程又憨,具體的實現(xiàn)在cpp的Dalvik_dalvik_system_Zygote_forkAndSpecialize方法當(dāng)中翠霍,在創(chuàng)建完新的進程,因為Android是基于linux蠢莺,新進程是從zygote進程中fork來的寒匙,所以在這里pid是為0的會調(diào)用。相信這里還有人疑問躏将,接下來的是在zygote進程還是新的子進程執(zhí)行的锄弱?
答:linux中調(diào)用fork創(chuàng)建的子進程,將共享父進程的代碼空間祸憋,復(fù)制父進程數(shù)據(jù)空間会宪,此時子進程會獲得父進程的所有變量的一份拷貝。接下來的代碼會有兩個進程執(zhí)行蚯窥,而子進程的pid==0掸鹅,所以handleChildProc是在子進程中執(zhí)行的塞帐,同時else的語句也會執(zhí)行,不過這里分析Android應(yīng)用的啟動巍沙,所以就暫不分析了葵姥。(同樣當(dāng)你在Application中發(fā)現(xiàn)onCreate的方法有多次執(zhí)行,其實這也應(yīng)該是啟動了多個進程導(dǎo)致的) ZygoteConnection.handleChildProc方法:

step 17:

以上的15-16 步都是在zygote進程中執(zhí)行句携,接下來是在新建的子線程中執(zhí)行

private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        {
            closeSocket();
            ZygoteInit.closeServerSocket();
            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);
            }
            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 {
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, null,/* classLoader */);
            }
        }

因為在arg.equals("--invoke-with")我們才會對parsedArgs.invokeWith進行賦值榔幸,我們在之前是沒有增加--invoke-with這個字符串的,所以parsedArgs.invokeWith為null }所以會執(zhí)行RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs, null);}

step 18:

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
    
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();
    
        commonInit();
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv, classLoader);
}

執(zhí)行applicationInit方法,里面會調(diào)用invokeStaticMain(args.startClass, args.startArgs, classLoader),這里的args.startClass是為android.app.ActivityThread,具體為什么這個值度迂,一直在查找各種資料還沒有找到原因,又碰到vpn掛了,后面會一直追查的麸澜,看系統(tǒng)源碼情景分析一書是這樣寫的挺尿。

step 19:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            ...
        }

        Method m;
        try {
            // 獲取它的靜態(tài)成員函數(shù)main,并且保存在Method對象m中
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            ...
        } catch (SecurityException ex) {
            ...
        }

        ...

        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    
    }

step 20:

這個異常是在ZygoteInit.main函數(shù)中捕獲到炊邦,

public static void main(String argv[]) {
        ...
        } catch (MethodAndArgsCaller caller) {
            // 捕獲MethodAndArgsCaller異常以后會調(diào)用MethodAndArgsCaller的run函數(shù)
            // ActivityThread.main
            caller.run();
        } catch (Throwable ex) {
            ...
        }
    }

在這里拋出了一個異常编矾,是在ZygoteInit.main函數(shù)捕獲到的,

public static void main(String argv[]) {
        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        try {
        
        ......
        
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

在這里捕獲到異常會執(zhí)行caller.run()方法:

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

根據(jù)step13馁害,我們知道入口是ActivityThread窄俏,所以我們子進程在啟動完成后,會調(diào)用ActivityThread.main方法碘菜。

step 21:

ActivityThread.main()方法:

public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        ......

        Looper.prepareMainLooper();//1

        ActivityThread thread = new ActivityThread();
        thread.attach(false);//1

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

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

在這里注釋1和3凹蜈,我們初始化looper,并開啟loop循環(huán)從消息隊列中取數(shù)據(jù)忍啸,注釋2我們執(zhí)行attach方法

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            // Watch for getting close to heap limit.
            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 {
                            mgr.releaseSomeActivities(mAppThread);
                        } catch (RemoteException e) {
                            throw e.rethrowFromSystemServer();
                        }
                    }
                }
            });
        } else {
        ......
        }
        ......
    }

因為傳過來的是false仰坦,所以會進入if判斷,這里我們會執(zhí)行 mgr.attachApplication(mAppThread);這里會執(zhí)行ActivityManagerProxy.attachApplication(IApplicationThread app)方法:

step 22:

public void attachApplication(IApplicationThread app) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(app.asBinder());
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

如上计雌,通過mRemote的binder發(fā)送一個code為ATTACH_APPLICATION_TRANSACTION的通信請求悄晃,這個時候ActivityManagerService所在的進程會執(zhí)行onTransact方法,這里的code是在父類ActivityManagerNative中執(zhí)行的凿滤。

step 23:

前面17-22步是在子線程(應(yīng)用程序啟動的進程)中執(zhí)行,接下來的操作又要進入到SystemServer進程執(zhí)行了妈橄,

@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
......
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
attachApplication(app);
}
reply.writeNoException();
return true;
}
......

        }

在上面會執(zhí)行attachApplication(IApplicationThread thread)方法,這個是ActivityManagerService中有實現(xiàn)的翁脆。

step 24:

ActivityManagerService.attachApplication方法:

@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

step 25:

如上23-24步是在systemServer進程執(zhí)行眷蚓,接下來的切回到子進程中執(zhí)行了,

private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
            ......
            // Check if a next-broadcast receiver is in this process...
           // See if the top visible activity is waiting to run in this process...
            if (normalMode) {
                try {
                    if (mStackSupervisor.attachApplicationLocked(app)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                    badApp = true;
                }
            }
            ......
        }

我們看下boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);這里第一個是進程已經(jīng)ready的情況反番,或者是參數(shù)中明確指定可以在boot過程中啟動應(yīng)用這里就為true溪椎,按照前面的分析普舆,應(yīng)用程序的進程是啟動起來的,所以normalMode為true校读,執(zhí)行mStackSupervisor.attachApplicationLocked(app)方法沼侣。

step 26:

ActivityStackSupervisor.attachApplicationLocked:

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                ......
                ActivityRecord hr = stack.topRunningActivityLocked();
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                  + hr.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }
            }
        }
        if (!didSomething) {
            ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
        }
        return didSomething;
    }

遍歷activityStack,查詢最頂端的ActivityRecord歉秫,因為應(yīng)用程序的activity還沒有啟動起來蛾洛,所以if判斷滿足的情況下,就是啟動的ActivityRecord雁芙,執(zhí)行realStartActivityLocked方法:

step 27:

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, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
            ......
            }

這里會調(diào)用ApplicationThread.scheduleLaunchActivity方法:

step 28:

public 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) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        intent.writeToParcel(data, 0);
        data.writeStrongBinder(token);
        data.writeInt(ident);
        info.writeToParcel(data, 0);
        curConfig.writeToParcel(data, 0);
        if (overrideConfig != null) {
            data.writeInt(1);
            overrideConfig.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        compatInfo.writeToParcel(data, 0);
        data.writeString(referrer);
        data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
        data.writeInt(procState);
        data.writeBundle(state);
        data.writePersistableBundle(persistentState);
        data.writeTypedList(pendingResults);
        data.writeTypedList(pendingNewIntents);
        data.writeInt(notResumed ? 1 : 0);
        data.writeInt(isForward ? 1 : 0);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }

通過binder發(fā)出通信請求轧膘,切換到app進程,執(zhí)行ApplicationThreadNative.onTransact方法兔甘,code為SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION

step 29:

上面23-28步實在SystemServer進程中執(zhí)行谎碍,接下來切換到子進程(App進程) 執(zhí)行ActivityThread.ApplicationThread.scheduleLaunchActivity()方法:

@Override
        public 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發(fā)送what為LAUNCH_ACTIVITY的消息洞焙,執(zhí)行

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

執(zhí)行handleLaunchActivity方法:

step 30:

ActivityThrad.handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            ......
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

            if (!r.activity.mFinished && r.startsNotResumed) {
              
                performPauseActivityIfNeeded(r, reason);
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    
}

如上蟆淀,會執(zhí)行performLaunchActivity方法,實現(xiàn)Activity的launchr處理澡匪,

step 31:

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

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        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) {
                Context appContext = createBaseContextForActivity(r, activity);
                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;
                }
                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);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                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;
    }

到這里我們那就可以看到Application的OnCreate的執(zhí)行和launcher的Activity的onCreate的執(zhí)行熔任,基本上一個應(yīng)用程序就啟動了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末唁情,一起剝皮案震驚了整個濱河市疑苔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌甸鸟,老刑警劉巖惦费,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異抢韭,居然都是意外死亡趁餐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門篮绰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來后雷,“玉大人,你說我怎么就攤上這事吠各⊥瓮唬” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵贾漏,是天一觀的道長候学。 經(jīng)常有香客問我,道長纵散,這世上最難降的妖魔是什么梳码? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任隐圾,我火速辦了婚禮,結(jié)果婚禮上掰茶,老公的妹妹穿的比我還像新娘暇藏。我一直安慰自己,他們只是感情好濒蒋,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布盐碱。 她就那樣靜靜地躺著,像睡著了一般沪伙。 火紅的嫁衣襯著肌膚如雪瓮顽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天围橡,我揣著相機與錄音暖混,去河邊找鬼。 笑死翁授,一個胖子當(dāng)著我的面吹牛拣播,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播黔漂,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼禀酱!你這毒婦竟也來了炬守?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤剂跟,失蹤者是張志新(化名)和其女友劉穎减途,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體曹洽,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡鳍置,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了送淆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片税产。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖偷崩,靈堂內(nèi)的尸體忽然破棺而出辟拷,到底是詐尸還是另有隱情,我是刑警寧澤阐斜,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布衫冻,位于F島的核電站,受9級特大地震影響谒出,放射性物質(zhì)發(fā)生泄漏隅俘。R本人自食惡果不足惜邻奠,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望为居。 院中可真熱鬧碌宴,春花似錦、人聲如沸颜骤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忍抽。三九已至八孝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鸠项,已是汗流浹背干跛。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祟绊,地道東北人楼入。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像牧抽,于是被迫代替她去往敵國和親嘉熊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容