Activity啟動過程(以Android9.0為例)

一、Android Application啟動流程分析

1. App基礎(chǔ)理論

每個Android App都在一個獨(dú)立空間里, 意味著其運(yùn)行在一個單獨(dú)的進(jìn)程中, 擁有自己的VM, 被系統(tǒng)分配一個唯一的user ID.

與眾多基于Linux內(nèi)核的系統(tǒng)類似, 啟動系統(tǒng)時, bootloader啟動內(nèi)核和init進(jìn)程. init進(jìn)程分裂出更多名為"daemons(守護(hù)進(jìn)程)"的底層的Linux進(jìn)程, 諸如android debug deamon, USB deamon等. 這些守護(hù)進(jìn)程處理底層硬件相關(guān)的接口历恐。

隨后, init進(jìn)程會啟動一個非常有意思的進(jìn)程---"Zygote". 顧名思義, 這是一個Android平臺的非忱湃粒基礎(chǔ)的進(jìn)程(起到了預(yù)加載資源和類到虛擬機(jī)提高應(yīng)用程序提高的作用)捶惜。 這個進(jìn)程初始化了第一個VM, 并且預(yù)加載了framework和眾多App所需要的通用資源搬卒。 然后它開啟一個Socket接口來監(jiān)聽請求, 根據(jù)請求孵化出新的VM來管理新的App進(jìn)程棕兼。 一旦收到新的請求, Zygote會基于自身預(yù)先加載的VM來孵化出一個新的VM創(chuàng)建一個新的進(jìn)程梅掠。

Zygote會孵化出一個超級管理進(jìn)程---System Server。 SystemServer會啟動所有系統(tǒng)核心服務(wù), 例如Activity Manager Service, 硬件相關(guān)的Service等玉掸。接下來Zygote孵化出第一個App進(jìn)程Launcher刃麸,也就是桌面App。

2. 啟動App流程

我們點(diǎn)擊了一個桌面圖標(biāo)啟動一個App的Activity司浪,Launcher里會執(zhí)行:

Intent intent = new Intent("xxx");
startActivity(intent);

此時會通過Binder IPC機(jī)制, 最終調(diào)用到ActivityManagerService泊业。 該Service會執(zhí)行如下操作:

  • 分析intent對象的指向信息,驗(yàn)證用戶是否有足夠的權(quán)限啊易。
  • 如果有權(quán)限, ActivityManagerService需要檢查并在新的task中啟動目標(biāo)activity吁伺。
  • 檢查這個進(jìn)程的ProcessRecord是否存在了,即是否存在該進(jìn)程租谈,如果ProcessRecord是null篮奄,就需要創(chuàng)建新的進(jìn)程

3. 創(chuàng)建新的進(jìn)程

ActivityManagerService調(diào)用startProcessLocked()方法來創(chuàng)建新的進(jìn)程, 該方法會通過前面講到的socket通道傳遞參數(shù)給Zygote進(jìn)程割去。 Zygote孵化自身fork出一個新的進(jìn)程窟却,在子進(jìn)程中會接著關(guān)閉socket,調(diào)用ZygoteInit.invokeStaticMain(cloader, className, mainArgs)劫拗,即調(diào)用ActivityThread.main()间校。新的應(yīng)用進(jìn)程會從ActivityThread的main()函數(shù)處開始執(zhí)行。

    //ActivityThread.main()方法
    public static void main(String[] args) {
        ...
        //創(chuàng)建Looper
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        //主要做一些新進(jìn)程起來后的工作页慷,比如設(shè)置ProcessRecord信息憔足、attach application,啟動該進(jìn)程的Activity
        thread.attach(false);
        ...
        Looper.loop();
    }

4. 啟動Activity

經(jīng)過前兩個步驟之后, 系統(tǒng)已經(jīng)擁有了該application的進(jìn)程. 后面的調(diào)用順序就是普通的從一個已經(jīng)存在的進(jìn)程中啟動一個新進(jìn)程的activity了酒繁。
實(shí)際調(diào)用方法是realStartActivity()滓彰,是下面要重點(diǎn)闡述的內(nèi)容。

二州袒、Activity的啟動流程

