原始碼閱讀之Activity啟動與App啟動流程 - Android 9.0

100斤發表於2019-02-20

前言

為了面試與被面試閱讀了Activity的啟動流程,整理了這篇文章。 之前一直好奇為什麼Android面試經常問Activity啟動流程,因為在工作中沒有相關的實踐。閱讀完原始碼以後才發現,Activity啟動流程中包含了許多知識,例如Activity的啟動模式如何處理、外掛化的hook點等等。不過由於原始碼冗長,本文只分析Activity的啟動流程。

閱讀建議:

1、分析基於Android 9.0原始碼,整理了3張流程圖。由於圖文排版稀疏,建議新建一個API28的工程配合流程圖閱讀原始碼,如果發現文章有什麼問題,可以聯絡我。

2、原始碼冗長,閱讀需要耐心。

3、紙上得來終覺淺,絕知此事要躬行。

4、如果流程圖不能放大預覽,請閱讀原文fiftykg.com

Activity在應用內啟動流程

話不多說,先上圖,流程圖1

熱啟動

簡單介紹一下涉及的類:

工具類,包裝了ActivityManagerService的呼叫。一些外掛化方案就是通過hook該類實現的,例如didi的VirtualApk

Android核心服務,負責排程各應用程式,管理四大元件。實現了IActivityManager介面,應用程式能通過Binder機制呼叫系統服務。

Activity啟動的工具類,處理啟動activity的各種flag。

管理所有應用的Activity的棧,其中mFocusedStack就是當前應用的activity棧。

啟動Activity的訊息。收到訊息後執行execute方法啟動activity。

應用的主執行緒。

接下來開始分析流程: 流程圖1,第1-3步,Activity的startActivity會呼叫startActivityForResult。當應用已經啟動時,會先呼叫startActivityFromChild。但是無論應用是否啟動,最後都會呼叫Instrumentation.execStartActivity。 正如前面所說,ActivityManagerService實現了IActivityManager.aidl介面,提供了應用程式呼叫系統服務的方法,而Instrumentation包裝了ActivityManagerService的呼叫。

        public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            ...
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ...
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

    public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,
            int requestCode, @Nullable Bundle options) {
        ...
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, child,
                intent, requestCode, options);
        ...
    }
複製程式碼

流程圖1,第4步,Instrumentation呼叫ActivityManagerService的startActivity

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ...
        try {
            ...
            int result = ActivityManager.getService()
                .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;
    }
複製程式碼

流程圖1,第5-6步,ActivityManagerService建立ActivityStarter並執行。

    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        ...
        return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }
複製程式碼

流程圖1,第7步,由於第6步setMayWait將mayWait設定為true,所以執行startActivityMayWait方法。

    ActivityStarter setMayWait(int userId) {
        mRequest.mayWait = true;
        mRequest.userId = userId;

        return this;
    }
    
    int execute() {
        try {
            if (mRequest.mayWait) {
                return startActivityMayWait(...);
            } else {
                return startActivity(...);
            }
        } finally {
            onExecutionComplete();
        }
    }
複製程式碼

流程圖1,第8-11步,ActivityStarter處理啟動activity的intent和flag比較繁瑣,最後會呼叫ActivityStackSupervisor的resumeFocusedStackTopActivityLocked。

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        ...
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }

        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || !r.isState(RESUMED)) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.isState(RESUMED)) {
            ...
        }
        return false;
    }
複製程式碼

流程圖1,第12步,resumeTopActivityInnerLocked是一個非常冗長的方法,該方法會判斷棧中是否有需要啟動的Activity,判斷Activity是否在棧頂等等。如果需要啟動的Activity沒有被建立,就會執行流程圖13步ActivityStackSupervisor的startSpecificActivityLocked方法。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
        if (next.app != null && next.app.thread != null) {
            ...
        }else{
            // Whoops, need to restart this activity!
            ...
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }
   }
複製程式碼

流程圖1,第13-14步,startSpecificActivityLocked方法中先判斷App是否啟動,如果啟動則執行realStartActivityLocked。如果未啟動則呼叫ActivityManagerService.startProcessLocked方法啟動App。 為了分析方便,我們先看App啟動的情況。在realStartActivityLocked方法中,ActivityManangerService會呼叫應用程式的介面,最終執行ClientTransaction的callBack,也就是LaunchActivityItem。這個呼叫過程將在稍後分析。

    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);
        if (app != null && app.thread != null) {
            try {
                ...
                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);
    }
    
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
                ...
                // Create activity launch transaction.
                final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                        r.appToken);
                clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                        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, mService.isNextTransitionForward(),
                        profilerInfo));
                ...
                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                ...
    }
複製程式碼

流程圖1,第15步,LaunchActivityItem的execute方法執行了ClientTransactionHandler的handleLaunchActivity。而這個ClientTransactionHandler就是ActivityThread。至於為什麼是ActivityThread,可以看第二部分。

    @Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
複製程式碼

