Android源碼分析-Activity啟動流程(一)

前言

其實(shí)在之前就研究過Activity的啟動流程,查看過很多資料,說實(shí)話這不是一時半會就能弄明白了解透徹的,這里面牽扯到的東西和知識也是非常多,那么我呢將對其做一個比較詳細(xì)的總結(jié)和分析,至于一些細(xì)節(jié)以后有機(jī)會再單獨(dú)分析,我相信只要閱讀此文你將會對Activity的啟動模式有一個大概的了解,如果您想要深入了解還得自己多結(jié)合源碼分析翻閱相關(guān)資料,此篇文章基于Android 8.0源碼進(jìn)行分析,有不對的地方還請多指教。


1. Activity是什么?

一個界面

2.如何啟動一個Activity?

調(diào)用startActivity()

3.Activity啟動流程源碼分析

好了讓我們直接步入正題吧

    >>> 步驟1
   @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
    
    >>> 步驟2
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            //此時options為null將調(diào)用else
            startActivityForResult(intent, -1);
        }
    }

     >>> 步驟3
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        //如果是第一次啟動mParent肯定為null
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                //委托mInstrumentation調(diào)用execStartActivity
                //activity的生命周期方法都是它來調(diào)用
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
             //為什么要判斷requestCode對于0呢?
             //因?yàn)椴淮笥?的話onActivityResult不起作用
             //所以在調(diào)用startActivityForResult設(shè)置requestCode必須等于等于0才起作用!
            if (requestCode >= 0) {
                mStartedActivity = true;
            }
        } else {
        ...
        }
    }

這里簡單的介紹一下Instrumentation因?yàn)槭堑谝淮卧诜治鲞^程中出現(xiàn)所以我簡單的先介紹一下

  • 調(diào)用activity的生命周期相關(guān)方法,一個Activity對象的生命周期開始于被一個Intent啟動的時候
  • 這時候該Activity對象的onCreate()方法就會被調(diào)用,緊跟著就是onResume()
  • Android的API框架并沒有為你的代碼提供一種方法去直接調(diào)用這些回調(diào)函數(shù),但是通過instrumentation就可以做到這一點(diǎn)。

下面我們來看一下委托Instrumentation調(diào)用的 execStartActivity()方法

   /**
     * @param who The Context from which the activity is being started.
     * @param contextThread The main thread of the Context from which the activity
     *                      is being started.
     * @param token Internal token identifying to the system who is starting 
     *              the activity; may be null.
     * @param target Which element is performing the start (and thus receiving 
     *               any result).
     * @param intent The actual Intent to start.
     * @param requestCode Identifier for this request's result; less than zero 
     *                    if the caller is not expecting a result.
     * 
     * @return To force the return of a particular result, return an 
     *         ActivityResult object containing the desired data; otherwise
     *         return null.  The default implementation always returns null.
     */
  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);
            >>> 重點(diǎn)關(guān)注這個方法
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

            //checkStartActivityResult作用
            // 比如如果啟動的activity沒有在xml里面進(jìn)行注冊那么在這個check里就會報錯
            checkStartActivityResult(result, intent);
        } 
        return null;
    }

ActivityManager.getService()實(shí)際上返回的結(jié)果就是ActivityManagerService簡稱AMS,詳細(xì)細(xì)節(jié)可查閱相關(guān)資料,在一開始的啟動流程中主要的還是一些參數(shù)傳遞過程,到了后面就比較復(fù)雜了,下面就是AMS的startActivity函數(shù)

    @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) {
        >>> 步驟1
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    
     >>>  步驟2
    @Override
    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) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        >>> 步驟3
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }

在上面的步驟3中調(diào)用了startActivityMayWait()函數(shù)這個函數(shù)在ActivityStarter類里,我們重點(diǎn)分析,如下:

    final 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, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask, String reason) {

        //檢測intent的合法性
        //...
          
        //方法分析1:
        //a.此方法實(shí)際上的調(diào)用PackageManagerService的resolveIntent
        //b.根據(jù)intent的信息查找匹配的activity  
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);

        ...

        // 方法分析2:
        // a.收集Intent所指向的Activity信息,
        // b.當(dāng)存在多個可供選擇的Activity,則直接向用戶彈出選擇框供用戶選擇
        // c.設(shè)置Intent的Component
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
        ActivityStackSupervisor.ActivityContainer container =
                (ActivityStackSupervisor.ActivityContainer)iContainer;

        synchronized (mService) {
            if (container != null && container.mParentActivity != null &&
                    container.mParentActivity.state != RESUMED) {
                // Cannot start a child activity if the parent is not resumed.
                return ActivityManager.START_CANCELED;
            }
            final int realCallingPid = Binder.getCallingPid();
            final int realCallingUid = Binder.getCallingUid();
            // 設(shè)置uuid
            int callingPid;
            if (callingUid >= 0) {
                callingPid = -1;
            } else if (caller == null) {
                callingPid = realCallingPid;
                callingUid = realCallingUid;
            } else {
                callingPid = callingUid = -1;
            }

             ...

            if (aInfo != null &&
                    (aInfo.applicationInfo.privateFlags
                            & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
                // This may be a heavy-weight process!  Check to see if we already
                // have another, different heavy-weight process running.
                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
                    final ProcessRecord heavy = mService.mHeavyWeightProcess;
                    if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
                            || !heavy.processName.equals(aInfo.processName))) {
                          //這里面比較長我就不貼出來了說一下內(nèi)容
                          //a.如果當(dāng)前系統(tǒng)中已經(jīng)存在重量級進(jìn)程,但不是將要啟動的這個
                          //b.實(shí)例化這個重量級的Intent,并且賦值給當(dāng)前的Intent,關(guān)于重量級下面我會講到
                    }
                }
            }

            final ActivityRecord[] outRecord = new ActivityRecord[1];
            
            // 重點(diǎn)關(guān)注1
            >>> 啟動activity并將啟動結(jié)果返回。
            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask, reason);
          
          // 如果configuration發(fā)生變化,則調(diào)用AMS的updateConfigurationLocked進(jìn)行處理
          if (stack.mConfigWillChange) {
                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
                        "updateConfiguration()");
                stack.mConfigWillChange = false;
                if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
                        "在啟動活動后更新到新的配置。");
                mService.updateConfigurationLocked(globalConfig, null, false);
            }
            
            // 分析:
            // a. outResult是作為參數(shù)傳遞進(jìn)來
            // b. 在上個方法中可以發(fā)現(xiàn)傳遞過來的為null,所以這個if語句將不會被執(zhí)行
            if (outResult != null) {  
                //關(guān)注如果不為null的情況
             
                outResult.result = res;
                //res是調(diào)用startActivityLocked返回的結(jié)果
                //在startActivityLocked之后給啟動結(jié)果賦值

                if (res == ActivityManager.START_SUCCESS) {
                    mSupervisor.mWaitingActivityLaunched.add(outResult);
                    //將成功的結(jié)果保存
                    do {
                        try {
                            mService.wait();
                            //AMS執(zhí)行線程等待
                        } catch (InterruptedException e) {
                        }
                    } while (outResult.result != START_TASK_TO_FRONT
                            && !outResult.timeout && outResult.who == null);
                    //while循環(huán)里面的判斷條件要看activity被喚醒的方式了

                    if (outResult.result == START_TASK_TO_FRONT) {
                         // START_TASK_TO_FRONT解釋為 : 一個activity被帶到前臺,但是還沒有完全啟動

                        res = START_TASK_TO_FRONT;
                         
                    }
                }
                
                if (res == START_TASK_TO_FRONT) {
                    // 當(dāng)這個activity被帶到前臺的時候           

                    final ActivityRecord r = outRecord[0];

                    if (r.nowVisible && r.state == RESUMED) {
                        //如果ActivityRecord 是可見的并且是RESUME狀態(tài)的話
                        outResult.timeout = false;
                        outResult.who = r.realActivity;
                        outResult.totalTime = 0;
                        outResult.thisTime = 0;
                        //對outResult進(jìn)行賦值
                      
                    } else {
                       ...
                    }
                }
            }
            // 作用
            // a.通知監(jiān)聽者,activity正在啟動。
            // b.更新狀態(tài)
            mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, outRecord[0]);
            return res;
        }
    }

結(jié)合代碼以及注釋可以得出這樣的結(jié)論startActivityMayWait這個函數(shù)有以下幾點(diǎn)
1.讓PKMS來解析Intent并得到ResolveInfo
2.匹配最相符的Intent
3.判斷是否是啟動重量級的任務(wù)

ResolveInfo : 這個任務(wù)在manifast中的信息,IntentFilter之類的
重量級:所謂重量級在這里的意思就是有多個任務(wù)被匹配到

注釋里的重點(diǎn)關(guān)注就是啟動流程調(diào)用的方法,下面我們接著看startActivityLocked這個函數(shù)

  
  int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask, String reason) {
      
        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;
        // 為變量賦值
      
        >>> 啟動activity,并將結(jié)果返回。上段代碼用到的res就是它返的
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                container, inTask);

        return mLastStartActivityResult;
    }

在這個方法里面?zhèn)鬟f了一些參數(shù)給startActivity這個函數(shù)IApplicationThread callerIntentcallingPid調(diào)用者的進(jìn)程pid,realCallingPid當(dāng)前進(jìn)程pid,startFlags=0等。startActivity這個函數(shù)也是比較重要的那我們來看一下

