上一回讲到复用task,Activity的部分
流程
复用部分逻辑
1259 if (reusedActivity != null) {
1260 // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
1261 // still needs to be a lock task mode violation since the task gets cleared out and
1262 // the device would otherwise leave the locked task.
1263 if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
1264 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1265 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
1266 Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
1267 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
1268 }
1269
1270 // True if we are clearing top and resetting of a standard (default) launch mode
1271 // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
1272 final boolean clearTopAndResetStandardLaunchMode =
1273 (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
1274 == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
1275 && mLaunchMode == LAUNCH_MULTIPLE;
1276
1277 // If mStartActivity does not have a task associated with it, associate it with the
1278 // reused activity's task. Do not do so if we're clearing top and resetting for a
1279 // standard launchMode activity.
1280 if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
1281 mStartActivity.setTask(reusedActivity.getTask());
1282 }
1283
1284 if (reusedActivity.getTask().intent == null) {
1285 // This task was started because of movement of the activity based on affinity...
1286 // Now that we are actually launching it, we can assign the base intent.
1287 reusedActivity.getTask().setIntent(mStartActivity);
1288 }
1289
1290 // This code path leads to delivering a new intent, we want to make sure we schedule it
1291 // as the first operation, in case the activity will be resumed as a result of later
1292 // operations.
1293 if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
1294 || isDocumentLaunchesIntoExisting(mLaunchFlags)
1295 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1296 final TaskRecord task = reusedActivity.getTask();
1297
1298 // In this situation we want to remove all activities from the task up to the one
1299 // being started. In most cases this means we are resetting the task to its initial
1300 // state.
1301 final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
1302 mLaunchFlags); //将要复用的Activity上面的ActivityRecord都清除
//如果没有找到要复用的Activity,说明是第一次创建,则返回null
//注意,前面是task复用,这里如果top也不为null,那么就是ActivityRecord也复用了
1303
1304 // The above code can remove {@code reusedActivity} from the task, leading to the
1305 // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
1306 // task reference is needed in the call below to
1307 // {@link setTargetStackAndMoveToFrontIfNeeded}.
1308 if (reusedActivity.getTask() == null) {
1309 reusedActivity.setTask(task);
1310 }
1311
1312 if (top != null) { //如果找到了复用的Activity
1313 if (top.frontOfTask) { //且复用的Activity是root Activity
1314 // Activity aliases may mean we use different intents for the top activity,
1315 // so make sure the task now has the identity of the new intent.
1316 top.getTask().setIntent(mStartActivity); //重新设置task的Intent属性
1317 }
1318 deliverNewIntent(top); //调用Activity的omNewIntent方法
1319 }
1320 }
1322 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
1323
1324 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
//将复用task及其ActivityStack移到前台(如果必要的话) ;比如,使sourceTask和StartActivity的task不同,但是StartActivity指定的task已经存在了,可以复用(sourceTask和StartActivity的task不同,这也就是NEW_TASK这个flag的意思,可以找到可复用task的top running Activity,若没找到返回null),将其移到前台来即可;
1325
1326 final ActivityRecord outResult =
1327 outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
1328
1329 // When there is a reused activity and the current result is a trampoline activity,
1330 // set the reused activity as the result.
1331 if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
1332 outActivity[0] = reusedActivity;
1333 }
1334
1335 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1336 // We don't need to start a new activity, and the client said not to do anything
1337 // if that is the case, so this is it! And for paranoia, make sure we have
1338 // correctly resumed the top activity.
1339 resumeTargetStackIfNeeded();
1340 return START_RETURN_INTENT_TO_CALLER;
1341 }
1342
1343 if (reusedActivity != null) {
1344 setTaskFromIntentActivity(reusedActivity);
1345
1346 if (!mAddingToTask && mReuseTask == null) {
//mAddingToTask为false,且在复用的逻辑中,那么说明task中有复用Activity
1347 // We didn't do anything... but it was needed (a.k.a., client don't use that
1348 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1349 //按理说前面已经将Activity之上的全部清空了,保险起见,再调用一次resume的逻辑
1350 resumeTargetStackIfNeeded();//其实就是调用
//如同一个栈中A->B->A,A是singleTask模式,那么task,Activity均可复用,这里就是先将B pause,然后A resume,最后B finish;介绍大致流程resumeFocusedStackTopActivityLocked
1351 if (outActivity != null && outActivity.length > 0) {
1352 outActivity[0] = reusedActivity;
1353 }
1354
1355 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP; //mMovedToFront 代表是否将ActivityStack移到了前台,如果本来就在前台,则为false
1356 }
1357 }
1358 }
ActivityStarter#deliverNewIntent
2092 private void deliverNewIntent(ActivityRecord activity) {
2093 if (mIntentDelivered) {
2094 return;
2095 }
2096
2097 ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
2098 activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
2099 mStartActivity.launchedFromPackage);
2100 mIntentDelivered = true;
2101 }
ActivityRecord#deliverNewIntentLocked
1464 /**
1465 * Deliver a new Intent to an existing activity, so that its onNewIntent()
1466 * method will be called at the proper time.
1467 */
1468 final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
1469 // The activity now gets access to the data associated with this Intent.
1470 service.grantUriPermissionFromIntentLocked(callingUid, packageName,
1471 intent, getUriPermissionsLocked(), userId);
1472 final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
1473 boolean unsent = true;
1474 final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
1475
1476 // We want to immediately deliver the intent to the activity if:
1477 // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
1478 // the user to see the visual effects caused by the intent delivery now.
1479 // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
//当Activity处于paused或者resumed状态(用户还可见时,调用Activity的onNewIntent)
1480 if ((mState == RESUMED || mState == PAUSED
1481 || isTopActivityWhileSleeping) && app != null && app.thread != null) {
1482 try {
1483 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
1484 ar.add(rintent);
1485 service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
1486 NewIntentItem.obtain(ar, mState == PAUSED));
1487 unsent = false; //调用onNewIntent
1488 } catch (RemoteException e) {
1489 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1490 } catch (NullPointerException e) {
1491 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1492 }
1493 }
1494 if (unsent) {
//将intent加入到ActivityRecord中的newIntents队列
1495 addNewIntentLocked(rintent);
1496 }
1497 }
如何调用Activity相关的声明周期函数呢?大致逻辑如下
ClientLifecycleManager#scheduleTransaction
56 /**
57 * Schedule a single lifecycle request or callback to client activity.
58 * @param client Target client.
59 * @param activityToken Target activity token.
60 * @param stateRequest A request to move target activity to a desired lifecycle state.
61 * @throws RemoteException
62 *
63 * @see ClientTransactionItem
64 */
65 void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
66 @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
67 final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
68 stateRequest);
69 scheduleTransaction(clientTransaction);
70 }
38 /**
39 * Schedule a transaction, which may consist of multiple callbacks and a lifecycle request.
40 * @param transaction A sequence of client transaction items.
41 * @throws RemoteException
42 *
43 * @see ClientTransaction
44 */
45 void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
46 final IApplicationThread client = transaction.getClient();
47 transaction.schedule();
48 if (!(client instanceof Binder)) {
49 // If client is not an instance of Binder - it's a remote call and at this point it is
50 // safe to recycle the object. All objects used for local calls will be recycled after
51 // the transaction is executed on client in ActivityThread.
52 transaction.recycle();
53 }
54 }
55
ClientTransaction#schedule
118 /**
119 * Schedule the transaction after it was initialized. It will be send to client and all its
120 * individual parts will be applied in the following sequence:
121 * 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
122 * that needs to be done before actually scheduling the transaction for callbacks and
123 * lifecycle state request.
124 * 2. The transaction message is scheduled.
125 * 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
126 * all callbacks and necessary lifecycle transitions.
127 */
128 public void schedule() throws RemoteException {
129 mClient.scheduleTransaction(this);
130 }
53 /** Target client. */
54 private IApplicationThread mClient;
我们同样注意到
public final class ActivityThread extends ClientTransactionHandler
则
ClientTransactionHandler#scheduleTransaction
42 /** Prepare and schedule transaction for execution. */
43 void scheduleTransaction(ClientTransaction transaction) {
44 transaction.preExecute(this);
45 sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
46 }
ActivityThread#handleMessage
1809 case EXECUTE_TRANSACTION:
1810 final ClientTransaction transaction = (ClientTransaction) msg.obj;
1811 mTransactionExecutor.execute(transaction);
1812 if (isSystem()) {
1813 // Client transactions inside system process are recycled on the client side
1814 // instead of ClientLifecycleManager to avoid being cleared before this
1815 // message is handled.
1816 transaction.recycle();
1817 }
TransactionExecutor#execute
/**
* Resolve transaction.
* First all callbacks will be executed in the order they appear in the list. If a callback
* requires a certain pre- or post-execution state, the client will be transitioned accordingly.
* Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
* either remain in the initial state, or last state needed by a callback.
*/
public void execute(ClientTransaction transaction) {
final IBinder token = transaction.getActivityToken();
log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
executeCallbacks(transaction);
executeLifecycleState(transaction);
mPendingActions.clear();
log("End resolving transaction");
}
TransactionExecutor#executeLifecycleState
private void executeLifecycleState(ClientTransaction transaction) {
final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
if (lifecycleItem == null) {
// No lifecycle request, return early.
return;
}
log("Resolving lifecycle state: " + lifecycleItem);
final IBinder token = transaction.getActivityToken();
final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (r == null) {
// Ignore requests for non-existent client records for now.
return;
}
// Cycle to the state right before the final requested state.
cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
// Execute the final transition with proper parameters.
lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
}
执行对应ActivityLifecycleItem的excute,如
NewIntentItem#execute
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
client.handleNewIntent(token, mIntents, mPause);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ActivityThread#handleNewIntent
3142 @Override
3143 public void handleNewIntent(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
3144 performNewIntents(token, intents, andPause);
3145 }
3115 void performNewIntents(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
3116 final ActivityClientRecord r = mActivities.get(token);
3117 if (r == null) {
3118 return;
3119 }
3120
3121 final boolean resumed = !r.paused;
3122 if (resumed) {
3123 r.activity.mTemporaryPause = true;
3124 mInstrumentation.callActivityOnPause(r.activity);
3125 }
3126 checkAndBlockForNetworkAccess();
3127 deliverNewIntents(r, intents);
3128 if (resumed) {
3129 r.activity.performResume(false, "performNewIntents");
3130 r.activity.mTemporaryPause = false;
3131 }
3132
3133 if (r.paused && andPause) {
3134 // In this case the activity was in the paused state when we delivered the intent,
3135 // to guarantee onResume gets called after onNewIntent we temporarily resume the
3136 // activity and pause again as the caller wanted.
3137 performResumeActivity(token, false, "performNewIntents");
3138 performPauseActivityIfNeeded(r, "performNewIntents");
3139 }
3140 }
以上全是在Activity的服务端执行的逻辑
回到task,Activity复用的逻辑
ActivityStarter#setTargetStackAndMoveToFrontIfNeeded
保证复用的task,stack在前台
1855 /**
1856 * Figure out which task and activity to bring to front when we have found an existing matching
1857 * activity record in history. May also clear the task if needed.
1858 * @param intentActivity Existing matching activity.
1859 * @return {@link ActivityRecord} brought to front.
1860 */
1861 private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
1862 mTargetStack = intentActivity.getStack(); //得到reusedActivity相应的stack
1863 mTargetStack.mLastPausedActivity = null;
1864 // If the target task is not in the front, then we need to bring it to the front...
1865 // except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
1866 // the same behavior as if a new instance was being started, which means not bringing it
1867 // to the front if the caller is not itself in the front.
1868 final ActivityStack focusStack = mSupervisor.getFocusedStack();
1869 ActivityRecord curTop = (focusStack == null)
1870 ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
1871
1872 final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
1873 if (topTask != null
1874 && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
1875 && !mAvoidMoveToFront) { //针对task需要移动到前台的情况
//要复用的task不是当前focus stack的top task
1876 mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1877 if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
1878 mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
1879 // We really do want to push this one into the user's face, right now.
1880 if (mLaunchTaskBehind && mSourceRecord != null) {
1881 intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
1882 }
1883
1884 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
1885 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
1886 // So no point resuming any of the activities here, it just wastes one extra
1887 // resuming, plus enter AND exit transitions.
1888 // Here we only want to bring the target stack forward. Transition will be applied
1889 // to the new activity that's started after the old ones are gone.
1890 final boolean willClearTask =
1891 (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
1892 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
1893 if (!willClearTask) {
1894 final ActivityStack launchStack = getLaunchStack(
1895 mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
//getLaunchStack返回The stack to use for the launch or INVALID_STACK_ID.
1896 final TaskRecord intentTask = intentActivity.getTask();
1897 if (launchStack == null || launchStack == mTargetStack) {
1898 // We only want to move to the front, if we aren't going to launch on a
1899 // different stack. If we launch on a different stack, we will put the
1900 // task on top there.
//将要复用的task放到stack前面,并将改ActivityStack也设为focus
1901 mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
1902 mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
1903 mMovedToFront = true;
1904 } else if (launchStack.inSplitScreenWindowingMode()) {
1905 if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1906 // If we want to launch adjacent and mTargetStack is not the computed
1907 // launch stack - move task to top of computed stack.
1908 intentTask.reparent(launchStack, ON_TOP,
1909 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1910 "launchToSide");
1911 } else {
1912 // TODO: This should be reevaluated in MW v2.
1913 // We choose to move task to front instead of launching it adjacent
1914 // when specific stack was requested explicitly and it appeared to be
1915 // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
1916 mTargetStack.moveTaskToFrontLocked(intentTask,
1917 mNoAnimation, mOptions, mStartActivity.appTimeTracker,
1918 "bringToFrontInsteadOfAdjacentLaunch");
1919 }
1920 mMovedToFront = launchStack != launchStack.getDisplay()
1921 .getTopStackInWindowingMode(launchStack.getWindowingMode());
1922 } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
1923 // Target and computed stacks are on different displays and we've
1924 // found a matching task - move the existing instance to that display and
1925 // move it to front.
1926 intentActivity.getTask().reparent(launchStack, ON_TOP,
1927 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1928 "reparentToDisplay");
1929 mMovedToFront = true;
1930 } else if (launchStack.isActivityTypeHome()
1931 && !mTargetStack.isActivityTypeHome()) {
1932 // It is possible for the home activity to be in another stack initially.
1933 // For example, the activity may have been initially started with an intent
1934 // which placed it in the fullscreen stack. To ensure the proper handling of
1935 // the activity based on home stack assumptions, we must move it over.
1936 intentActivity.getTask().reparent(launchStack, ON_TOP,
1937 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
1938 "reparentingHome");
1939 mMovedToFront = true;
1940 }
1941 mOptions = null;
1942
1943 // We are moving a task to the front, use starting window to hide initial drawn
1944 // delay.
1945 intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
1946 true /* taskSwitch */);
1947 }
1948 }
1949 }
1950 // Need to update mTargetStack because if task was moved out of it, the original stack may
1951 // be destroyed.
1952 mTargetStack = intentActivity.getStack();
1953 if (!mMovedToFront && mDoResume) {
1954 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
1955 + " from " + intentActivity);
1956 mTargetStack.moveToFront("intentActivityFound");
1957 }
1958
1959 mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
1960 WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
1961
1962 // If the caller has requested that the target task be reset, then do so.
1963 if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1964 return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
1965 }
1966 return intentActivity;
1967 }
ActivityStack#moveTaskToFrontLocked
4651 final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
4652 AppTimeTracker timeTracker, String reason) {
4653 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
4654
4655 final ActivityStack topStack = getDisplay().getTopStack();
4656 final ActivityRecord topActivity = topStack != null ? topStack.getTopActivity() : null;
4657 final int numTasks = mTaskHistory.size();
4658 final int index = mTaskHistory.indexOf(tr);
4659 if (numTasks == 0 || index < 0) {
4660 // nothing to do!
4661 if (noAnimation) {
4662 ActivityOptions.abort(options);
4663 } else {
4664 updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
4665 }
4666 return;
4667 }
4668
4669 if (timeTracker != null) {
4670 // The caller wants a time tracker associated with this task.
4671 for (int i = tr.mActivities.size() - 1; i >= 0; i--) {
4672 tr.mActivities.get(i).appTimeTracker = timeTracker;
4673 }
4674 }
4675
4676 try {
4677 // Defer updating the IME target since the new IME target will try to get computed
4678 // before updating all closing and opening apps, which can cause the ime target to
4679 // get calculated incorrectly.
4680 getDisplay().deferUpdateImeTarget();
4681
4682 // Shift all activities with this task up to the top
4683 // of the stack, keeping them in the same internal order.
4684 insertTaskAtTop(tr, null); //将task放到当前ActivityStack的top位置
4685
4686 // Don't refocus if invisible to current user
4687 final ActivityRecord top = tr.getTopActivity();
4688 if (top == null || !top.okToShowLocked()) {
4689 if (top != null) {
4690 mStackSupervisor.mRecentTasks.add(top.getTask());
4691 }
4692 ActivityOptions.abort(options);
4693 return;
4694 }
4695
4696 // Set focus to the top running activity of this stack.
//得到当前stack的top running Activity
4697 final ActivityRecord r = topRunningActivityLocked();
//然后调用到这里,将当前栈设置为focus
4698 mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
4699
4700 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
4701 if (noAnimation) {
4702 mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
4703 if (r != null) {
4704 mStackSupervisor.mNoAnimActivities.add(r);
4705 }
4706 ActivityOptions.abort(options);
4707 } else {
4708 updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
4709 }
4710 // If a new task is moved to the front, then mark the existing top activity as
4711 // supporting
4712
4713 // picture-in-picture while paused only if the task would not be considered an oerlay
4714 // on top
4715 // of the current activity (eg. not fullscreen, or the assistant)
4716 if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
4717 options)) {
4718 topActivity.supportsEnterPipOnTaskSwitch = true;
4719 }
4720
4721 mStackSupervisor.resumeFocusedStackTopActivityLocked();
//然后调用到这里,在resumeTopActivityInnerLocked中的pauseBackStacks,将上一个stack中的Activity pause
//resumeFocusedStackTopActivityLocked可以等到后面再说
4722 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
4723
4724 mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
4725 } finally {
4726 getDisplay().continueUpdateImeTarget();
4727 }
4728 }
ActivityStackSupervisor#moveFocusableActivityStackToFrontLocked
将ActivityRecord所在stack移到前台,并设置为focus
3411 /** Move activity with its stack to front and make the stack focused. */
3412 boolean moveFocusableActivityStackToFrontLocked(ActivityRecord r, String reason) {
3413 if (r == null || !r.isFocusable()) {
3414 if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
3415 "moveActivityStackToFront: unfocusable r=" + r);
3416 return false;
3417 }
3418
3419 final TaskRecord task = r.getTask();
3420 final ActivityStack stack = r.getStack();
3421 if (stack == null) {
3422 Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
3423 + r + " task=" + task);
3424 return false;
3425 }
3426
3427 if (stack == mFocusedStack && stack.topRunningActivityLocked() == r) {
3428 if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
3429 "moveActivityStackToFront: already on top, r=" + r);
3430 return false;
3431 }
3432
3433 if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
3434 "moveActivityStackToFront: r=" + r);
3435
3436 stack.moveToFront(reason, task);
3437 return true;
3438 }
ActivityStack#moveToFront
1022 /**
1023 * @param reason The reason for moving the stack to the front.
1024 * @param task If non-null, the task will be moved to the top of the stack.
1025 * */
1026 void moveToFront(String reason, TaskRecord task) {
1027 if (!isAttached()) {
1028 return;
1029 }
1030
1031 final ActivityDisplay display = getDisplay();
1032
1033 if (inSplitScreenSecondaryWindowingMode()) {
1034 // If the stack is in split-screen seconardy mode, we need to make sure we move the
1035 // primary split-screen stack forward in the case it is currently behind a fullscreen
1036 // stack so both halves of the split-screen appear on-top and the fullscreen stack isn't
1037 // cutting between them.
1038 // TODO(b/70677280): This is a workaround until we can fix as part of b/70677280.
1039 final ActivityStack topFullScreenStack =
1040 display.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
1041 if (topFullScreenStack != null) {
1042 final ActivityStack primarySplitScreenStack = display.getSplitScreenPrimaryStack();
1043 if (display.getIndexOf(topFullScreenStack)
1044 > display.getIndexOf(primarySplitScreenStack)) {
1045 primarySplitScreenStack.moveToFront(reason + " splitScreenToTop");
1046 }
1047 }
1048 }
1049
1050 if (!isActivityTypeHome() && returnsToHomeStack()) {
1051 // Make sure the home stack is behind this stack since that is where we should return to
1052 // when this stack is no longer visible.
1053 mStackSupervisor.moveHomeStackToFront(reason + " returnToHome");
1054 }
1055
1056 display.positionChildAtTop(this);
1057 mStackSupervisor.setFocusStackUnchecked(reason, this);//将当前的ActivityStack设置为focus
1058 if (task != null) {
1059 insertTaskAtTop(task, null); //task放到stack的top位置
1060 return;
1061 }
1062 }
ActivityStackSupervisor#setFocusStackUnchecked
713 /** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
714 void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
715 if (!focusCandidate.isFocusable()) {
716 // The focus candidate isn't focusable. Move focus to the top stack that is focusable.
717 focusCandidate = getNextFocusableStackLocked(focusCandidate, false /* ignoreCurrent */);
718 }
719
720 if (focusCandidate != mFocusedStack) {
721 mLastFocusedStack = mFocusedStack;
722 mFocusedStack = focusCandidate;
723
724 EventLogTags.writeAmFocusedStack(
725 mCurrentUser, mFocusedStack == null ? -1 : mFocusedStack.getStackId(),
726 mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), reason);
727 }
728
729 final ActivityRecord r = topRunningActivityLocked();
730 if (mService.mBooting || !mService.mBooted) {
731 if (r != null && r.idle) {
732 checkFinishBootingLocked();
733 }
734 }
735 }
回到复用的逻辑
ActivityStarter#setTaskFromIntentActivity
setTaskFromIntentActivity也是针对task复用而言的;这个是用来设置复用task相关的一些属性的;注意mAddingToTask,个人理解,当mAddingToTask的值为true时,代表要创建新的Activity添加到复用task中
2130 private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
2131 if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
2132 == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
2133 // The caller has requested to completely replace any existing task with its new
2134 // activity. Well that should not be too hard...
2135 // Note: we must persist the {@link TaskRecord} first as intentActivity could be
2136 // removed from calling performClearTaskLocked (For example, if it is being brought out
2137 // of history or if it is finished immediately), thus disassociating the task. Also note
2138 // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
2139 // launching another activity.
2140 // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
2141 // already launching one.
2142 final TaskRecord task = intentActivity.getTask();
2143 task.performClearTaskLocked();
2144 mReuseTask = task;
2145 mReuseTask.setIntent(mStartActivity);
2146 } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
2147 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
2148 ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
2149 mLaunchFlags);
2150 if (top == null) {
//比如这里,虽然复用task,但是在task中找不到复用的ActivityRecord;如要启动的flag包含NEW_TASK;但是这个Activity是第一次启动
//则mAddingToTask为true,代表要创建new Activity放到复用task中
2151 // A special case: we need to start the activity because it is not currently
2152 // running, and the caller has asked to clear the current task to have this
2153 // activity at the top.
2154 mAddingToTask = true;
2155
2156 // We are no longer placing the activity in the task we previously thought we were.
2157 mStartActivity.setTask(null);
//注意这里将StartActivity的task置空,后续还会通过setTaskFromSourceRecord()赋值
2158 // Now pretend like this activity is being started by the top of its task, so it
2159 // is put in the right place.
2160 mSourceRecord = intentActivity;
//mSourceRecord的值赋值为intentActivity
2161 final TaskRecord task = mSourceRecord.getTask();
2162 if (task != null && task.getStack() == null) {
2163 // Target stack got cleared when we all activities were removed above.
2164 // Go ahead and reset it.
2165 mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
2166 mLaunchFlags, mOptions);
2167 mTargetStack.addTask(task,
2168 !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
2169 }
2170 }
2171 } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
2172 // In this case the top activity on the task is the same as the one being launched,
2173 // so we take that as a request to bring the task to the foreground. If the top
2174 // activity in the task is the root activity, deliver this new intent to it if it
2175 // desires.
2176 if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
2177 || LAUNCH_SINGLE_TOP == mLaunchMode)
2178 && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
2179 if (intentActivity.frontOfTask) {
2180 intentActivity.getTask().setIntent(mStartActivity);
2181 }
2182 deliverNewIntent(intentActivity);
2183 } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
2184 // In this case we are launching the root activity of the task, but with a
2185 // different intent. We should start a new instance on top.
2186 mAddingToTask = true;
2187 mSourceRecord = intentActivity;
2188 }
2189 } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
2190 // In this case an activity is being launched in to an existing task, without
2191 // resetting that task. This is typically the situation of launching an activity
2192 // from a notification or shortcut. We want to place the new activity on top of the
2193 // current task.
2194 mAddingToTask = true;
2195 mSourceRecord = intentActivity;
2196 } else if (!intentActivity.getTask().rootWasReset) {
2197 // In this case we are launching into an existing task that has not yet been started
2198 // from its front door. The current task has been brought to the front. Ideally,
2199 // we'd probably like to place this new task at the bottom of its stack, but that's
2200 // a little hard to do with the current organization of the code so for now we'll
2201 // just drop it.
2202 intentActivity.getTask().setIntent(mStartActivity);
2203 }
2204 }
ActivityStarter#resumeTargetStackIfNeeded
上面说道resumeTargetStackIfNeeded,这也只是在复用task的时候才会调用的
A->B->A A为singleTask模式的大致流程
1477 if (reusedActivity != null) {
1478 setTaskFromIntentActivity(reusedActivity);
1479
1480 if (!mAddingToTask && mReuseTask == null) {
1481 // We didn't do anything... but it was needed (a.k.a., client don't use that
1482 // intent!) And for paranoia, make sure we have correctly resumed the top activity.
1483 //mAddingToTask = false,不用创建新的Activity,那么就是复用原来的
1484 resumeTargetStackIfNeeded(); //调用resumeTargetStackIfNeeded
1485 if (outActivity != null && outActivity.length > 0) {
1486 outActivity[0] = reusedActivity;
1487 }
1488
1489 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
1490 }
1491 }
2206 private void resumeTargetStackIfNeeded() {
2207 if (mDoResume) {
2208 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
2209 } else {
2210 ActivityOptions.abort(mOptions);
2211 }
2212 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
2213 }
ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
2307 boolean resumeFocusedStackTopActivityLocked(
2308 ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
2309
2310 if (!readyToResume()) {
2311 return false;
2312 }
2313
2315 // if resume one non-fullscreen task, also resume the other one
2316 boolean resumed = false;
2317 if (targetStack != null && isFocusedStack(targetStack)) {
2321
2331 if (target != null && target.getState() == RESUMED && mNeedScheduleIdle) {
2332 scheduleIdleLocked();
2333 mNeedScheduleIdle = false;
2334 if (target.getTask().inMultiWindowMode()) {
2335 return false;
2336 }
2337 }
2338 resumed = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
2339 } else {
2340 ActivityStack recentsStack = getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS);
2341 if (mLaunchRecentsFromGesture && recentsStack != null && !mHasResumeRecentsBehind
2342 && !mStopLaunchRecentsBehind) {
2343 recentsStack.resumeTopActivityUncheckedLocked(null, null);
2344 } else {
2345 final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
2346 if (r == null || r.getState() != RESUMED) {
2347 mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
2348 } else if (r.getState() == RESUMED) {
2349 if (!r.getTask().inMultiWindowMode()) {
2350 mFocusedStack.executeAppTransition(targetOptions);
2351 }
2352 if (mNeedScheduleIdle) {
2353 scheduleIdleLocked();
2354 mNeedScheduleIdle = false;
2355 }
2356 return false;
2357 }
2358 }
2359 }
2360 // resume non-fullscreen task
2361 if (mFocusedStack.topTask() != null && mFocusedStack.topTask().inMultiWindowMode()
2362 && !mService.isSleepingOrShuttingDownLocked()) {
2364 ActivityStack multiWindowStack = null;
2365 if (mFocusedStack.inSplitScreenPrimaryWindowingMode()) {
2366 multiWindowStack = mFocusedStack.getDisplay().getTopStackInWindowingMode(
2367 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
2368 } else if (mFocusedStack.inSplitScreenSecondaryWindowingMode()) {
2369 multiWindowStack = mFocusedStack.getDisplay().getTopStackInWindowingMode(
2370 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
2371 }
2372
2373 if (multiWindowStack != null
2374 && multiWindowStack.shouldBeVisible(null)) {
2375 final ActivityRecord r = multiWindowStack.topRunningActivityLocked();
2376 if (r != null && r.getState() != RESUMED && r.getTask().inMultiWindowMode()) {
2377 multiWindowStack.resumeTopActivityUncheckedLocked(null, null);
2378 }
2379 }
2380 }
2381 return resumed;
2382 // END
2383 }
ActivityStack#resumeTopActivityUncheckedLocked
2397 /**
2398 * Ensure that the top activity in the stack is resumed.
2399 *
2400 * @param prev The previously resumed activity, for when in the process
2401 * of pausing; can be null to call from elsewhere.
2402 * @param options Activity options.
2403 *
2404 * @return Returns true if something is being resumed, or false if
2405 * nothing happened.
2406 *
2407 * NOTE: It is not safe to call this method directly as it can cause an activity in a
2408 * non-focused stack to be resumed.
2409 * Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the
2410 * right activity for the current system state.
2411 */
2412 @GuardedBy("mService")
2413 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
2414 if (mStackSupervisor.inResumeTopActivity) {
2415 // Don't even start recursing.
2416 return false;
2417 }
2418
2419 boolean result = false;
2420 try {
2421 // Protect against recursion.
2422 mStackSupervisor.inResumeTopActivity = true;
2423 result = resumeTopActivityInnerLocked(prev, options);
2424
2425 // When resuming the top activity, it may be necessary to pause the top activity (for
2426 // example, returning to the lock screen. We suppress the normal pause logic in
2427 // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
2428 // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
2429 // to ensure any necessary pause logic occurs. In the case where the Activity will be
2430 // shown regardless of the lock screen, the call to
2431 // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
2432 final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
2433 if (next == null || !next.canTurnScreenOn()) {
2434 checkReadyForSleep();
2435 }
2436 } finally {
2437 mStackSupervisor.inResumeTopActivity = false;
2438 }
2439
2440 return result;
2441 }
调用resumeTopActivityInnerLocked,这个逻辑比较复杂,放在下面的文章中讲
网友评论