這里各個API版本的啟動稍微有一點(diǎn)點(diǎn)差別揭绑,但是主要流程還是不變的。這里以Android 9.0為例郎哭。

1. 相關(guān)類簡介

Instrumentation
用于實(shí)現(xiàn)應(yīng)用程序測試代碼的基類他匪。這個類將在任何應(yīng)用程序代碼之前為您實(shí)例化(估計(jì)是在Android系統(tǒng)的啟動的時候就已經(jīng)實(shí)例化了),允許您監(jiān)視系統(tǒng)與應(yīng)用程序的所有交互夸研“蠲郏可以通過AndroidManifest.xml的<Instrumentation>標(biāo)簽描述該類的實(shí)現(xiàn)。

ActivityManager
該類提供與Activity亥至、Service和Process相關(guān)的信息以及交互方法悼沈, 可以被看作是ActivityManagerService的輔助類

ActivityManagerService
Android中最核心的服務(wù)姐扮,主要負(fù)責(zé)系統(tǒng)中四大組件的啟動絮供、切換、調(diào)度及應(yīng)用程序的管理和調(diào)度等工作茶敏。

ActivityThread
管理應(yīng)用程序進(jìn)程中主線程的執(zhí)行壤靶,根據(jù)Activity管理者的請求調(diào)度和執(zhí)行activities、broadcasts及其相關(guān)的操作惊搏。

ActivityStack:
負(fù)責(zé)單個Activity棧的狀態(tài)和管理贮乳。

ActivityStackSupervisor:
負(fù)責(zé)所有Activity棧的管理。內(nèi)部管理了mHomeStack胀屿、mFocusedStack和mLastFocusedStack三個Activity棧塘揣。其中,mHomeStack管理的是Launcher相關(guān)的Activity棧宿崭;mFocusedStack管理的是當(dāng)前顯示在前臺Activity的Activity棧亲铡;mLastFocusedStack管理的是上一次顯示在前臺Activity的Activity棧。

ClientLifecycleManager:
用來管理多個客戶端生命周期執(zhí)行請求的管理類葡兑。

2. 發(fā)出啟動請求

我們調(diào)用startActivity(intent)奖蔓,會調(diào)用的是startActivityForResult方法來傳遞啟動請求

// 位于android.app.Activity.java中

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) { 
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
        } else {    //不是第一次啟動
            ...
        }
    }

startActivityForResult()我們只需要關(guān)注mParent == null的部分就好,在API13以后嵌入多個子Activity已經(jīng)過時了(取而代之應(yīng)用Fragment)讹堤。mParent為空會去調(diào)用Instrumentation.execStartActivity()方法:

//android.app.Instrumentation.java中
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        ......
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            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;
    }

可以看到實(shí)際上調(diào)用了ActivityManager.getService().startActivity吆鹤,這里實(shí)際上是個IPC遠(yuǎn)程調(diào)用,去請求ActivityManagerService(簡稱AMS)的服務(wù)洲守,我們轉(zhuǎn)到AMS去看看疑务。

3. ActivityManagerService接收并處理啟動請求

轉(zhuǎn)到AMS的startActivity()康康:

//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    
    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) {
        enforceNotIsolatedCaller("startActivity");

        userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");

        // TODO: Switch to user app stacks here.
        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();

    }

經(jīng)過多個方法調(diào)用會去執(zhí)行startActivityAsUser方法沾凄,在startActivityAsUser方法最后會通過ActivityStartController.obtainStarter方法獲得一個包含所有啟動信息的ActivityStarter對象并調(diào)用execute方法執(zhí)行。

//frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java中
int execute() {
        try {
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) {
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                        ........
                        );
            } else {
                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        .........
                        );
            }
        } finally {
            onExecutionComplete();
        }
    }

因?yàn)樵贏ctivityManagerService.startActivityAsUser中調(diào)用了.setMayWait(userId)方法知允,所以這里 mRequest.mayWait值為true撒蟀,會去調(diào)用startActivityMayWait方法。

//frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
    private int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
            int userId, TaskRecord inTask, String reason,
            boolean allowPendingRemoteAnimationRegistryLookup) {
            ...
            int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup);
            ...
            return res;
        }
    }
    
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                ActivityRecord[] outActivity) {
        ...
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        ...

        postStartActivityProcessing(r, result, mTargetStack);

        return result;
    }

經(jīng)過多次輾轉(zhuǎn)調(diào)用ActivityStarter的startActivity()方法温鸽,然后調(diào)用startActivityUnchecked()方法

//frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
            
            .....//省略n行代碼
            
            if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                // If the activity is not focusable, we can't resume it, but still would like to
                // make sure it becomes visible as it starts (this will also trigger entry
                // animation). An example of this are PIP activities.
                // Also, we don't want to resume activities in a task that currently has an overlay
                // as the starting activity just needs to be in the visible paused state until the
                // over is removed.
                mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                // Go ahead and tell window manager to execute app transition for this activity
                // since the app transition will not be triggered through the resume channel.
                mService.mWindowManager.executeAppTransition();
            } else {
                // If the target stack was not previously focusable (previous top running activity
                // on that stack was not visible) then any prior calls to move the stack to the
                // will not update the focused stack.  If starting the new activity now allows the
                // task stack to be focusable, then ensure that we now update the focused stack
                // accordingly.
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else if (mStartActivity != null) {
            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
        }
        //調(diào)用到這里
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
                preferredLaunchDisplayId, mTargetStack);

        return START_SUCCESS;
}

這個方法里會根據(jù)啟動標(biāo)志位和Activity啟動模式來決定如何啟動一個Activity以及是否要調(diào)用deliverNewIntent方法通知Activity有一個Intent試圖重新啟動它保屯。無論以何種模式啟動最終都會調(diào)用ActivityStackSupervisor.resumeFocusedStackTopActivityLocked方法。

//frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    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)) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        ...
        return false;
    }

//frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
            ...
            result = resumeTopActivityInnerLocked(prev, options);
            ...

        return result;
    }


    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        ...
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
        if (mResumedActivity != null) {
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        ...
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
        ...
        return true;
    }

ActivityStackSupervisor.resumeFocusedStackTopActivityLocked方法會最終調(diào)用startSpecificActivityLocked涤垫。

4.根據(jù)需要創(chuàng)建應(yīng)用進(jìn)程

上面分析到ActivityStackSupervisor.startSpecificActivityLocked方法:

//frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    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) {
                ...
                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);
    }

可以看出姑尺,在這個方法中會去根據(jù)進(jìn)程和線程是否存在判斷App是否已經(jīng)啟動,如果已經(jīng)啟動蝠猬,就會調(diào)用realStartActivityLocked方法繼續(xù)處理切蟋。如果沒有啟動則調(diào)用ActivityManagerService.startProcessLocked方法創(chuàng)建新的進(jìn)程處理。對應(yīng)了第一部分的進(jìn)程創(chuàng)建的部分吱雏。
ActivityManagerService.startProcessLocked方法經(jīng)過多次跳轉(zhuǎn)最終會通過Process.start方法來為應(yīng)用創(chuàng)建進(jìn)程敦姻。

//frameworks/base/services/core/java/com/android/server/am/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) {
        ...
        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});
        ...
    }

//frameworks/base/core/java/android/os/Process.java
    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);
    }

//frameworks/base/core/java/android/os/ZygoteProcess.java
    public final Process.ProcessStartResult start(final String processClass,
                                                  final String niceName,..........) {
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
                    zygoteArgs);
        } catch (ZygoteStartFailedEx ex) {
            Log.e(LOG_TAG,
                    "Starting VM process through Zygote failed");
            throw new RuntimeException(
                    "Starting VM process through Zygote failed", ex);
        }
    }

    private Process.ProcessStartResult startViaZygote(final String processClass,
                                                      final String niceName,
                                                      final int uid, final int gid,
                                                      .........)
                                                      throws ZygoteStartFailedEx {
        ...
        synchronized(mLock) {
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
        }
    }
    
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");

        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(mSocket);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
            maybeSetApiBlacklistExemptions(primaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
        }
        if (primaryZygoteState.matches(abi)) {
            return primaryZygoteState;
        }

        // The primary zygote didn't match. Try the secondary.
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            try {
                secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
            }
            maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
        }

        if (secondaryZygoteState.matches(abi)) {
            return secondaryZygoteState;
        }

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

     /**
     * 可以看一下這里注釋寫的很清楚
     * Sends an argument list to the zygote process, which starts a new child
     * and returns the child's pid. Please note: the present implementation
     * replaces newlines in the argument list with spaces.
     *
     * @throws ZygoteStartFailedEx if process start failed for any reason
     */
    @GuardedBy("mLock")
    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
            ......
            
            //fork一個新進(jìn)程
            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;
    }

