Android14 - AMS之Activity启动过程(3)

Android14 - AMS之Activity启动过程(1)-CSDN博客
Android14 - AMS之Activity启动过程(2)-CSDN博客

上篇中我们梳理完ActivityStarter的startActivityInner,本篇从这里开始:

platform/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

boolean resumeFocusedTasksTopActivities(
		Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
		boolean deferPause) {
	if (!mTaskSupervisor.readyToResume()) {
		return false;
	}

	boolean result = false;
   // targetRootTask不为空,isTopRootTaskInDisplayArea为true
	if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
			|| getTopDisplayFocusedRootTask() == targetRootTask)) {
		result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,
				deferPause);
	}

	for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
		final DisplayContent display = getChildAt(displayNdx);
		final boolean curResult = result;
		boolean[] resumedOnDisplay = new boolean[1];
		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 == rootTask.getDisplayArea().topRunningActivity()) {
				// 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);
			} else if (targetRootTask == null) {
				result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
						display.getDefaultTaskDisplayArea());
			}
		}
	}

	return result;
}

通过之前的分析我们知道targetRootTask不为空,isTopRootTaskInDisplayArea为true,因此会走targetRootTask.resumeTopActivityUncheckedLocked

platform/frameworks/base/services/core/java/com/android/server/wm/Task.java

/**
 * 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;
     // 本身没有子Task,所以isLeafTask为true
		if (isLeafTask()) {
        // isFocusableAndVisible为true
			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) {
						// Skip the task if no running activity and continue resuming next task.
						continue;
					}
					// Otherwise, assuming everything behind this task should also be invisible.
					break;
				}

				someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
						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;
}

继续走到

@GuardedBy("mService")
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
            boolean deferPause) {
        if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
            // Not ready yet!
            return false;
        }
        // topActivity是新建的ActivityRecord
        final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
        if (topActivity == null) {
            // There are no activities left in this task, let's look somewhere else.
            return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
        }

        final boolean[] resumed = new boolean[1];
        final TaskFragment topFragment = topActivity.getTaskFragment();
        resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
        forAllLeafTaskFragments(f -> {
            if (topFragment == f) {
                return;
            }
            if (!f.canBeResumed(null /* starting */)) {
                return;
            }
            resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
        }, true);
        return resumed[0];
    }

ActivityRecord topActivity = topRunningActivity(true), topActivity返回的是刚进件的ActivityRecord,topActivity.getTaskFragment()返回的是当前Task本身。后续调用topFragment.resumeTopActivity(), 其中参数prev为新建的ActivityRecord。


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 */, 0 /* configChanges */,
				false /* preserveWindows */, 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
		if (taskDisplayArea.inMultiWindowMode() && taskDisplayArea.mDisplayContent != null
				&& taskDisplayArea.mDisplayContent.mFocusedApp != next) {
			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);

    // 记录当前新建的ActivityRecord的uid	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);
   // 位置2
	if (mResumedActivity != null) {
		ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivity: Pausing %s", mResumedActivity);
		pausing |= startPausing(mTaskSupervisor.mUserLeaving, false /* uiSleeping */,
				next, "resumeTopActivity");
	}
   // 位置1
	if (pausing) {
		ProtoLog.v(WM_DEBUG_STATES, "resumeTopActivity: Skip resume: need to"
				+ " start pausing");
       // 此时还没有启动进程attachedToProcess为false
		// 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 */,
					true /* activityChange */, false /* updateOomAdj */,
					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,
					isTop ? HostingRecord.HOSTING_TYPE_NEXT_TOP_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);
			}
		}
	}

	// Launching this app's activity, make sure the app is no longer
	// considered stopped.
	try {
		mTaskSupervisor.getActivityMetricsLogger()
				.notifyBeforePackageUnstopped(next.packageName);
		mAtmService.getPackageManager().setPackageStoppedState(
				next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
	} catch (RemoteException e1) {
	} catch (IllegalArgumentException e) {
		Slog.w(TAG, "Failed trying to unstop package "
				+ next.packageName + ": " + e);
	}

	// We are starting up the next activity, so tell the window manager
	// that the previous one will be hidden soon.  This way it can know
	// to ignore it when computing the desired screen orientation.
	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,
						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");

		// Have the window manager re-evaluate the orientation of
		// the screen based on the new activity order.
		boolean notUpdated = true;

		// 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.
			notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
					true /* markFrozenIfConfigChanged */, false /* deferResume */);
		}

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

		try {
			final ClientTransaction transaction =
					ClientTransaction.obtain(next.app.getThread(), next.token);
			// Deliver all pending results.
			ArrayList<ResultInfo> a = next.results;
			if (a != null) {
				final int size = a.size();
				if (!next.finishing && size > 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();

			EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next),
					next.getTask().mTaskId, next.shortComponentName);

			mAtmService.getAppWarningsLocked().onResumeActivity(next);
			next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState);
			next.abortAndClearOptionsAnimation();
			transaction.setLifecycleStateRequest(
					ResumeActivityItem.obtain(next.app.getReportedProcState(),
							dc.isNextTransitionForward(), next.shouldSendCompatFakeFocus()));
			mAtmService.getLifecycleManager().scheduleTransaction(transaction);

			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;
		}

		// From this point on, if something goes wrong there is no way
		// to recover the activity.
		try {
			next.completeResumeLocked();
		} catch (Exception e) {
			// If any exception gets thrown, toss away this
			// activity and try the next one.
			Slog.w(TAG, "Exception thrown during resume of " + next, e);
			next.finishIfPossible("resume-exception", true /* oomAdj */);
			return true;
		}
	} 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;
    }

暂停前一个Activity

ActivityRecord next = topRunningActivity(true /* focusableOnly */);

next是当前顶部activity,等于prev。

mResumedActivity、mLastPausedActivity此时都为空。taskDisplayArea.pauseBackTasks(next);来pause前一个activity

platform/frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java

boolean pauseBackTasks(ActivityRecord resuming) {
	final int[] someActivityPaused = {0};
	forAllLeafTasks(leafTask -> {
		// Check if the direct child resumed activity in the leaf task needed to be paused if
		// the leaf task is not a leaf task fragment.
		if (!leafTask.isLeafTaskFragment()) {
			final ActivityRecord top = topRunningActivity();
			final ActivityRecord resumedActivity = leafTask.getResumedActivity();
			if (resumedActivity != null && top.getTaskFragment() != leafTask) {
				// Pausing the resumed activity because it is occluded by other task fragment.
				if (leafTask.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
					someActivityPaused[0]++;
				}
			}
		}

		leafTask.forAllLeafTaskFragments((taskFrag) -> {
			final ActivityRecord resumedActivity = taskFrag.getResumedActivity();
			if (resumedActivity != null && !taskFrag.canBeResumed(resuming)) {
				if (taskFrag.startPausing(false /* uiSleeping*/, resuming, "pauseBackTasks")) {
					someActivityPaused[0]++;
				}
			}
		}, true /* traverseTopToBottom */);
	}, true /* traverseTopToBottom */);
	return someActivityPaused[0] > 0;
}

