Android 10 Activity啟動流程

今天開始寫Android 10 Activity啟動流程,主要目的在于鞏固自己學(xué)到掂榔。

每次調(diào)用startActivity到顯示新的Activity的過程,我從未關(guān)心過,不知道它是否跨進程調(diào)用寨昙,垮了幾次進程,進程之間是如何通信掀亩,任務(wù)棧關(guān)系如何毅待,每個Activity的信息又是如何處理,進程之間Activity又是如何做到消息同步等等

調(diào)用startActivity()最后代碼執(zhí)行都會跳轉(zhuǎn)到startActivityForResult()

 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
           ...
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }
  1. 參數(shù)mMainThread.getApplicationThread()實際是ApplicationThread归榕,是ActivityThread內(nèi)部類尸红,繼承IApplicationThread.Stub,通過繼承能看出提供給其他進程調(diào)用刹泄。

  2. 參數(shù)mToken我們要記住它外里,它是負責(zé)跨進程通信(Activity跨進程信息同步)。舉例:ActivityA跳轉(zhuǎn)到ActivityB此時mToken不為空特石,讓下一個進程能找到ActivityA信息盅蝗。

  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(who);
            int result = ActivityTaskManager.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;
    }

此時我們可以看到啟動Activity馬上要跨進程

//frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                true /*validateIncomingUser*/);
    }

    int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        enforceNotIsolatedCaller("startActivityAsUser");

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

        // TODO: Switch to user app stacks here.
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
 ActivityStarter setMayWait(int userId) {
        mRequest.mayWait = true;
        mRequest.userId = userId;

        return this;
    }

通過上面代碼,現(xiàn)在代碼分析到ActivityTaskManagerService 繼承IActivityTaskManager.Stub 姆蘸,這個進程主要是分擔(dān)了ActivityManagerService的一些功能墩莫。我們可以主要到setMayWait(userId),幫助我們分析跳轉(zhuǎn)到下面方法的走向逞敷。

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
  int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) {
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                        mRequest.intent, mRequest.resolvedType,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                        mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            } else {
                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            }
        } finally {
            onExecutionComplete();
        }
    }

  private int startActivityMayWait(IApplicationThread caller, int callingUid,
                                     String callingPackage, int requestRealCallingPid, int requestRealCallingUid,
                                     Intent intent, String resolvedType, IVoiceInteractionSession voiceSession,
                                     IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode,
                                     int startFlags, ProfilerInfo profilerInfo, WaitResult outResult,
                                     Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
                                     int userId, TaskRecord inTask, String reason,
                                     boolean allowPendingRemoteAnimationRegistryLookup,
                                     PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
        
        ...
        //解析數(shù)據(jù)
        ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                0 /* matchFlags */,
                computeResolveFilterUid(
                        callingUid, realCallingUid, mRequest.filterCallingUid));
        ...
        // Collect information about the target of the Intent.
        ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

        ...

        final ActivityRecord[] outRecord = new ActivityRecord[1];
        int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
                    voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
                    ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
                    allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
                    allowBackgroundActivityStart);

        Binder.restoreCallingIdentity(origId);
        ...
        return res;
        }
    }
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,
                              SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
                              ActivityRecord[] outActivity, TaskRecord inTask, String reason,
                              boolean allowPendingRemoteAnimationRegistryLookup,
                              PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {

        ...
        mLastStartActivityRecord[0] = null;

        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                inTask, allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent,
                allowBackgroundActivityStart);

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

        return getExternalResult(mLastStartActivityResult);
    }
    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,
                              SafeActivityOptions options,
                              boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
                              TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup,
                              PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
        ...

        ActivityRecord sourceRecord = null;
        ActivityRecord resultRecord = null;
        if (resultTo != null) {
            //
            sourceRecord = mRootActivityContainer.isInAnyStack(resultTo);
            if (sourceRecord != null) {
                if (requestCode >= 0 && !sourceRecord.finishing) {
                    resultRecord = sourceRecord;
                }
            }
        }
        
        ...
        
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
                resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
                mSupervisor, checkedOptions, sourceRecord);
        ...
        mController.doPendingActivityLaunches(false);

        final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true /* doResume */, checkedOptions, inTask, outActivity, restrictedBgActivity);
        ...
        return res;
    }
//frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
     ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
            int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent,
            String _resolvedType, ActivityInfo aInfo, Configuration _configuration,
            ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
            boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
            ActivityOptions options, ActivityRecord sourceRecord) {
        mAtmService = _service;
        mRootActivityContainer = _service.mRootActivityContainer;
        appToken = new Token(this, _intent);
      ...
    }
    static class Token extends IApplicationToken.Stub {
        private final WeakReference<ActivityRecord> weakActivity;
        private final String name;

        Token(ActivityRecord activity, Intent intent) {
            weakActivity = new WeakReference<>(activity);
            name = intent.getComponent().flattenToShortString();
        }

        private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
            if (token == null) {
                return null;
            }
            ActivityRecord r = token.weakActivity.get();
            if (r == null || r.getActivityStack() == null) {
                return null;
            }
            return r;
        }
}

ActivityRecord的大量成員變量都是記錄Activity相關(guān)信息狂秦,每個Activity都有一個ActivityRecord。
局部變量 sourceRecord 這是發(fā)起啟動Activity的信息推捐,這個resultTo都是之前提到啟動Activity的參數(shù)mToken裂问。然后我們都要為新的Activity創(chuàng)建新的ActivityRecord, 在創(chuàng)建此對象的時候一起創(chuàng)建了的Token對象并且把ActivityRecord一起關(guān)聯(lián)。繼續(xù)在同一個類分析

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
                              IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                              int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
                              ActivityRecord[] outActivity, boolean restrictedBgActivity) {
        int result = START_CANCELED;
        final ActivityStack startedActivityStack;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity, restrictedBgActivity);
        } finally {
            ...
        }

        return result;
    }

  private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity, boolean restrictedBgActivity) {
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor, restrictedBgActivity);

        ...

        boolean newTask = false;
        final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
                ? mSourceRecord.getTaskRecord() : null;

        // Should this be considered a new task?
        int result = START_SUCCESS;
        if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
                && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
            newTask = true;
            // 1 創(chuàng)建所需要的 ActivityDisplay,ActivityStack堪簿,TaskRecord
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);
        } else if (mSourceRecord != null) {
            result = setTaskFromSourceRecord();
        } else if (mInTask != null) {
            result = setTaskFromInTask();
        } else {
            // This not being started from an existing activity, and not part of a new task...
            // just put it in the top task, though these days this case should never happen.
            result = setTaskToCurrentTopOrCreateNewTask();
        }
        ...
        if (mDoResume) {
            final ActivityRecord topTaskActivity =
                    mStartActivity.getTaskRecord().topRunningActivityLocked();
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                // If the activity is not focusable, we can't resume it, but still would like to
                // make sure it becomes visible as it starts (this will also trigger entry
                // animation). An example of this are PIP activities.
                // Also, we don't want to resume activities in a task that currently has an overlay
                // as the starting activity just needs to be in the visible paused state until the
                // over is removed.
                mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS);
                // Go ahead and tell window manager to execute app transition for this activity
                // since the app transition will not be triggered through the resume channel.
                mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
            } else {
                // If the target stack was not previously focusable (previous top running activity
                // on that stack was not visible) then any prior calls to move the stack to the
                // will not update the focused stack.  If starting the new activity now allows the
                // task stack to be focusable, then ensure that we now update the focused stack
                // accordingly.
                if (mTargetStack.isFocusable()
                        && !mRootActivityContainer.isTopDisplayFocusedStack(mTargetStack)) {
                    mTargetStack.moveToFront("startActivityUnchecked");
                }
                //2 與應(yīng)用層交互
                mRootActivityContainer.resumeFocusedStacksTopActivities(
                        mTargetStack, mStartActivity, mOptions);
            }
        } else if (mStartActivity != null) {
            mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord());
        }
        ...

        return START_SUCCESS;
    }

