找回密码
 立即注册
首页 业界区 安全 startActivity到底发生了什么(二)

startActivity到底发生了什么(二)

归筠溪 前天 21:43
startActivity到底发生了什么(二)

启动另外一个应用的MainActivity
  1.         <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>
复制代码
注意必须设置exported为true才能被另一个进程启动。
  1. val intent = Intent()
  2. intent.setClassName("io.github.customview", "io.github.customview.activity.MainActivity")
  3. intent.putExtra("name", "ITGuoKe")
  4. context.startActivity(intent)
复制代码
启动另一个app的Activity,并传递参数。
app startActivity

context.startActivity(intent)通过多态实际上调用的是Activity的startActivity方法,然后startActivityForResult->Instrumentation.execStartActivity(注意是第四个参数为Activity的重载方法),最后IPC调用ActivityTaskManagerService的startActivity方法ActivityTaskManager.getService().startActivity.
系统服务ActivityTaskManagerService

startActivity -> startActivityAsUser -> getActivityStartController().obtainStarter
查看ActivityStartController的方法obtainStarter的源码如下
  1. ActivityStarter obtainStarter(Intent intent, String reason) {
  2.         return mFactory.obtain().setIntent(intent).setReason(reason);
  3. }
复制代码
然后查看ActivityStarter的execute的方法源码:
  1. int execute() {        // Required for logging ContentOrFileUriEventReported in the finally block.        String callerActivityName = null;        ActivityRecord launchingRecord = null;        try {                onExecutionStarted();                if (mRequest.intent != null) {                        // Refuse possible leaked file descriptors                        if (mRequest.intent.hasFileDescriptors()) {                                throw new IllegalArgumentException("File descriptors passed in Intent");                        }                        // Remove existing mismatch flag so it can be properly updated later                        mRequest.intent.removeExtendedFlags(Intent.EXTENDED_FLAG_FILTER_MISMATCH);                }                final LaunchingState launchingState;                synchronized (mService.mGlobalLock) {                        final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);                        final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID                                ?  Binder.getCallingUid() : mRequest.realCallingUid;                        launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(                                mRequest.intent, caller, callingUid);                        callerActivityName = caller != null ? caller.info.name : null;                }                if (mRequest.intent != null) {                        mRequest.componentSpecified |= mRequest.intent.getComponent() != null;                }                // If the caller hasn't already resolved the activity, we're willing                // to do so here. If the caller is already holding the WM lock here,                // and we need to check dynamic Uri permissions, then we're forced                // to assume those permissions are denied to avoid deadlocking.                if (mRequest.activityInfo == null) {                        mRequest.resolveActivity(mSupervisor);                }                // Add checkpoint for this shutdown or reboot attempt, so we can record the original                // intent action and package name.                if (mRequest.intent != null) {                        String intentAction = mRequest.intent.getAction();                        String callingPackage = mRequest.callingPackage;                        if (intentAction != null && callingPackage != null                                && (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)                                        || Intent.ACTION_SHUTDOWN.equals(intentAction)                                        || Intent.ACTION_REBOOT.equals(intentAction))) {                                ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);                        }                }                int res = START_CANCELED;                synchronized (mService.mGlobalLock) {                        final boolean globalConfigWillChange = mRequest.globalConfig != null                                && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;                        final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();                        if (rootTask != null) {                                rootTask.mConfigWillChange = globalConfigWillChange;                        }                        ProtoLog.v(WM_DEBUG_CONFIGURATION, "Starting activity when config "                                           + "will change = %b", globalConfigWillChange);                        final long origId = Binder.clearCallingIdentity();                        try {                                res = resolveToHeavyWeightSwitcherIfNeeded();                                if (res != START_SUCCESS) {                                        return res;                                }                                res = executeRequest(mRequest); // 1                        } finally {                                Binder.restoreCallingIdentity(origId);                                mRequest.logMessage.append(" result code=").append(res);                                Slog.i(TAG, mRequest.logMessage.toString());                                mRequest.logMessage.setLength(0);                        }                        if (globalConfigWillChange) {                                // If the caller also wants to switch to a new configuration, do so now.                                // This allows a clean switch, as we are waiting for the current activity                                // to pause (so we will not destroy it), and have not yet started the                                // next activity.                                mService.mAmInternal.enforceCallingPermission(                                        android.Manifest.permission.CHANGE_CONFIGURATION,                                        "updateConfiguration()");                                if (rootTask != null) {                                        rootTask.mConfigWillChange = false;                                }                                ProtoLog.v(WM_DEBUG_CONFIGURATION,        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>   "Updating to new configuration after starting activity.");                                mService.updateConfigurationLocked(mRequest.globalConfig, null, false);                        }                        // The original options may have additional info about metrics. The mOptions is not                        // used here because it may be cleared in setTargetRootTaskIfNeeded.                        final ActivityOptions originalOptions = mRequest.activityOptions != null                                ? mRequest.activityOptions.getOriginalOptions() : null;                        // Only track the launch time of activity that will be resumed.                        if (mDoResume || (isStartResultSuccessful(res)        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>          && mLastStartActivityRecord.getTask().isVisibleRequested())) {                                launchingRecord = mLastStartActivityRecord;                        }                        // If the new record is the one that started, a new activity has created.                        final boolean newActivityCreated = mStartActivity == launchingRecord;                        // Notify ActivityMetricsLogger that the activity has launched.                        // ActivityMetricsLogger will then wait for the windows to be drawn and populate                        // WaitResult.                        mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,        <intent-filter>
  10.                
  11.                 <category android:name="android.intent.category.LAUNCHER" />
  12.         </intent-filter>
  13. </activity>        <intent-filter>
  14.                
  15.                 <category android:name="android.intent.category.LAUNCHER" />
  16.         </intent-filter>
  17. </activity>        <intent-filter>
  18.                
  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.         </intent-filter>
  21. </activity>  newActivityCreated, launchingRecord, originalOptions);                        if (mRequest.waitResult != null) {                                mRequest.waitResult.result = res;                                res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,        <intent-filter>
  22.                
  23.                 <category android:name="android.intent.category.LAUNCHER" />
  24.         </intent-filter>
  25. </activity>                                 launchingState);                        }                        return getExternalResult(res);                }        } finally {                // Notify UriGrantsManagerService that activity launch completed. Required for logging                // the ContentOrFileUriEventReported message.                mSupervisor.mService.mUgmInternal.notifyActivityLaunchRequestCompleted(                        mRequest.hashCode(),                        // isSuccessfulLaunch                        launchingRecord != null,                        // Intent action                        mRequest.intent != null ? mRequest.intent.getAction() : null,                        mRequest.realCallingUid,                        callerActivityName,                        // Callee UID                        mRequest.activityInfo != null                        ? mRequest.activityInfo.applicationInfo.uid : INVALID_UID,                        // Callee Activity name                        mRequest.activityInfo != null ? mRequest.activityInfo.name : null,                        // isStartActivityForResult                        launchingRecord != null && launchingRecord.resultTo != null);                onExecutionComplete();        }}
复制代码
由注释1处的代码可知ActivityStarter的executeRequest源码如下:
  1. private int executeRequest(Request request) {        if (TextUtils.isEmpty(request.reason)) {                throw new IllegalArgumentException("Need to specify a reason.");        }        mLastStartReason = request.reason;        mLastStartActivityTimeMs = System.currentTimeMillis();        ...        final ActivityRecord r = new ActivityRecord.Builder(mService)                .setCaller(callerApp)                .setLaunchedFromPid(callingPid)                .setLaunchedFromUid(callingUid)                .setLaunchedFromPackage(callingPackage)                .setLaunchedFromFeature(callingFeatureId)                .setIntent(intent)                .setResolvedType(resolvedType)                .setActivityInfo(aInfo)                .setConfiguration(mService.getGlobalConfiguration())                .setResultTo(resultRecord)                .setResultWho(resultWho)                .setRequestCode(requestCode)                .setComponentSpecified(request.componentSpecified)                .setRootVoiceInteraction(voiceSession != null)                .setActivityOptions(checkedOptions)                .setSourceRecord(sourceRecord)                .build();        mLastStartActivityRecord = r;        if (r.appTimeTracker == null && sourceRecord != null) {                // If the caller didn't specify an explicit time tracker, we want to continue                // tracking under any it has.                r.appTimeTracker = sourceRecord.appTimeTracker;        }        // Only allow app switching to be resumed if activity is not a restricted background        // activity and target app is not home process, otherwise any background activity        // started in background task can stop home button protection mode.        // As the targeted app is not a home process and we don't need to wait for the 2nd        // activity to be started to resume app switching, we can just enable app switching        // directly.        WindowProcessController homeProcess = mService.mHomeProcess;        boolean isHomeProcess = homeProcess != null                && aInfo.applicationInfo.uid == homeProcess.mUid;        if (balVerdict.allows() && !isHomeProcess) {                mService.resumeAppSwitches();        }        // Only do the create here since startActivityInner can abort. If it doesn't abort,        // the requestStart will be sent in handleStartRequest.        final Transition newTransition = r.mTransitionController.isShellTransitionsEnabled()                ? r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN) : null;        // Because startActivity must run immediately, it can get combined with another        // transition meaning it is no-longer independent. This is NOT desirable, but is the        // only option for the time being.        final boolean isIndependent = newTransition != null;        final Transition transition = isIndependent ? newTransition                : mService.getTransitionController().getCollectingTransition();    // 1        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>          request.voiceInteractor, startFlags, checkedOptions,        <intent-filter>
  10.                
  11.                 <category android:name="android.intent.category.LAUNCHER" />
  12.         </intent-filter>
  13. </activity>        <intent-filter>
  14.                
  15.                 <category android:name="android.intent.category.LAUNCHER" />
  16.         </intent-filter>
  17. </activity>          inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid, transition,        <intent-filter>
  18.                
  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.         </intent-filter>
  21. </activity>        <intent-filter>
  22.                
  23.                 <category android:name="android.intent.category.LAUNCHER" />
  24.         </intent-filter>
  25. </activity>          isIndependent);        if (request.outActivity != null) {                request.outActivity[0] = mLastStartActivityRecord;        }        return mLastStartActivityResult;}
复制代码
由文档注释可知:
startActivityUnchecked -> startActivityInner
startActivityUnchecked源码如下:
ActivityStarter.java
  1. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, BalVerdict balVerdict,  NeededUriGrants intentGrants, int realCallingUid, Transition transition,   boolean isIndependentLaunch) {        int result = START_CANCELED;        final Task startedActivityRootTask;        RemoteTransition remoteTransition = r.takeRemoteTransition();        // Create a display snapshot as soon as possible.        if (isIndependentLaunch && mRequest.freezeScreen) {                final TaskDisplayArea tda = mLaunchParams.hasPreferredTaskDisplayArea()                        ? mLaunchParams.mPreferredTaskDisplayArea                        : mRootWindowContainer.getDefaultTaskDisplayArea();                final DisplayContent dc = mRootWindowContainer.getDisplayContentOrCreate(                        tda.getDisplayId());                if (dc != null) {                        transition.collect(dc);                        transition.collectVisibleChange(dc);                }        }        try {                mService.deferWindowLayout();                r.mTransitionController.collect(r);                try {                        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");                        result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, options, inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid);                } catch (Exception ex) {                        Slog.e(TAG, "Exception on startActivityInner", ex);                } finally {                        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);                        startedActivityRootTask = handleStartResult(r, options, result, isIndependentLaunch,        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>                remoteTransition, transition);                }        } finally {                mService.continueWindowLayout();        }        postStartActivityProcessing(r, result, startedActivityRootTask);        return result;}
复制代码
startActivityInner源码如下:
ActivityStarter.java
  1. /**     * Start an activity and determine if the activity should be adding to the top of an existing     * task or delivered new intent to an existing activity. Also manipulating the activity task     * onto requested or valid root-task/display.     *     * Note: This method should only be called from {@link #startActivityUnchecked}.     */// TODO(b/152429287): Make it easier to exercise code paths through startActivityInner@VisibleForTestingint startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,                                           IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,                                           int startFlags, ActivityOptions options, Task inTask,                                           TaskFragment inTaskFragment, BalVerdict balVerdict,                                           NeededUriGrants intentGrants, int realCallingUid) {        setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,                                        voiceSession, voiceInteractor, balVerdict.getCode(), realCallingUid);        computeLaunchingTaskFlags();        mIntent.setFlags(mLaunchFlags);        boolean dreamStopping = false;        if (!com.android.window.flags.Flags.removeActivityStarterDreamCallback()) {                for (ActivityRecord stoppingActivity : mSupervisor.mStoppingActivities) {                        if (stoppingActivity.getActivityType()                                == WindowConfiguration.ACTIVITY_TYPE_DREAM) {                                dreamStopping = true;                                break;                        }                }        }        // Get top task at beginning because the order may be changed when reusing existing task.        final Task prevTopRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();        final Task prevTopTask = prevTopRootTask != null ? prevTopRootTask.getTopLeafTask() : null;        final boolean sourceActivityLaunchedFromBubble =                sourceRecord != null && sourceRecord.getLaunchedFromBubble();        // if the flag is enabled, allow reusing bubbled tasks only if the source activity is        // bubbled.        final boolean includeLaunchedFromBubble =                Flags.onlyReuseBubbledTaskWhenLaunchedFromBubble()                ? sourceActivityLaunchedFromBubble : true;        final Task reusedTask = resolveReusableTask(includeLaunchedFromBubble);        // If requested, freeze the task list        if (mOptions != null && mOptions.freezeRecentTasksReordering()                && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid)                && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) {                mFrozeTaskList = true;                mSupervisor.mRecentTasks.setFreezeTaskListReordering();        }        // Compute if there is an existing task that should be used for.        final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask();        final boolean newTask = targetTask == null;        mTargetTask = targetTask;        computeLaunchParams(r, sourceRecord, targetTask);        // Check if starting activity on given task or on a new task is allowed.        int startResult = isAllowedToStart(r, newTask, targetTask);        if (startResult != START_SUCCESS) {                if (r.resultTo != null) {                        r.resultTo.sendResult(INVALID_UID, r.resultWho, r.requestCode, RESULT_CANCELED,        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>                  null /* data */, null /* callerToken */, null /* dataGrants */);                }                return startResult;        }        if (targetTask != null) {                if (targetTask.getTreeWeight() > MAX_TASK_WEIGHT_FOR_ADDING_ACTIVITY) {                        Slog.e(TAG, "Remove " + targetTask + " because it has contained too many"                                   + " activities or windows (abort starting " + r                                   + " from uid=" + mCallingUid);                        targetTask.removeImmediately("bulky-task");                        return START_ABORTED;                }                // When running transient transition, the transient launch target should keep on top.                // So disallow the transient hide activity to move itself to front, e.g. trampoline.                if (!avoidMoveToFront() && (mService.mHomeProcess == null        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>                        || mService.mHomeProcess.mUid != realCallingUid)                        && (prevTopTask != null && prevTopTask.isActivityTypeHomeOrRecents())                        && r.mTransitionController.isTransientHide(targetTask)) {                        mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_LEGACY;                }                // If the activity is started by sending a pending intent and only its creator has the                // privilege to allow BAL (its sender does not), avoid move it to the front. Only do                // this when it is not a new task and not already been marked as avoid move to front.                // Guarded by a flag: balDontBringExistingBackgroundTaskStackToFg                if (balDontBringExistingBackgroundTaskStackToFg() && !avoidMoveToFront()                        && balVerdict.onlyCreatorAllows()) {                        mCanMoveToFrontCode = MOVE_TO_FRONT_AVOID_PI_ONLY_CREATOR_ALLOWS;                }                mPriorAboveTask = TaskDisplayArea.getRootTaskAbove(targetTask.getRootTask());        }        final ActivityRecord targetTaskTop = newTask                ? null : targetTask.getTopNonFinishingActivity();        if (targetTaskTop != null) {                // Removes the existing singleInstance activity in another task (if any) while                // launching a singleInstance activity on sourceRecord's task.                if (LAUNCH_SINGLE_INSTANCE == mLaunchMode && mSourceRecord != null                        && targetTask == mSourceRecord.getTask()) {                        final ActivityRecord activity = mRootWindowContainer.findActivity(mIntent,        <intent-filter>
  10.                
  11.                 <category android:name="android.intent.category.LAUNCHER" />
  12.         </intent-filter>
  13. </activity>        <intent-filter>
  14.                
  15.                 <category android:name="android.intent.category.LAUNCHER" />
  16.         </intent-filter>
  17. </activity>        <intent-filter>
  18.                
  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.         </intent-filter>
  21. </activity>          mStartActivity.info, false);                        if (activity != null && activity.getTask() != targetTask) {                                activity.destroyIfPossible("Removes redundant singleInstance");                        }                }                if (mLastStartActivityRecord != null) {                        targetTaskTop.mLaunchSourceType = mLastStartActivityRecord.mLaunchSourceType;                }                targetTaskTop.mTransitionController.collect(targetTaskTop);                recordTransientLaunchIfNeeded(targetTaskTop);                // Recycle the target task for this launch.                startResult =                        recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants, balVerdict);                if (startResult != START_SUCCESS) {                        return startResult;                }        } else {                mAddingToTask = true;        }        // If the activity being launched is the same as the one currently at the top, then        // we need to check if it should only be launched once.        final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask();        if (topRootTask != null) {                startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants);                if (startResult != START_SUCCESS) {                        return startResult;                }        }        if (mTargetRootTask == null) {                mTargetRootTask = getOrCreateRootTask(mStartActivity, mLaunchFlags, targetTask,        <intent-filter>
  22.                
  23.                 <category android:name="android.intent.category.LAUNCHER" />
  24.         </intent-filter>
  25. </activity>                                          mOptions);        }        if (newTask) {                final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)                        ? mSourceRecord.getTask() : null;                setNewTask(taskToAffiliate);        } else if (mAddingToTask) {                addOrReparentStartingActivity(targetTask, "adding to task");        }        // After activity is attached to task, but before actual start        recordTransientLaunchIfNeeded(mLastStartActivityRecord);        if (mDoResume) {                if (!avoidMoveToFront()) {                        mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask);                        final boolean launchBehindDream;                        if (com.android.window.flags.Flags.removeActivityStarterDreamCallback()) {                                final TaskDisplayArea tda = mTargetRootTask.getTaskDisplayArea();                                final Task top = (tda != null ? tda.getTopRootTask() : null);                                launchBehindDream = (top != null && top != mTargetRootTask)                                        && top.getActivityType() == WindowConfiguration.ACTIVITY_TYPE_DREAM                                        && top.getTopNonFinishingActivity() != null;                        } else {                                launchBehindDream = !mTargetRootTask.isTopRootTaskInDisplayArea()                                        && mService.isDreaming()                                        && !dreamStopping;                        }                        if (launchBehindDream) {                                // Launching underneath dream activity (fullscreen, always-on-top). Run the                                // launch--behind transition so the Activity gets created and starts                                // in visible state.                                mLaunchTaskBehind = true;                                r.mLaunchTaskBehind = true;                        }                } else {                        logPIOnlyCreatorAllowsBAL();                }        }        mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,        <intent-filter>
  26.                
  27.                 <category android:name="android.intent.category.LAUNCHER" />
  28.         </intent-filter>
  29. </activity>        <intent-filter>
  30.                
  31.                 <category android:name="android.intent.category.LAUNCHER" />
  32.         </intent-filter>
  33. </activity>                                mStartActivity.getUriPermissionsLocked());        if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) {                // we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs                final PackageManagerInternal pmInternal =                        mService.getPackageManagerInternalLocked();                final int resultToUid = pmInternal.getPackageUid(                        mStartActivity.resultTo.info.packageName, 0 /* flags */,                        mStartActivity.mUserId);                pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,        <intent-filter>
  34.                
  35.                 <category android:name="android.intent.category.LAUNCHER" />
  36.         </intent-filter>
  37. </activity>                           UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,        <intent-filter>
  38.                
  39.                 <category android:name="android.intent.category.LAUNCHER" />
  40.         </intent-filter>
  41. </activity>                           resultToUid /*visible*/, true /*direct*/);        } else if (mStartActivity.mShareIdentity) {                final PackageManagerInternal pmInternal =                        mService.getPackageManagerInternalLocked();                pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent,        <intent-filter>
  42.                
  43.                 <category android:name="android.intent.category.LAUNCHER" />
  44.         </intent-filter>
  45. </activity>                           UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/,        <intent-filter>
  46.                
  47.                 <category android:name="android.intent.category.LAUNCHER" />
  48.         </intent-filter>
  49. </activity>                           r.launchedFromUid /*visible*/, true /*direct*/);        }        final Task startedTask = mStartActivity.getTask();        if (newTask) {                EventLogTags.writeWmCreateTask(mStartActivity.mUserId, startedTask.mTaskId,        <intent-filter>
  50.                
  51.                 <category android:name="android.intent.category.LAUNCHER" />
  52.         </intent-filter>
  53. </activity>                           startedTask.getRootTaskId(), startedTask.getDisplayId());        }        mStartActivity.logStartActivity(EventLogTags.WM_CREATE_ACTIVITY, startedTask);        mStartActivity.getTaskFragment().clearLastPausedActivity();        mRootWindowContainer.startPowerModeLaunchIfNeeded(                false /* forceSend */, mStartActivity);        final boolean isTaskSwitch = startedTask != prevTopTask;        mTargetRootTask.startActivityLocked(mStartActivity, topRootTask, newTask, isTaskSwitch,        <intent-filter>
  54.                
  55.                 <category android:name="android.intent.category.LAUNCHER" />
  56.         </intent-filter>
  57. </activity>                                mOptions, sourceRecord);        if (mDoResume) {                final ActivityRecord topTaskActivity = startedTask.topRunningActivityLocked();                if (!mTargetRootTask.isTopActivityFocusable()                        || (topTaskActivity != null && topTaskActivity.isTaskOverlay()                                && 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.                        // Passing {@code null} as the start parameter ensures all activities are made                        // visible.                        mTargetRootTask.ensureActivitiesVisible(null /* starting */);                        // 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.                        mTargetRootTask.mDisplayContent.executeAppTransition();                } else {                        // If the target root-task was not previously focusable (previous top running                        // activity on that root-task was not visible) then any prior calls to move the                        // root-task to the will not update the focused root-task.  If starting the new                        // activity now allows the task root-task to be focusable, then ensure that we                        // now update the focused root-task accordingly.                        if (mTargetRootTask.isTopActivityFocusable()                                && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) {                                if (!avoidMoveToFront()) {                                        mTargetRootTask.moveToFront("startActivityInner");                                } else {                                        logPIOnlyCreatorAllowsBAL();                                }                        }                        mRootWindowContainer.resumeFocusedTasksTopActivities(                                mTargetRootTask, mStartActivity, mOptions, mTransientLaunch); // 1                }        }        mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask);        // Update the recent tasks list immediately when the activity starts        mSupervisor.mRecentTasks.add(startedTask);        mSupervisor.handleNonResizableTaskIfNeeded(startedTask,        <intent-filter>
  58.                
  59.                 <category android:name="android.intent.category.LAUNCHER" />
  60.         </intent-filter>
  61. </activity>                                           mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask);        // If Activity's launching into PiP, move the mStartActivity immediately to pinned mode.        // Note that mStartActivity and source should be in the same Task at this point.        if (mOptions != null && mOptions.isLaunchIntoPip()                && sourceRecord != null && sourceRecord.getTask() == mStartActivity.getTask()                && balVerdict.allows()) {                mRootWindowContainer.moveActivityToPinnedRootTask(mStartActivity,        <intent-filter>
  62.                
  63.                 <category android:name="android.intent.category.LAUNCHER" />
  64.         </intent-filter>
  65. </activity>        <intent-filter>
  66.                
  67.                 <category android:name="android.intent.category.LAUNCHER" />
  68.         </intent-filter>
  69. </activity>                  sourceRecord, "launch-into-pip", null /* bounds */);        }        mSupervisor.getBackgroundActivityLaunchController()                .onNewActivityLaunched(mStartActivity);        return START_SUCCESS;}
