Android AOSP 6.0.1 常規startActivity啓動流程分析

在App開發過程中,界面之間的跳轉非常頻繁,在一個Activity中啓動另一個Activity一般都是通過startActivity方法實現的。Activity如何在Framework中運作這是我多年以來的困惑之一。以下代碼分析基於Android 6.0.1,因爲筆者有臺Nexus 5,這款老爺機的最新代碼只能更新到6.0.1了。下面一段代碼是摘自某個Demo App中的啓動另一個Activity的代碼。

startActivity(Intent(this, DemoActivity::class.java))

startActivity方法的形參是一個Intent,我們很容易找到App中startActivity方法實際上是調用在Activity.java中的startActivity方法。

frameworks/base/core/java/android/app/Activity.java

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

緊接着調用了同名方法startActivity,只不過第二個參數爲null。

frameworks/base/core/java/android/app/Activity.java

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            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);
        }
    }

然後繼續調用startActivityForResult方法,由於我們沒有傳遞Bundle攜帶的附加參數,最後就會走到else分支。

frameworks/base/core/java/android/app/Activity.java

    public void startActivityForResult(Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

startActivityForResult方法調用帶有三個參數的重載版本,形參分別是Intent、請求碼和Bundle。給下面的函數傳遞的實參分別是從上面傳下來的Intent實例、-1和null。這個方法的作用對於App開發並不陌生,它是啓動希望在完成後得到結果的Activity,當此Activity退出時,將使用給定的requestCode調用onActivityResult()方法。

frameworks/base/core/java/android/app/Activity.java

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

            cancelInputsAndStartExitTransition(options);
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

mMainThread.getApplicationThread()拿到ApplicationThread,mToken是IBinder類型,execStartActivity方法是Instrumentation中定義的,馬上轉到Instrumentation類。

frameworks/base/core/java/android/app/Instrumentation.java

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

在execStartActivity函數中又調用了ActivityManagerNative.getDefault().startActivity(…),首先要搞清楚ActivityManagerNative.getDefault()返回了什麼?

frameworks/base/core/java/android/app/ActivityManagerNative.java

    /**
     * 檢索系統默認或全局 activity manager
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }

gDefault是一個全局變量,它是IActivityManager類型的單例對象。我們看到create()方法中從ServiceManager中getService(“activity”),這是使用Binder通信所必須的,返回ActivityManagerService的遠程接口,即ActivityManagerProxy。

frameworks/base/core/java/android/app/ActivityManagerNative.java

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

callingPackage ---- 當前Activity包名

resolvedType ---- 返回intent的MIME類型

frameworks/base/core/java/android/app/ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager {
    ......
    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }
    ......
}

接下來經過Binder通信調用了AMS的startActivity方法。

profilerInfo ---- 用於傳遞分析器設置的系統私有API。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
            resultWho, requestCode, startFlags, profilerInfo, options,
            UserHandle.getCallingUserId());
    }

startActivity函數內部實際調用了startActivityAsUser。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: 在此處切換到用戶app stacks
        return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, options, false, userId, null, null);
    }

mStackSupervisor是ActivityStackSupervisor類型對象,通過它運行所有的ActivityStack。

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.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 config,
            Bundle options, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
        // 拒絕可能的泄漏文件描述符
        if (intent != null && intent.hasFileDescriptors()) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        boolean componentSpecified = intent.getComponent() != null;

        // 不要修改客戶端的對象!
        intent = new Intent(intent);

        // 收集有關Intent目標的信息。
        ActivityInfo aInfo =
                resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);

        ActivityContainer container = (ActivityContainer)iContainer;
        synchronized (mService) {
            if (container != null && container.mParentActivity != null &&
                    container.mParentActivity.state != RESUMED) {
                // 如果未恢復父級 Activity,則無法啓動子級 Activity。
                return ActivityManager.START_CANCELED;
            }
            
            ......
            
            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho,
                    requestCode, callingPid, callingUid, callingPackage,
                    realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                    componentSpecified, null, container, inTask);

            ......

            return res;
        }
    }

函數startActivityLocked代碼非常冗長,結合system_process進程打印的Log,我們可以確定:

userId = 0

intent.toShortString(true, true, true, false) 爲 cmp=com.demo.framework/.DemoActivity

pid = 10124

I/ActivityManager: START u0 {cmp=com.demo.framework/.DemoActivity} from uid 10124 on display 0

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

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

        if (err == ActivityManager.START_SUCCESS) {
            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                    + "} from uid " + callingUid
                    + " on display " + (container == null ? (mFocusedStack == null ?
                            Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) :
                            (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
                                    container.mActivityDisplay.mDisplayId)));
        }

        ......
        // 創建 ActivityRecord
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, this, container, options);
        
        ......

        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);

        ......
        
        return err;
    }

轉入startActivityUncheckedLocked函數

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {
        ......

        // 查看Activity啓動模式,Demo中這幾種都沒配置
        final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
        final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
        final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;

        int launchFlags = intent.getFlags();
        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
                (launchSingleInstance || launchSingleTask)) {
            //不滿足此分支    
            ......
        } else {
            // 設置對應的launchFlags
            switch (r.info.documentLaunchMode) {
                case ActivityInfo.DOCUMENT_LAUNCH_NONE:
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
                    break;
                case ActivityInfo.DOCUMENT_LAUNCH_NEVER:
                    launchFlags &= ~Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
                    break;
            }
        }
        // 後臺啓動任務?
        final boolean launchTaskBehind = r.mLaunchTaskBehind
                && !launchSingleTask && !launchSingleInstance
                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;

        ......

        // 如果我們實際上要開始一項新任務,則在某些情況下,我們還想做多個任務。
        if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            if (launchTaskBehind
                    || r.info.documentLaunchMode == ActivityInfo.DOCUMENT_LAUNCH_ALWAYS) {
                launchFlags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
            }
        }

        ......

        // 如果調用者不是來自另一個 Ativity,而是給了我們明確的任務,他們希望我們啓動新的 Ativity,那麼讓我們來看看。
        if (sourceRecord == null && inTask != null && inTask.stack != null) {
            ......
        } else {
            inTask = null;
        }

        ActivityInfo newTaskInfo = null;
        Intent newTaskIntent = null;
        ActivityStack sourceStack;
        ......

        boolean movedHome = false;
        ActivityStack targetStack;

        intent.setFlags(launchFlags);
        final boolean noAnimation = (launchFlags & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0;

        // 我們可能想嘗試將新的 Ativity 放置到現有任務中。 
        // 如果目標 Ativity 是 singleTask 或 singleInstance,我們總是這樣做;
        // 如果已請求 NEW_TASK,我們也將執行此操作,並且沒有其他限定符告訴我們仍將其放置在新任務中:
        // 多任務,始終爲doc模式,或被要求將其作爲當前任務之後的新任務啓動 。
        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                || launchSingleInstance || launchSingleTask) {
            ......
        }

        if (r.packageName != null) {
            // 如果正在啓動的 Activity 與當前頂部的 Activity 相同,那麼我們需要檢查是否僅應啓動一次。
            ActivityStack topStack = mFocusedStack;
            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
            if (top != null && r.resultTo == null) {
                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                    if (top.app != null && top.app.thread != null) {
                        if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                            || launchSingleTop || launchSingleTask) {
                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
                                    top.task);
                            ......
                            return ActivityManager.START_DELIVERED_TO_TOP;
                        }
                    }
                }
            }

        } else {
            if (r.resultTo != null && r.resultTo.task.stack != null) {
                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
                        r.requestCode, Activity.RESULT_CANCELED, null);
            }
            ActivityOptions.abort(options);
            return ActivityManager.START_CLASS_NOT_FOUND;
        }

        boolean newTask = false;
        boolean keepCurTransition = false;

        TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ?
                sourceRecord.task : null;

        // Should this be considered a new task?
        if (r.resultTo == null && inTask == null && !addingToTask
                && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
            ......
        } else if (sourceRecord != null) {
            final TaskRecord sourceTask = sourceRecord.task;
            if (isLockTaskModeViolation(sourceTask)) {
                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            targetStack = sourceTask.stack;
            targetStack.moveToFront("sourceStackToFront");
            final TaskRecord topTask = targetStack.topTask();
            if (topTask != sourceTask) {
                targetStack.moveTaskToFrontLocked(sourceTask, noAnimation, options,
                        r.appTimeTracker, "sourceTaskToFront");
            }
            if (!addingToTask && (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
                // 在這種情況下,我們要向現有任務添加 Activity,但是如果 Activity 已經在運行,則要求調用者清除該任務。
                ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
                keepCurTransition = true;
                if (top != null) {
                    ......
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
            } else if (!addingToTask &&
                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
                // 在這種情況下,我們將在自己的任務中啓動一個 Activity ,
                // 該 Activity 可能已經在歷史記錄中的某個位置運行了,如果是這樣,我們希望將其放到棧的最前面。
                final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
                if (top != null) {
                    ......
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
            }
            // 現有 Activity 正在啓動該新 Activity ,因此我們希望將新 Activity 與啓動該 Activity 的任務保持在同一任務中。
            r.setTask(sourceTask, null);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                    + " in existing task " + r.task + " from source " + sourceRecord);

        } else if (inTask != null) {
            // 調用者要求在提供給我們的明確任務中啓動新 Activity 。
            if (isLockTaskModeViolation(inTask)) {
                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
            }
            targetStack = inTask.stack;
            targetStack.moveTaskToFrontLocked(inTask, noAnimation, options, r.appTimeTracker,
                    "inTaskToFront");

            // 檢查我們是否應該在任務中實際啓動新 Activity ,還是僅在頂部重用當前 Activity 。
            ActivityRecord top = inTask.getTopActivity();
            if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
                if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                        || launchSingleTop || launchSingleTask) {
                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
                        // 我們不需要啓動新的 Activity 
                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
                    }
                    top.deliverNewIntentLocked(callingUid, r.intent, r.launchedFromPackage);
                    return ActivityManager.START_DELIVERED_TO_TOP;
                }
            }

            if (!addingToTask) {
                // 我們實際上並不希望將此 Activity 添加到任務中,因此僅在此處停止,但仍告訴調用者我們已經使用了該 Intent。
                ActivityOptions.abort(options);
                return ActivityManager.START_TASK_TO_FRONT;
            }

            r.setTask(inTask, null);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                    + " in explicit task " + r.task);

        } else {
            // 這不是從現有 Activity 開始的,也不是新任務的一部分……只是將其放在任務棧頂上,儘管如今這種情況永遠不會發生。
            targetStack = computeStackFocus(r, newTask);
            targetStack.moveToFront("addingToTopTask");
            ActivityRecord prev = targetStack.topActivity();
            r.setTask(prev != null ? prev.task : targetStack.createTaskRecord(getNextTaskId(),
                            r.info, intent, null, null, true), null);
            mWindowManager.moveTaskToTop(r.task.taskId);
            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + r
                    + " in new guessed " + r.task);
        }

        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                intent, r.getUriPermissionsLocked(), r.userId);

        if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
            r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
        }
        if (newTask) {
            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
        }
        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
        targetStack.mLastPausedActivity = null;
        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
        if (!launchTaskBehind) {
            // Don't set focus on an activity that's going to the back.
            mService.setFocusedActivityLocked(r, "startedActivity");
        }
        return ActivityManager.START_SUCCESS;
    }

targetStack是ActivityStack類型,它是管理 Activity 的任務棧。接着調用它的startActivityLocked函數。

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

    final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
        TaskRecord rTask = r.task;
        final int taskId = rTask.taskId;
        ......
        TaskRecord task = null;
        if (!newTask) {
            // 開始從一個存在的任務棧中查找
            boolean startIt = true;
            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                task = mTaskHistory.get(taskNdx);
                if (task.getTopActivity() == null) {
                    // 任務中所有的 Activity 都已經結束掉了
                    continue;
                }
                if (task == r.task) {
                    // 找到了! 現在,如果對用戶尚不可見,則無需啓動即可添加它;當用戶導航回它時它將啓動。
                    if (!startIt) {
                        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
                                + task, new RuntimeException("here").fillInStackTrace());
                        task.addActivityToTop(r);
                        r.putInHistory();
                        mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                                r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                                (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0,
                                r.userId, r.info.configChanges, task.voiceSession != null,
                                r.mLaunchTaskBehind);
                        if (VALIDATE_TOKENS) {
                            validateAppTokensLocked();
                        }
                        ActivityOptions.abort(options);
                        return;
                    }
                    break;
                } else if (task.numFullscreen > 0) {
                    startIt = false;
                }
            }
        }

        // 將新 Activity 放在任務棧頂部,以便與用戶進行交互。

        // 如果我們沒有將新 Activity 放在最前面,我們不想將 onUserLeaving 回調傳遞到實際最前面的 Activity 
        if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
            mStackSupervisor.mUserLeaving = false;
            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                    "startActivity() behind front, mUserLeaving=false");
        }

        task = r.task;

        // 將 Activity 放入歷史記錄棧並繼續
        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
                new RuntimeException("here").fillInStackTrace());
        task.addActivityToTop(r);
        task.setFrontOfTask();

        r.putInHistory();
        if (!isHomeStack() || numActivities() > 0) {
            // 如果我們要切換到新任務,或者當前未運行下一個 Activity 的流程,我們想顯示啓動預覽窗口。
            boolean showStartingIcon = newTask;
            ProcessRecord proc = r.app;
            if (proc == null) {
                proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
            }
            if (proc == null || proc.thread == null) {
                showStartingIcon = true;
            }
            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                    "Prepare open transition: starting " + r);
            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
                mNoAnimActivities.add(r);
            } else {
                mWindowManager.prepareAppTransition(newTask
                        ? r.mLaunchTaskBehind
                                ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
                                : AppTransition.TRANSIT_TASK_OPEN
                        : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
                mNoAnimActivities.remove(r);
            }
            mWindowManager.addAppToken(task.mActivities.indexOf(r),
                    r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                    (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
            boolean doShow = true;
            if (newTask) {
                // 即使此 Activity 剛剛開始,我們仍然需要對其進行重置,
                // 以確保我們應用關聯性將任何其他任務中現有的 Activity 移入其中。 
                // 如果調用方已請求重置目標任務,請執行此操作。
                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
                    resetTaskIfNeededLocked(r, r);
                    doShow = topRunningNonDelayedActivityLocked(null) == r;
                }
            } else if (options != null && new ActivityOptions(options).getAnimationType()
                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
                doShow = false;
            }
            if (r.mLaunchTaskBehind) {
                // 不要爲 mLaunchTaskBehind 做一個開始窗口。 更重要的是,確保我們告訴 WindowManager 即使 r 在任務棧的後面,r 還是可見的。
                mWindowManager.setAppVisibility(r.appToken, true);
                ensureActivitiesVisibleLocked(null, 0);
            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
                // 確定我們是否要從另一個 Activity (與下一個 Activity 具有相同的啓動圖標)過渡。 
                // 這允許窗口管理器保留它以前創建的前一個窗口(如果仍有的話)。
                ActivityRecord prev = mResumedActivity;
                if (prev != null) {
                    // 在以下情況下,我們不想重複使用先前的開始預覽:
                    // (1)當前 Activity 處於不同的任務中。
                    if (prev.task != r.task) {
                        prev = null;
                    }
                    // (2)當前 Activity 已經顯示。
                    else if (prev.nowVisible) {
                        prev = null;
                    }
                }
                mWindowManager.setAppStartingWindow(
                        r.appToken, r.packageName, r.theme,
                        mService.compatibilityInfoForPackageLocked(
                                r.info.applicationInfo), r.nonLocalizedLabel,
                        r.labelRes, r.icon, r.logo, r.windowFlags,
                        prev != null ? prev.appToken : null, showStartingIcon);
                r.mStartingWindowShown = true;
            }
        } else {
            // 如果這是第一個 Activity ,請不要做任何動畫
            mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
                    r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
                    (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId,
                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
            ActivityOptions.abort(options);
            options = null;
        }
        if (VALIDATE_TOKENS) {
            validateAppTokensLocked();
        }

        if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

接着調用 ActivityStackSupervisor 對象的 resumeTopActivitiesLocked方法。這個函數調用 targetStack 的 resumeTopActivityLocked 方法。

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = mFocusedStack;
        }
        // 首先處理 targetStack
        boolean result = false;
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (stack == targetStack) {
                    // 已經在上面處理了
                    continue;
                }
                if (isFrontStack(stack)) {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

確保 ActivityStack 中的最頂部的 Activity 已恢復。查到 inResumeTopActivity 變量作用是防止以遞歸方式進入resumeTopActivityLocked()函數。

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
                mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
                mService.updateSleepIfNeededLocked();
            }
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        return result;
    }

下一步調用 resumeTopActivityInnerLocked 函數。

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

        ......

        // 如果我們當前正在暫停某個 Activity,那麼在此之前不要執行任何操作。
        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);

        // 我們需要開始暫停當前 Activity,以便恢復任務棧頂的 Activity...
        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }
        
        ......
        
        return true;
    }

開始暫停當前 Activity,以便啓動新的 Activity。

Start pausing the currently resumed activity. It is an error to call this if there is already an activity being paused or there is no resumed activity.

這個函數的註釋表明此函數負責暫停當前處於 resume 狀態的 Activity。

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
            boolean dontWait) {
            
        ......
        
        ActivityRecord prev = mResumedActivity;
        if (prev == null) {
            if (!resuming) {
                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
                mStackSupervisor.resumeTopActivitiesLocked();
            }
            return false;
        }

        if (mActivityContainer.mParentActivity == null) {
            // Top level stack, not a child. Look for child stacks.
            mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait);
        }

        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
        else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
        mResumedActivity = null;
        mPausingActivity = prev;
        mLastPausedActivity = prev;
        mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
        prev.state = ActivityState.PAUSING;
        prev.task.touchActiveTime();
        clearLaunchTime(prev);
        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
        if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) {
            prev.updateThumbnailLocked(screenshotActivities(prev), null);
        }
        stopFullyDrawnTraceIfNeeded();

        mService.updateCpuStats();

        if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                // 暫停之前的 Activity
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } catch (Exception e) {
                // Ignore exception, if process died other code will cleanup.
                Slog.w(TAG, "Exception thrown during pause", e);
                mPausingActivity = null;
                mLastPausedActivity = null;
                mLastNoHistoryActivity = null;
            }
        } else {
            mPausingActivity = null;
            mLastPausedActivity = null;
            mLastNoHistoryActivity = null;
        }

        // If we are not going to sleep, we want to ensure the device is
        // awake until the next activity is started.
        if (!uiSleeping && !mService.isSleepingOrShuttingDown()) {
            mStackSupervisor.acquireLaunchWakelock();
        }

        if (mPausingActivity != null) {
            // Have the window manager pause its key dispatching until the new
            // activity has started.  If we're pausing the activity just because
            // the screen is being turned off and the UI is sleeping, don't interrupt
            // key dispatch; the same activity will pick it up again on wakeup.
            if (!uiSleeping) {
                prev.pauseKeyDispatchingLocked();
            } else if (DEBUG_PAUSE) {
                 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
            }

            if (dontWait) {
                // 立即完成 Activity 暫停
                completePauseLocked(false);
                return false;

            } else {
                // Schedule a pause timeout in case the app doesn't respond.
                // We don't give it much time because this directly impacts the
                // responsiveness seen by the user.
                Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
                msg.obj = prev;
                prev.pauseTime = SystemClock.uptimeMillis();
                mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
                return true;
            }

        } else {
            ......
            
            return false;
        }
    }

prev.app.thread 經過查找 prev 是一個ActivityRecord對象,app 是一個 ProcessRecord 對象,thread 是 ApplicationThreadProxy 對象,接着調用它的 schedulePauseActivity 方法。

frameworks/base/core/java/android/app/ApplicationThreadNative.java

class ApplicationThreadProxy implements IApplicationThread {
    ......
    
    public final void schedulePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        data.writeInt(finished ? 1 : 0);
        data.writeInt(userLeaving ? 1 :0);
        data.writeInt(configChanges);
        data.writeInt(dontReport ? 1 : 0);
        mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }
    ......
}

通過 Binder 機制我們可以調用遠程方法 ApplicationThread 中的 schedulePauseActivity。此函數只是發送一個消息。

frameworks/base/core/java/android/app/ActivityThread.java

    private class ApplicationThread extends ApplicationThreadNative {
        ......

        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }
        ......
    }

實際發送消息是通過 mH 對象去做的,它是 H 類型。

frameworks/base/core/java/android/app/ActivityThread.java

public final class ActivityThread {

    final H mH = new H();
    
    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);
        }
        mH.sendMessage(msg);
    }
    ......
}

H 對象中 handleMessage 方法是處理髮送過來的消息的。

frameworks/base/core/java/android/app/ActivityThread.java

    private class H extends Handler {
        ......
        
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
            
                ......
                
                case PAUSE_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                
                ......
        }
    }

PAUSE_ACTIVITY 消息處理 case 中最終調用 handlePauseActivity 方法。

frameworks/base/core/java/android/app/ActivityThread.java

    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb());

            // 確保現在提交所有未決的寫入。
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // 告訴 activity manager 我們已經暫停了
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }
    // 根據 token 獲取 ActivityClientRecord類型 r 對象,然後調用重載版本函數
    final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState) {
        ActivityClientRecord r = mActivities.get(token);
        return r != null ? performPauseActivity(r, finished, saveState) : null;
    }

    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
        if (r.paused) {
            if (r.activity.mFinished) {
                // If we are finishing, we won't call onResume() in certain cases.
                // So here we likewise don't want to call onPause() if the activity
                // isn't resumed.
                return null;
            }
            RuntimeException e = new RuntimeException(
                    "Performing pause of activity that is not resumed: "
                    + r.intent.getComponent().toShortString());
            Slog.e(TAG, e.getMessage(), e);
        }
        if (finished) {
            r.activity.mFinished = true;
        }
        try {
            // 接下來讓 Activity 保存其當前狀態並管理對話框...
            if (!r.activity.mFinished && saveState) {
                callCallActivityOnSaveInstanceState(r);
            }
            // Now we are idle.
            r.activity.mCalled = false;
            mInstrumentation.callActivityOnPause(r.activity);
            EventLog.writeEvent(LOG_AM_ON_PAUSE_CALLED, UserHandle.myUserId(),
                    r.activity.getComponentName().getClassName());
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException(
                    "Activity " + r.intent.getComponent().toShortString() +
                    " did not call through to super.onPause()");
            }

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
            if (!mInstrumentation.onException(r.activity, e)) {
                throw new RuntimeException(
                        "Unable to pause activity "
                        + r.intent.getComponent().toShortString()
                        + ": " + e.toString(), e);
            }
        }
        r.paused = true;

        // Notify any outstanding on paused listeners
        ArrayList<OnActivityPausedListener> listeners;
        synchronized (mOnPauseListeners) {
            listeners = mOnPauseListeners.remove(r.activity);
        }
        int size = (listeners != null ? listeners.size() : 0);
        for (int i = 0; i < size; i++) {
            listeners.get(i).onPaused(r.activity);
        }

        return !r.activity.mFinished && saveState ? r.state : null;
    }

接着進入了mInstrumentation.callActivityOnPause(r.activity)方法。

frameworks/base/core/java/android/app/Instrumentation.java

    /* Perform calling of an activity's {@link Activity#onPause} method.  The
     * default implementation simply calls through to that method.
     * 
     * @param activity The activity being paused.
     */
    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }

執行 activity 的{Activity#onPause}方法的調用。 默認實現只是調用該方法。函數內的 onPause() 多麼親切,它正是我們經常要在 Activity 中重寫的 onPause() 函數。

frameworks/base/core/java/android/app/Activity.java

    final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

當一個 Activity 暫停以後,就會通知 AMS Activity 已經暫停了。

frameworks/base/core/java/android/app/ActivityThread.java

    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            ......
            // Log 明確 dontReport=false,告訴 activity manager 我們已經暫停了
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

ActivityManagerNative.getDefault() 拿到 ActivityManagerProxy 對象,通過 Binder 機制調用 AMS 的 activityPaused 方法。

frameworks/base/core/java/android/app/ActivityManagerNative.java

class ActivityManagerProxy implements IActivityManager
{
    ......
    public void activityPaused(IBinder token) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(token);
        mRemote.transact(ACTIVITY_PAUSED_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
    ......
}

這裏是 AMS 中的 activityPaused 方法。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    @Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }

以上進一步調用了 ActivityStack 的 activityPausedLocked 方法。此方法內部最終調用 completePauseLocked 完成暫停工作。

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

    final void activityPausedLocked(IBinder token, boolean timeout) {
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
            "Activity paused: token=" + token + ", timeout=" + timeout);

        final ActivityRecord r = isInStackLocked(token);
        if (r != null) {
            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
            if (mPausingActivity == r) {
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
                        + (timeout ? " (due to timeout)" : " (pause complete)"));
                completePauseLocked(true);
            } else {
                EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
                        r.userId, System.identityHashCode(r), r.shortComponentName,
                        mPausingActivity != null
                            ? mPausingActivity.shortComponentName : "(none)");
                if (r.finishing && r.state == ActivityState.PAUSING) {
                    if (DEBUG_PAUSE) Slog.v(TAG,
                            "Executing finish of failed to pause activity: " + r);
                    finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false);
                }
            }
        }
    }
    
    private void completePauseLocked(boolean resumeNext) {
        ......
        if (resumeNext) {
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            if (!mService.isSleepingOrShuttingDown()) {
                mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
            } else {
                mStackSupervisor.checkReadyForSleepLocked();
                ActivityRecord top = topStack.topRunningActivityLocked(null);
                if (top == null || (prev != null && top != prev)) {
                    // 如果沒有更多 Activity 可運行,則無論如何都要恢復以開始某些 Activity 運行。
                    mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
                }
            }
        }
        ......
    }