上述代碼和下面的代碼是同一個類里面痊乾,下面代碼分為4個點,后面會一一列出來分析

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
        if (mRestrictedBgActivity && (mReuseTask == null || !mReuseTask.containsAppUid(mCallingUid))
                && handleBackgroundActivityAbort(mStartActivity)) {
            return START_ABORTED;
        }

        //1.獲取或者創(chuàng)建合適任務(wù)ActivityStack對象椭更,里面創(chuàng)建的ActivityDisplay且與之關(guān)聯(lián)
        mTargetStack = computeStackFocus(mStartActivity, true, mLaunchFlags, mOptions);

        // Do no move the target stack to front yet, as we might bail if
        // isLockTaskModeViolation fails below.

        if (mReuseTask == null) {
            //2.ActivityStack 創(chuàng)建TaskRecord實例并且與之關(guān)聯(lián)添加到 mTaskHistory
            final TaskRecord task = mTargetStack.createTaskRecord(
                    mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
                    mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                    mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                    mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
                    mOptions);
            //3.TaskRecord與ActivityRecord關(guān)聯(lián)
            addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
            updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds);

            if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
                    + " in new task " + mStartActivity.getTaskRecord());
        } else {
            addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
        }

        if (taskToAffiliate != null) {
            mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
        }

        if (mService.getLockTaskController().isLockTaskModeViolation(
                mStartActivity.getTaskRecord())) {
            Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
            return START_RETURN_LOCK_TASK_MODE_VIOLATION;
        }

        if (mDoResume) {
            //4.將要顯示的ActivityStack移動到棧頂
            mTargetStack.moveToFront("reuseOrNewTask");
        }
        return START_SUCCESS;
    }

上述代碼做了4件事情哪审,分別用代碼一一闡述

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
  private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
            ActivityOptions aOptions) {
        final TaskRecord task = r.getTaskRecord();
        ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
        if (stack != null) {
            return stack;
        }
}

 private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task,
            ActivityOptions aOptions) {
        // We are reusing a task, keep the stack!
        if (mReuseTask != null) {
            return mReuseTask.getStack();
        }

        if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
                 || mPreferredDisplayId != DEFAULT_DISPLAY) {
            final boolean onTop = aOptions == null || !aOptions.getAvoidMoveToFront();
            final ActivityStack stack =
                    mRootActivityContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams);
            return stack;
        }
}
//frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
 <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
                                               @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
                                               @Nullable LaunchParamsController.LaunchParams launchParams) {
        int taskId = INVALID_TASK_ID;
        int displayId = INVALID_DISPLAY;
        //Rect bounds = null;
        ...
        if (displayId != INVALID_DISPLAY && canLaunchOnDisplay(r, displayId)) {
            if (r != null) {
                //獲取在ActivityDisplay最頂端的stack
                stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
                        launchParams);
                if (stack != null) {
                    return stack;
                }
            }

            //如果發(fā)現(xiàn)沒有現(xiàn)成的ActivityDisplay則創(chuàng)建它并且添加到此類的mActivityDisplays與之關(guān)聯(lián)
            final ActivityDisplay display = getActivityDisplayOrCreate(displayId);
            if (display != null) {
                // 在ActivityDisplay創(chuàng)建ActivityStack對象,并且添加到ActivityDisplay的mStacks關(guān)聯(lián)
                stack = display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
                if (stack != null) {
                    return stack;
                }
            }
        }

        ...

        return display.getOrCreateStack(r, options, candidateTask, activityType, onTop);
    }

1.首先在RootActivityContainer這個類創(chuàng)建ActivityDisplay(主屏幕)對象虑瀑,然后添加在數(shù)組RootActivityContainer.mActivityDisplays與之關(guān)聯(lián)协饲。在ActivityDisplay創(chuàng)建ActivityStack對象,并且添加到ActivityDisplay的mStacks關(guān)聯(lián)缴川。

//frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
 TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            boolean toTop, ActivityRecord activity, ActivityRecord source,
            ActivityOptions options) {
        //創(chuàng)建實例
        final TaskRecord task = TaskRecord.create(
                mService, taskId, info, intent, voiceSession, voiceInteractor);
        // add the task to stack first, mTaskPositioner might need the stack association
        //實例添加到ActivityStack.mTaskHistory與之關(guān)聯(lián)
        addTask(task, toTop, "createTaskRecord");
        ...
        return task;
    }

