Android 8.0 源碼分析 (四) Activity 啓動

前言

咱們熟知通常 Android 工程師都是在應用層上開發,不會涉及系統源碼,可是若是你想往底層發展,或者深刻插件化、Framework 系統層等開發工做,若是不瞭解 Android 源碼但是不行的,那麼接下來我基於本身的理解跟學習來記錄跟 Android 開發息息相關的源碼分析,大概從 Android 中的 SystemServer 啓動、四大組件啓動、AMS、PMS 等幾個維度來介紹,下面是個人計劃,固然在將來也有可能改變。java

尚未關注的小夥伴,能夠先關注一波,系列文章會持續更新。android

Android 8.0 源碼分析 (一) SystemServer 進程啓動數組

Android 8.0 源碼分析 (二) Launcher 啓動緩存

Android 8.0 源碼分析 (三) 應用程序進程建立到應用程序啓動的過程app

Android 8.0 源碼分析 (四) Activity 啓動async

Android 8.0 源碼分析 (五) Service 啓動ide

Android 8.0 源碼分析 (六) BroadcastReceiver 啓動函數

Android 8.0 源碼分析 (七) ContentProvider 啓動源碼分析

介紹

前面 3 篇文章分別分析了系統進程、系統桌面 Launcher 進程、應用程序進程的啓動過程,那麼接下來點擊系統桌面圖標就該進入到應用程序進程的根 Activity 了,這篇文章就給你們帶來 Android 中四大組件之一的 Activity 啓動分析,尚未看過我以前的源碼分析能夠先去了解下,由於前面講解的內容至關於基礎或者至關於四大組件啓動的鋪墊。佈局

應用程序根 Activity 啓動過程

Activity 啓動過程分爲 2 種,一種是應用程序根 Activity 的啓動也就是在 XML 佈局中有該配置的屬性,

<action android:name="android.intent.action.MAIN"/>
複製代碼

第二種就是咱們程序中調用 startActivity 啓動。不過這 2 種在最後源碼中的調用幾乎同樣,能夠這樣說只要理解了第一種,那麼第二種理解起來就輕鬆多了。下面咱們先來分析第一種。

Launcher 請求 AMS 過程

Android 8.0 源碼分析 (二) Launcher 啓動 這一節中,咱們知道 Launcher 啓動後會將已經安裝應用安裝應用程序的快捷圖標顯示到桌面上,這些應用圖標就是啓動應用程序根 Activity 入口,當咱們點擊某個應用的快捷圖標的時候,就會經過 Launcher 請求 AMS 來啓動該應用程序。 Launcher 請求 AMS 的時序圖以下:

KfEHMV.png

當咱們點擊應用圖標的時候,就會調用 Launcher 的 startActivitySafely 函數,以下所示:

//Launcher.java
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
            Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
            return false;
        }
        /** * 1. 爲啓動應用的 Activity 添加一個新的任務棧 */
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (v != null) {
            intent.setSourceBounds(getViewBounds(v));
        }
        try {
            if (Utilities.ATLEAST_MARSHMALLOW
                    && (item instanceof ShortcutInfo)
                    && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                     || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                    && !((ShortcutInfo) item).isPromise()) {
                // Shortcuts need some special checks due to legacy reasons.
                startShortcutIntentSafely(intent, optsBundle, item);
            } else if (user == null || user.equals(Process.myUserHandle())) {
                // Could be launching some bookkeeping activity
                /** * 2. 執行 Activity 的 startActivity 函數 */
                startActivity(intent, optsBundle);
            } else {
                LauncherAppsCompat.getInstance(this).startActivityForProfile(
                        intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
            }
            return true;
        } catch (ActivityNotFoundException|SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + item + " intent=" + intent, e);
        }
        return false;
    }
複製代碼

註釋 1 處爲將要啓動的 Activity 添加 Flag 爲 Intent.FLAG_ACTIVITY_NEW_TASK 模式,表明啓動的 Activity 將在新的任務棧中啓動,註釋 2 處調用 Activity 內部的函數 startActivity,詳細代碼以下:

//Activity.java
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        /** * 判斷是否有傳參行爲 */
        if (options != null) {
            /** * 1. 調用 Activity startActivityForResult 函數,將參數傳遞下去 */
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }
複製代碼