接着就會轉入 ActivityStackSupervisor 去調用 resumeTopActivitiesLocked。經過一些調用之後(同上)最後在 ActivityStack 類 resumeTopActivityInnerLocked 函數中調用了 mStackSupervisor.startSpecificActivityLocked(next, true, true)

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {

        ......

        if (next.app != null && next.app.thread != null) {
            ......
        } else {
            // Whoops, need to restart this activity!
            if (!next.hasBeenLaunched) {
                next.hasBeenLaunched = true;
            } else {
                if (SHOW_APP_STARTING_PREVIEW) {
                    mWindowManager.setAppStartingWindow(
                            next.appToken, next.packageName, next.theme,
                            mService.compatibilityInfoForPackageLocked(
                                    next.info.applicationInfo),
                            next.nonLocalizedLabel,
                            next.labelRes, next.icon, next.logo, next.windowFlags,
                            null, true);
                }
                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
            }
            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

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

下一步調用 realStartActivityLocked。

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

    void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // 這個 activity 的 application 是否已經運行?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // 如果它是標記爲可以在多個進程中運行的平臺組件,則不要添加此組件,
                    // 因爲它實際上是框架的一部分,因此在進程中作爲單獨的apk進行跟蹤沒有意義。
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
    
    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
            ......
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);  
            ......        
    }