流程圖1,第16-19,ActivityThread執行handleLaunchActivity方法,呼叫真正Activity啟動方法performLaunchActivity。 performLaunchActivity中呼叫Instrumentation.newActivity方法建立Activity物件! 建立完成後,performLaunchActivity會繼續呼叫Instrumentation.callActivityOnCreate。這裡往下走就會呼叫Activity.OnCreate。

    // ActivityThread.java:
    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        ...
        final Activity a = performLaunchActivity(r, customIntent);
        ...
        return a;
    }
    
    // ActivityThread.java:
    /**  Core implementation of activity launch. */
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            ...
        } catch (Exception e) {
            ...
        }

        try {
            ...
            if (activity != 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, r.configCallback);
                ...
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ...
            }
            ...
        } catch (SuperNotCalledException e) {
            throw e;
        } catch (Exception e) {
            ...
        }
        return activity;
    }
    
    // Instrumentation.java:
    public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);
    }
    
    // AppComponentFactory.java:
    public @NonNull Activity instantiateActivity(@NonNull ClassLoader cl, @NonNull String className,
            @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity) cl.loadClass(className).newInstance();
    }
複製程式碼

流程圖1,第20-21,Instrumentation.callActivityOnCreate中呼叫Activity的performCreate。performCreate呼叫Activity.onCreate!

    // Instrumentation.java
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

    // Activity.java
    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        ...
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        ...
    }
複製程式碼

IApplicationThread & IActivityManager

上面流程中最難理解的大概就是第15步了,clientTransaction中新增的LaunchActivityItem是如何被執行的?要理解這一步就需要先了解一下系統與應用之間的通訊。

Android程式間通過Binder機制進行通訊。AMS(ActivityManagerService)與應用程式之間的通訊,Android設計了IApplicationThread與IActivityManager兩個介面。 兩個通訊介面都是單向的: IApplicationThread是AMS請求應用程式的介面。 IActivityManager是應用程式請求AMS的介面。

public class ActivityManagerService extends IActivityManager.Stub
// ActivityThread的內部類
private class ApplicationThread extends IApplicationThread.Stub
複製程式碼

再來看一下,上面流程第15步的分解流程,流程圖2

原始碼閱讀之Activity啟動與App啟動流程 - Android 9.0

流程圖2,第3步,mClient就是IApplicationThread。

    private IApplicationThread mClient;
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }
複製程式碼

流程圖2,第4步,ApplicationThread中scheduleTransaction方法直接呼叫外部類ActivityThread的scheduleTransaction,但是ActivityThread.java中沒有scheduleTransaction方法,而是在父類ClientTransactionHandler。

    // ApplicationThread
    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        ActivityThread.this.scheduleTransaction(transaction);
    }
        
    //ClientTransactionHandler.java
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
複製程式碼

流程圖2,第5步,ClientTransactionHandler中發了一個handler訊息EXECUTE_TRANSACTION。這個Handler就是ActivityThread的子類H。在H的handleMessage中可以找到EXECUTE_TRANSACTION的處理。

    case EXECUTE_TRANSACTION:
            final ClientTransaction transaction = (ClientTransaction) msg.obj;
            mTransactionExecutor.execute(transaction);
        if (isSystem()) {
            transaction.recycle();
        }
    break;
複製程式碼

最終會在TransactionExecutor中取出LaunchActivityItem,執行execute。也是Activity啟動流程圖中的第15步。

AMS是何時獲取到IApplicationThread? App如何獲取IActivityManager? 答案就在ActivityThread.main方法中,main中呼叫了attach方法。

    // ActivityThread.java
    private void attach(boolean system, long startSeq) {
        ...
        if (!system) {
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } else {
            //system 
        }
        ...
    }
複製程式碼

App程式在啟動時通過ActivityManager獲取單例的IActivityManager,利用IActivityManager的attachApplication介面將IApplicationThread註冊到AMS。這樣就實現了App與AMS的通訊。

App的啟動流程

剛才提到了ActivityThread的main方法,這是應用程式的入口。在Activity啟動流程中,第13步startSpecificActivityLocked,如果App未啟動mService.startProcessLocked就會走到ActivityThread.main方法。

接下來看一下App的啟動流程,流程圖3

冷啟動

流程圖3,第14-15步,startSpecificActivityLocked中判斷app未啟動進入AMS的startProcessLocked,startProcessLocked經過多次過載呼叫走到startProcess,startProcess呼叫Process.start啟動程式。 這裡注意下,Process.start的第一個引數,在其中一個startProcessLocked方法中賦值為"android.app.ActivityThread",搜尋字串就可以找到!

    // ActivityStackSupervisor.java
    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // application is not running
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
    // ActivityManagerService.java
    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 {
            ...
            final ProcessStartResult startResult;
            if (hostingType.equals("webview_service")) {
                // webview process
            } 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);
        }
    }
複製程式碼

流程圖3,第16步,Process.start中出現了著名的ZygoteProcess! 傳說中Android的所有程式起源於Zygote,Process類只是對Zygote的包裝而已。

    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);
    }