这里遍历TaskDisplayArea下所有Task,如果有已经Resumed的Activity,则会执行pausing流程先暂停:


boolean startPausing(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming,
		String reason) {

    ActivityRecord prev = mResumedActivity;
    ...
    
    mPausingActivity = prev;
	mLastPausedActivity = prev;
	if (!prev.finishing && prev.isNoHistory()
			&& !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
		mTaskSupervisor.mNoHistoryActivities.add(prev);
	}
	prev.setState(PAUSING, "startPausingLocked");
	prev.getTask().touchActiveTime();

	mAtmService.updateCpuStats();
    ..
    if (resuming != null) {
		// We do not want to trigger auto-PiP upon launch of a translucent activity.
		final boolean resumingOccludesParent = resuming.occludesParent();
		// Resuming the new resume activity only if the previous activity can't go into Pip
		// since we want to give Pip activities a chance to enter Pip before resuming the
		// next activity.
		final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
				"shouldAutoPipWhilePausing", userLeaving);
		if (userLeaving && resumingOccludesParent && lastResumedCanPip
				&& prev.pictureInPictureArgs.isAutoEnterEnabled()) {
			shouldAutoPip = true;
		} else if (!lastResumedCanPip) {
			// If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
			// activity to be paused.
			pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
		} else {
			// The previous activity may still enter PIP even though it did not allow auto-PIP.
		}
	}
    ...
    if (prev.attachedToProcess()) {
		if (shouldAutoPip) {
			prev.mPauseSchedulePendingForPip = true;
			boolean didAutoPip = mAtmService.enterPictureInPictureMode(
					prev, prev.pictureInPictureArgs, false /* fromClient */);
			ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
					+ "directly: %s, didAutoPip: %b", prev, didAutoPip);
		} else {
			schedulePauseActivity(prev, userLeaving, pauseImmediately,
					false /* autoEnteringPip */, reason);
		}
	} else {
		mPausingActivity = null;
		mLastPausedActivity = null;
		mTaskSupervisor.mNoHistoryActivities.remove(prev);
	}
    ...
    // If already entered PIP mode, no need to keep pausing.
	if (mPausingActivity != null) {
		// Have the window manager pause its key dispatching until the new
		// activity has started.  If we're pausing the activity just because
		// the screen is being turned off and the UI is sleeping, don't interrupt
		// key dispatch; the same activity will pick it up again on wakeup.
		if (!uiSleeping) {
			prev.pauseKeyDispatchingLocked();
		} else {
			ProtoLog.v(WM_DEBUG_STATES, "Key dispatch not paused for screen off");
		}

		if (pauseImmediately) {
			// If the caller said they don't want to wait for the pause, then complete
			// the pause now.
			completePause(false, resuming);
			return false;

		} else {
			prev.schedulePauseTimeout();
			// All activities will be stopped when sleeping, don't need to wait for pause.
			if (!uiSleeping) {
				// Unset readiness since we now need to wait until this pause is complete.
				mTransitionController.setReady(this, false /* ready */);
			}
			return true;
		}

	} else {
		// This activity either failed to schedule the pause or it entered PIP mode,
		// so just treat it as being paused now.
		ProtoLog.v(WM_DEBUG_STATES, "Activity not running or entered PiP, resuming next.");
		if (resuming == null) {
			mRootWindowContainer.resumeFocusedTasksTopActivities();
		}
		return false;
	}
}

首先会更新前一个Task几个成员的状态:

mPausingActivity = prev;

mLastPausedActivity = prev;

prev.setState(PAUSING, "startPausingLocked");

然后会执行schedulePauseActivity(prev, ...) 暂停前一个Task里的mResumedActivity

其中,如果正在resuming的,也就是新启动的activity设置了info.flags & FLAG_RESUME_WHILE_PAUSING, 那么回立即执行completePause(false, resuming);并且startPausing()返回false, 否则返回true。

本场景下没有设置flags,startPausing返回true。因此resumeTopActivity()的“位置1”处,pausing为true。

接下来,因为新activity对应的进程还没有启动,next.attachedToProcess()是false。接下来会走mAtmService.startProcessAsync()启动进程。

我们先看看attachedToProcess是怎么判断的。

platform/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

boolean hasProcess() {
	return app != null;
}

boolean attachedToProcess() {
	return hasProcess() && app.hasThread();
}

本质判断的是app属性。这个将在后续进程启动后设置。

启动进程

startProcessAsync启动进程:

platform/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
		String hostingType) {
	try {
		if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
			Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
					+ 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());
		mH.sendMessage(m);
	} finally {
		Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
	}
}

这里通过向mH发送异步消息,执行ActivityManagerInternal::startProcess来启动进程:

ActivityManagerInternal的实现类是ActivityManagerService

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

public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
			boolean isTop, String hostingType, ComponentName hostingName) {
		try {
			...
			synchronized (ActivityManagerService.this) {
				// If the process is known as top app, set a hint so when the process is
				// started, the top priority can be applied immediately to avoid cpu being
				// preempted by other processes before attaching the process of top app.
				startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
						new HostingRecord(hostingType, hostingName, isTop),
						ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
						false /* isolated */);
			}
		} finally {
			Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
		}
	}

final ProcessRecord startProcessLocked(String processName,
		ApplicationInfo info, boolean knownToBeDead, int intentFlags,
		HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
		boolean isolated) {
	return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
			hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
			false /* isSdkSandbox */, 0 /* sdkSandboxClientAppUid */,
			null /* sdkSandboxClientAppPackage */,
			null /* ABI override */, null /* entryPoint */,
			null /* entryPointArgs */, null /* crashHandler */);
}

通过ProcessList.startProcessLocked()启动进程:

platform/frameworks/base/services/core/java/com/android/server/am/ProcessList.java

ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
            int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
            boolean isSdkSandbox, int sdkSandboxUid, String sdkSandboxClientAppPackage,
            String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
        
    ...
    app = newProcessRecordLocked(info, processName, isolated, isolatedUid, isSdkSandbox,
                    sdkSandboxUid, sdkSandboxClientAppPackage, hostingRecord);
    ...
    final boolean success =
                startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
    ...
}

newProcessRecordLocked() :这里new了ProcessRecord。

startProcessLocked():继续往下启动进程

platform/frameworks/base/services/core/java/com/android/server/am/ProcessList.java

boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
            int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
            String abiOverride) {
    ...
    String useAppImageCache = SystemProperties.get(
				PROPERTY_USE_APP_IMAGE_STARTUP_CACHE, "");
		// Property defaults to true currently.
		if (!TextUtils.isEmpty(useAppImageCache) && !useAppImageCache.equals("false")) {
			runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
		}
    ...
    app.setGids(gids);
	app.setRequiredAbi(requiredAbi);
	app.setInstructionSet(instructionSet);
    ...
    return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,instructionSet, invokeWith, startUptime, startElapsedTime);
}