startActivity

    
    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {



        int err = ActivityManager.START_SUCCESS;
        //err 表示錯誤的啟動結(jié)果,在下面會對其賦值默認(rèn)是啟動成功


        // Pull the optional Ephemeral Installer-only bundle out of the options early.
        final Bundle verificationBundle
                = options != null ? options.popAppVerificationBundle() : null;

        ProcessRecord callerApp = null;
        if (caller != null) {
            callerApp = mService.getRecordForAppLocked(caller);
            // 檢測caller是否有權(quán)限啟動目標(biāo)Activity

            if (callerApp != null) {
                callingPid = callerApp.pid;
                callingUid = callerApp.info.uid;
            } else {
                Slog.w(TAG, "Unable to find app for caller " + caller
                        + " (pid=" + callingPid + ") when starting: "
                        + intent.toString());
                err = ActivityManager.START_PERMISSION_DENIED;
                //調(diào)用者沒有權(quán)限
            }
        }

        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;

        if (err == ActivityManager.START_SUCCESS) {
            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                    + "} from uid " + callingUid);
        }

        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                    "Will send result to " + resultTo + " " + sourceRecord);
            if (sourceRecord != null) {
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }

        final int launchFlags = intent.getFlags();

        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {

            //對IntentFlags為FLAG_ACTIVITY_FORWARD_RESULT這種特殊情況進(jìn)行特殊處理
            // 1.Activity A 啟動了Activity B,Activity B又啟動了C,A-->B-->C, 這種情況下
            // 2.A啟動B要求B返回result給A,但是如果B在啟動C時,Intent設(shè)置了Intent.FLAG_ACTIVITY_FORWARD_RESULT標(biāo)志
            // 3.那么此時將會交由C向A setResult。

            if (requestCode >= 0) {
                ActivityOptions.abort(options);
                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
            }

            resultRecord = sourceRecord.resultTo;
            if (resultRecord != null && !resultRecord.isInStackLocked()) {
                resultRecord = null;
            }
            resultWho = sourceRecord.resultWho;
            requestCode = sourceRecord.requestCode;
            sourceRecord.resultTo = null;
            if (resultRecord != null) {
                resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
            }
            if (sourceRecord.launchedFromUid == callingUid) {
                callingPackage = sourceRecord.launchedFromPackage;
            }
        }


        //...省略了檢測參數(shù)部分
        // (包括檢查intent,ActivityInfo),檢測結(jié)果賦值給了err

        if (err != START_SUCCESS) {
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(
                        -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);

            //如果檢查不SUCCESS那么startActivity到此結(jié)束直接
            return err;

        }



        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
                resultRecord, resultStack, options);
        // 檢查啟動activity它自己的相關(guān)權(quán)限,其中里面有一個判斷(!aInfo.exported)的時候會報錯
        // 這個exported屬性是什么意思呢?
        // 1.意思就是說Activity的屬性exported的值為false時
        // 2.然后別的app就打不開這個Activity了,
        // 3.如果要打開的話,就必須和這個Activity在同一Application下或者uid相同才

        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                callingPid, resolvedType, aInfo.applicationInfo);

        if (mService.mController != null) {
            try {
                // The Intent we give to the watcher has the extra data
                // stripped off, since it can contain private information.
                Intent watchIntent = intent.cloneFilter();
                abort |= !mService.mController.activityStarting(watchIntent,
                        aInfo.applicationInfo.packageName);
            } catch (RemoteException e) {
                mService.mController = null;
            }
        }

        mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
        mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,
                options);
        // mInterceptor 屬于一個攔截類,將這些信息攔截下來,給自己的變量保存
        // 然后再重新賦值給這些信息,其實(shí)這個值還是和以前一樣沒有變
        // 但是這樣做的好處就是在之后可以攔截器里進(jìn)行修改

        intent = mInterceptor.mIntent;
        rInfo = mInterceptor.mRInfo;
        aInfo = mInterceptor.mAInfo;
        resolvedType = mInterceptor.mResolvedType;
        inTask = mInterceptor.mInTask;
        callingPid = mInterceptor.mCallingPid;
        callingUid = mInterceptor.mCallingUid;
        options = mInterceptor.mActivityOptions;
        if (abort) {
            //1如果要終止
            if (resultRecord != null) {
                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                        RESULT_CANCELED, null);
            }
            // We pretend to the caller that it was really started, but
            // they will just get a cancel result.
            //2我們向打電話的人假裝它真的開始了,但是他們會得到取消的結(jié)果。
            ActivityOptions.abort(options);
            return START_SUCCESS;
        }

        ...

        // If we have an ephemeral app, abort the process of launching the resolved intent.
        // Instead, launch the ephemeral installer. Once the installer is finished, it
        // starts either the intent we resolved here [on install error] or the ephemeral
        // app [on install success].
        //如果我們有一個短暫的應(yīng)用程序,中止啟動解決意圖的過程。
        //相反,啟動臨時安裝程序。安裝程序完成之后。
        //開始我們在這里解決的意圖[安裝錯誤]或短暫的
        // app[安裝成功]。
        if (rInfo != null && rInfo.auxiliaryInfo != null) {
            intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
                    callingPackage, verificationBundle, resolvedType, userId);
            resolvedType = null;
            callingUid = realCallingUid;
            callingPid = realCallingPid;

            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
        }

        //ActivityRecord,用于存儲Activity的各種狀態(tài)和歷史信息。
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, container, options, sourceRecord);
     
      ...
        
        >>> 一個正常的啟動最終會return這里
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }

這個方法我們看完了,總結(jié)一下

1.檢測callerApp是否有權(quán)限啟動目標(biāo)activity否則報錯誤信息ActivityManager.START_PERMISSION_DENIED
2.判斷intent帶進(jìn)來的flag
3.在上述代碼里面我把對處理VOICE Session的代碼減掉了,可以理解為語音會話
4.調(diào)用Supervisor.checkStartAnyActivityPermission 檢查這個activity自己的相關(guān)權(quán)限
5.設(shè)置mInterceptor 保存一些變量信息放到攔截器里面,比如這個intent,uid,pid,ResolveInfo,ActivityInfo等
6.創(chuàng)建一個ActivityRecord它可以理解為,任務(wù)載里面的一個任務(wù),所有的信息都會放到這個里面,具體是什么信息呢?我再貼一份代碼你們就知道了如下:

 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, container, options, sourceRecord);

還沒完別急!接著往下看,它return了一個重載方法

   private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            >>> 步驟1
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } finally {
         ...
        }
      
        postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
                mTargetStack);

        return result;
    }


這個重載方法里面執(zhí)行了startActivityUnchecked這個函數(shù)代碼也是巨多,不打緊下面接著分析,在這之前我先說一些籠統(tǒng)的東西這個函數(shù)主要做了那些事情,比如判斷即將啟動的Activity是否需要在task中進(jìn)行創(chuàng)建和是否創(chuàng)建新的Task啟動,如何去復(fù)用這個activity的邏輯,然后又把這個Task帶到前臺并設(shè)置對應(yīng)的Task。OK讓我們帶著這些線索繼續(xù)看代碼。