下一步,app 是一個 ProcessRecord 對象,thread 是 ApplicationThreadProxy 對象,接着調用它的 scheduleLaunchActivity 方法。

frameworks/base/core/java/android/app/ApplicationThreadNative.java

class ApplicationThreadProxy implements IApplicationThread {
    ......
    
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        intent.writeToParcel(data, 0);
        data.writeStrongBinder(token);
        data.writeInt(ident);
        info.writeToParcel(data, 0);
        curConfig.writeToParcel(data, 0);
        if (overrideConfig != null) {
            data.writeInt(1);
            overrideConfig.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        compatInfo.writeToParcel(data, 0);
        data.writeString(referrer);
        data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
        data.writeInt(procState);
        data.writeBundle(state);
        data.writePersistableBundle(persistentState);
        data.writeTypedList(pendingResults);
        data.writeTypedList(pendingNewIntents);
        data.writeInt(notResumed ? 1 : 0);
        data.writeInt(isForward ? 1 : 0);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }
    ......
}

通過 Binder 機制我們可以調用遠程方法 ApplicationThread 中的 scheduleLaunchActivity。此函數只是發送一個消息。

frameworks/base/core/java/android/app/ActivityThread.java

    private class ApplicationThread extends ApplicationThreadNative {
    
        ......
        
        @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

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

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

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

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }
        
        ......
        
    }
    
    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);
        }
        mH.sendMessage(msg);
    }
    
    private class H extends Handler {
        ......
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                ......
            }
        }
        ......
    }
    
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

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

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

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

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

        Activity a = performLaunchActivity(r, customIntent);

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);

            if (!r.activity.mFinished && r.startsNotResumed) {
                // The activity manager actually wants this one to start out
                // paused, because it needs to be visible but isn't in the
                // foreground.  We accomplish this by going through the
                // normal startup (because activities expect to go through
                // onResume() the first time they run, before their window
                // is displayed), and then pausing it.  However, in this case
                // we do -not- need to do the full pause cycle (of freezing
                // and such) because the activity manager assumes it can just
                // retain the current state it has.
                try {
                    r.activity.mCalled = false;
                    mInstrumentation.callActivityOnPause(r.activity);
                    // We need to keep around the original state, in case
                    // we need to be created again.  But we only do this
                    // for pre-Honeycomb apps, which always save their state
                    // when pausing, so we can not have them save their state
                    // when restarting from a paused state.  For HC and later,
                    // we want to (and can) let the state be saved as the normal
                    // part of stopping the activity.
                    if (r.isPreHoneycomb()) {
                        r.state = oldState;
                    }
                    if (!r.activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPause()");
                    }

                } catch (SuperNotCalledException e) {
                    throw e;

                } catch (Exception e) {
                    if (!mInstrumentation.onException(r.activity, e)) {
                        throw new RuntimeException(
                                "Unable to pause activity "
                                + r.intent.getComponent().toShortString()
                                + ": " + e.toString(), e);
                    }
                }
                r.paused = true;
            }
        } else {
            // If there was an error, for any reason, tell the activity
            // manager to stop us.
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
            } catch (RemoteException ex) {
                // Ignore
            }
        }
    }
    
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    進入此分支
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }  
        ......
    }