2.在ActivityStack創(chuàng)建TaskRecord對象茉稠,并且添加到數(shù)組ActivityStack.mTaskHistory與之關(guān)聯(lián)。
3.這里都不把代碼貼出來把夸,其實都是ActivityRecord對象添加到數(shù)組TaskRecord.mActivities中且與之關(guān)聯(lián)而线。
4.將要顯示的ActivityStack移動到棧頂。
如圖所示他們之間的關(guān)系恋日,



以上都是ActivityDisplay膀篮,ActivityStack,TaskRecord岂膳,ActivityRecord他們之間的關(guān)系誓竿,了解了他們之間關(guān)系,對我們分析Activity啟動流程很重要谈截。

接下來我們分析發(fā)起調(diào)用的Activity執(zhí)行暫停過程

//frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity, boolean restrictedBgActivity) {
        setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
                voiceInteractor, restrictedBgActivity);
...
            // 1 創(chuàng)建所需要的 ActivityDisplay筷屡,ActivityStack,TaskRecord
            result = setTaskFromReuseOrCreateNewTask(taskToAffiliate);

...
            //2 與應(yīng)用層交互
         mRootActivityContainer.resumeFocusedStacksTopActivities(
                        mTargetStack, mStartActivity, mOptions);
...
}

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

        ...
        if (targetStack != null && (targetStack.isTopStackOnDisplay()
                || getTopDisplayFocusedStack() == targetStack)) {
            result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
       ...
}
//frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mInResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mInResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
            ...
        } finally {
            mInResumeTopActivity = false;
        }

        return result;
    }

 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        ...
        boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            //暫停上一個activity
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
       ...
         //是否有所屬的進程
        if (next.attachedToProcess()) {
           ...
            
            try {
                final ClientTransaction transaction =
                        ClientTransaction.obtain(next.app.getThread(), next.appToken);
                // Deliver all pending results.
                ArrayList<ResultInfo> a = next.results;
                if (a != null) {
                    final int N = a.size();
                    if (!next.finishing && N > 0) {
                        if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
                                "Delivering results to " + next + ": " + a);
                        transaction.addCallback(ActivityResultItem.obtain(a));
                    }
                }

                if (next.newIntents != null) {
                    transaction.addCallback(
                            NewIntentItem.obtain(next.newIntents, true /* resume */));
                }

                // Well the app will no longer be stopped.
                // Clear app token stopped state in window manager if needed.
                next.notifyAppResumed(next.stopped);
                ...
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                getDisplay().mDisplayContent.isNextTransitionForward()));
                mService.getLifecycleManager().scheduleTransaction(transaction);

            } catch (Exception e) {
                // Whoops, need to restart this activity!
                if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
                        + lastState + ": " + next);
                next.setState(lastState, "resumeTopActivityInnerLocked");

                // lastResumedActivity being non-null implies there is a lastStack present.
                if (lastResumedActivity != null) {
                    lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
                }

                Slog.i(TAG, "Restarting because process died: " + next);
                if (!next.hasBeenLaunched) {
                    next.hasBeenLaunched = true;
                } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null
                        && lastFocusedStack.isTopStackOnDisplay()) {
                    next.showStartingWindow(null /* prev */, false /* newTask */,
                            false /* taskSwitch */);
                }
                mStackSupervisor.startSpecificActivityLocked(next, true, false);
                return true;
            }

            
        } else {
            //開始啟動activity
            mStackSupervisor.startSpecificActivityLocked(next, true, true);
        }

        return true;
    }

final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
                                     ActivityRecord resuming, boolean pauseImmediately) {
        ...
    
        if (prev.attachedToProcess()) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
                        prev.shortComponentName, "userLeaving=" + userLeaving);
              //執(zhí)行下面代碼
            mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
                        prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
                                prev.configChangeFlags, pauseImmediately));
            } catch (Exception e) {
                ...
            }
        } 
        ...
    }

經(jīng)過上述流程簸喂,最后執(zhí)行到了startPausingLocked這個方法毙死。在調(diào)用scheduleTransaction方法是有個參數(shù)appToken需要我們留意,看是如何與應(yīng)用進程Activity關(guān)聯(lián)的喻鳄,參數(shù)ActivityLifecycleItem看下面源碼分析扼倘。

//frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
   void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
                            @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
       final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
               stateRequest);
       scheduleTransaction(clientTransaction);
   }
   private static ClientTransaction transactionWithState(@NonNull IApplicationThread client,
           @NonNull IBinder activityToken, @NonNull ActivityLifecycleItem stateRequest) {
       final ClientTransaction clientTransaction = ClientTransaction.obtain(client, activityToken);
       clientTransaction.setLifecycleStateRequest(stateRequest);
       return clientTransaction;
   }
  void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
       final IApplicationThread client = transaction.getClient();
       transaction.schedule();
       if (!(client instanceof Binder)) {
           // If client is not an instance of Binder - it's a remote call and at this point it is
           // safe to recycle the object. All objects used for local calls will be recycled after
           // the transaction is executed on client in ActivityThread.
           transaction.recycle();
       }
   }
//frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
public void schedule() throws RemoteException {
       mClient.scheduleTransaction(this);
   }

   //frameworks/base/core/java/android/app/servertransaction
   public class PauseActivityItem extends ActivityLifecycleItem {
      
       @Override
       public void execute(ClientTransactionHandler client, IBinder token,
                           PendingTransactionActions pendingActions) {
           Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
           client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
                   "PAUSE_ACTIVITY_ITEM");
           Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
       }

       @Override
       public int getTargetState() {
           return ON_PAUSE;
       }

       @Override
       public void postExecute(ClientTransactionHandler client, IBinder token,
                               PendingTransactionActions pendingActions) {
           if (mDontReport) {
               return;
           }
           try {
               // TODO(lifecycler): Use interface callback instead of AMS.
//AMS需要同步數(shù)據(jù)了
               ActivityTaskManager.getService().
(token);
           } catch (RemoteException ex) {
               throw ex.rethrowFromSystemServer();
           }
       }
   }

在上述的代碼可以看出 ,最終調(diào)用了IApplicationThread.scheduleTransaction()方法實現(xiàn)了跨進程調(diào)用除呵,現(xiàn)在我們看下PauseActivityItem這個類再菊,它繼承ClientTransactionItem,這個類最終繼承了BaseClientRequest颜曾,實現(xiàn)了execute()方法纠拔,我先提一下,等會再下面的分析有用泛啸。

public final class ActivityThread extends ClientTransactionHandler {
   private class ApplicationThread extends IApplicationThread.Stub   
   {
        //上述代碼最終調(diào)用到這個方法
       @Override
        public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
            ActivityThread.this.scheduleTransaction(transaction);
        }
   }
  class H extends Handler {
       case EXECUTE_TRANSACTION:
                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
                    mTransactionExecutor.execute(transaction);
                    if (isSystem()) {
                        // Client transactions inside system process are recycled on the client side
                        // instead of ClientLifecycleManager to avoid being cleared before this
                        // message is handled.
                        transaction.recycle();
                    }
                    // TODO(lifecycler): Recycle locally scheduled transactions.
                    break;
   }
}
public abstract class ClientTransactionHandler {
    void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    }
}

先代碼執(zhí)行到應(yīng)用進程里了绿语,ActivityThread有個內(nèi)部類H繼承了Handler秃症,通過發(fā)送指令EXECUTE_TRANSACTION候址,執(zhí)行TransactionExecutor.execute方法吕粹。

//frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
        ...
        final IBinder token = transaction.getActivityToken();
       ...
        executeCallbacks(transaction);
       //通過前后源碼分析 執(zhí)行這個方法暫停Activity
        executeLifecycleState(transaction);
        mPendingActions.clear();
        if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
    }