複製程式碼

流程圖3,第17-20步,zygoteProcess.start呼叫zygoteProcess.startViaZygote。startViaZygote中通過socket與zygote通訊,啟動app程式,zygoteSendArgsAndGetResult方法返回app程式的pid。

    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<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);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        ...
        synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }
複製程式碼

接下來就是需要尋找argsForZygote中的引數在哪裡解析,在zygoteSendArgsAndGetResult方法中有這樣一段註釋:

/**
 * 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.
 */
複製程式碼

然而找不到SystemZygoteInit這個類! 既然argsForZygote中引數是一些hardcode的字串,那解析的地方應該也是hardcode。所以搜了一下引數。 果然在ZygoteInit.java和ZygoteConnection.java中發現了這些引數。ZygoteInit是zygote程式啟動類,main方法中建立了ZygoteServer。由ZygoteServer監聽Socket請求,並執行相應的命令。ZygoteServer與客戶端的通訊協議定義在ZygoteConnection.Arguments中。

流程圖3,第21-22步,經過上面一波分析,我們看到ZygoteServer的runSelectLoop方法中,接收到Socket請求後,執行了ZygoteConnection.processOneCommand。

    Runnable runSelectLoop(String abiList) {
        while (true) {
            ...
            ZygoteConnection connection = peers.get(i);
            final Runnable command = connection.processOneCommand(this);
            ...
        }
複製程式碼

流程圖3,第23-24步,processOneCommand中通過readArgumentList方法讀取引數,建立Arguments物件時,在Arguments.parseArgs方法中解析引數。將解析後的引數傳入Zygote.forkAndSpecialize建立子程式。

    Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
        Arguments parsedArgs = null;
        FileDescriptor[] descriptors;
        try {
            args = readArgumentList();
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            throw new IllegalStateException("IOException on command socket", ex);
        }
        ...
        parsedArgs = new Arguments(args);
        ....
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
                parsedArgs.instructionSet, parsedArgs.appDataDir);
        ....
    }
複製程式碼

在readArgumentList中看到了一段與zygoteSendArgsAndGetResult方法遙相呼應的註釋

/**
 * See android.os.Process.zygoteSendArgsAndGetPid()
 * 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.
 */
複製程式碼

然而在Process中也找不到zygoteSendArgsAndGetPid。感覺是歷史程式碼的註釋,誤導啊!

流程圖3,第25步,processOneCommand執行完forkAndSpecialize後,在子程式(pid=0)中,執行handleChildProc進行子程式初始化。

    Runnable processOneCommand(ZygoteServer zygoteServer) {
        ...
        pid = Zygote.forkAndSpecialize(...);

        try {
            if (pid == 0) {
                // in child
                zygoteServer.setForkChild();

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.startChildZygote);
            } else {
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, descriptors, serverPipeFd);
                return null;
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }
複製程式碼

流程圖3,第26步,handleChildProc中,invokeWith是socket引數"--invoke-with",在ActivityManagerService的startProcessLocked中賦值,只有在debug的情況下才!null。 isZygote是引數"--start-child-zygote",在ZygoteProcess.start方法中為false。 所以handleChildProc會走到ZygoteInit.zygoteInit。 這裡比較奇怪,為什麼不是走childZygoteInit,希望有想法的朋友告知一下=。=

    private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
        ...
        if (parsedArgs.invokeWith != null) {
            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.remainingArgs);

            // Should not get here.
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
        } else {
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
                        null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
                        parsedArgs.remainingArgs, null /* classLoader */);
            }
        }
    }
複製程式碼

流程圖3,第27-28步,zygoteInit中執行RuntimeInit.applicationInit,applicationInit呼叫findStaticMain,反射ActivityThread.main方法!

    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        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();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ...
        final Arguments args = new Arguments(argv);
        ...
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

    protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        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);
        }
        ...
        return new MethodAndArgsCaller(m, argv);
    }
複製程式碼

流程圖3,第29-33步,回到ActivityThread.main方法中,走到attach中,向AMS註冊IApplicationThread,經過多次attachApplicationLocked走到Activity的啟動流程,ActivityStackSupervisor的realStartActivityLocked,也就是流程圖1的第14步。

    // ActivityManagerService.java
    public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
            Binder.restoreCallingIdentity(origId);
        }
    }
複製程式碼

巨人的肩膀

老羅:Android應用程式內部啟動Activity過程(startActivity)的原始碼分析

Android四大元件之Activity--應用程式與系統程式的通訊

ps: 原始碼閱讀過程中,遇得了許多疑惑的地方。一方面是能力有限,需要多參考前輩的文章,另一方面原始碼也並非完美,程式碼中也有許多todo存在,也許還能發現一些bug。對於ZygoteProcess.zygoteSendArgsAndGetResult()與ZygoteConnection.readArgumentList中出現的誤導註釋,給google提了一個issue,就當閱讀原始碼的紀念了。

以上。

如果覺得文章還不錯,幫忙點個贊。

相關文章