可以發(fā)現(xiàn)其最終調(diào)用了Zygote并通過socket通信的方式讓Zygote進(jìn)程fork出一個新的進(jìn)程,并根據(jù)傳遞的”android.app.ActivityThread”字符串歧杏,反射出該對象并執(zhí)行ActivityThread的main方法對其進(jìn)行初始化镰惦。

5.啟動Activity

回到ActivityStackSupervisor.startSpecificActivityLocked方法,如果已經(jīng)啟動犬绒,就會調(diào)用realStartActivityLocked方法繼續(xù)處理:

//frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
    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));

                // Set desired final state.
                final ActivityLifecycleItem lifecycleItem;
                if (andResume) {
                    lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
                } else {
                    lifecycleItem = PauseActivityItem.obtain();
                }
                clientTransaction.setLifecycleStateRequest(lifecycleItem);

                // Schedule transaction.
                mService.getLifecycleManager().scheduleTransaction(clientTransaction);
                ...

        return true;
    }

在ActivityStackSupervisor.realStartActivityLocked方法中為ClientTransaction對象添加LaunchActivityItem的callback旺入,然后設(shè)置當(dāng)前的生命周期狀態(tài),最后調(diào)用ClientLifecycleManager.scheduleTransaction方法執(zhí)行凯力。

//frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java 
    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        ...
    }

    frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
    public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
    }

可以看到執(zhí)行了mClient的scheduleTransaction方法茵瘾,這里mClient實(shí)際上是一個IApplicationThread類型,ActivityThread的內(nèi)部類ApplicationThread派生這個接口類并實(shí)現(xiàn)了對應(yīng)的方法咐鹤,所以是一個IPC遠(yuǎn)程調(diào)用拗秘。因此又回到客戶端了。

//android.app.ActivityThread中的內(nèi)部類ApplicationThread
    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        ActivityThread.this.scheduleTransaction(transaction);
    }
    
//android.app.ActivityThread
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }

這里向ActivityThread的Handler發(fā)送了一個消息祈惶,Handler有一個很簡潔的名字H,我們看一下他處理消息EXECUTE_TRANSACTION的代碼:

public void handleMessage(Message msg) {
    ...
    case EXECUTE_TRANSACTION:
        final ClientTransaction transaction = (ClientTransaction) msg.obj;
        mTransactionExecutor.execute(transaction);
        if (isSystem()) {
        // Client transactions inside system process are recycled on the client side
        // instead of ClientLifecycleManager to avoid being cleared before this
        // message is handled.
        transaction.recycle();
        }
        // TODO(lifecycler): Recycle locally scheduled transactions.
        break;
    ...
}

//android.app.servertransaction.TransactionExecutor.java
    public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

        executeCallbacks(transaction);

        executeLifecycleState(transaction);
        mPendingActions.clear();
        log("End resolving transaction");
    }

executeLifecycleState(transaction)我們在后面再說(在7. Activity的onStart()和onResume()里講)雕旨。先看TransactionExecutor.execute()被執(zhí)行,然后執(zhí)行了executeCallbacks()方法。


public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    ...
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);
            log("Resolving callback: " + item);
            final int postExecutionState = item.getPostExecutionState();
            final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
                    item.getPostExecutionState());
            if (closestPreExecutionState != UNDEFINED) {
                cycleToPath(r, closestPreExecutionState);
            }

            //callback得到執(zhí)行
            item.execute(mTransactionHandler, token, mPendingActions);
            item.postExecute(mTransactionHandler, token, mPendingActions);
            if (r == null) {
                // Launch activity request will create an activity record.
                r = mTransactionHandler.getActivityClient(token);
            }

            if (postExecutionState != UNDEFINED && r != null) {
                // Skip the very last transition and perform it by explicit state request instead.
                final boolean shouldExcludeLastTransition =
                        i == lastCallbackRequestingState && finalState == postExecutionState;
                cycleToPath(r, postExecutionState, shouldExcludeLastTransition);
            }
        }
    ...
}