在 Activity startActivity 函數中最終會調用 startActivityForResult 函數,第二個參數 -1 表明 Activity 不須要知道結果,第三個參數就是啓動設置進去的參數 Bundle,接着咱們看註釋 1 處調用的源碼

//Activity.java
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
        /** * 1. mParent 表明 Activity 的父類 */
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);

            /** * Instrumentation:主要用來監控應用程序和系統的交互 * * 2. 調用 Instrumentation 的 execStartActivity 函數。 * */
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                /** * 3. 內部給 Activity onActivityResult 回調 */
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
          ...
        } else {
            ...
        }
    }
複製代碼

註釋 1 處的 mParent 表明的是 Activity 的類型,表示當前 Activity 的父類。由於目前根 Activity 尚未建立出來,所以判斷成立執行註釋 2 Instrumentation 的 execStartActivity 函數,註釋 3 就是若是是以 startActivityForResult 函數啓動的 Activity 那麼就會回調給 Activity結果。咱們看註釋 2 的源碼實現,以下:

//Instrumentation.java
    public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
      	//1. 拿到 IAPPlicationThead 這個類能夠說是是啓動 Activity 的關鍵
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ....
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            /** * 2. 拿到 AMS 代理對象 IActivityManager 調用 startActivity 函數 */
            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;
    }
複製代碼

首先拿到 IApplicationThead . aidl 進程間通訊方式,而後拿到 AMS 代理對象 IActivityManager .aidl ,調用 aidl 中的 startActivity 函數最後在 AMS 中執行。咱們來看下 ActivityManager.getService() 實現,代碼以下:

//ActivityManager.java
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                  	//1. 拿到 AMS 的引用
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                  	//2. 
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
複製代碼

getService 函數調用 IActivityManagerSingleton 的 get 函數 ,IActivityManagerSingleton 是一個 Singleton 類。最後會直接回調到 AMS 中的 startActivity 函數。

AMS 到 ApplicationThread 的調用過程

Launcher 請求 AMS 後,代碼邏輯就已經執行到了 AMS 也就是系統 SystemServer 進程中了,接着 AMS 到 ApplicationThread 的調用流程,時序圖以下:

KfMa4S.png

上一小節咱們知道,在 Instrumentation 類中最後會經過獲取 AMS 代理類 IActivityManager ,而後調用 startActivity 利用 aidl 進程間通訊,最後會執行 AMS 中的 startActivity 函數,代碼以下:

//AMS.java

    /** * Instrumentation startActivity 傳遞過來的 * @param caller * @param callingPackage * @param intent * @param resolvedType * @param resultTo * @param resultWho * @param requestCode * @param startFlags * @param profilerInfo * @param bOptions * @return */
    @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) {
        /** * 調用內部 startActivityAsUser 函數 */
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }


    @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) {
        /** * 1. 判斷調用者進程是否被隔離 */
        enforceNotIsolatedCaller("startActivity");
        /** * 2. 檢查調用者權限 */
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        /** * 3. 調用 ActivityStarter 的 startActivityMayWait 函數,啓動的理由 */
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }
複製代碼

在 AMS 的 startActivity 函數中調用內部的 startActivityAsUser 函數,在該函數中咱們主要作了 3 個步驟

  1. 判斷調用者進程是否被隔離
  2. 檢查調用者權限
  3. 調用 ActivityStarter 的 startActivityMayWait 函數,啓動 Activity 的理由

startActivityMayWait 函數中須要注意倒數第二個參數 TaskRecord,表明啓動的 Activity 任務棧,最後一個是啓動的理由

註釋 3 代碼以下:

//ActivityStarter.java
    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) {

...
            /** * ActivityStarter 是加載 Activity 控制類,會蒐集全部的邏輯來決定若是將 Intent 和 Flags 轉換爲 Activity ,並將Activity 和 Task 以及 Stack 相關聯。 */
            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);


...
}
複製代碼

ActivityStarter 是 7.0 中新加入的類,它是加載 Activity 的控制類,會收集全部的邏輯來決定若是將 Intent 和 Flag 轉爲 Activity ,並將 Activity 和 Task 以及 Stack 相關聯。

繼續看內部 startActivityLocked 調用,代碼以下:

//ActivityStarter.java
    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) {

        /** * 1. 判斷啓動的理由不爲空 */
        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;

        /** * 2. 繼續調用當前類裏面的 startActivity 函數 */
        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);

        if (outActivity != null) {
            // mLastStartActivityRecord[0] is set in the call to startActivity above.
            outActivity[0] = mLastStartActivityRecord[0];
        }
        return mLastStartActivityResult;
    }
複製代碼

判斷啓動的理由,而後繼續調用 startActivity 函數,代碼以下:

//ActivityStarter.java

    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) {
 ...
        /** * 1. 判斷 IApplicationThread 是否爲空 */
        if (caller != null) {
            /** * 1.1 獲得 Launcher 所在進程 */
            callerApp = mService.getRecordForAppLocked(caller);
            /** * 1.2 得到 Launcher 進程的 pid , uid */
            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;
            }
        }
			...

        /** * 2. 建立即將要啓動 Activity 的描述類 */
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, container, options, sourceRecord);
        if (outActivity != null) {
            /** * 3. 將建立的 ActivityRecord 賦值給 ActivityRecord 數組的第一個位置,最後會把 outActivity 傳遞給 startActivity */
            outActivity[0] = r;
        }

        if (r.appTimeTracker == null && sourceRecord != null) {
            // If the caller didn't specify an explicit time tracker, we want to continue
            // tracking under any it has.
            r.appTimeTracker = sourceRecord.appTimeTracker;
        }

       ...

        doPendingActivityLaunchesLocked(false);


        /** * 4. 繼續調用內部的 startActivity 函數 */
        return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
                options, inTask, outActivity);
    }
複製代碼

該類函數邏輯比較多,大概以上面註釋總結了幾點小點

  1. 判斷上層傳遞過來的 IApplicationThread 是否爲空,由於這裏咱們是一路傳遞下來的,因此不爲空。
  2. 註釋 1.1 處調用 AMS 的 getRecordForAppLocked 函數獲得的表明 Launcher 進程的 callerApp 對象,它是 ProcessRecord 類型的, ProcessRecord 用於描述一個應用程序進程。
  3. 建立 ActivityRecord 類,用於描述一個 Activity 全部的信息。
  4. 將建立出來 ActivityRecord 賦值給 ActivityRecord 數組的第一個位置
  5. 繼續調用內部重載函數 startActivity 把 啓動 Activity 的描述信息也一併傳遞過去。

接下來咱們看註釋 4 的代碼實現:

//ActivityStarter.java
    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 {
            /** * 拿到 WMS */
            mService.mWindowManager.deferSurfaceLayout();
            /** * 繼續調用內部函數 startActivityUnchecked */
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } finally {
            ....

        return result;
    }
複製代碼

接着調用 ActivityStarter 內部函數 startActivityUnchecked

//ActivityStarter.java
    /** * 主要處理 棧管理相關的邏輯 * @param r * @param sourceRecord * @param voiceSession * @param voiceInteractor * @param startFlags * @param doResume * @param options * @param inTask * @param outActivity * @return */
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) {

        ...
          
        /** * 1. 判斷條件是否知足,是不是 新建立的任務棧模式 */
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            /** * 2. 建立新的 TaskRecord ,用來描述 Activity 任務棧 */
            result = setTaskFromReuseOrCreateNewTask(
                    taskToAffiliate, preferredLaunchStackId, topStack);
        } else if (mSourceRecord != null) {
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            setTaskToCurrentTopOrCreateNewTask();
        }
        ...
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTask().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ...
                mWindowManager.executeAppTransition();
            } else {
               ...
                if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                /** * 3. 調用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 函數 */
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
       ...
        return START_SUCCESS;
    }
複製代碼

startActivityUnchecked 函數主要處理與棧管理相關的邏輯。在註釋 1 處咱們得知啓動 Activity 時會將 Intent 的

Flag 設置爲 FLAG_ACTIVITY_NEW_TASK 模式,這樣註釋 1 條件知足,接着執行註釋 2 處的 setTaskFromReuseOrCreateNewTask 函數,其內部會建立一個新的 TaskRecord ,用來描述一個 Activity 的任務棧。在註釋 3 處會調用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 函數,代碼以下所示:

//ActivityStackSupervisor.java
    boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        //須要啓動的目標棧不爲空,而且啓動的棧跟須要啓動棧同樣就執行
        if (targetStack != null && isFocusedStack(targetStack)) {
            /** * ActivityStack 描述堆棧的 */
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        /** * 1. 獲取須要啓動的 Activity 所在棧的棧頂 不是處於中止狀態的 ActivityRecord */
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        /** * 2. 若是 ActivityRecord 不爲 null,或者要啓動的 Activity 的狀態不是Resumed 狀態 */
        if (r == null || r.state != RESUMED) {
            /** * 3.表明是即將啓動的 Activity */
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }
複製代碼

這裏主要是獲取正在運行的任務棧,若是獲取到的棧不爲空而且不是 Resumed 狀態 ,那麼就表明即將要啓動一個新的 Activity,註釋 3 的代碼以下:

//ActivityStack.java
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
       ...
        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            /** * 1.調用內部 resumeTopActivityInnerLocked 函數 */
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        mStackSupervisor.checkReadyForSleepLocked();

        return result;
    }
複製代碼

把 mStackSupervisor.inResumeTopActivity 設置爲 true ,而後繼續調用內部 resumeTopActivityInnerLocked 函數,代碼以下:

//ActivityStack.java
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
       ...

            /** * 1. 調用 startSpecificActivityLocked 函數 */
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return true;
    }
複製代碼

該函數邏輯處理比較多,咱們只關注註釋 1 的調用

//ActivityStackSupervisor.java
    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        /** * 1. 獲取即將啓動的 Activity 所在的應用程序進程 */
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);

        /** * 2. 判斷要啓動的 Activity 所在的應用程序進程若是已經運行的話,就會調用註釋 3 */
        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                   
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                /** * 3. 若是已經正在運行調用 realStartActivityLocked 函數 */
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
               ...
            }

        }
				//4. 
        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
複製代碼

這裏主要判斷當前啓動 Activity 所在的進程是否已經運行,若是運行調用註釋 3 ,若是處於沒有運行的狀態調用註釋 4,最後會通知 AMS 與 Zygote 通訊請求建立一個新的進程,這裏咱們直接看註釋 3

//ActivityStackSupervisor.java
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException {
			
      ...
            
        /*** 這裏的 app.thread 表明的是 IApplicationThread ,調用它內部 scheduleLaunchActivity 函 數, * 它的實如今 ActivityThread 的內部類 ApplicationThread ,其中 ApplicationThread 繼承了 IApplicationThread.Stub., * app 指的是Activity 所在的應用程序進程。 */

            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) {
            ...

        return true;
    }
複製代碼

這裏只拿出了核心代碼,注意看上面代碼,這裏說明一下,app.thread 指的就是 IApplicationThread, 它的實現類在 ActivityThread 的內部類,其中 ApplicationThread 繼承了 IApplicationThread.Stub。app 指的是傳入的要啓動的 Activity 所在應用程序進程,所以,這段代碼指的就是要在目標應用進程進行啓動 Activity 。當前代碼邏輯運行在 AMS 所在的 SystemServer 進程中,經過 ApplicationThread 來與應用程序進程進行 Binder 通訊,換句話說,ApplicationThread 是 SystemServer 和應用程序進程通訊的中間人。

KfddeS.png

到這裏下面就該看 ActivityThread 類裏面執行 Activity 任務了,由下一小節詳細講解。

ActivityThread 啓動 Activity 過程

經過上一小節講解的內容,咱們知道目前已經運行在了應用程序進程中,先來看一下 ActivityThread 啓動 Activity 的時序圖

Kfwth9.png

接着咱們來看 ActivityThread 內部類 ApplicationThread 的 scheduleLaunchActivity 函數,ActivityThread 在應用程序進程建立成功後會運行在當前進程的主線程中。scheduleLaunchActivity 代碼以下:

//ActivityThread.java
public final class ActivityThread {
 ...
   
 private class ApplicationThread extends IApplicationThread.Stub {  
   
 ...
 
 private class ApplicationThread extends IApplicationThread.Stub {
   
 ....
   