复制代码
源码中
mStartActivity 是 ActivityStarter对象的ActivityRecord类型的成员变量.
mSupervisor是ActivityTaskSupervisor类型的对象,管理任务栈逻辑.
mRootWindowContainer是RootWindowContainer类型的对象.
我们看下RootWindowContainer类型的对象的resumeFocusedTasksTopActivities方法的源码:
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
  1. boolean resumeFocusedTasksTopActivities(        Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause) {        if (!mTaskSupervisor.readyToResume()) {                return false;        }        boolean result = false;        if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>                   || getTopDisplayFocusedRootTask() == targetRootTask)) {                result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>        <intent-filter>
  10.                
  11.                 <category android:name="android.intent.category.LAUNCHER" />
  12.         </intent-filter>
  13. </activity>                                 deferPause);        }        for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {                final DisplayContent display = getChildAt(displayNdx);                final boolean curResult = result;                boolean[] resumedOnDisplay = new boolean[1];                final ActivityRecord topOfDisplay = display.topRunningActivity();                display.forAllRootTasks(rootTask -> {                        final ActivityRecord topRunningActivity = rootTask.topRunningActivity();                        if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {                                return;                        }                        if (rootTask == targetRootTask) {                                // Simply update the result for targetRootTask because the targetRootTask                                // had already resumed in above. We don't want to resume it again,                                // especially in some cases, it would cause a second launch failure                                // if app process was dead.                                resumedOnDisplay[0] |= curResult;                                return;                        }                        if (topRunningActivity.isState(RESUMED) && topRunningActivity == topOfDisplay) {                                // Kick off any lingering app transitions form the MoveTaskToFront operation,                                // but only consider the top activity on that display.                                rootTask.executeAppTransition(targetOptions);                        } else {                                resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);                        }                });                result |= resumedOnDisplay[0];                if (!resumedOnDisplay[0]) {                        // In cases when there are no valid activities (e.g. device just booted or launcher                        // crashed) it's possible that nothing was resumed on a display. Requesting resume                        // of top activity in focused root task explicitly will make sure that at least home                        // activity is started and resumed, and no recursion occurs.                        final Task focusedRoot = display.getFocusedRootTask();                        if (focusedRoot != null) {                                result |= focusedRoot.resumeTopActivityUncheckedLocked(                                        target, targetOptions, false /* skipPause */); // 1                        } else if (targetRootTask == null) {                                result |= resumeHomeActivity(null /* prev */, "no-focusable-task",        <intent-filter>
  14.                
  15.                 <category android:name="android.intent.category.LAUNCHER" />
  16.         </intent-filter>
  17. </activity>                                         display.getDefaultTaskDisplayArea());                        }                }        }        return result;}