设置了一系列参数后,调用startProcessLocked()

platform/frameworks/base/services/core/java/com/android/server/am/ProcessList.java

boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
		int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
		String seInfo, String requiredAbi, String instructionSet, String invokeWith,
		long startUptime, long startElapsedTime) {
		...
		app.setStartSeq(startSeq);
        app.setStartParams(uid, hostingRecord, seInfo, startUptime, startElapsedTime);
        app.setUsingWrapper(invokeWith != null
                || Zygote.getWrapProperty(app.processName) != null);
        mPendingStarts.put(startSeq, app);
		...
		if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
            if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                    "Posting procStart msg for " + app.toShortString());
            mService.mProcStartHandler.post(() -> handleProcessStart(
                    app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
                    requiredAbi, instructionSet, invokeWith, startSeq));
            return true;
        } else {
            try {
                final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                        entryPoint, app,
                        uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
                        requiredAbi, instructionSet, invokeWith, startUptime);
                handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                        startSeq, false);
            } catch (RuntimeException e) {
                Slog.e(ActivityManagerService.TAG, "Failure starting process "
                        + app.processName, e);
                app.setPendingStart(false);
                mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                        false, false, true, false, false, app.userId, "start failure");
            }
            return app.getPid() > 0;
        }
}

合理首先记录了mPendingStarts.put(startSeq, app);用来启动进程后从客户端回来能找到刚刚启动的这个进程。随后通过启动startProcess启动进程。

客户端进程具体启动过程不详述。在通过zygote孵化出进程后,客户端会回调ActivityManagerService的attachApplication。

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

public final void attachApplication(IApplicationThread thread, long startSeq) {
	if (thread == null) {
		throw new SecurityException("Invalid application interface");
	}
	synchronized (this) {
		int callingPid = Binder.getCallingPid();
		final int callingUid = Binder.getCallingUid();
		final long origId = Binder.clearCallingIdentity();
		attachApplicationLocked(thread, callingPid, callingUid, startSeq);
		Binder.restoreCallingIdentity(origId);
	}
}

private void attachApplicationLocked(@NonNull IApplicationThread thread,
	int pid, int callingUid, long startSeq) {
	...
	if (app.getIsolatedEntryPoint() != null) {
		// This is an isolated process which should just call an entry point instead of
		// being bound to an application.
		thread.runIsolatedEntryPoint(
				app.getIsolatedEntryPoint(), app.getIsolatedEntryPointArgs());
	} else if (instr2 != null) {
		thread.bindApplication(processName, appInfo,
				app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
				providerList,
				instr2.mClass,
				profilerInfo, instr2.mArguments,
				instr2.mWatcher,
				instr2.mUiAutomationConnection, testMode,
				mBinderTransactionTrackingEnabled, enableTrackAllocation,
				isRestrictedBackupMode || !normalMode, app.isPersistent(),
				new Configuration(app.getWindowProcessController().getConfiguration()),
				app.getCompat(), getCommonServicesLocked(app.isolated),
				mCoreSettingsObserver.getCoreSettingsLocked(),
				buildSerial, autofillOptions, contentCaptureOptions,
				app.getDisabledCompatChanges(), serializedSystemFontMap,
				app.getStartElapsedTime(), app.getStartUptime());
	} else {
		thread.bindApplication(processName, appInfo,
				app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
				providerList, null, profilerInfo, null, null, null, testMode,
				mBinderTransactionTrackingEnabled, enableTrackAllocation,
				isRestrictedBackupMode || !normalMode, app.isPersistent(),
				new Configuration(app.getWindowProcessController().getConfiguration()),
				app.getCompat(), getCommonServicesLocked(app.isolated),
				mCoreSettingsObserver.getCoreSettingsLocked(),
				buildSerial, autofillOptions, contentCaptureOptions,
				app.getDisabledCompatChanges(), serializedSystemFontMap,
				app.getStartElapsedTime(), app.getStartUptime());
	}
	...
	if (!mConstants.mEnableWaitForFinishAttachApplication) {
		finishAttachApplicationInner(startSeq, callingUid, pid);
	}
}

thread.bindApplication() 是调用客户端,最终触发Application的onCreate等方法。

finishAttachApplicationInner()则继续完成之前的Activity启动过程。

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

private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
	...
	// See if the top visible activity is waiting to run in this process...
	if (normalMode) {
		try {
			didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
		} catch (Exception e) {
			Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
			badApp = true;
		}
	}
	
	// Find any services that should be running in this process...
	if (!badApp) {
		try {
			didSomething |= mServices.attachApplicationLocked(app, processName);
			checkTime(startTime, "finishAttachApplicationInner: "
					+ "after mServices.attachApplicationLocked");
		} catch (Exception e) {
			Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
			badApp = true;
		}
	}

	// Check if a next-broadcast receiver is in this process...
	if (!badApp) {
		try {
			for (BroadcastQueue queue : mBroadcastQueues) {
				didSomething |= queue.onApplicationAttachedLocked(app);
			}
			checkTime(startTime, "finishAttachApplicationInner: "
					+ "after dispatching broadcasts");
		} catch (BroadcastDeliveryFailedException e) {
			// If the app died trying to launch the receiver we declare it 'bad'
			Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
			badApp = true;
		}
	}
	...
}

依次检查是否有未完成的Activity、Service、Broadcast的启动流程。本场景只关注Activity的启动 mAtmInternal.attachApplication(),其具体实现在ActivityTaskManagerService

platform/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
	synchronized (mGlobalLockWithoutBoost) {
		if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
			Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
		}
		try {
			return mRootWindowContainer.attachApplication(wpc);
		} finally {
			Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
		}
	}
}
platform/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

boolean attachApplication(WindowProcessController app) throws RemoteException {
	try {
		return mAttachApplicationHelper.process(app);
	} finally {
		mAttachApplicationHelper.reset();
	}
}

platform/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java$AttachApplicationHelper

boolean process(WindowProcessController app) throws RemoteException {
	mApp = app;
	for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
      // 递归RootWindowContainer下的所有Child的forAllRootTasks,最终调用到Task的forAllRootTasks,执行了本类的test方法。
		getChildAt(displayNdx).forAllRootTasks(this);
		if (mRemoteException != null) {
			throw mRemoteException;
		}
	}
	if (!mHasActivityStarted) {
		ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
				false /* preserveWindows */);
	}
	return mHasActivityStarted;
}

public void accept(Task rootTask) {
	if (mRemoteException != null) {
		return;
	}
	if (rootTask.getVisibility(null /* starting */)
			== TASK_FRAGMENT_VISIBILITY_INVISIBLE) {
		return;
	}
	mTop = rootTask.topRunningActivity();
	rootTask.forAllActivities(this);
}