//這個方法只在步驟一調(diào)用了
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {

        // 方法分析:
        // 作用: a.設(shè)置一些初始化狀態(tài)
        //       b.校驗(yàn)intent的flag是否是特定的flag
        //       c.將傳過去的參數(shù)重新賦值給本類的成員變量
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor);


        computeLaunchingTaskFlags();
        // 進(jìn)過一些條件判斷之后設(shè)置activity的啟動模式
        // 以后有時間做詳細(xì)分析

        computeSourceStack();
        // 這個方法其實(shí)就是針對啟動模式為FLAG_ACTIVITY_NEW_TASK的時候判斷要不要為其重新NEW一個task

        mIntent.setFlags(mLaunchFlags);


        ActivityRecord reusedActivity = getReusableIntentActivity();
        //決定是否將新的Activity插入到現(xiàn)有的Task中
        //返回null表示否,否則新啟動的Activity將插入到該Task的Top位置。


        final int preferredLaunchStackId =
                (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
        //preferredLaunchStackId : 要加入的StackID

        final int preferredLaunchDisplayId =
                (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;


        if (reusedActivity != null) {
            //1.reusedActivity不為null的時候
            //2.將新的Activity插入到現(xiàn)有的Task

            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
            // still needs to be a lock task mode violation since the task gets cleared out and
            // the device would otherwise leave the locked task.
            if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
                mSupervisor.showLockTaskToast();
                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }

            if (mStartActivity.getTask() == null) {
                mStartActivity.setTask(reusedActivity.getTask());
            }
            if (reusedActivity.getTask().intent == null) {
                // This task was started because of movement of the activity based on affinity...
                // Now that we are actually launching it, we can assign the base intent.
                reusedActivity.getTask().setIntent(mStartActivity);
            }

            // This code path leads to delivering a new intent, we want to make sure we schedule it
            // as the first operation, in case the activity will be resumed as a result of later
            // operations.
            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                    || isDocumentLaunchesIntoExisting(mLaunchFlags)
                    || mLaunchSingleInstance || mLaunchSingleTask) {
                // 判斷當(dāng)前activity啟動模式是否為SinleTask,
                // 并且當(dāng)前要啟動的activity在現(xiàn)有的Task中的話


                final TaskRecord task = reusedActivity.getTask();

                // In this situation we want to remove all activities from the task up to the one
                // being started. In most cases this means we are resetting the task to its initial
                // state.
                final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
                        mLaunchFlags);
                //清空在它在上的任務(wù)


                // The above code can remove {@code reusedActivity} from the task, leading to the
                // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
                // task reference is needed in the call below to
                // {@link setTargetStackAndMoveToFrontIfNeeded}.
                if (reusedActivity.getTask() == null) {
                    reusedActivity.setTask(task);
                }

                if (top != null) {
                    if (top.frontOfTask) {
                        // Activity aliases may mean we use different intents for the top activity,
                        // so make sure the task now has the identity of the new intent.
                        top.getTask().setIntent(mStartActivity);

                    }
                    ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
                    top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
                            mStartActivity.launchedFromPackage);
                    //top就是要啟動的activty,deliverNewIntentLocked將會回調(diào)它的onNewIntent方法

                }
            }

            //將其他任務(wù)棧隱藏如果你需要的話
            sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);


            //將這個activity的任務(wù)棧移動到前臺
            reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);

            final ActivityRecord outResult =
                    outActivity != null && outActivity.length > 0 ? outActivity[0] : null;

            // When there is a reused activity and the current result is a trampoline activity,
            // set the reused activity as the result.
            if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
                outActivity[0] = reusedActivity;
            }

            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                // We don't need to start a new activity, and the client said not to do anything
                // if that is the case, so this is it!  And for paranoia, make sure we have
                // correctly resumed the top activity.
                resumeTargetStackIfNeeded();
                return START_RETURN_INTENT_TO_CALLER;
            }

            //最后修改這個任務(wù)棧的信息
            setTaskFromIntentActivity(reusedActivity);

            if (!mAddingToTask && mReuseTask == null) {
                // We didn't do anything...  but it was needed (a.k.a., client don't use that
                // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
                resumeTargetStackIfNeeded();
                if (outActivity != null && outActivity.length > 0) {
                    outActivity[0] = reusedActivity;
                }
                return START_TASK_TO_FRONT;
            }
        }

        if (mStartActivity.packageName == null) {
            final ActivityStack sourceStack = mStartActivity.resultTo != null
                    ? mStartActivity.resultTo.getStack() : null;
            if (sourceStack != null) {
                sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
                        mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
                        null /* data */);
            }
            ActivityOptions.abort(mOptions);
            return START_CLASS_NOT_FOUND;
        }

        // If the activity being launched is the same as the one currently at the top, then
        // we need to check if it should only be launched once.
        // 從上面這段注釋我們得知當(dāng)啟動的Task和位于頂部的Tas相同的時候,我們檢查一下是否應(yīng)該只啟動一次
        // 這也是下面這部分代碼的核心工作
        final ActivityStack topStack = mSupervisor.mFocusedStack;
        final ActivityRecord topFocused = topStack.topActivity();
        final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
        final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
        // 從dontstart的賦值過程不難看出它代表要啟動的activity和前臺activity是否一致
        // 以及是否需要重新創(chuàng)建一個實(shí)例


        if (dontStart) {
            //以下代碼就是重新使用這個activity


            ActivityStack.logStartActivity(AM_NEW_INTENT, top, top.getTask());
            // For paranoia, make sure we have correctly resumed the top activity.
            topStack.mLastPausedActivity = null;
            if (mDoResume) {
                mSupervisor.resumeFocusedStackTopActivityLocked();
            }
            ActivityOptions.abort(mOptions);
            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                // We don't need to start a new activity, and the client said not to do
                // anything if that is the case, so this is it!
                return START_RETURN_INTENT_TO_CALLER;
            }

            //將回調(diào)onNewIntent
            top.deliverNewIntentLocked(
                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);

            // Don't use mStartActivity.task to show the toast. We're not starting a new activity
            // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
            mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
                    preferredLaunchDisplayId, topStack.mStackId);


            return START_DELIVERED_TO_TOP;
        }



        boolean newTask = false;
        //newTask:是否創(chuàng)建一個新的任務(wù)棧

        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTask() : null;

        // Should this be considered a new task?
        // 上面這個英文的解釋就是:是否應(yīng)該被視為一項(xiàng)新任務(wù)?
        int result = START_SUCCESS;
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;


            result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack)
             // 重新創(chuàng)建一個任務(wù)棧

        } else if (mSourceRecord != null) {
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            setTaskToCurrentTopOrCreateNewTask();
        }
        if (result != START_SUCCESS) {
            return result;
        }

    
        if (mDoResume) {
           ...

            } 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)) {
                    // 如果目標(biāo)堆棧以前沒有可用的焦點(diǎn)(該堆棧上以前的頂部運(yùn)行活動是不可見的)
                    // 那么任何先前的調(diào)用都會將堆棧移動到不會更新集中的堆棧。如果現(xiàn)在開始新的活動
                    // 可以使任務(wù)堆棧成為焦點(diǎn),然后確保我們現(xiàn)在相應(yīng)地更新聚焦堆棧。對應(yīng)上面的英文翻譯
                    mTargetStack.moveToFront("startActivityUnchecked");
                }

                >>> 最終會來到這里
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }

        //更新最后一個堆載的id
        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);

        mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
                preferredLaunchDisplayId, mTargetStack.mStackId);

        return START_SUCCESS;
    }