下一步調用 Instrumentation 類型的 mInstrumentation 對象上的 callActivityOnCreate 方法。

frameworks/base/core/java/android/app/Instrumentation.java

    /**
     * Perform calling of an activity's {@link Activity#onCreate}
     * method.  The default implementation simply calls through to that method.
     *
     * @param activity The activity being created.
     * @param icicle The previously frozen state (or null) to pass through to onCreate().
     */
    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

最後進入 Activity 的 performCreate 看看。他最後調用了 Activity 中的 onCreate 方法。

frameworks/base/core/java/android/app/Activity.java

    final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }
    
    @MainThread
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
        if (mLastNonConfigurationInstances != null) {
            mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
        }
        if (mActivityInfo.parentActivityName != null) {
            if (mActionBar == null) {
                mEnableDefaultActionBarUp = true;
            } else {
                mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
            }
        }
        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                    ? mLastNonConfigurationInstances.fragments : null);
        }
        mFragments.dispatchCreate();
        getApplication().dispatchActivityCreated(this, savedInstanceState);
        if (mVoiceInteractor != null) {
            mVoiceInteractor.attachActivity(this);
        }
        mCalled = true;
    }

下面是調試跟蹤Log,對應的每個方法名都有打印,另外有一些首字母縮寫代表對應的類。