         /** * Launcher 點擊應用圖標啓動對應的應用 .... -> ActivityStackSupervisor . realStartActivityLocked 函數調用 * @param intent * @param token * @param ident * @param info * @param curConfig * @param overrideConfig * @param compatInfo * @param referrer * @param voiceInteractor * @param procState * @param state * @param persistentState * @param pendingResults * @param pendingNewIntents * @param notResumed * @param isForward * @param profilerInfo */
        @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

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

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

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

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);
            /** * 1. 調用內部 sendMessage 函數,將啓動 Activity 的信息封裝成 ActivityClientRecord 對象,而後跟 H.LAUNCH_ACTIVITY 一塊兒傳遞下去 */
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
   
 ...
 }
   
 ...
}
複製代碼

上面代碼中的 ActivityClientRecord 類會把啓動 Activity 全部傳遞過來的參數所有封裝進去,而後調用內部 sendMessage 函數(**ps:這裏記住 H.LAUNCH_ACTIVITY **),代碼以下:

//ActivityThread.java 
	private void sendMessage(int what, Object obj) {
        /** * 繼續調用內部重載函數 what = H.LAUNCH_ACTIVITY */

        sendMessage(what, obj, 0, 0, false);
    }
複製代碼

繼續調用重載函數

//ActivityThread.java

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        /** * 2. 經過 H 的 Handler 將 what = H.LAUNCH_ACTIVITY 消息 what 發送出去 */
        mH.sendMessage(msg);
    }
複製代碼

mH 是 AcitivtyThread 非靜態內部類,它繼承自 Handler,下面咱們看下 H 是實現

//ActivityThread.java
public final class ActivityThread {
  
//應用程序進程 主線程 H 
final H mH = new H(); 
  
  ......
    
 private class H extends Handler {
 
  //啓動 Activity 標誌
  public static final int LAUNCH_ACTIVITY         = 100;
    
    public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                /** * 1. 收到發送過來 LAUNCH_ACTIVITY 標誌的消息 */
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    /** * 1.1 拿到封裝啓動 Activity 信息的 ActivityClientRecord 類 */
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    /** * 1.2 經過 getPackageInfoNoCheck 函數得到 LoadedApk 類型的對象並賦值給 ActivityClientRecord 的成員變量 packageInfo。 * 應用程序進程要啓動 Activity 時,須要將該 Activity 所屬的 APK 加載進來,而 LoadedApk 就是用來描述已加載的 APk 文件的。 */
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    /** * 1.3 調用內部 handleLaunchActivity */
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                
                
               ....
  ......
}
複製代碼

在上一小節咱們知道由 mH.sendMessage 將標誌 LAUNCH_ACTIVITY 的消息發送到了 H 類,請看上面註釋 1 表明接收發送過來 LAUNCH_ACTIVITY 的消息入口,註釋 1.1 表明拿到封裝啓動 Activity 信息,註釋 1.2 拿到 加載 APK 的描述類 LoadedApk,最後調用註釋 3 ,代碼以下:

//ActivityThread.java
    /** * *啓動 Activity * @param r * @param customIntent * @param reason */
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
       ...

        /** * 1. 實施啓動 Activity 的實例 */
        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            /** * 2. 將 Activity 的狀態設置爲 Resume */
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);

            if (!r.activity.mFinished && r.startsNotResumed) {
               ...
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
           
            try {
                /** * 若是出現異常,中止 Activity */
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }
複製代碼

該函數經過 performLaunchActivity 函數啓動了 Activity ,而且將 啓動的 Activity 執行了 onCreate 生命週期函數,註釋 2 表明將啓動的 Activity 設置爲可交互的生命週期狀態,固然若是內部執行錯誤,又會以 aidl 的形式通知 AMS 關閉當前 Activity。

咱們先看註釋 1 代碼以下:

//ActivityThread.java


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

        /** * 1. 經過封裝啓動 Activity 信息類 ActivityClientRecord 來獲取到 ActivityInfo */
        ActivityInfo aInfo = r.activityInfo;
        /** * 2. 若是 r.packageInfo == null 就獲取 LoadedApk 實例 */
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        /** * 3. 經過封裝啓動 Activity 信息類 ActivityClientRecord 來獲取啓動 Activity 組件的 ComponentName */
        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);
        }
        /** * 4. 建立Activity 中的上下文環境 */
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            /** * 拿到當前上下文加載的 ClassLoader 加載器 */
            java.lang.ClassLoader cl = appContext.getClassLoader();
            /** * 5. 調用 Instrumentation.newActivity 函數 ,內部經過 ClassLoader 類加載器來建立 Activity 的實例 */
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            /** * 6. 獲得 Application 對象 */
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

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

            if (activity != null) {

                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (r.overrideConfig != null) {
                    config.updateFrom(r.overrideConfig);
                }
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
                /** * 7. 將 appContext 等對象依附在 Activity 的 attach 函數中,進行 Activity attach 初始化 */
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);

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

                activity.mCalled = false;
                //是不是持久化
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    /** * 8. 內部調用 Activity 的 onCreate 方法 */
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

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

        return activity;
    }