在這個函數(shù)里面進(jìn)行了很多的校驗(yàn)邏輯,細(xì)節(jié)很多我總結(jié)幾個重要的點(diǎn), 通過computeLaunchingTaskFlags()這個函數(shù)在經(jīng)過一些判斷之后設(shè)置了activity的啟動模式,再決定是否要加入現(xiàn)有的Task中去,如果不加入就創(chuàng)建一個新的task。還有如果他的啟動模式是SingleTask的話,在啟動它之前會清空壓在它上面的activity,然后把這個Task帶到前臺,之后就可以啟動activity了, 將會調(diào)用ActivityStackSupervisorresumeFocusedStackTopActivityLocked()這個函數(shù)

 boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

        if (targetStack != null && isFocusedStack(targetStack)) {
            >>> 步驟1 
            //
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
       ...
        return false;
    }
    
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
     ...
        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            >>> 步驟2
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
      ...

        return result;
    }

在上面的代碼中的步驟2會調(diào)用ActivityStack類中的resumeTopActivityInnerLocked()函數(shù)。還是一樣先和大家簡單的說明一下這個函數(shù)的作用,在啟動這個activity之前先暫停正在運(yùn)行的activity,之后就會進(jìn)行一個轉(zhuǎn)場動畫并且更新一些進(jìn)程數(shù)據(jù),新舊交替但是還是沒有真正啟動,請看代碼(我做了一些刪減)

   private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        if (!mService.mBooting && !mService.mBooted) {
            // Not ready yet!
            return false;
        }

        // Find the next top-most activity to resume in this stack that is not finishing and is
        // focusable. If it is not focusable, we will fall into the case below to resume the
        // top activity in the next focusable task.
        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
        //拿到這個將要運(yùn)行的activity信息


        final boolean hasRunningActivity = next != null;

        final ActivityRecord parent = mActivityContainer.mParentActivity;
        final boolean isParentNotResumed = parent != null && parent.state != ActivityState.RESUMED;
        if (hasRunningActivity
            && (isParentNotResumed || !mActivityContainer.isAttachedLocked())) {
            // Do not resume this stack if its parent is not resumed.
            // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
            // 看上面的注釋就能明白了
            return false;

        }

        mStackSupervisor.cancelInitializingActivities();

        // Remember how we'll process this pause/resume situation, and ensure
        // that the state is reset however we wind up proceeding.
        final boolean userLeaving = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;
        // 將mUserLeaving放置在userLeaving中,并且重置mUserLeaving為false,因此就可以通過userLeaving
        // 判斷是否需要向源Activity組件發(fā)送一個用戶離開的時間通知了


        if (!hasRunningActivity) {
            // There are no activities left in the stack, let's look somewhere else.
            return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
            //方法作用:將焦點(diǎn)轉(zhuǎn)移到下一個activity

        }

        next.delayedResume = false;

        // If the top activity is the resumed one, nothing to do.
        // 如果啟動的activity是進(jìn)入重新恢復(fù)狀態(tài)執(zhí)行onResume的話,直接return false
        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
            mStackSupervisor.allResumedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.
            executeAppTransition(options);
            // 重新恢復(fù)這個activity會有一個過渡公話


            if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        final TaskRecord nextTask = next.getTask();
        final TaskRecord prevTask = prev != null ? prev.getTask() : null;
        if (prevTask != null && prevTask.getStack() == this &&
            prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {


            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
            if (prevTask == nextTask) {
                prevTask.setFrontOfTask();
            } else if (prevTask != topTask()) {
                // This task is going away but it was supposed to return to the home stack.
                // Now the task above it has to return to the home task instead.
                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
            } else if (!isOnHomeDisplay()) {
                return false;
            } else if (!isHomeStack()){
                if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Launching home next");
                return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
                // 啟動到Home Task

            }
        }

        // If we are sleeping, and there is no resumed activity, and the top
        // activity is paused, well that is the state we want.
        if (mService.isSleepingOrShuttingDownLocked()
            && mLastPausedActivity == next
            && mStackSupervisor.allPausedActivitiesComplete()) {
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.


            executeAppTransition(options);
            // 在回到Home的時候回執(zhí)行一個過度動畫
            // 按一下home鍵就能看到這個動畫的效果了trying!

            if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Going to sleep and all paused");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        // Make sure that the user who owns this activity is started.  If not,
        // we will just leave it as is because someone should be bringing
        // another user's activities to the top of the stack.
        if (!mService.mUserController.hasStartedUserState(next.userId)) {
            Slog.w(TAG, "Skipping resume of top activity " + next
                + ": user " + next.userId + " is stopped");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        // The activity may be waiting for stop, but that is no longer
        // appropriate for it.

        mStackSupervisor.mStoppingActivities.remove(next);
        //在會stop掉了activity里面移除掉將會啟動的activity,因?yàn)樗鼤恢匦逻\(yùn)行起來

        mStackSupervisor.mGoingToSleepActivities.remove(next);
        //和上面的意思一樣

        next.sleeping = false;
        mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);

        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

        // If we are currently pausing an activity, then don't do anything until that is done.
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                "resumeTopActivityLocked: Skip resume: some activity pausing.");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return false;
        }

        mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);

        boolean lastResumedCanPip = false;
        final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
        if (lastFocusedStack != null && lastFocusedStack != this) {
            // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
            // represent the last resumed activity. However, the last focus stack does if it isn't null.
            final ActivityRecord lastResumed = lastFocusedStack.mResumedActivity;
            lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
                "resumeTopActivity", true /* noThrow */, userLeaving /* beforeStopping */);
        }
        // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
        // to be paused, while at the same time resuming the new resume activity only if the
        // previous activity can't go into Pip since we want to give Pip activities a chance to
        // enter Pip before resuming the next activity.
        final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
            && !lastResumedCanPip;



        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
        // 暫停任務(wù)棧中的其他activity
        if (mResumedActivity != null) {
            // 我們從一個Activity啟動另一個Activity的時候,源Activity不是空,mResumedActivity指向源Activity,
            // 因此mResumedActivity不為空

            if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);

            pausing |= startPausingLocked(userLeaving, false, next, false);
            //暫停當(dāng)前正在運(yùn)行的activity
        }
        if (pausing && !resumeWhilePausing) {
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                "resumeTopActivityLocked: Skip resume: need to start pausing");
            // At this point we want to put the upcoming activity's process
            // at the top of the LRU list, since we know we will be needing it
            // very soon and it would be a waste to let it get killed if it
            // happens to be sitting towards the end.
            if (next.app != null && next.app.thread != null) {
                mService.updateLruProcessLocked(next.app, true, null);
                // 把即將啟動的activity放到這個Lru列表的最上面,關(guān)于什么是Lru大家可以去查閱相關(guān)資料

            }
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        } else if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
            mStackSupervisor.allResumedActivitiesComplete()) {
            // It is possible for the activity to be resumed when we paused back stacks above if the
            // next activity doesn't have to wait for pause to complete.
            // So, nothing else to-do except:
            // Make sure we have executed any pending transitions, since there
            // should be nothing left to do at this point.

            // 如果啟動的這個任務(wù)不需要等其他的任務(wù)先暫停,那么當(dāng)在我們上面的任務(wù)已經(jīng)暫停的時候
            // 就可以直接啟動了

            executeAppTransition(options);
            // 運(yùn)行重新恢復(fù)任務(wù)的過度動畫
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return true;
        }
 
      ...
  
        // Launching this app's activity, make sure the app is no longer
        // considered stopped.
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(
                next.packageName, false, next.userId); /* TODO: Verify if correct userid */
        } catch (RemoteException e1) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package "
                + next.packageName + ": " + e);
        }

        // We are starting up the next activity, so tell the window manager
        // that the previous one will be hidden soon.  This way it can know
        // to ignore it when computing the desired screen orientation.

        // 下面這個if else 會通知WindowManager 告訴它前面那個activity很快就要隱藏了
        boolean anim = true;
        if (prev != null) {
            if (prev.finishing) {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare close transition: prev=" + prev);
                if (mNoAnimActivities.contains(prev)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                        ? TRANSIT_ACTIVITY_CLOSE
                        : TRANSIT_TASK_CLOSE, false);
                }
                prev.setVisibility(false);
            } else {
                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: prev=" + prev);
                if (mNoAnimActivities.contains(next)) {
                    anim = false;
                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
                } else {
                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
                        ? TRANSIT_ACTIVITY_OPEN
                        : next.mLaunchTaskBehind
                        ? TRANSIT_TASK_OPEN_BEHIND
                        : TRANSIT_TASK_OPEN, false);
                }
            }
        } else {
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
            if (mNoAnimActivities.contains(next)) {
                anim = false;
                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
            } else {
                mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
            }
        }

        Bundle resumeAnimOptions = null;
        if (anim) {
            ActivityOptions opts = next.getOptionsForTargetActivityLocked();
            if (opts != null) {
                resumeAnimOptions = opts.toBundle();
            }
            next.applyOptionsLocked();
        } else {
            next.clearOptionsLocked();
        }

        ActivityStack lastStack = mStackSupervisor.getLastStack();
        if (next.app != null && next.app.thread != null) {
            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
                + " stopped=" + next.stopped + " visible=" + next.visible);

            // If the previous activity is translucent, force a visibility update of
            // the next activity, so that it's added to WM's opening app list, and
            // transition animation can be set up properly.
            // For example, pressing Home button with a translucent activity in focus.
            // Launcher is already visible in this case. If we don't add it to opening
            // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
            // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
            // 如果之前的活動是半透明的,則強(qiáng)制進(jìn)行可見性更新
            // 下一個活動,將它添加到WM的開放應(yīng)用列表中
            // 過渡動畫可以正確設(shè)置。
            // 例如,按下Home鍵,焦點(diǎn)是半透明的活動。
            // 在這種情況下,啟動程序已經(jīng)可見。如果我們不把它加進(jìn)去。
            // 將無法運(yùn)行一些動畫。

            final boolean lastActivityTranslucent = lastStack != null
                && (!lastStack.mFullscreen
                || (lastStack.mLastPausedActivity != null
                && !lastStack.mLastPausedActivity.fullscreen));

            // This activity is now becoming visible.
            if (!next.visible || next.stopped || lastActivityTranslucent) {
                next.setVisibility(true);
                // 將這個活動變?yōu)榭梢?            }

           ...
           //省略了一部分更新任務(wù)載的代碼
           ...


            if (notUpdated) {
                // The configuration update wasn't able to keep the existing
                // instance of the activity, and instead started a new one.
                // We should be all done, but let's just make sure our activity
                // is still at the top and schedule another run if something
                // weird happened.
                ActivityRecord nextNext = topRunningActivityLocked();
                if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
                    "Activity config changed during resume: " + next
                        + ", new next: " + nextNext);
                if (nextNext != next) {
                    // Do over!
                    mStackSupervisor.scheduleResumeTopActivities();
                }
                if (!next.visible || next.stopped) {
                    next.setVisibility(true);
                }
                next.completeResumeLocked();
                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
                return true;
            }

            try {
                // Deliver all pending results.
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int N = a.size();
                    if (!next.finishing && N > 0) {
                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                            "Delivering results to " + next + ": " + a);
                        next.app.thread.scheduleSendResult(next.appToken, a);
                        // 這一步將調(diào)用onActivityResult
                    }
                }

                if (next.newIntents != null) {
                    next.app.thread.scheduleNewIntent(
                        next.newIntents, next.appToken, false /* andPause */);
                }

               ....

                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
                    mService.isNextTransitionForward(), resumeAnimOptions);
                // scheduleResumeActivity會觸發(fā)activity的onResume


                if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next);
            } catch (Exception e) {
               ...
            }
          
            ...
          
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    next.showStartingWindow(null /* prev */, false /* newTask */,
                        false /* taskSwich */);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            >>> 如果新啟動一個activity調(diào)用這個函數(shù)
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
            

        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }

總結(jié)一下resumeTopActivityInnerLocked函數(shù),在這里面調(diào)用topRunningActivityLocked()把要啟動的activity信息取出來,在啟動之前先暫停其他activity,并把當(dāng)前這個activity在要暫停的任務(wù)列表里面移除,之后又判斷這個要啟動Activity是否已經(jīng)存在,是否為home應(yīng)用,接著又判斷是否要執(zhí)行它的onNewIntent方法和onResume,以及之前是半透明的狀態(tài)現(xiàn)在恢復(fù)可見,這些情況都在這個方法里面體現(xiàn)到。如果是創(chuàng)建一個新的就會調(diào)用 ASS.startSpecificActivityLocked 方法創(chuàng)建 Activity 并啟動。接下來我們繼續(xù)分析startSpecificActivityLocked方法

  void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);

        if (app != null && app.thread != null) {
            // 判斷這個活動是否已經(jīng)準(zhǔn)備好了,前面代碼就是做準(zhǔn)備的,所以會進(jìn)入到這里面

            try {
                ...
                >>> 啟動流程會到這一步,在下面分析
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
               ...
        }

        // 如果拋出異常或者進(jìn)程為空, 需要AMS重新fork一個進(jìn)程來起來
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

如你所見startSpecificActivityLocked()方法里面就一個主要功能調(diào)用了realStartActivityLocked()函數(shù),并在拋出異常和判斷這個進(jìn)程為空的時候執(zhí)行startProcessLocked()重新fork一個進(jìn)程出來,讓我們直接來看主要功能。代碼如下

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {

        if (!allPausedActivitiesComplete()) {
            // 當(dāng)有活動暫停的時候,我們會跳過開始任何新的活動,直到停止為止。
            // 注意:對于以暫停狀態(tài)開始的活動,我們也這樣做,因?yàn)樗鼈儗⑹紫缺换謴?fù),然后在客戶端暫停。
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "realStartActivityLocked: Skipping start of r=" + r
                    + " some activities pausing...");
            return false;
        }

        r.startFreezingScreenLocked(app, 0);
        if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */, true /* isTop */)) {

            r.setVisibility(true);
        }

        // schedule launch ticks to collect information about slow apps.
        r.startLaunchTickingLocked();


        //讓窗口管理器根據(jù)新的活動順序重新評估屏幕的方向。注意,由于這個原因,
        //方向調(diào)用activity manager。我們不關(guān)心這個,因?yàn)閍ctivity目前沒有運(yùn)行,所以我們只是重新啟動它。
        if (checkConfig) {
            //這個checkConfig是作為參數(shù)傳遞進(jìn)來的,傳遞進(jìn)來的是true所以會執(zhí)行if里面的代碼

            final int displayId = r.getDisplayId();
            final Configuration config = mWindowManager.updateOrientationFromAppTokens(
                    getDisplayOverrideConfiguration(displayId),
                    r.mayFreezeScreenLocked(app) ? r.appToken : null, displayId);
            // Deferring resume here because we're going to launch new activity shortly.
            // We don't want to perform a redundant launch of the same record while ensuring
            // configurations and trying to resume top activity of focused stack.


            mService.updateDisplayOverrideConfigurationLocked(config, r, true /* deferResume */,
                    displayId);
            //作用:更新這個activity的覆蓋配置。如果沒有提供配置,將根據(jù)當(dāng)前顯示信息在WM中計(jì)算新的配置。
        }

        if (mKeyguardController.isKeyguardLocked()) {
            r.notifyUnknownVisibilityLaunched();
            //啟動的時候顯示軟鍵盤
        }
        final int applicationInfoUid =
                (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
        if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
            Slog.wtf(TAG,
                    "User ID for activity changing for " + r
                            + " appInfo.uid=" + r.appInfo.uid
                            + " info.ai.uid=" + applicationInfoUid
                            + " old=" + r.app + " new=" + app);
        }



        r.app = app;
        //設(shè)置這個任務(wù)的進(jìn)程
        app.waitingToKill = null;

        r.launchCount++;
        // 增加啟動次數(shù)
        r.lastLaunchTime = SystemClock.uptimeMillis();
        // 設(shè)置啟動時間
        if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);

        int idx = app.activities.indexOf(r);
        if (idx < 0) {
            app.activities.add(r);
        }

        mService.updateLruProcessLocked(app, true, null);
        //更新AMS最近啟動的進(jìn)程列表

        mService.updateOomAdjLocked();

        final TaskRecord task = r.getTask();
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
                task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
            setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
            // 固定屏幕不允許其他activity啟動
        }

        ...

            // 一波賦值操作
            r.sleeping = false;
            r.forceNewConfig = false;
            mService.showUnsupportedZoomDialogIfNeededLocked(r);
            mService.showAskCompatModeDialogLocked(r);
            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
            ProfilerInfo profilerInfo = null;
            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
                // 條件是成立的 在之前這個函數(shù)resolveActivity 對它進(jìn)行過賦值

                if (mService.mProfileProc == null || mService.mProfileProc == app) {
                    mService.mProfileProc = app;
                    final String profileFile = mService.mProfileFile;
                    if (profileFile != null) {
                        ParcelFileDescriptor profileFd = mService.mProfileFd;
                        if (profileFd != null) {
                            try {
                                profileFd = profileFd.dup();
                            } catch (IOException e) {
                                if (profileFd != null) {
                                    try {
                                        profileFd.close();
                                    } catch (IOException o) {
                                    }
                                    profileFd = null;
                                }
                            }
                        }
                        // 重點(diǎn)就是在這里new一個 ProfilerInfo出來,傳遞給ActivityTherad類的          
                        // scheduleLaunchActivity函數(shù)
                        profilerInfo = new ProfilerInfo(profileFile, profileFd,
                                mService.mSamplingInterval, mService.mAutoStopProfiler,
                                mService.mStreamingOutput);
                    }
                }
            }

            app.hasShownUi = true;
            app.pendingUiClean = true;
            app.forceProcessStateUpTo(mService.mTopProcessState);
            // Because we could be starting an Activity in the system process this may not go across
            // a Binder interface which would create a new Configuration. Consequently we have to
            // always create a new Configuration here.
            //因?yàn)槲覀兛赡茉谙到y(tǒng)進(jìn)程中啟動一個活動,所以這可能不會通過綁定器接口來創(chuàng)建一個新的配置。
            // 因此,我們必須始終在這里創(chuàng)建一個新的配置。
            final MergedConfiguration mergedConfiguration = new MergedConfiguration(
                    mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
            r.setLastReportedConfiguration(mergedConfiguration);
            
            >>> 最后啟動流程來到了這里
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    // TODO: Have this take the merged configuration instead of separate global and
                    // override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

            ...

        } catch (RemoteException e) {
           ...
        }

       ...

        // Update any services we are bound to that might care about whether
        // their client may have activities.
        if (r.app != null) {
            mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
            // 更新綁定的服務(wù)
        }

        return true;
    }

看到這里那么恭喜你Activity的啟動流程第一部分分析到這里就結(jié)束了,到了realStartActivityLocked()這個方法activity的啟動也就真正的到了路口了,我大概的梳理一下realStartActivityLocked()這個方法的作用,先是mWindowManager.updateOrientationFromAppTokens()讓窗口管理器根據(jù)新的活動順序重新評估屏幕的方向,緊接著更新這個activity的覆蓋配置mService.updateDisplayOverrideConfigurationLocked() ,然后判斷是否在啟動的時候顯示軟鍵盤,然后固定屏幕,這個時候不允許其他的activity啟動,最后來到scheduleLaunchActivity()這個函數(shù),到了這個函數(shù)后面就是啟動Activity的生命周期,View的繪制,之類的等等。后續(xù)接著為大家分析。


5. 總結(jié)

以上就是Activity啟動流程第一部分的總結(jié)已經(jīng)分析完了,有什么不對的地方還望指出,后續(xù)我將會推出第二部分。在這個分析過程中我也學(xué)到了了解到了收獲了很多,我相信您再仔細(xì)閱讀過之后也會有所收獲。感謝您的閱讀,。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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