@Override
public boolean test(ActivityRecord r) {
	if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard
			|| r.app != null || mApp.mUid != r.info.applicationInfo.uid
			|| !mApp.mName.equals(r.processName)) {
		return false;
	}

	try {
		if (mTaskSupervisor.realStartActivityLocked(r, mApp,
				mTop == r && r.getTask().canBeResumed(r) /* andResume */,
				true /* checkConfig */)) {
			mHasActivityStarted = true;
		}
	} catch (RemoteException e) {
		Slog.w(TAG, "Exception in new application when starting activity " + mTop, e);
		mRemoteException = e;
		return true;
	}
	return false;
}

注意这里的process方法首先记录了下mApp, 随后getChildAt(displayNdx).forAllRootTasks(this);这里的this指AttachApplicationHelper自身作为一个callback传入。

由于基类WindowContainer对该方法的定义是遍历递归所有child的forAllRootTasks,而作为Child的Task类对其的实现是调用callback的accept

platform/frameworks/base/services/core/java/com/android/server/wm/Task.java

@Override
void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
	if (isRootTask()) {
		callback.accept(this);
	}
}

AttachApplicationHelper中, accept方法获取到该Task的最顶部Activity,随后调用的rootTask.forAllActivities(this);也来自WindowContainer,最终会递归到最底层Child ActivityRecord,传入的参数是ActivityRecord自身。

platform/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

@Override
boolean forAllActivities(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
	return callback.test(this);
}

因此最终会调用AttachApplicationHelper的test方法,并调用mTaskSupervisor.realStartActivityLocked()

经过了accept和test方法的筛选后,只针对刚启动的这个app,并且是其顶部activity执行realStartActivityLocked,也就是说第一个r参数是我们之前要启动的Activity。

realStartActivityLocked参数r启动activity,proc启动app andResumetrue

realStartActivityLocked真正调用客户端Activity

调用客户端Activity

realStartActivityLocked代码

platform/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
		boolean andResume, boolean checkConfig) throws RemoteException {

	...
	
	try {
		r.startFreezingScreenLocked(proc, 0);

		// schedule launch ticks to collect information about slow apps.
		r.startLaunchTickingLocked();
		r.lastLaunchTime = SystemClock.uptimeMillis();
		r.setProcess(proc);

		// Ensure activity is allowed to be resumed after process has set.
		if (andResume && !r.canResumeByCompat()) {
			andResume = false;
		}
		...

		// Have the window manager re-evaluate the orientation of the screen based on the new
		// activity order.  Note that as a result of this, it can call back into the activity
		// manager with a new orientation.  We don't care about that, because the activity is
		// not currently running so we are just restarting it anyway.
		if (checkConfig) {
			// Deferring resume here because we're going to launch new activity shortly.
			// We don't want to perform a redundant launch of the same record while ensuring
			// configurations and trying to resume top activity of focused root task.
			mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(),
					false /* markFrozenIfConfigChanged */, true /* deferResume */);
		}

		if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) {
			// We only set the visibility to true if the activity is not being launched in
			// background, and is allowed to be visible based on keyguard state. This avoids
			// setting this into motion in window manager that is later cancelled due to later
			// calls to ensure visible activities that set visibility back to false.
			r.setVisibility(true);
		}

		try {
			if (!proc.hasThread()) {
				throw new RemoteException();
			}
			List<ResultInfo> results = null;
			List<ReferrerIntent> newIntents = null;
			if (andResume) {
				// We don't need to deliver new intents and/or set results if activity is going
				// to pause immediately after launch.
				results = r.results;
				newIntents = r.newIntents;
			}
			...

			// Create activity launch transaction.
			final ClientTransaction clientTransaction = ClientTransaction.obtain(
					proc.getThread(), r.token);

			final boolean isTransitionForward = r.isTransitionForward();
			final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();

			final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
			clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
					System.identityHashCode(r), r.info,
					// TODO: Have this take the merged configuration instead of separate global
					// and override configs.
					mergedConfiguration.getGlobalConfiguration(),
					mergedConfiguration.getOverrideConfiguration(), deviceId,
					r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,
					proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
					results, newIntents, r.takeOptions(), isTransitionForward,
					proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
					r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));

			// Set desired final state.
			final ActivityLifecycleItem lifecycleItem;
			if (andResume) {
				lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,
						r.shouldSendCompatFakeFocus());
			} else {
				lifecycleItem = PauseActivityItem.obtain();
			}
			clientTransaction.setLifecycleStateRequest(lifecycleItem);

			// Schedule transaction.
			mService.getLifecycleManager().scheduleTransaction(clientTransaction);

			if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) {
				// If the seq is increased, there should be something changed (e.g. registered
				// activity configuration).
				proc.setLastReportedConfiguration(procConfig);
			}
			if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
					&& mService.mHasHeavyWeightFeature) {
				// This may be a heavy-weight process! Note that the package manager will ensure
				// that only activity can run in the main process of the .apk, which is the only
				// thing that will be considered heavy-weight.
				if (proc.mName.equals(proc.mInfo.packageName)) {
					if (mService.mHeavyWeightProcess != null
							&& mService.mHeavyWeightProcess != proc) {
						Slog.w(TAG, "Starting new heavy weight process " + proc
								+ " when already running "
								+ mService.mHeavyWeightProcess);
					}
					mService.setHeavyWeightProcess(r);
				}
			}

		} catch (RemoteException e) {
			if (r.launchFailed) {
				// This is the second time we failed -- finish activity and give up.
				Slog.e(TAG, "Second failure launching "
						+ r.intent.getComponent().flattenToShortString() + ", giving up", e);
				proc.appDied("2nd-crash");
				r.finishIfPossible("2nd-crash", false /* oomAdj */);
				return false;
			}

			// This is the first time we failed -- restart process and
			// retry.
			r.launchFailed = true;
			r.detachFromProcess();
			throw e;
		}
	} finally {
		endDeferResume();
		proc.resumeConfigurationDispatch();
	}

	r.launchFailed = false;

	// TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
	// so updating the state should be done accordingly.
	if (andResume && readyToResume()) {
		// As part of the process of launching, ActivityThread also performs
		// a resume.
		rootTask.minimalResumeActivityLocked(r);
	} else {
		// This activity is not starting in the resumed state... which should look like we asked
		// it to pause+stop (but remain visible), and it has done so and reported back the
		// current icicle and other state.
		ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s "
				+ "(starting in paused state)", r);
		r.setState(PAUSED, "realStartActivityLocked");
		mRootWindowContainer.executeAppTransitionForAllDisplay();
	}
	// Perform OOM scoring after the activity state is set, so the process can be updated with
	// the latest state.
	proc.onStartActivity(mService.mTopProcessState, r.info);

	// Launch the new version setup screen if needed.  We do this -after-
	// launching the initial activity (that is, home), so that it can have
	// a chance to initialize itself while in the background, making the
	// switch back to it faster and look better.
	if (mRootWindowContainer.isTopDisplayFocusedRootTask(rootTask)) {
		mService.getActivityStartController().startSetupActivity();
	}

	// Update any services we are bound to that might care about whether
	// their client may have activities.
	if (r.app != null) {
		r.app.updateServiceConnectionActivities();
	}

	return true;
}