也就是說每一項(xiàng)ClientTransactionItem都會得到執(zhí)行捧请,
之前在realStartActivityLocked中添加了CallbackclientTransaction.addCallback(LaunchActivityItem.obtain(...))凡涩,此時在客戶端這個LaunchActivityItem就會被執(zhí)行了,會執(zhí)行它的execute()方法:

//frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
    @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);
    }
    
//frameworks/base/core/java/android/app/ActivityThread.java
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        ...
        final Activity a = performLaunchActivity(r, customIntent);
        ...
        return a;
    }

又回到了了我們的ActivityThread疹蛉,接下來康康performLaunchActivity()

6. 創(chuàng)建Activity

performLaunchActivity()主要完成了以下幾件事:

  1. 從ActivityClientRecord獲取待啟動的Activity信息
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        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);
        }
        ...
  1. 通過Instrumentation的newActivity()創(chuàng)建Activity活箕,這里是用反射的方式創(chuàng)建的。
    ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.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);
            }
        }
        ...
  1. 通過LoadApk的makeApplication()方法嘗試創(chuàng)建Application對象可款。
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
//android.app.LoadApk.java
    public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {
            return mApplication;
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");

        Application app = null;

        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            if (!mPackageName.equals("android")) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        "initializeJavaContextClassLoader");
                initializeJavaContextClassLoader();
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                ...
            }
        }

        // Rewrite the R 'constants' for all library apks.
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
        final int N = packageIdentifiers.size();
        for (int i = 0; i < N; i++) {
            final int id = packageIdentifiers.keyAt(i);
            if (id == 0x01 || id == 0x7f) {
                continue;
            }

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

        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        return app;
    }

可以看到在makeApplication()方法中育韩,如果Application已經(jīng)創(chuàng)建了就不用再創(chuàng)建了直接返回克蚂。創(chuàng)建Application同樣用的是反射,然后instrumentation.callApplicationOnCreate(app)被調(diào)用座慰,再這里面Application的onCreate()方法得到了執(zhí)行陨舱。

  1. 創(chuàng)建的ContextImp對象通過Activity的attach()方法翠拣,使得二者獲得關(guān)聯(lián)版仔,并做一些重要的數(shù)據(jù)初始化工作,
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);
//android.app.Activity.java
    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback) {
        attachBaseContext(context);

        mFragments.attachHost(null /*parent*/);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        ...
        ...
        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);

        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    }

比如在attach()方法中完成了PhoneWindow的創(chuàng)建并與Activity獲得關(guān)聯(lián)误墓。

  1. 調(diào)用Activity的onCreate()方法
if (r.isPersistable()) {
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
    mInstrumentation.callActivityOnCreate(activity, r.state);
}

...
//更新Activity狀態(tài)
r.setState(ON_CREATE);

mActivities.put(r.token, r);

到這里Activity的創(chuàng)建已經(jīng)完成了蛮粮。

7. Activity的onStart()和onResume()

回到TransactionExecutor的execute()方法,前面說完了executeCallbacks()執(zhí)行完谜慌。

//android.app.servertransaction.TransactionExecutor.java
    public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

        executeCallbacks(transaction);

        executeLifecycleState(transaction);
        mPendingActions.clear();
        log("End resolving transaction");
    }

接下來該說executeLifecycleState(transaction)了然想。