AMN ---- ActivityManagerNative,實際上是調用的內部ActivityManagerProxy

AMS ---- ActivityManagerService

ASS ---- ActivityStackSupervisor

AS ---- ActivityStack

ATP ---- ApplicationThreadProxy

07-06 20:45:38.474 2356-2356/com.demo.framework D/lhw: AMN startActivity callingPackage = com.demo.framework,resolvedType = null,resultWho = null,requestCode = -1,startFlags = 0
07-06 20:45:38.475 771-1744/system_process I/lhw: AMS startActivity callingPackage = com.demo.framework,resolvedType = null,resultWho = null,requestCode = -1,startFlags = 0
07-06 20:45:38.475 771-1744/system_process I/lhw: AMS startActivityAsUser callingPackage = com.demo.framework,resolvedType = null,resultWho = null,requestCode = -1,startFlags = 0,userId = 0
07-06 20:45:38.476 771-1744/system_process I/lhw: ASS startActivityMayWait callingUid = -1,callingPackage = com.demo.framework,resolvedType = null,resultWho = null,requestCode = -1,startFlags = 0,userId = 0
07-06 20:45:38.476 771-1744/system_process I/lhw: ASS startActivityLocked callingUid = -1,callingPackage = com.demo.framework,resolvedType = null,callingPid = -1,realCallingPid = 2356,realCallingUid = 10124,resultWho = null,requestCode = -1,startFlags = 0
07-06 20:45:38.476 771-1744/system_process I/lhw: ASS startActivityUncheckedLocked doResume = true,startFlags = 0
07-06 20:45:38.477 771-1744/system_process I/lhw: AS startActivityLocked doResume = true,newTask = false,keepCurTransition = false
07-06 20:45:38.477 771-1744/system_process I/lhw: ASS resumeTopActivitiesLocked
07-06 20:45:38.477 771-1744/system_process I/lhw: AS resumeTopActivityLocked
07-06 20:45:38.477 771-1744/system_process I/lhw: AS resumeTopActivityInnerLocked
07-06 20:45:38.477 771-1744/system_process I/lhw: AS resumeTopActivityInnerLocked startPausingLocked start Pausing = ActivityRecord{75912a6 u0 com.demo.framework/.MainActivity t530},pausing=false
07-06 20:45:38.477 771-1744/system_process I/lhw: AS startPausingLocked userLeaving=true,uiSleeping=false,resuming=true,dontWait=false
07-06 20:45:38.477 771-1744/system_process I/lhw: AS startPausingLocked Enqueueing pending pause:ActivityRecord{75912a6 u0 com.demo.framework/.MainActivity t530}
07-06 20:45:38.477 771-1744/system_process I/lhw: ATP schedulePauseActivity finished=false,userLeaving=true,configChanges=0,dontReport=false
07-06 20:45:38.477 2356-2367/com.demo.framework I/lhw: ApplicationThread schedulePauseActivity finished=false,userLeaving=true,configChanges=0,dontReport=false
07-06 20:45:38.477 2356-2367/com.demo.framework I/lhw: ActivityThread sendMessage SCHEDULE 101 101: 1 / android.os.BinderProxy@c3122b9
07-06 20:45:38.478 771-1744/system_process I/lhw: AS resumeTopActivityInnerLocked startPausingLocked end pausing = true
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: H handleMessage handling: 101
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: H handleMessage PAUSE_ACTIVITY case
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: ActivityThread handlePauseActivity finished=false,userLeaving=true,configChanges=0,dontReport=false
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: ActivityThread performPauseActivity finished=false,saveState=false
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: Instrumentation callActivityOnPause
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: Activity performPause
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: Activity onPause com.demo.framework.MainActivity@f9690ac
07-06 20:45:38.480 2356-2356/com.demo.framework I/lhw: ActivityManagerProxy activityPaused
07-06 20:45:38.481 771-1744/system_process V/lhw: AMS activityPaused: token=Token{6ffb4e7 ActivityRecord{75912a6 u0 com.demo.framework/.MainActivity t530}}
07-06 20:45:38.481 771-1744/system_process V/lhw: AS activityPausedLocked token=Token{6ffb4e7 ActivityRecord{75912a6 u0 com.demo.framework/.MainActivity t530}}, timeout=false
07-06 20:45:38.481 771-1744/system_process V/lhw: AS completePauseLocked resumeNext=true,Complete pause: ActivityRecord{75912a6 u0 com.demo.framework/.MainActivity t530}
07-06 20:45:38.481 771-1744/system_process I/lhw: ASS resumeTopActivitiesLocked
07-06 20:45:38.481 771-1744/system_process I/lhw: AS resumeTopActivityLocked
07-06 20:45:38.481 771-1744/system_process I/lhw: AS resumeTopActivityInnerLocked
07-06 20:45:38.481 771-1744/system_process I/lhw: AS resumeTopActivityLocked: Restarting ActivityRecord{99f7f24 u0 com.demo.framework/.DemoActivity t530}
07-06 20:45:38.481 771-1744/system_process I/lhw: ASS startSpecificActivityLocked andResume = true,checkConfig = true
07-06 20:45:38.481 771-1744/system_process I/lhw: ASS realStartActivityLocked andResume = true,checkConfig = true
07-06 20:45:38.482 771-1744/system_process I/lhw: ATP scheduleLaunchActivity referrer=com.demo.framework,notResumed=false,isForward=true,ident=161447716
07-06 20:45:38.483 2356-2394/com.demo.framework V/lhw: ApplicationThread scheduleLaunchActivity referrer=com.demo.framework,procState=2,notResumed=false,isForward=true
07-06 20:45:38.483 2356-2394/com.demo.framework I/lhw: ActivityThread sendMessage SCHEDULE 100 100: 0 / ActivityRecord{db690e token=android.os.BinderProxy@6422f2f {com.demo.framework/com.demo.framework.DemoActivity}}
07-06 20:45:38.489 2356-2356/com.demo.framework I/lhw: H handleMessage handling: 100
07-06 20:45:38.489 2356-2356/com.demo.framework I/lhw: H handleMessage LAUNCH_ACTIVITY case
07-06 20:45:38.489 2356-2356/com.demo.framework I/lhw: ActivityThread handleLaunchActivity r=ActivityRecord{db690e token=android.os.BinderProxy@6422f2f {com.demo.framework/com.demo.framework.DemoActivity}}
07-06 20:45:38.489 2356-2356/com.demo.framework I/lhw: ActivityThread performLaunchActivity r=ActivityRecord{db690e token=android.os.BinderProxy@6422f2f {com.demo.framework/com.demo.framework.DemoActivity}}
07-06 20:45:38.498 2356-2356/com.demo.framework I/lhw: Activity onCreate com.demo.framework.DemoActivity@f21b6c5: null

最後附上一張時序圖作爲總結
startActivity

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章