这里ClientTransaction形式客户端通信

ClientTransaction

ClientTransaction用于AMS服务端调用客户端生命周期相关事务通道

1. 服务端obtain一个ClientTransaction

platform/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

public static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {
        ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);
        if (instance == null) {
            instance = new ClientTransaction();
        }
        instance.mClient = client;
        instance.mActivityToken = activityToken;

        return instance;
    }

2. 服务端addCallbacksetLifecycleStateRequest

clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
...
lifecycleItem = ResumeActivityItem.obtain(isTransitionForward,
                            r.shouldSendCompatFakeFocus());
clientTransaction.setLifecycleStateRequest(lifecycleItem);

3. mService.getLifecycleManager().scheduleTransaction(clientTransaction);

getLifecycleManager()ActivityTaskManagerService的ClientLifecycleManager因此调用ClientLifecycleManagerscheduleTransaction()

platform/frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java

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();
	}
}
platform/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java

public void schedule() throws RemoteException {
    mClient.scheduleTransaction(this);
}

mClientIApplicationThread也就是客户端所持有的binder服务端因此scheduleTransaction调用客户端ApplicationThreadscheduleTransaction

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

public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
	ActivityThread.this.scheduleTransaction(transaction);
}

4. 客户端执行scheduleTransaction

ActivityThread这个方法父类执行

platform/frameworks/base/core/java/android/app/ClientTransactionHandler.java

void scheduleTransaction(ClientTransaction transaction) {
	transaction.preExecute(this);
	sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

执行transaction.preExecute(this);执行任务EXECUTE_TRANSACTION

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

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;
platform/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

public void execute(ClientTransaction transaction) {
	if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Start resolving transaction");

	final IBinder token = transaction.getActivityToken();
	if (token != null) {
		final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed =
				mTransactionHandler.getActivitiesToBeDestroyed();
		final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token);
		if (destroyItem != null) {
			if (transaction.getLifecycleStateRequest() == destroyItem) {
				// It is going to execute the transaction that will destroy activity with the
				// token, so the corresponding to-be-destroyed record can be removed.
				activitiesToBeDestroyed.remove(token);
			}
			if (mTransactionHandler.getActivityClient(token) == null) {
				// The activity has not been created but has been requested to destroy, so all
				// transactions for the token are just like being cancelled.
				Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n"
						+ transactionToString(transaction, mTransactionHandler));
				return;
			}
		}
	}

	if (DEBUG_RESOLVER) Slog.d(TAG, transactionToString(transaction, mTransactionHandler));

	executeCallbacks(transaction);

	executeLifecycleState(transaction);
	mPendingActions.clear();
	if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}

先后执行两个方法

executeCallbacks()

executeLifecycleState()

platform/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

public void executeCallbacks(ClientTransaction transaction) {
    final int size = callbacks.size();
for (int i = 0; i < size; ++i) {
	final ClientTransactionItem item = callbacks.get(i);
	if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "Resolving callback: " + item);
	final int postExecutionState = item.getPostExecutionState();

	if (item.shouldHaveDefinedPreExecutionState()) {
		final int closestPreExecutionState = mHelper.getClosestPreExecutionState(r,
				item.getPostExecutionState());
		if (closestPreExecutionState != UNDEFINED) {
			cycleToPath(r, closestPreExecutionState, transaction);
		}
	}

	item.execute(mTransactionHandler, token, mPendingActions);
	item.postExecute(mTransactionHandler, token, mPendingActions);
	if (== null) {
		// Launch activity request will create an activity record.
= mTransactionHandler.getActivityClient(token);
	}

	if (postExecutionState != UNDEFINED && r != null) {
		// Skip the very last transition and perform it by explicit state request instead.
		final boolean shouldExcludeLastTransition =
== lastCallbackRequestingState && finalState == postExecutionState;
		cycleToPath(r, postExecutionState, shouldExcludeLastTransition, transaction);
	}
}
platform/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java

private void executeLifecycleState(ClientTransaction transaction) {
	final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
	...

	// Execute the final transition with proper parameters.
	lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
	lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}

调用客户端Activity

回到ActivityTaskSupervisorrealStartActivityLocked()

通过ClientTransaction先后执行以下生命周期相关事务:

LaunchActivityItem -- 客户端新建Activity

ResumeActivityItem -- 执行ActivityonResume

新建Activity
platform/frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java

@Override
public void execute(ClientTransactionHandler client, IBinder token,
		PendingTransactionActions pendingActions) {
	Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
	ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
			mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
			mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
			client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
			mTaskFragmentToken);
	client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
	Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

这里构建ActivityClientRecord调用ClientTransactionHandlerhandleLaunchActivity具体实现ActivityThread

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