/** Transition to the final state if requested by the transaction. */
    private void executeLifecycleState(ClientTransaction transaction) {
        final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
        if (lifecycleItem == null) {
            // No lifecycle request, return early.
            return;
        }

        //這個token都是之前我反復(fù)提到的 appToken
        final IBinder token = transaction.getActivityToken();
        //1.這個ActivityClientRecord 都是記錄應(yīng)用進程Activity的信息,在地層都是通過這個token獲取底層的這個ActivityRecord
        final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
        if (DEBUG_RESOLVER) {
            Slog.d(TAG, tId(transaction) + "Resolving lifecycle state: "
                    + lifecycleItem + " for activity: "
                    + getShortActivityName(token, mTransactionHandler));
        }

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

        // Cycle to the state right before the final requested state.
        cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);

        // Execute the final transition with proper parameters.
        //2.開始執(zhí)行生命周期
        lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
        lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
    }

上述代碼有兩點需要我們注意
1.應(yīng)用進程使用token都可以獲取得到ActivityClientRecord岗仑,ActivityClientRecord 都是記錄應(yīng)用進程Activity的信息匹耕,在實例化ActivityClientRecord時候與之關(guān)聯(lián)token(后面創(chuàng)建Activity源碼會分析到)。
ActivityTaskManagerService 進程ActivityRecord記錄的是Activity信息荠雕,在實例化ActivityRecord 都實例化了Token這個類并且持有ActivityRecord這個類的引用稳其。
2.這都開始執(zhí)行了暫停Activity的調(diào)用,都是前面提到的類PauseActivityItem執(zhí)行execute()炸卑。

當我們看到下面代碼的時候既鞠,有一種豁然開朗的感覺,離我們的目的地原來越近了盖文。

//ActivityThread.java
 @Override
    public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
            int configChanges, PendingTransactionActions pendingActions, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(r, finished, reason, pendingActions);

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }
            mSomeActivitiesChanged = true;
        }
    }

 private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
            PendingTransactionActions pendingActions) {
       ...

        // Pre-Honeycomb apps always save their state before pausing
        final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
        if (shouldSaveState) {
            callActivityOnSaveInstanceState(r);
        }

        performPauseActivityIfNeeded(r, reason);

        ...
        return shouldSaveState ? r.state : null;
    }

private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
        if (r.paused) {
            // You are already paused silly...
            return;
        }

        // Always reporting top resumed position loss when pausing an activity. If necessary, it
        // will be restored in performResumeActivity().
        reportTopResumedActivityChanged(r, false /* onTop */, "pausing");

        try {
            r.activity.mCalled = false;
            //這個方法都是調(diào)用了 activity.performPause();
            mInstrumentation.callActivityOnPause(r.activity);
            if (!r.activity.mCalled) {
                throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
                        + " 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 "
                        + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
            }
        }
        r.setState(ON_PAUSE);
    }

上述代碼看出嘱蛋,最后調(diào)用了activity.performPause();
這里都完整的分析了AMS到應(yīng)用進程的暫停過程。

參考資料:Android 10.0 Activity啟動詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末五续,一起剝皮案震驚了整個濱河市洒敏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疙驾,老刑警劉巖凶伙,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異它碎,居然都是意外死亡函荣,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門扳肛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偏竟,“玉大人,你說我怎么就攤上這事敞峭∮荒保” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵旋讹,是天一觀的道長殖蚕。 經(jīng)常有香客問我,道長沉迹,這世上最難降的妖魔是什么蜈垮? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮移国,結(jié)果婚禮上篇恒,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好瓦糕,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布底洗。 她就那樣靜靜地躺著,像睡著了一般咕娄。 火紅的嫁衣襯著肌膚如雪亥揖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天圣勒,我揣著相機與錄音费变,去河邊找鬼。 笑死圣贸,一個胖子當著我的面吹牛挚歧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吁峻,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滑负,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了锡搜?” 一聲冷哼從身側(cè)響起橙困,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耕餐,沒想到半個月后凡傅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡肠缔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年夏跷,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片明未。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡槽华,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出趟妥,到底是詐尸還是另有隱情猫态,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布披摄,位于F島的核電站亲雪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疚膊。R本人自食惡果不足惜义辕,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寓盗。 院中可真熱鬧灌砖,春花似錦璧函、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至续镇,卻和暖如春美澳,著一層夾襖步出監(jiān)牢的瞬間销部,已是汗流浹背摸航。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舅桩,地道東北人酱虎。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像擂涛,于是被迫代替她去往敵國和親读串。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

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