//android.app.servertransaction.TransactionExecutor.java
    /** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(ClientTransaction transaction) {
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        if (lifecycleItem == null) {
            // No lifecycle request, return early.
            return;
        }
        log("Resolving lifecycle state: " + lifecycleItem);

        final IBinder token = transaction.getActivityToken();
        final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);

        if (r == null) {
            // Ignore requests for non-existent client records for now.
            return;
        }

        // Cycle to the state right before the final requested state.
        //執(zhí)行這里
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);

        // Execute the final transition with proper parameters.
        
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }
    
    private void cycleToPath(ActivityClientRecord r, int finish,
            boolean excludeLastState) {
        final int start = r.getLifecycleState();
        log("Cycle from: " + start + " to: " + finish + " excludeLastState:" + excludeLastState);
        //這里計(jì)算了路徑,path中包含了ON_START ON_RESUME
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        performLifecycleSequence(r, path);
    }
    
    /** Transition the client through previously initialized state sequence. */
    private void performLifecycleSequence(ActivityClientRecord r, IntArray path) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            log("Transitioning to state: " + state);
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                            r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                    break;
                case ON_PAUSE:
                    mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
                            false /* userLeaving */, 0 /* configChanges */, mPendingActions,
                            "LIFECYCLER_PAUSE_ACTIVITY");
                    break;
                case ON_STOP:
                    mTransactionHandler.handleStopActivity(r.token, false /* show */,
                            0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
                            "LIFECYCLER_STOP_ACTIVITY");
                    break;
                case ON_DESTROY:
                    mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
                            0 /* configChanges */, false /* getNonConfigInstance */,
                            "performLifecycleSequence. cycling to:" + path.get(size - 1));
                    break;
                case ON_RESTART:
                    mTransactionHandler.performRestartActivity(r.token, false /* start */);
                    break;
                default:
                    throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
            }
        }
    }

先執(zhí)行cycleToPath方法欣范,生命周期狀態(tài)是從ON_CREATE狀態(tài)到ON_RESUME狀態(tài)变泄,中間有一個ON_START狀態(tài),執(zhí)行到performLifecycleSequence()恼琼,path中包含ON_START和ON_RESUME妨蛹,所以會先后執(zhí)行handleStartActivity方法和handleResumeActivity方法,這里生命周期已經(jīng)看得很清楚了晴竞。接下來熟悉的onStart和onResume方法就會得到執(zhí)行了蛙卤。

三、總結(jié)

Activity啟動過程包括APP的啟動和創(chuàng)建其實(shí)是很復(fù)雜的噩死,這里用到了IPC和ActivityManagerService通信颤难,Android9.0和8.0以及之前不同的地方就是使用了一個LifeCycleManager來統(tǒng)一管理Activity的生命周期,然后在TransactionExecutor中處理和執(zhí)行各種回調(diào)已维。

參考
Android 9.0 Activity啟動流程源碼分析
Android Application啟動流程分析

有紕漏之處行嗤,歡迎指正。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末垛耳,一起剝皮案震驚了整個濱河市栅屏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌艾扮,老刑警劉巖既琴,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異泡嘴,居然都是意外死亡甫恩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門酌予,熙熙樓的掌柜王于貴愁眉苦臉地迎上來磺箕,“玉大人奖慌,你說我怎么就攤上這事∷擅遥” “怎么了简僧?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長雕欺。 經(jīng)常有香客問我岛马,道長,這世上最難降的妖魔是什么屠列? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任啦逆,我火速辦了婚禮,結(jié)果婚禮上笛洛,老公的妹妹穿的比我還像新娘夏志。我一直安慰自己,他們只是感情好苛让,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布沟蔑。 她就那樣靜靜地躺著,像睡著了一般狱杰。 火紅的嫁衣襯著肌膚如雪瘦材。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天浦旱,我揣著相機(jī)與錄音宇色,去河邊找鬼。 笑死颁湖,一個胖子當(dāng)著我的面吹牛宣蠕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播甥捺,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼抢蚀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了镰禾?” 一聲冷哼從身側(cè)響起皿曲,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吴侦,沒想到半個月后屋休,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡备韧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年劫樟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡叠艳,死狀恐怖奶陈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情附较,我是刑警寧澤吃粒,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站拒课,受9級特大地震影響徐勃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捕发,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一疏旨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扎酷,春花似錦、人聲如沸遏匆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幅聘。三九已至凡纳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帝蒿,已是汗流浹背荐糜。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留葛超,地道東北人暴氏。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像绣张,于是被迫代替她去往敵國和親答渔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

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