public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
	...
	final Activity a = performLaunchActivity(r, customIntent);
	...
	if (!= null) {
		r.createdConfig = new Configuration(mConfigurationController.getConfiguration());
		reportSizeConfigurations(r);
		if (!r.activity.mFinished && pendingActions != null) {
			pendingActions.setOldState(r.state);
			pendingActions.setRestoreInstanceState(true);
			pendingActions.setCallOnPostCreate(true);
		}
	} else {
		// If there was an error, for any reason, tell the activity manager to stop us.
		ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED,
				null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
	}
}
platform/frameworks/base/core/java/android/app/ActivityThread.java

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	ActivityInfo aInfo = r.activityInfo;
	if (r.packageInfo == null) {
		r.packageInfo = getPackageInfo(aInfo.applicationInfo, mCompatibilityInfo,
				Context.CONTEXT_INCLUDE_CODE);
	}

	ComponentName component = r.intent.getComponent();
	if (component == null) {
		component = r.intent.resolveActivity(
			mInitialApplication.getPackageManager());
		r.intent.setComponent(component);
	}

	if (r.activityInfo.targetActivity != null) {
		component = new ComponentName(r.activityInfo.packageName,
				r.activityInfo.targetActivity);
	}

    // 创建Context
	ContextImpl appContext = createBaseContextForActivity(r);
	Activity activity = null;
	try {
      // 创建Activity
		java.lang.ClassLoader cl = appContext.getClassLoader();
		activity = mInstrumentation.newActivity(
				cl, component.getClassName(), r.intent);
		StrictMode.incrementExpectedActivityCount(activity.getClass());
		r.intent.setExtrasClassLoader(cl);
		r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo),
				appContext.getAttributionSource());
		if (r.state != null) {
			r.state.setClassLoader(cl);
		}
	} catch (Exception e) {
		if (!mInstrumentation.onException(activity, e)) {
			throw new RuntimeException(
				"Unable to instantiate activity " + component
				+ ": " + e.toString(), e);
		}
	}

	try {
		Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation);

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

		// updatePendingActivityConfiguration() reads from mActivities to update
		// ActivityClientRecord which runs in a different thread. Protect modifications to
		// mActivities to avoid race.
		synchronized (mResourcesManager) {
			mActivities.put(r.token, r);
		}

		if (activity != null) {
			CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
			Configuration config =
					new Configuration(mConfigurationController.getCompatConfiguration());
			if (r.overrideConfig != null) {
				config.updateFrom(r.overrideConfig);
			}
			if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
					+ r.activityInfo.name + " with config " + config);
			Window window = null;
			if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
				window = r.mPendingRemoveWindow;
				r.mPendingRemoveWindow = null;
				r.mPendingRemoveWindowManager = null;
			}

			// Activity resources must be initialized with the same loaders as the
			// application context.
			appContext.getResources().addLoaders(
					app.getResources().getLoaders().toArray(new ResourcesLoader[0]));

			appContext.setOuterContext(activity);
			activity.attach(appContext, this, getInstrumentation(), r.token,
					r.ident, app, r.intent, r.activityInfo, title, r.parent,
					r.embeddedID, r.lastNonConfigurationInstances, config,
					r.referrer, r.voiceInteractor, window, r.activityConfigCallback,
					r.assistToken, r.shareableActivityToken);

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

			if (r.mActivityOptions != null) {
				activity.mPendingOptions = r.mActivityOptions;
				r.mActivityOptions = null;
			}
			activity.mLaunchedFromBubble = r.mLaunchedFromBubble;
			activity.mCalled = false;
			// Assigning the activity to the record before calling onCreate() allows
			// ActivityThread#getActivity() lookup for the callbacks triggered from
			// ActivityLifecycleCallbacks#onActivityCreated() or
			// ActivityLifecycleCallback#onActivityPostCreated().
			r.activity = activity;
          // 调用Activity的onCreate
			if (r.isPersistable()) {
				mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
			} else {
				mInstrumentation.callActivityOnCreate(activity, r.state);
			}
			if (!activity.mCalled) {
				throw new SuperNotCalledException(
					"Activity " + r.intent.getComponent().toShortString() +
					" did not call through to super.onCreate()");
			}
			r.mLastReportedWindowingMode = config.windowConfiguration.getWindowingMode();
		}
		r.setState(ON_CREATE);

	} catch (SuperNotCalledException e) {
		throw e;

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

	return activity;
}

这里最终

  1. 创建appContext:ContextImpl appContext = createBaseContextForActivity(r)
  2. 创建Activityactivity = mInstrumentation.newActivity(...)
  3. activity.attach()
  4. 调用Activity的onCreatemInstrumentation.callActivityOnCreate(...)
onResume
platform/frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java

@Override
public void execute(ClientTransactionHandler client, ActivityClientRecord r,
		PendingTransactionActions pendingActions) {
	Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
	client.handleResumeActivity(r, true /* finalStateRequest */, mIsForward,
			mShouldSendCompatFakeFocus, "RESUME_ACTIVITY");
	Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

同样具体实现ActivityThread

D:\AndroidSource\Android11\platform\frameworks\base\core\java\android\app\ActivityThread.java

@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
		boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {
	// If we are getting ready to gc after going to the background, well
	// we are back active so skip it.
	unscheduleGcIdler();
	mSomeActivitiesChanged = true;

	// TODO Push resumeArgs into the activity for consideration
	// skip below steps for double-resume and r.mFinish = true case.
	if (!performResumeActivity(r, finalStateRequest, reason)) {
		return;
	}
	if (mActivitiesToBeDestroyed.containsKey(r.token)) {
		// Although the activity is resumed, it is going to be destroyed. So the following
		// UI operations are unnecessary and also prevents exception because its token may
		// be gone that window manager cannot recognize it. All necessary cleanup actions
		// performed below will be done while handling destruction.
		return;
	}

	final Activity a = r.activity;

	if (localLOGV) {
		Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
				+ ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
	}

	final int forwardBit = isForward
			? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

	// If the window hasn't yet been added to the window manager,
	// and this guy didn't finish itself or start another activity,
	// then go ahead and add the window.
	boolean willBeVisible = !a.mStartedActivity;
	if (!willBeVisible) {
		willBeVisible = ActivityClient.getInstance().willActivityBeVisible(
				a.getActivityToken());
	}
	if (r.window == null && !a.mFinished && willBeVisible) {
		r.window = r.activity.getWindow();
		View decor = r.window.getDecorView();
		decor.setVisibility(View.INVISIBLE);
		ViewManager wm = a.getWindowManager();
		WindowManager.LayoutParams l = r.window.getAttributes();
		a.mDecor = decor;
		l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
		l.softInputMode |= forwardBit;
		if (r.mPreserveWindow) {
			a.mWindowAdded = true;
			r.mPreserveWindow = false;
			// Normally the ViewRoot sets up callbacks with the Activity
			// in addView->ViewRootImpl#setView. If we are instead reusing
			// the decor view we have to notify the view root that the
			// callbacks may have changed.
			ViewRootImpl impl = decor.getViewRootImpl();
			if (impl != null) {
				impl.notifyChildRebuilt();
			}
		}
		if (a.mVisibleFromClient) {
			if (!a.mWindowAdded) {
				a.mWindowAdded = true;
				wm.addView(decor, l);
			} else {
				// The activity will get a callback for this {@link LayoutParams} change
				// earlier. However, at that time the decor will not be set (this is set
				// in this method), so no action will be taken. This call ensures the
				// callback occurs with the decor set.
				a.onWindowAttributesChanged(l);
			}
		}

		// If the window has already been added, but during resume
		// we started another activity, then don't yet make the
		// window visible.
	} else if (!willBeVisible) {
		if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
		r.hideForNow = true;
	}

	// Get rid of anything left hanging around.
	cleanUpPendingRemoveWindows(r, false /* force */);

	// The window is now visible if it has been added, we are not
	// simply finishing, and we are not starting another activity.
	if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
		if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward);
		ViewRootImpl impl = r.window.getDecorView().getViewRootImpl();
		WindowManager.LayoutParams l = impl != null
				? impl.mWindowAttributes : r.window.getAttributes();
		if ((l.softInputMode
				& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
				!= forwardBit) {
			l.softInputMode = (l.softInputMode
					& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
					| forwardBit;
			if (r.activity.mVisibleFromClient) {
				ViewManager wm = a.getWindowManager();
				View decor = r.window.getDecorView();
				wm.updateViewLayout(decor, l);
			}
		}

		r.activity.mVisibleFromServer = true;
		mNumVisibleActivities++;
		if (r.activity.mVisibleFromClient) {
			r.activity.makeVisible();
		}

		if (shouldSendCompatFakeFocus) {
			// Attaching to a window is asynchronous with the activity being resumed,
			// so it's possible we will need to send a fake focus event after attaching
			if (impl != null) {
				impl.dispatchCompatFakeFocus();
			} else {
				r.window.getDecorView().fakeFocusAfterAttachingToWindow();
			}
		}
	}

	mNewActivities.add(r);
	if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
	Looper.myQueue().addIdleHandler(new Idler());
}

这里主要关注performResumeActivity

D:\AndroidSource\Android11\platform\frameworks\base\core\java\android\app\ActivityThread.java

@VisibleForTesting
public boolean performResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
		String reason) {
	if (localLOGV) {
		Slog.v(TAG, "Performing resume of " + r + " finished=" + r.activity.mFinished);
	}
	if (r.activity.mFinished) {
		return false;
	}
	if (r.getLifecycleState() == ON_RESUME) {
		if (!finalStateRequest) {
			final RuntimeException e = new IllegalStateException(
					"Trying to resume activity which is already resumed");
			Slog.e(TAG, e.getMessage(), e);
			Slog.e(TAG, r.getStateString());
			// TODO(lifecycler): A double resume request is possible when an activity
			// receives two consequent transactions with relaunch requests and "resumed"
			// final state requests and the second relaunch is omitted. We still try to
			// handle two resume requests for the final state. For cases other than this
			// one, we don't expect it to happen.
		}
		return false;
	}
	if (finalStateRequest) {
		r.hideForNow = false;
		r.activity.mStartedActivity = false;
	}
	try {
		r.activity.onStateNotSaved();
		r.activity.mFragments.noteStateNotSaved();
		checkAndBlockForNetworkAccess();
		if (r.pendingIntents != null) {
			deliverNewIntents(r, r.pendingIntents);
			r.pendingIntents = null;
		}
		if (r.pendingResults != null) {
			deliverResults(r, r.pendingResults, reason);
			r.pendingResults = null;
		}
		r.activity.performResume(r.startsNotResumed, reason);

		r.state = null;
		r.persistentState = null;
		r.setState(ON_RESUME);

		reportTopResumedActivityChanged(r, r.isTopResumedActivity, "topWhenResuming");
	} catch (Exception e) {
		if (!mInstrumentation.onException(r.activity, e)) {
			throw new RuntimeException("Unable to resume activity "
					+ r.intent.getComponent().toShortString() + ": " + e.toString(), e);
		}
	}
	return true;
}