複製代碼

根據個人上面註釋能夠看出來 ,該函數裏面幾乎每一行代碼都是核心代碼,那麼內部主要乾了些什麼了,這裏就簡單說一下,由於上面註釋真的已經很清楚了,拿到啓動 Activity 組件 Component 的信息,經過 Instrumentation 類的 newActivity 函數,內部是經過 ClassLoader 的 loadClass 實例化了 Activity, 拿到 Application 進行與 Activity 綁定,最後調用 Instrumentation 函數的 callActivityOnCreate 執行了 Activity onCreate 生命週期 這裏我就拿 註釋 5,6,8 來看一下源碼,由於比較典型,註釋 5 代碼以下

//Instrumentation.java
	public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        //經過 ClassLoader 實例化了 Activity 
        return (Activity)cl.loadClass(className).newInstance();
    }
複製代碼

註釋 6 ,代碼以下

//LoadApk.java

    public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
        /** * 若是 mApplication 已經建立了就直接返回 */
        if (mApplication != null) {
            return mApplication;
        }

       ...

        Application app = null;

       ...

        try {
            ...
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            /** * 內部經過反射實例化 Application */
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
           ...
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

        ....

        return app;
    }
複製代碼

這裏拿到緩存 mApplication ,由於在建立應用程序進程的時候 Application 已經被實例化了,有不明白的能夠看 Android 8.0 源碼分析 (三) 應用程序進程建立到應用程序啓動的過程 該文章。

註釋 8 代碼以下:

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

    final void performCreate(Bundle icicle) {
      ....
        //調用Activity 生命週期 onCreate 函數
        onCreate(icicle);
      ...
     
    }
複製代碼

到這裏 Launcher 點擊應用圖標到啓動應用程序的根 Activity 已經啓動了,啓動根 Activity 中涉及到的進程有 4 個分別爲 Zygote 進程、Launcher 桌面進程、SystemServer 進程、應用程序進程。過程比較複雜,涉及知識點比較多,若是想詳細瞭解的,建議能夠跟着個人源碼分析,而後本身跟一遍,這樣效果最好。

應用程序內部 startActivity 調用過程

根 Activity 啓動成功了以後,應用程序啓動 Activity 就簡單多了,我這裏簡單說一點,由於剩下邏輯都同樣。

從應用程序中咱們本身調用 startActivity(Intent intent) 會直接調用 Activity 以下代碼:

//Activity.java
    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }
複製代碼

執行內部重載 startActivity(intent, null); 函數

@Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        /** * 判斷是否有傳參行爲 */
        if (options != null) {
            /** * 1. 調用 Activity startActivityForResult 函數,將參數傳遞下去 */
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }
複製代碼

看到這裏是否已經有一點影響了,就是咱們最開始講過的,在 應用程序根 Activity 啓動過程#Launcher請求 AMS 過程 小節中,後面邏輯就徹底同樣了,因此再也不將第二遍了。其中本身應用程序涉及到的進程就 2 個,一個是本身的應用程序進程,另外一個就是 AMS 所在的 SystemServer 進程,ActivityThread 是跟着當前啓動的組件進程走。

到這裏 Activity 啓動過程就將完了,不知道你們有沒有看明白,不明白了能夠跟着個人思路本身跟一下源碼,若是仍是不明白,那麼個人好好反思一下,是否是我描述的有問題了。

下面我就簡單以一張圖來總結下 Launcher 啓動應用程序根 Activity 所通過的進程。

總結

這裏就以一張圖片來簡單歸納一下啓動根 Activity 進程間交互的時序圖,相信這張圖會比較容易理解一點。

Kfg29O.png

參考

  • 《Android 進階解密》
相關文章
相關標籤/搜索