复制代码
focusedRoot是Task类型的对象,接下来查看方法resumeTopActivityUncheckedLocked的源码:
frameworks/base/services/core/java/com/android/server/wm/Task.java
  1. /**     * Ensure that the top activity in the root task is resumed.     *     * @param prev The previously resumed activity, for when in the process     * of pausing; can be null to call from elsewhere.     * @param options Activity options.     * @param deferPause When {@code true}, this will not pause back tasks.     *     * @return Returns true if something is being resumed, or false if     * nothing happened.     *     * NOTE: It is not safe to call this method directly as it can cause an activity in a     *       non-focused root task to be resumed.     *       Use {@link RootWindowContainer#resumeFocusedTasksTopActivities} to resume the     *       right activity for the current system state.     */@GuardedBy("mService")boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,  boolean deferPause) {        if (mInResumeTopActivity) {                // Don't even start recursing.                return false;        }        boolean someActivityResumed = false;        try {                // Protect against recursion.                mInResumeTopActivity = true;                if (isLeafTask()) {                        if (isFocusableAndVisible()) {                                someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);                        }                } else {                        int idx = mChildren.size() - 1;                        while (idx >= 0) {                                final Task child = (Task) getChildAt(idx--);                                if (!child.isTopActivityFocusable()) {                                        continue;                                }                                if (child.getVisibility(null /* starting */)                                        != TASK_FRAGMENT_VISIBILITY_VISIBLE) {                                        if (child.topRunningActivity() == null) {        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>// Skip the task if no running activity and continue resuming next task.        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>continue;                                        }                                        // Otherwise, assuming everything behind this task should also be invisible.                                        break;                                }                                someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,        <intent-filter>
  10.                
  11.                 <category android:name="android.intent.category.LAUNCHER" />
  12.         </intent-filter>
  13. </activity>        <intent-filter>
  14.                
  15.                 <category android:name="android.intent.category.LAUNCHER" />
  16.         </intent-filter>
  17. </activity>        <intent-filter>
  18.                
  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.         </intent-filter>
  21. </activity>          deferPause);                                // Doing so in order to prevent IndexOOB since hierarchy might changes while                                // resuming activities, for example dismissing split-screen while starting                                // non-resizeable activity.                                if (idx >= mChildren.size()) {                                        idx = mChildren.size() - 1;                                }                        }                }                // When resuming the top activity, it may be necessary to pause the top activity (for                // example, returning to the lock screen. We suppress the normal pause logic in                // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the                // end. We call the {@link ActivityTaskSupervisor#checkReadyForSleepLocked} again here                // to ensure any necessary pause logic occurs. In the case where the Activity will be                // shown regardless of the lock screen, the call to                // {@link ActivityTaskSupervisor#checkReadyForSleepLocked} is skipped.                final ActivityRecord next = topRunningActivity(true /* focusableOnly */);                if (next == null || !next.canTurnScreenOn()) {                        checkReadyForSleep();                }        } finally {                mInResumeTopActivity = false;        }        return someActivityResumed;}
复制代码
继续看Task对象的resumeTopActivityInnerLocked方法:
  1. @GuardedBy("mService")
  2. private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) {
  3.         if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
  4.                 // Not ready yet!
  5.                 return false;
  6.         }
  7.         final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
  8.         if (topActivity == null) {
  9.                 // There are no activities left in this task, let's look somewhere else.
  10.                 return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
  11.         }
  12.         final boolean[] resumed = new boolean[1];
  13.         final TaskFragment topFragment = topActivity.getTaskFragment();
  14.         resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
  15.         forAllLeafTaskFragments(f -> {
  16.                 if (topFragment == f) {
  17.                         return;
  18.                 }
  19.                 if (!f.canBeResumed(null /* starting */)) {
  20.                         return;
  21.                 }
  22.                 resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
  23.         }, true);
  24.         return resumed[0];
  25. }