r.activity.performResume(r.startsNotResumed, reason);


final void performResume(boolean followedByPause, String reason) {
	if (Trace.isTagEnabled(Trace.TRACE_TAG_WINDOW_MANAGER)) {
		Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "performResume:"
				+ mComponent.getClassName());
	}
	dispatchActivityPreResumed();

	mFragments.execPendingActions();

	mLastNonConfigurationInstances = null;

	getAutofillClientController().onActivityPerformResume(followedByPause);

	mCalled = false;
	final long startTime = SystemClock.uptimeMillis();
	// mResumed is set by the instrumentation
	mInstrumentation.callActivityOnResume(this);
	final long duration = SystemClock.uptimeMillis() - startTime;
	EventLogTags.writeWmOnResumeCalled(mIdent, getComponentName().getClassName(), reason,
			duration);
	if (!mCalled) {
		throw new SuperNotCalledException(
			"Activity " + mComponent.toShortString() +
			" did not call through to super.onResume()");
	}

	// invisible activities must be finished before onResume) completes
	if (!mVisibleFromClient && !mFinished) {
		Log.w(TAG, "An activity without a UI must call finish() before onResume() completes");
		if (getApplicationInfo().targetSdkVersion
				> android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
			throw new IllegalStateException(
					"Activity " + mComponent.toShortString() +
					" did not call finish() prior to onResume() completing");
		}
	}

	// Now really resume, and install the current status bar and menu.
	mCalled = false;

	mFragments.dispatchResume();
	mFragments.execPendingActions();

	onPostResume();
	if (!mCalled) {
		throw new SuperNotCalledException(
			"Activity " + mComponent.toShortString() +
			" did not call through to super.onPostResume()");
	}
	dispatchActivityPostResumed();
	Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}

mInstrumentation.callActivityOnResume(this);执行onResumeEventLogTags.writeWmOnResumeCalled记录onResume执行时间

更新服务端状态

回到ActivityTaskSupervisorrealStartActivityLocked()

执行clientTransaction调用rootTask.minimalResumeActivityLocked(r);

platform/frameworks/base/services/core/java/com/android/server/wm/Task.java

void minimalResumeActivityLocked(ActivityRecord r) {
	ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (starting new instance) "
			+ "callers=%s", r, Debug.getCallers(5));
	r.setState(RESUMED, "minimalResumeActivityLocked");
	r.completeResumeLocked();
}

这里ActivityRecord状态设置成了RESUMED

platform/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java

void completeResumeLocked() {
	final boolean wasVisible = mVisibleRequested;
	setVisibility(true);
	if (!wasVisible) {
		// Visibility has changed, so take a note of it so we call the TaskStackChangedListener
		mTaskSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
	}
	idle = false;
	results = null;
	if (newIntents != null && newIntents.size() > 0) {
		mLastNewIntent = newIntents.get(newIntents.size() - 1);
	}
	newIntents = null;

	if (isActivityTypeHome()) {
		mTaskSupervisor.updateHomeProcess(task.getBottomMostActivity().app);
	}

	if (nowVisible) {
		mTaskSupervisor.stopWaitingForActivityVisible(this);
	}

	// Schedule an idle timeout in case the app doesn't do it for us.
	mTaskSupervisor.scheduleIdleTimeout(this);

	mTaskSupervisor.reportResumedActivityLocked(this);

	resumeKeyDispatchingLocked();
	final Task rootTask = getRootTask();
	mTaskSupervisor.mNoAnimActivities.clear();
	returningOptions = null;

	if (canTurnScreenOn()) {
		mTaskSupervisor.wakeUp("turnScreenOnFlag");
	} else {
		// If the screen is going to turn on because the caller explicitly requested it and
		// the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
		// pause and then resume again later, which will result in a double life-cycle event.
		rootTask.checkReadyForSleep();
	}
}

此处调用setVisibility(true);相关方法更新状态

至此,Activity启动流程梳理完毕。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/470844.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

c++类和对象(三)

c类和对象&#xff08;三&#xff09; 再谈构造函数 Static成员 友元 内部 匿名对象 拷贝对象时的一些编译器优化 再次理解封装 1.再谈构造函数 1.1构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。…

YOLOv9有效改进|加入RT-DETR中的AIFI结构。

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 一、改进点介绍 AIFI是RT-DETR中使用的尺度内特征交互模块。 二、AIFI模块详解 2.1 模块简介 AIFI的主要思想&#xff1a; 与Transformer的Encoder类…

【leetcode热题】二叉搜索树迭代器

实现一个二叉搜索树迭代器类BSTIterator &#xff0c;表示一个按中序遍历二叉搜索树&#xff08;BST&#xff09;的迭代器&#xff1a; BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在…

【2024最新版,redis7】redis底层的10种数据结构

前言&#xff1a;本文redis版本&#xff1a;7.2.4 本文语雀原文地址&#xff08;首发更新&#xff09;&#xff1a;https://www.yuque.com/wzzz/redis/xg2cp37kx1s4726y 本文CSDN转载地址&#xff1a; https://blog.csdn.net/u013625306/article/details/136842107 1. 常见的数…

【JavaScript】JavaScript 程序流程控制 ① ( 顺序流程控制 | 分支流程控制 )

文章目录 一、JavaScript 程序流程控制简介1、顺序流程控制2、分支流程控制3、分支流程控制 - 代码示例 一、JavaScript 程序流程控制简介 JavaScript 程序 执行过程中 , 不同的代码执行顺序 , 得到的结果是不同的 , 在编程中 经常 需要 根据 不同的条件 执行不同的代码块 , 或…

Redis数据结构对象中的对象共享、对象的空转时长

对象共享 概述 除了用于实现引用计数内存回收机制之外&#xff0c;对象的引用计数属性还带有对象共享的作用。 在Redis中&#xff0c;让多个键共享同一个值对象需要执行以下两个步骤: 1.将数据库键的值指针指向一个现有的值对象2.将被共享的值对象的引用计数增一 目前来说…

实验03-OSPF高级实验

1.实验拓扑 2.实验需求 3.配置思路 根据所给的IP地址配置完成后进行OSPF的配置&#xff1a; #R1 [r1]ospf 1 router-id 10.0.1.1 [r1-ospf-1]a 0 [r1-ospf-1-area-0.0.0.0]network 10.0.1.1 0.0.0.0 [r1-ospf-1-area-0.0.0.0]network 10.0.12.1 0.0.0.0 [r1-ospf-1-area-0.0.…

图书馆管理系统 1.架构项目以及加搭建项目

项目架构图 技术栈 后端 开发语言&#xff1a;java 开发环境&#xff1a;jdk11.0.12 开发工具&#xff1a;IntelliJ IDEA 2022.2.4 项目管理工具&#xff1a;maven 集成框架&#xff1a;springboot 权限控制框架&#xff1a;springSecurity 数据库&#xff1a;mysql 数据库框架…

QT-绘制动态曲线

QT-绘制动态曲线 pro文件中添加chart 在串口工程中添加控件 将控件功能提升为QChartView 点击添加 添加相关的头文件和变量

Selenium不同版本配置自动下载驱动及打包细节

Selenium配置浏览器驱动 自动下载浏览器驱动的方法 selenium4.7.0自动下载浏览器驱动的方法 selenium4.11.0 或4.11.1手动设置浏览器驱动路径的方法pyinstaller打包程序时同时打包ChromeDriverchromedriver路径需要sys._MEIPASS的路径进行引用方法一&#xff1a;通过–add-data…

【目标检测】图解 YOLOv3 的网络结构(Darknet-53 作为 backbone)

到了 YOLOv3&#xff0c;backbone 从 YOLOv2 的 Darknet-19 升级到了 Darknet-53。 下面一张完整的结构示意图来一起理解一下 YOLOv3 的网络结构。 我们怎么理解最后输出的 3 个特征图&#xff08;feature map&#xff09;的这个 255&#xff1f; 同 YOLOv2 一样&#xff0c;…

【蓝桥杯-单片机】基于定时器的倒计时程序设计

基于定时器的倒计时程序 题目如下所示&#xff1a; 实现过程中遇到的一些问题 01 如何改变Seg_Buf数组的值数码管总是一致地显示0 1 2 3 4 5 首先这个问题不是在main.c中关于数码管显示部分的逻辑错误&#xff0c;就是发生在数码管的底层错误。 检查了逻辑部分&#xff…

玩转C语言——深入理解指针

一、指针概念 1.1 内存和地址 在开始学习指针前&#xff0c;我们先来讲一个例子&#xff0c;假如你身处一栋楼中&#xff0c;你点了一份外卖&#xff0c;那么&#xff0c;外卖员如何能找到你&#xff1f;有两种方法。法一&#xff1a;直接一间一间找&#xff0c;这样做不仅消耗…

线程和进程的区别和联系

一、什么是进程 进程(Process), 是一个具有独立功能的程序关于某个数据集合的一次运行活动&#xff0c;是系统进行 【资源分配和调度】 的一个独立单位。 进程是【程序】的【一次执行】(是计算机中程序的执行过程&#xff0c;而不是计算机中的程序)进程是系统进行【资源分配和…

十二 超级数据查看器 讲解稿 详情7 其他功能

十二 超级数据查看器 讲解稿 详情7 其他功能 点击此处 以新页面 打开B站 播放当前教学视频 点击访问app下载页面 百度手机助手 下载地址 ​ 讲解稿全文&#xff1a; 其他操作&#xff0c;主要用来完成替换和批量修改&#xff0c; 这里&#xff0c;我们想给成语字段增…

YOLOv9改进策略:卷积魔改 | 分布移位卷积(DSConv),提高卷积层的内存效率和速度

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a; YOLOv9如何魔改卷积进一步提升检测精度&#xff1f;提出了一种卷积的变体&#xff0c;称为DSConv&#xff08;分布偏移卷积&#xff09;&#xff0c;其可以容易地替换进标准神经网络体系结构并且实现较低的存…

二、Kubernetes(k8s)中部署项目wordpress(php博客项目,数据库mysql)

前期准备 1、关机顺序 2、开机顺序 (1)、k8s-ha1、k8s-ha2 (2)、master01、master02、master03 (3)、node01、node02 一、集群服务对外提供访问&#xff0c;需要通过Ingress代理发布域名 mast01上传 ingress-nginx.yaml node01、node02 上传 ingress-nginx.tar 、kube-webh…

【知识库系统】JWT实现前后端分离验证

本文会先从理论和实践两部分讲述如何去理解和实现通过JWT进行身份认证。 一、理论 1. SpringSecurity 默认的认证是需要通过 UsernamePasswordAuthenticationFilter 进行认证的&#xff0c;该过滤器认证前&#xff0c;会到 SecurityContextHolder 中寻找是否有符合的 Authent…

Issue 2046:Missing array size check in NewFixedArray

文章目录 环境搭建漏洞分析漏洞触发 漏洞利用总结参考 环境搭建 sudo apt install pythongit reset --hard 64cadfcf4a56c0b3b9d3b5cc00905483850d6559 export DEPOT_TOOLS_UPDATE0 gclient sync -D// debug version tools/dev/v8gen.py x64.debug ninja -C out.gn/x64.debug/…

java数据结构与算法刷题-----LeetCode135. 分发糖果

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 左右遍历2. 进阶&#xff1a;常数空间遍历&#xff0c;升序降…