复制代码
TaskFragment的resumeTopActivity源码如下:
frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
  1. final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options, boolean skipPause) {        ActivityRecord next = topRunningActivity(true /* focusableOnly */);        if (next == null || !next.canResumeByCompat()) {                return false;        }        next.delayedResume = false;        if (!skipPause && !mRootWindowContainer.allPausedActivitiesComplete()) {                // If we aren't skipping pause, then we have to wait for currently pausing activities.                ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: some activity pausing.");                return false;        }        final TaskDisplayArea taskDisplayArea = getDisplayArea();        // If the top activity is the resumed one, nothing to do.        if (mResumedActivity == next && next.isState(RESUMED)                && taskDisplayArea.allResumedActivitiesComplete()) {                // Ensure the visibility gets updated before execute app transition.                taskDisplayArea.ensureActivitiesVisible(null /* starting */, true /* notifyClients */);                // Make sure we have executed any pending transitions, since there                // should be nothing left to do at this point.                executeAppTransition(options);                // In a multi-resumed environment, like in a freeform device, the top                // activity can be resumed, but it might not be the focused app.                // Set focused app when top activity is resumed. However, we shouldn't do it for a                // same task because it can break focused state. (e.g. activity embedding)                if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null) {                        final ActivityRecord focusedApp = taskDisplayArea.mDisplayContent.mFocusedApp;                        if (focusedApp == null || focusedApp.getTask() != next.getTask()) {                                taskDisplayArea.mDisplayContent.setFocusedApp(next);                        }                }                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity "                                   + "resumed %s", next);                return false;        }        // If we are sleeping, and there is no resumed activity, and the top activity is paused,        // well that is the state we want.        if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {                // Make sure we have executed any pending transitions, since there                // should be nothing left to do at this point.                executeAppTransition(options);                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Going to sleep and"                                   + " all paused");                return false;        }        // Make sure that the user who owns this activity is started.  If not,        // we will just leave it as is because someone should be bringing        // another user's activities to the top of the stack.        if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {                Slog.w(TAG, "Skipping resume of top activity " + next                           + ": user " + next.mUserId + " is stopped");                return false;        }        // The activity may be waiting for stop, but that is no longer        // appropriate for it.        mTaskSupervisor.mStoppingActivities.remove(next);        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);        mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);        ActivityRecord lastResumed = null;        final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();        if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTaskFragment().asTask()) {                // So, why aren't we using prev here??? See the param comment on the method. prev                // doesn't represent the last resumed activity. However, the last focus stack does if                // it isn't null.                lastResumed = lastFocusedRootTask.getTopResumedActivity();        }        boolean pausing = !skipPause && taskDisplayArea.pauseBackTasks(next);        if (mResumedActivity != null) {                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);                pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>                next, "resumeTopActivity");        }        if (pausing) {                ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"                                   + " start pausing");                // At this point we want to put the upcoming activity's process                // at the top of the LRU list, since we know we will be needing it                // very soon and it would be a waste to let it get killed if it                // happens to be sitting towards the end.                if (next.attachedToProcess()) {                        next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>                           true /* activityChange */, false /* updateOomAdj */,        <intent-filter>
  10.                
  11.                 <category android:name="android.intent.category.LAUNCHER" />
  12.         </intent-filter>
  13. </activity>                           false /* addPendingTopUid */);                } else if (!next.isProcessRunning()) {                        // Since the start-process is asynchronous, if we already know the process of next                        // activity isn't running, we can start the process earlier to save the time to wait                        // for the current activity to be paused.                        final boolean isTop = this == taskDisplayArea.getFocusedRootTask();                        mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop,        <intent-filter>
  14.                
  15.                 <category android:name="android.intent.category.LAUNCHER" />
  16.         </intent-filter>
  17. </activity>                                  isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_ACTIVITY        <intent-filter>
  18.                
  19.                 <category android:name="android.intent.category.LAUNCHER" />
  20.         </intent-filter>
  21. </activity>                                  : HostingRecord.HOSTING_TYPE_NEXT_ACTIVITY);                }                if (lastResumed != null) {                        lastResumed.setWillCloseOrEnterPip(true);                }                return true;        } else if (mResumedActivity == next && next.isState(RESUMED)                           && taskDisplayArea.allResumedActivitiesComplete()) {                // It is possible for the activity to be resumed when we paused back stacks above if the                // next activity doesn't have to wait for pause to complete.                // So, nothing else to-do except:                // Make sure we have executed any pending transitions, since there                // should be nothing left to do at this point.                executeAppTransition(options);                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Top activity resumed "                                   + "(dontWaitForPause) %s", next);                return true;        }        // If the most recent activity was noHistory but was only stopped rather        // than stopped+finished because the device went to sleep, we need to make        // sure to finish it as we're making a new activity topmost.        if (shouldSleepActivities()) {                mTaskSupervisor.finishNoHistoryActivitiesIfNeeded(next);        }        if (prev != null && prev != next && next.nowVisible) {                // The next activity is already visible, so hide the previous                // activity's windows right now so we can show the new one ASAP.                // We only do this if the previous is finishing, which should mean                // it is on top of the one being resumed so hiding it quickly                // is good.  Otherwise, we want to do the normal route of allowing                // the resumed activity to be shown so we can decide if the                // previous should actually be hidden depending on whether the                // new one is found to be full-screen or not.                if (prev.finishing) {                        prev.setVisibility(false);                        if (DEBUG_SWITCH) {                                Slog.v(TAG_SWITCH, "Not waiting for visible to hide: " + prev                                           + ", nowVisible=" + next.nowVisible);                        }                } else {                        if (DEBUG_SWITCH) {                                Slog.v(TAG_SWITCH, "Previous already visible but still waiting to hide: " + prev                                           + ", nowVisible=" + next.nowVisible);                        }                }        }        try {                mTaskSupervisor.getActivityMetricsLogger()                        .notifyBeforePackageUnstopped(next.packageName);                mAtmService.getPackageManagerInternalLocked().notifyComponentUsed(                        next.packageName, next.mUserId,                        next.packageName, next.toString()); /* TODO: Verify if correct userid */        } catch (IllegalArgumentException e) {                Slog.w(TAG, "Failed trying to unstop package "                           + next.packageName + ": " + e);        }        // We are starting up the next activity, so tell the window manager        // that the previous one will be hidden soon.  This way it can know        // to ignore it when computing the desired screen orientation.        boolean anim = true;        final DisplayContent dc = taskDisplayArea.mDisplayContent;        if (prev != null) {                if (prev.finishing) {                        if (DEBUG_TRANSITION) {                                Slog.v(TAG_TRANSITION, "Prepare close transition: prev=" + prev);                        }                        if (mTaskSupervisor.mNoAnimActivities.contains(prev)) {                                anim = false;                                dc.prepareAppTransition(TRANSIT_NONE);                        } else {                                dc.prepareAppTransition(TRANSIT_CLOSE);                        }                        prev.setVisibility(false);                } else {                        if (DEBUG_TRANSITION) {                                Slog.v(TAG_TRANSITION, "Prepare open transition: prev=" + prev);                        }                        if (mTaskSupervisor.mNoAnimActivities.contains(next)) {                                anim = false;                                dc.prepareAppTransition(TRANSIT_NONE);                        } else {                                dc.prepareAppTransition(TRANSIT_OPEN,        <intent-filter>
  22.                
  23.                 <category android:name="android.intent.category.LAUNCHER" />
  24.         </intent-filter>
  25. </activity>                                next.mLaunchTaskBehind ? TRANSIT_FLAG_OPEN_BEHIND : 0);                        }                }        } else {                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");                if (mTaskSupervisor.mNoAnimActivities.contains(next)) {                        anim = false;                        dc.prepareAppTransition(TRANSIT_NONE);                } else {                        dc.prepareAppTransition(TRANSIT_OPEN);                }        }        if (anim) {                next.applyOptionsAnimation();        } else {                next.abortAndClearOptionsAnimation();        }        mTaskSupervisor.mNoAnimActivities.clear();        if (next.attachedToProcess()) {                if (DEBUG_SWITCH) {                        Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.mAppStopped                                   + " visibleRequested=" + next.isVisibleRequested());                }                // If the previous activity is translucent, force a visibility update of                // the next activity, so that it's added to WM's opening app list, and                // transition animation can be set up properly.                // For example, pressing Home button with a translucent activity in focus.                // Launcher is already visible in this case. If we don't add it to opening                // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a                // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.                final boolean lastActivityTranslucent = inMultiWindowMode()                        || mLastPausedActivity != null && !mLastPausedActivity.occludesParent();                // This activity is now becoming visible.                if (!next.isVisibleRequested() || next.mAppStopped || lastActivityTranslucent) {                        next.app.addToPendingTop();                        next.setVisibility(true);                }                // schedule launch ticks to collect information about slow apps.                next.startLaunchTickingLocked();                ActivityRecord lastResumedActivity =                        lastFocusedRootTask == null ? null                        : lastFocusedRootTask.getTopResumedActivity();                final ActivityRecord.State lastState = next.getState();                mAtmService.updateCpuStats();                ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next);                next.setState(RESUMED, "resumeTopActivity");                // Activity should also be visible if set mLaunchTaskBehind to true (see                // ActivityRecord#shouldBeVisibleIgnoringKeyguard()).                if (shouldBeVisible(next)) {                        // We have special rotation behavior when here is some active activity that                        // requests specific orientation or Keyguard is locked. Make sure all activity                        // visibilities are set correctly as well as the transition is updated if needed                        // to get the correct rotation behavior. Otherwise the following call to update                        // the orientation may cause incorrect configurations delivered to client as a                        // result of invisible window resize.                        // TODO: Remove this once visibilities are set correctly immediately when                        // starting an activity.                        final int originalRelaunchingCount = next.mPendingRelaunchCount;                        mRootWindowContainer.ensureVisibilityAndConfig(next, mDisplayContent,        <intent-filter>
  26.                
  27.                 <category android:name="android.intent.category.LAUNCHER" />
  28.         </intent-filter>
  29. </activity>        <intent-filter>
  30.                
  31.                 <category android:name="android.intent.category.LAUNCHER" />
  32.         </intent-filter>
  33. </activity>                   false /* deferResume */);                        if (next.mPendingRelaunchCount > originalRelaunchingCount) {                                // The activity is scheduled to relaunch, then ResumeActivityItem will be also                                // included (see ActivityRecord#relaunchActivityLocked) if it should resume.                                next.completeResumeLocked();                                return true;                        }                }                try {                        final IApplicationThread appThread = next.app.getThread();                        // Deliver all pending results.                        final ArrayList a = next.results;                        if (a != null) {                                final int size = a.size();                                if (!next.finishing && size > 0) {                                        if (DEBUG_RESULTS) {        <intent-filter>
  34.                
  35.                 <category android:name="android.intent.category.LAUNCHER" />
  36.         </intent-filter>
  37. </activity>Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a);                                        }                                        final ActivityResultItem item = new ActivityResultItem(next.token, a);                                        mAtmService.getLifecycleManager().scheduleTransactionItem(appThread, item);                                }                        }                        if (next.newIntents != null) {                                final NewIntentItem item =                                        new NewIntentItem(next.token, next.newIntents, true /* resume */);                                mAtmService.getLifecycleManager().scheduleTransactionItem(appThread, item);                        }                        // Well the app will no longer be stopped.                        // Clear app token stopped state in window manager if needed.                        next.notifyAppResumed();                        EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),        <intent-filter>
  38.                
  39.                 <category android:name="android.intent.category.LAUNCHER" />
  40.         </intent-filter>
  41. </activity>                                           next.getTask().mTaskId, next.shortComponentName);                        mAtmService.getAppWarningsLocked().onResumeActivity(next);                        final int topProcessState = mAtmService.mTopProcessState;                        next.app.setPendingUiCleanAndForceProcessStateUpTo(topProcessState);                        next.abortAndClearOptionsAnimation();                        final ResumeActivityItem resumeActivityItem = new ResumeActivityItem(                                next.token, topProcessState, dc.isNextTransitionForward(),                                next.shouldSendCompatFakeFocus());                        mAtmService.getLifecycleManager().scheduleTransactionItem(                                appThread, resumeActivityItem);                        ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Resumed %s", next);                } catch (Exception e) {                        // Whoops, need to restart this activity!                        ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: "                                           + "%s", 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 && lastFocusedRootTask != null                                           && lastFocusedRootTask.isTopRootTaskInDisplayArea()) {                                next.showStartingWindow(false /* taskSwitch */);                        }                        mTaskSupervisor.startSpecificActivity(next, true, false);                        return true;                }                next.completeResumeLocked();        } else {                // Whoops, need to restart this activity!                if (!next.hasBeenLaunched) {                        next.hasBeenLaunched = true;                } else {                        if (SHOW_APP_STARTING_PREVIEW) {                                next.showStartingWindow(false /* taskSwich */);                        }                        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);                }                ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Restarting %s", next);                mTaskSupervisor.startSpecificActivity(next, true, true);        }        return true;}
复制代码
注意:
记得留意andResume这个参数,此处的值为true,代表的是LifecyclePath的finish状态,即:ActivityLifecycleItem.ON_RESUME.
2处的代码,如果任务栈顶的Activity是处于Resume状态,则先将其置于Pause状态。
代码1处ActivityTaskSupervisor对象调用startSpecificActivity方法启动Activity,源码如下:
  1. void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {        // Is this activity's application already running?        final WindowProcessController wpc =                mService.getProcessController(r.processName, r.info.applicationInfo.uid);        boolean knownToBeDead = false;        if (wpc != null && wpc.hasThread()) {                try {                        realStartActivityLocked(r, wpc, andResume, checkConfig);                        return; // 1 如果进程已经存在                } 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.                knownToBeDead = true;                // Remove the process record so it won't be considered as alive.                mService.mProcessNames.remove(wpc.mName, wpc.mUid);                mService.mProcessMap.remove(wpc.getPid());        } else if (ActivityTaskManagerService.isSdkSandboxActivityIntent(                mService.mContext, r.intent)) {                Slog.e(TAG, "Abort sandbox activity launching as no sandbox process to host it.");                r.finishIfPossible("No sandbox process for the activity", false /* oomAdj */);                r.launchFailed = true;                r.detachFromProcess();                return;        }        r.notifyUnknownVisibilityLaunchedForKeyguardTransition();        final boolean isTop = andResume && r.isTopRunningActivity();        mService.startProcessAsync(r, knownToBeDead, isTop,        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>           isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY        <intent-filter>
  6.                
  7.                 <category android:name="android.intent.category.LAUNCHER" />
  8.         </intent-filter>
  9. </activity>           : HostingRecord.HOSTING_TYPE_ACTIVITY); // 2}
复制代码
如果Activity所在的应用的进程已经存在,则执行代码1处的代码然后返回,否则执行代码2处的代码,fork新的进程。
代码2处mService是ActivityTaskManagerService类型的示例,调用了其startProcessAsync方法,其源码如下:
  1. void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop, String hostingType) {        if (!mStartingProcessActivities.contains(activity)) {                mStartingProcessActivities.add(activity);                // Let the activity with higher z-order be started first.                if (mStartingProcessActivities.size() > 1) {                        mStartingProcessActivities.sort(null /* by WindowContainer#compareTo */);                }        } else if (mProcessNames.get(                activity.processName, activity.info.applicationInfo.uid) != null) {                // The process is already starting. Wait for it to attach.                return;        }        try {                if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {                        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"        <intent-filter>
  2.                
  3.                 <category android:name="android.intent.category.LAUNCHER" />
  4.         </intent-filter>
  5. </activity>         + activity.processName);                }                // Post message to start process to avoid possible deadlock of calling into AMS with the                // ATMS lock held.                final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,  mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead, isTop, hostingType, activity.intent.getComponent()); // 1                mH.sendMessage(m); // 2        } finally {                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);        }}
复制代码
代码1处接口PooledLambda的obtainMessage静态方法源码如下:
[code]static  Message obtainMessage(        HeptConsumer

相关推荐

您需要登录后才可以回帖 登录 | 立即注册