前面说道准备工作和检查工作做完之后开始进行真正的startActivity操作
流程
ActivityStarter#startActivityUnchecked
1223 // Note: This method should only be called from {@link startActivity}.
1224 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
1225 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1226 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1227 ActivityRecord[] outActivity) {
1228
1229 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
1230 voiceInteractor);
1231
1232 computeLaunchingTaskFlags();
1233
1234 computeSourceStack();
1235
1236 mIntent.setFlags(mLaunchFlags);
1237
1238 ActivityRecord reusedActivity = getReusableIntentActivity();
1239
1240 int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;
1241 int preferredLaunchDisplayId = DEFAULT_DISPLAY;
1242 if (mOptions != null) {
1243 preferredWindowingMode = mOptions.getLaunchWindowingMode();
1244 preferredLaunchDisplayId = mOptions.getLaunchDisplayId();
1245 }
1246
1247 // windowing mode and preferred launch display values from {@link LaunchParams} take
1248 // priority over those specified in {@link ActivityOptions}.
1249 if (!mLaunchParams.isEmpty()) {
1250 if (mLaunchParams.hasPreferredDisplay()) {
1251 preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId;
1252 }
1253
1254 if (mLaunchParams.hasWindowingMode()) {
1255 preferredWindowingMode = mLaunchParams.mWindowingMode;
1256 }
1257 }
1258
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);
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) {
1313 if (top.frontOfTask) {
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);
1317 }
1318 deliverNewIntent(top);
1319 }
1320 }
1321
1322 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
1323
1324 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
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) {
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
1350 resumeTargetStackIfNeeded();
1351 if (outActivity != null && outActivity.length > 0) {
1352 outActivity[0] = reusedActivity;
1353 }
1354
1355 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
1356 }
1357 }
1358 }
1359
1360 if (mStartActivity.packageName == null) {
1361 final ActivityStack sourceStack = mStartActivity.resultTo != null
1362 ? mStartActivity.resultTo.getStack() : null;
1363 if (sourceStack != null) {
1364 sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
1365 mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
1366 null /* data */);
1367 }
1368 ActivityOptions.abort(mOptions);
1369 return START_CLASS_NOT_FOUND;
1370 }
1371
1372 // If the activity being launched is the same as the one currently at the top, then
1373 // we need to check if it should only be launched once.
1374 final ActivityStack topStack = mSupervisor.mFocusedStack;
1375 final ActivityRecord topFocused = topStack.getTopActivity();
1376 final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
1377 final boolean dontStart = top != null && mStartActivity.resultTo == null
1378 && top.realActivity.equals(mStartActivity.realActivity)
1379 && top.userId == mStartActivity.userId
1380 && top.app != null && top.app.thread != null
1381 && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
1382 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
1383 if (dontStart) {
1384 // For paranoia, make sure we have correctly resumed the top activity.
1385 topStack.mLastPausedActivity = null;
1386 if (mDoResume) {
1387 mSupervisor.resumeFocusedStackTopActivityLocked();
1388 }
1389 ActivityOptions.abort(mOptions);
1390 if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1391 // We don't need to start a new activity, and the client said not to do
1392 // anything if that is the case, so this is it!
1393 return START_RETURN_INTENT_TO_CALLER;
1394 }
1395
1396 deliverNewIntent(top);
1397
1398 // Don't use mStartActivity.task to show the toast. We're not starting a new activity
1399 // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
1400 mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
1401 preferredLaunchDisplayId, topStack);
1402
1403 return START_DELIVERED_TO_TOP;
1404 }
1405
1406 boolean newTask = false;
1407 final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
1408 ? mSourceRecord.getTask() : null;
1409
1410 // Should this be considered a new task?
1411 int result = START_SUCCESS;
1412 if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
1413 && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1414 newTask = true;
1415 String packageName= mService.mContext.getPackageName();
1416 if (mPerf != null) {
1417 mPerf.perfHint(BoostFramework.VENDOR_HINT_FIRST_LAUNCH_BOOST,
1418 packageName, -1, BoostFramework.Launch.BOOST_V1);
1419 }
1420 result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);
1421 } else if (mSourceRecord != null) {
1422 result = setTaskFromSourceRecord();
1423 } else if (mInTask != null) {
1424 result = setTaskFromInTask();
1425 } else {
1426 // This not being started from an existing activity, and not part of a new task...
1427 // just put it in the top task, though these days this case should never happen.
1428 setTaskToCurrentTopOrCreateNewTask();
1429 }
1430 if (result != START_SUCCESS) {
1431 return result;
1432 }
1433
1434 mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,
1435 mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
1436 mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,
1437 mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
1438 if (newTask) {
1439 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
1440 mStartActivity.getTask().taskId);
1441 }
1442 ActivityStack.logStartActivity(
1443 EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
1444 mTargetStack.mLastPausedActivity = null;
1445
1446 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
1447
1448 mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
1449 mOptions);
1450 if (mDoResume) {
1451 final ActivityRecord topTaskActivity =
1452 mStartActivity.getTask().topRunningActivityLocked();
1453 if (!mTargetStack.isFocusable()
1454 || (topTaskActivity != null && topTaskActivity.mTaskOverlay
1455 && mStartActivity != topTaskActivity)) {
1456 // If the activity is not focusable, we can't resume it, but still would like to
1457 // make sure it becomes visible as it starts (this will also trigger entry
1458 // animation). An example of this are PIP activities.
1459 // Also, we don't want to resume activities in a task that currently has an overlay
1460 // as the starting activity just needs to be in the visible paused state until the
1461 // over is removed.
1462 mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1463 // Go ahead and tell window manager to execute app transition for this activity
1464 // since the app transition will not be triggered through the resume channel.
1465 mService.mWindowManager.executeAppTransition();
1466 } else {
1467 // If the target stack was not previously focusable (previous top running activity
1468 // on that stack was not visible) then any prior calls to move the stack to the
1469 // will not update the focused stack. If starting the new activity now allows the
1470 // task stack to be focusable, then ensure that we now update the focused stack
1471 // accordingly.
1472 if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
1473 mTargetStack.moveToFront("startActivityUnchecked");
1474 }
1475 mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
1476 mOptions);
1477 }
1478 } else if (mStartActivity != null) {
1479 mSupervisor.mRecentTasks.add(mStartActivity.getTask());
1480 }
1481 mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
1482
1483 mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
1484 preferredLaunchDisplayId, mTargetStack);
1485
1486 return START_SUCCESS;
1487 }
ActivityStarter#setInitialState
从ActivityRecord得到一些属性,如mStartActivity,mIntent,mLaunchMode,mLaunchFlags等初始化
1535 private void setInitialState(ActivityRecord r, ActivityOptions options, TaskRecord inTask,
1536 boolean doResume, int startFlags, ActivityRecord sourceRecord,
1537 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
1538 reset(false /* clearRequest */);
1539
1540 mStartActivity = r;
1541 mIntent = r.intent;
1542 mOptions = options;
1543 mCallingUid = r.launchedFromUid;
1544 mSourceRecord = sourceRecord;
1545 mVoiceSession = voiceSession;
1546 mVoiceInteractor = voiceInteractor;
1547
1548 mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options);
1549
1550 mLaunchParams.reset();
1551
1552 mSupervisor.getLaunchParamsController().calculate(inTask, null /*layout*/, r, sourceRecord,
1553 options, mLaunchParams);
1554
1555 mLaunchMode = r.launchMode;
1556
1557 mLaunchFlags = adjustLaunchFlagsToDocumentMode(
1558 r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
1559 LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
1560 mLaunchTaskBehind = r.mLaunchTaskBehind
1561 && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
1562 && (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
1563
1564 sendNewTaskResultRequestIfNeeded();
1565
1566 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0 && r.resultTo == null) {
1567 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1568 }
1569
1570 // If we are actually going to launch in to a new task, there are some cases where
1571 // we further want to do multiple task.
1572 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1573 if (mLaunchTaskBehind
1574 || r.info.documentLaunchMode == DOCUMENT_LAUNCH_ALWAYS) {
1575 mLaunchFlags |= FLAG_ACTIVITY_MULTIPLE_TASK;
1576 }
1577 }
1578
1579 // We'll invoke onUserLeaving before onPause only if the launching
1580 // activity did not explicitly state that this is an automated launch.
1581 mSupervisor.mUserLeaving = (mLaunchFlags & FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1582 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1583 "startActivity() => mUserLeaving=" + mSupervisor.mUserLeaving);
1584
1585 // If the caller has asked not to resume at this point, we make note
1586 // of this in the record so that we can skip it when trying to find
1587 // the top running activity.
1588 mDoResume = doResume;
1589 if (!doResume || !r.okToShowLocked()) {
1590 r.delayedResume = true;
1591 mDoResume = false;
1592 }
1593
1594 if (mOptions != null) {
1595 if (mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) {
1596 r.mTaskOverlay = true;
1597 if (!mOptions.canTaskOverlayResume()) {
1598 final TaskRecord task = mSupervisor.anyTaskForIdLocked(
1599 mOptions.getLaunchTaskId());
1600 final ActivityRecord top = task != null ? task.getTopActivity() : null;
1601 if (top != null && !top.isState(RESUMED)) {
1602
1603 // The caller specifies that we'd like to be avoided to be moved to the
1604 // front, so be it!
1605 mDoResume = false;
1606 mAvoidMoveToFront = true;
1607 }
1608 }
1609 } else if (mOptions.getAvoidMoveToFront()) {
1610 mDoResume = false;
1611 mAvoidMoveToFront = true;
1612 }
1613 }
1614
1615 mNotTop = (mLaunchFlags & FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1616
1617 mInTask = inTask;
1618 // In some flows in to this function, we retrieve the task record and hold on to it
1619 // without a lock before calling back in to here... so the task at this point may
1620 // not actually be in recents. Check for that, and if it isn't in recents just
1621 // consider it invalid.
1622 if (inTask != null && !inTask.inRecents) {
1623 Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
1624 mInTask = null;
1625 }
1626
1627 mStartFlags = startFlags;
1628 // If the onlyIfNeeded flag is set, then we can do this if the activity being launched
1629 // is the same as the one making the call... or, as a special case, if we do not know
1630 // the caller then we count the current top activity as the caller.
1631 if ((startFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
1632 ActivityRecord checkedCaller = sourceRecord;
1633 if (checkedCaller == null) {
1634 checkedCaller = mSupervisor.mFocusedStack.topRunningNonDelayedActivityLocked(
1635 mNotTop);
1636 }
1637 if (!checkedCaller.realActivity.equals(r.realActivity)) {
1638 // Caller is not the same as launcher, so always needed.
1639 mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
1640 }
1641 }
1642
1643 mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
1644 }
ActivityStarter#computeLaunchingTaskFlags
1.针对指定了启动task的情况(inTask不为null),判断mAddingToTask的值;mAddingToTask是针对复用task(指定task也算复用task)的情况,若可以创建新的Activity添加到复用task,则mAddingToTask为true
2.针对一些情况,需要为mLaunchFlags添加FLAG_ACTIVITY_NEW_TASK这个flag(FLAG_ACTIVITY_NEW_TASK这个名字起得有点奇怪,当寻找复用task时,如果有这个值代表可以查找复用task;但是这个值又可以决定是否创建新task,如当要启动的Activity和SourceRecord的task不同的情况)
1662 private void computeLaunchingTaskFlags() {
1663 // If the caller is not coming from another activity, but has given us an explicit task into
1664 // which they would like us to launch the new activity, then let's see about doing that.
1665 if (mSourceRecord == null && mInTask != null && mInTask.getStack() != null) {
1666 final Intent baseIntent = mInTask.getBaseIntent();
1667 final ActivityRecord root = mInTask.getRootActivity();
1668 if (baseIntent == null) {
1669 ActivityOptions.abort(mOptions);
1670 throw new IllegalArgumentException("Launching into task without base intent: "
1671 + mInTask);
1672 }
1673
1674 // If this task is empty, then we are adding the first activity -- it
1675 // determines the root, and must be launching as a NEW_TASK.
1676 if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1677 if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
1678 ActivityOptions.abort(mOptions);
1679 throw new IllegalArgumentException("Trying to launch singleInstance/Task "
1680 + mStartActivity + " into different task " + mInTask);
1681 }
1682 if (root != null) {
1683 ActivityOptions.abort(mOptions);
1684 throw new IllegalArgumentException("Caller with mInTask " + mInTask
1685 + " has root " + root + " but target is singleInstance/Task");
1686 }
1687 }
1688
1689 // If task is empty, then adopt the interesting intent launch flags in to the
1690 // activity being started.
1691 if (root == null) {
1692 final int flagsOfInterest = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK
1693 | FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS;
1694 mLaunchFlags = (mLaunchFlags & ~flagsOfInterest)
1695 | (baseIntent.getFlags() & flagsOfInterest);
1696 mIntent.setFlags(mLaunchFlags);
1697 mInTask.setIntent(mStartActivity);
1698 mAddingToTask = true;
1699
1700 // If the task is not empty and the caller is asking to start it as the root of
1701 // a new task, then we don't actually want to start this on the task. We will
1702 // bring the task to the front, and possibly give it a new intent.
1703 } else if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
1704 mAddingToTask = false;
1705
1706 } else {
1707 mAddingToTask = true;
1708 }
1709
1710 mReuseTask = mInTask;
1711 } else {
1712 mInTask = null;
1713 // Launch ResolverActivity in the source task, so that it stays in the task bounds
1714 // when in freeform workspace.
1715 // Also put noDisplay activities in the source task. These by itself can be placed
1716 // in any task/stack, however it could launch other activities like ResolverActivity,
1717 // and we want those to stay in the original task.
1718 if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
1719 && mSourceRecord.inFreeformWindowingMode()) {
1720 mAddingToTask = true;
1721 }
1722 }
1723
1724 if (mInTask == null) {
1725 if (mSourceRecord == null) {
1726 // This activity is not being started from another... in this
1727 // case we -always- start a new task.
1728 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0 && mInTask == null) {
1729 Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1730 "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1731 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1732 }
1733 } else if (mSourceRecord.launchMode == LAUNCH_SINGLE_INSTANCE) {
1734 // The original activity who is starting us is running as a single
1735 // instance... this new activity it is starting must go on its
1736 // own task.
1737 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1738 } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
1739 // The activity being started is a single instance... it always
1740 // gets launched into its own task.
1741 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1742 }
1743 }
1744 }
ActivityStarter#computeSourceStack
计算SourceStack
1746 private void computeSourceStack() {
1747 if (mSourceRecord == null) {
1748 mSourceStack = null;
1749 return;
1750 }
1751 if (!mSourceRecord.finishing) {
1752 mSourceStack = mSourceRecord.getStack();
1753 return;
1754 }
1755
1756 // If the source is finishing, we can't further count it as our source. This is because the
1757 // task it is associated with may now be empty and on its way out, so we don't want to
1758 // blindly throw it in to that task. Instead we will take the NEW_TASK flow and try to find
1759 // a task for it. But save the task information so it can be used when creating the new task.
1760 if ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) == 0) {
1761 Slog.w(TAG, "startActivity called from finishing " + mSourceRecord
1762 + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
1763 mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
1764 mNewTaskInfo = mSourceRecord.info;
1765
1766 // It is not guaranteed that the source record will have a task associated with it. For,
1767 // example, if this method is being called for processing a pending activity launch, it
1768 // is possible that the activity has been removed from the task after the launch was
1769 // enqueued.
1770 final TaskRecord sourceTask = mSourceRecord.getTask();
1771 mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
1772 }
1773 mSourceRecord = null;
1774 mSourceStack = null;
1775 }
ActivityStarter#getReusableIntentActivity
注意,这里虽然叫getReusableIntentActivity,但其实是复用task相关的函数,返回的可能是复用task的top running activity,而不是复用Activity
1777 /**
1778 * Decide whether the new activity should be inserted into an existing task. Returns null
1779 * if not or an ActivityRecord with the task into which the new activity should be added.
1780 */
1781 private ActivityRecord getReusableIntentActivity() {
1782 // We may want to try to place the new activity in to an existing task. We always
1783 // do this if the target activity is singleTask or singleInstance; we will also do
1784 // this if NEW_TASK has been requested, and there is not an additional qualifier telling
1785 // us to still place it in a new task: multi task, always doc mode, or being asked to
1786 // launch this as a new task behind the current one.
1787 boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
1788 (mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1789 || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
//可以复用的前提条件
1790 // If bring to front is requested, and no result is requested and we have not been given
1791 // an explicit task to launch in to, and we can find a task that was started with this
1792 // same component, then instead of launching bring that one to the front.
1793 putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
1794 ActivityRecord intentActivity = null;
1795 if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
1796 final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
1797 intentActivity = task != null ? task.getTopActivity() : null;
1798 } else if (putIntoExistingTask) {
1799 if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
//LAUNCH_SINGLE_INSTANCE这种启动模式,一个task里面只有一个Activity,所以直接用findActivityLocked查找是否有可复用的Activity即可
1800 // There can be one and only one instance of single instance activity in the
1801 // history, and it is always in its own unique task, so we do a special search.
1802 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1803 mStartActivity.isActivityTypeHome());
1804 } else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
1805 // For the launch adjacent case we only want to put the activity in an existing
1806 // task if the activity already exists in the history.
1807 intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
1808 !(LAUNCH_SINGLE_TASK == mLaunchMode));
1809 } else {
1810 // Otherwise find the best task to put the activity in.
//返回复用task的top running Activity
1811 intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
1812 }
1813 }
1814 return intentActivity;
1815 }
ActivityStackSupervisor#findActivityLocked
3524 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
3525 boolean compareIntentFilters) {
3526 for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
3527 final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
3528 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
3529 final ActivityStack stack = display.getChildAt(stackNdx);
3530 final ActivityRecord ar = stack.findActivityLocked(
3531 intent, info, compareIntentFilters);
3532 if (ar != null) {
3533 return ar;
3534 }
3535 }
3536 }
3537 return null;
3538 }
ActivityStack#findActivityLocked
注释已经说的很清楚了,查找一个满足条件的ActivityRecord
1194 /**
1195 * Returns the first activity (starting from the top of the stack) that
1196 * is the same as the given activity. Returns null if no such activity
1197 * is found.
1198 */
1199 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
1200 boolean compareIntentFilters) {
1201 ComponentName cls = intent.getComponent();
1202 if (info.targetActivity != null) {
1203 cls = new ComponentName(info.packageName, info.targetActivity);
1204 }
1205 final int userId = UserHandle.getUserId(info.applicationInfo.uid);
1206
1207 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1208 final TaskRecord task = mTaskHistory.get(taskNdx);
1209 final ArrayList<ActivityRecord> activities = task.mActivities;
1210
1211 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1212 ActivityRecord r = activities.get(activityNdx);
1213 if (!r.okToShowLocked()) {
1214 continue;
1215 }
1216 if (!r.finishing && r.userId == userId) {
1217 if (compareIntentFilters) {
1218 if (r.intent.filterEquals(intent)) {
1219 return r;
1220 }
1221 } else {
1222 if (r.intent.getComponent().equals(cls)) {
1223 return r;
1224 }
1225 }
1226 }
1227 }
1228 }
1229
1230 return null;
1231 }
ActivityStackSupervisor#findTaskLocked
3471 ActivityRecord findTaskLocked(ActivityRecord r, int displayId) {
3472 mTmpFindTaskResult.r = null;
3473 mTmpFindTaskResult.matchedByRootAffinity = false;
3474 ActivityRecord affinityMatch = null;
3475 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
3476 for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
3477 final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
3478 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
3479 final ActivityStack stack = display.getChildAt(stackNdx);
3480 if (!r.hasCompatibleActivityType(stack)) {
3481 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) "
3482 + stack);
3483 continue;
3484 }
3485 stack.findTaskLocked(r, mTmpFindTaskResult);
3486 // It is possible to have tasks in multiple stacks with the same root affinity, so
3487 // we should keep looking after finding an affinity match to see if there is a
3488 // better match in another stack. Also, task affinity isn't a good enough reason
3489 // to target a display which isn't the source of the intent, so skip any affinity
3490 // matches not on the specified display.
3491 if (mTmpFindTaskResult.r != null) {
3492 if (!mTmpFindTaskResult.matchedByRootAffinity) {
3493 if(mTmpFindTaskResult.r.getState() == ActivityState.DESTROYED ) {
3494 /*It's a new app launch */
3495 acquireAppLaunchPerfLock(r);
3496 }
3497 if(mTmpFindTaskResult.r.getState() == ActivityState.STOPPED) {
3498 /*Warm launch */
3499 acquireUxPerfLock(BoostFramework.UXE_EVENT_SUB_LAUNCH, r.packageName);
3500 }
3501 return mTmpFindTaskResult.r;
3502 } else if (mTmpFindTaskResult.r.getDisplayId() == displayId) {
3503 // Note: since the traversing through the stacks is top down, the floating
3504 // tasks should always have lower priority than any affinity-matching tasks
3505 // in the fullscreen stacks
3506 affinityMatch = mTmpFindTaskResult.r;
3507 } else if (DEBUG_TASKS && mTmpFindTaskResult.matchedByRootAffinity) {
3508 Slog.d(TAG_TASKS, "Skipping match on different display "
3509 + mTmpFindTaskResult.r.getDisplayId() + " " + displayId);
3510 }
3511 }
3512 }
3513 }
3514
3515 /* Acquire perf lock *only* during new app launch */
3516 if (mTmpFindTaskResult.r == null || mTmpFindTaskResult.r.getState() == ActivityState.DESTROYED) {
3517 acquireAppLaunchPerfLock(r);
3518 }
3519
3520 if (DEBUG_TASKS && affinityMatch == null) Slog.d(TAG_TASKS, "No task found");
3521 return affinityMatch;
3522 }
ActivityStack#findTaskLocked
查找复用task的top Activity,条件可能有
- Intent component相同
- affinityIntent component相同
- task的rootAffinity与Activity的taskAffinity相同(常见情况)
1098 /**
1099 * Returns the top activity in any existing task matching the given Intent in the input result.
1100 * Returns null if no such task is found.
1101 */
1102 void findTaskLocked(ActivityRecord target, FindTaskResult result) {
1103 Intent intent = target.intent;
1104 ActivityInfo info = target.info;
1105 ComponentName cls = intent.getComponent();
1106 if (info.targetActivity != null) {
1107 cls = new ComponentName(info.packageName, info.targetActivity);
1108 }
1109 final int userId = UserHandle.getUserId(info.applicationInfo.uid);
1110 boolean isDocument = intent != null & intent.isDocument();
1111 // If documentData is non-null then it must match the existing task data.
1112 Uri documentData = isDocument ? intent.getData() : null;
1113
1114 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
1115 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1116 final TaskRecord task = mTaskHistory.get(taskNdx);
1117 if (task.voiceSession != null) {
1118 // We never match voice sessions; those always run independently.
1119 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
1120 continue;
1121 }
1122 if (task.userId != userId) {
1123 // Looking for a different task.
1124 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
1125 continue;
1126 }
1127
1128 // Overlays should not be considered as the task's logical top activity.
1129 final ActivityRecord r = task.getTopActivity(false /* includeOverlays */);
1130 if (r == null || r.finishing || r.userId != userId ||
1131 r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1132 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
1133 continue;
1134 }
1135 if (!r.hasCompatibleActivityType(target)) {
1136 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
1137 continue;
1138 }
1139
1140 final Intent taskIntent = task.intent;
1141 final Intent affinityIntent = task.affinityIntent;
1142 final boolean taskIsDocument;
1143 final Uri taskDocumentData;
1144 if (taskIntent != null && taskIntent.isDocument()) {
1145 taskIsDocument = true;
1146 taskDocumentData = taskIntent.getData();
1147 } else if (affinityIntent != null && affinityIntent.isDocument()) {
1148 taskIsDocument = true;
1149 taskDocumentData = affinityIntent.getData();
1150 } else {
1151 taskIsDocument = false;
1152 taskDocumentData = null;
1153 }
1154
1155 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
1156 + taskIntent.getComponent().flattenToShortString()
1157 + "/aff=" + r.getTask().rootAffinity + " to new cls="
1158 + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
1159 // TODO Refactor to remove duplications. Check if logic can be simplified.
1160 if (taskIntent != null && taskIntent.getComponent() != null &&
1161 taskIntent.getComponent().compareTo(cls) == 0 &&
1162 Objects.equals(documentData, taskDocumentData)) {
1163 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
1164 //dump();
1165 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
1166 "For Intent " + intent + " bringing to top: " + r.intent);
1167 result.r = r;
1168 result.matchedByRootAffinity = false;
1169 break;
1170 } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
1171 affinityIntent.getComponent().compareTo(cls) == 0 &&
1172 Objects.equals(documentData, taskDocumentData)) {
1173 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
1174 //dump();
1175 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
1176 "For Intent " + intent + " bringing to top: " + r.intent);
1177 result.r = r;
1178 result.matchedByRootAffinity = false;
1179 break;
1180 } else if (!isDocument && !taskIsDocument
1181 && result.r == null && task.rootAffinity != null) {
1182 if (task.rootAffinity.equals(target.taskAffinity)) {
1183 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
1184 // It is possible for multiple tasks to have the same root affinity especially
1185 // if they are in separate stacks. We save off this candidate, but keep looking
1186 // to see if there is a better candidate.
1187 result.r = r;
1188 result.matchedByRootAffinity = true;
1189 }
1190 } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
1191 }
1192 }
那么ActivityRecord中的taskAffinity是怎么来的呢?
首先在startActivity的过程中创建一个待启动的ActivityRecord
830 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
831 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
832 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
833 mSupervisor, checkedOptions, sourceRecord);
注意其中的 taskAffinity = aInfo.taskAffinity;
final String taskAffinity; // as per ActivityInfo.taskAffinity
其赋值的地方在parseActivity
4092 private Activity parseActivity(Package owner, Resources res,
4093 XmlResourceParser parser, int flags, String[] outError, CachedComponentArgs cachedArgs,
4094 boolean receiver, boolean hardwareAccelerated)
4095 throws XmlPullParserException, IOException {
解析xml文件
4154 str = sa.getNonConfigurationString(
4155 R.styleable.AndroidManifestActivity_taskAffinity,
4156 Configuration.NATIVE_CONFIG_VERSION);
4157 a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
4158 owner.applicationInfo.taskAffinity, str, outError);
2912 private static String buildTaskAffinityName(String pkg, String defProc,
2913 CharSequence procSeq, String[] outError) {
2914 if (procSeq == null) {
2915 return defProc;
2916 }
2917 if (procSeq.length() <= 0) {
2918 return null;
2919 }
2920 return buildCompoundName(pkg, procSeq, "taskAffinity", outError);
2921 }
可见当没有定义R.styleable.AndroidManifestActivity_taskAffinity时,ActivityRecord的taskAffinity的值由owner.applicationInfo.taskAffinity决定
而owner.applicationInfo.taskAffinity的值为,见parseBaseApplication
3542 if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
3543 str = sa.getNonConfigurationString(
3544 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
3545 Configuration.NATIVE_CONFIG_VERSION);
3546 } else {
3547 // Some older apps have been seen to use a resource reference
3548 // here that on older builds was ignored (with a warning). We
3549 // need to continue to do this for them so they don't break.
3550 str = sa.getNonResourceString(
3551 com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
3552 }
3553 ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
3554 str, outError);
可见,没有使用android:taskAffinity时,ActivityRecord的taskAffinity就是由当前Activity的package name来决定的;同时,注意刚创建的ActivityRecord里面只有taskAffinity实行,还没有task,task还要再后面才会赋值
复用task的相关流程
1259 if (reusedActivity != null) {
//复用task的时候,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());
//startActivity的task设置为reusedActivity的task
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)) {
//复用Activity的情况,将task中复用Activity以上的Activity都清掉
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);
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) {
1313 if (top.frontOfTask) {
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);
1317 }
1318 deliverNewIntent(top);
1319 }
1320 }
1321
1322 mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
1323
1324 reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
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) {
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
1350 resumeTargetStackIfNeeded();
1351 if (outActivity != null && outActivity.length > 0) {
1352 outActivity[0] = reusedActivity;
1353 }
1354
1355 return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
1356 }
1357 }
1358 }
TaskRecord#performClearTaskForReuseLocked
1382 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1383 mReuseTask = true;
1384 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1385 mReuseTask = false;
1386 return result;
1387 }
1389 /**
1390 * Perform clear operation as requested by
1391 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1392 * stack to the given task, then look for
1393 * an instance of that activity in the stack and, if found, finish all
1394 * activities on top of it and return the instance.
1395 *
1396 * @param newR Description of the new activity being started.
1397 * @return Returns the old activity that should be continued to be used,
1398 * or null if none was found.
1399 */
1400 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
1401 int numActivities = mActivities.size();
1402 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
1403 ActivityRecord r = mActivities.get(activityNdx);
1404 if (r.finishing) {
1405 continue;
1406 }
1407 if (r.realActivity.equals(newR.realActivity)) {
1408 // Here it is! Now finish everything in front...
1409 final ActivityRecord ret = r; //找到要复用的Activity,将其上的Activity都finish掉
1410
1411 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
1412 r = mActivities.get(activityNdx);
1413 if (r.finishing) {
1414 continue;
1415 }
1416 ActivityOptions opts = r.takeOptionsLocked();
1417 if (opts != null) {
1418 ret.updateOptionsLocked(opts);
1419 }
1420 if (mStack != null && mStack.finishActivityLocked(
1421 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
//销毁之上的Activity
1422 --activityNdx;
1423 --numActivities;
1424 }
1425 }
1426
1427 // Finally, if this is a normal launch mode (that is, not
1428 // expecting onNewIntent()), then we will finish the current
1429 // instance of the activity so a new fresh one can be started.
1430 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
1431 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1432 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
//对于正常模式的Activity,不能复用,需要销毁重新launch一个new activity
1433 if (!ret.finishing) {
1434 if (mStack != null) {
1435 mStack.finishActivityLocked(
1436 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1437 }
1438 return null;
1439 }
1440 }
1441
1442 return ret;
1443 }
1444 }
1445
1446 return null;
1447 }
ActivityStack#finishActivityLocked
3756 /**
3757 * See {@link #finishActivityLocked(ActivityRecord, int, Intent, String, boolean, boolean)}
3758 */
3759 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
3760 String reason, boolean oomAdj) {
3761 return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY);
3762 }
3763
3764 /**
3765 * @return Returns true if this activity has been removed from the history
3766 * list, or false if it is still in the list and will be removed later.
3767 */
3768 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
3769 String reason, boolean oomAdj, boolean pauseImmediately) {
3770 if (r.finishing) { //已经申请了finish,finishing = true,直接返回了
3771 Slog.w(TAG, "Duplicate finish request for " + r);
3772 return false;
3773 }
3774
3775 mWindowManager.deferSurfaceLayout();
3776 try {
3777 r.makeFinishingLocked(); //设置ActivityRecord的finishing属性
3778 final TaskRecord task = r.getTask();
3779 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3780 r.userId, System.identityHashCode(r),
3781 task.taskId, r.shortComponentName, reason);
3782 final ArrayList<ActivityRecord> activities = task.mActivities;
3783 final int index = activities.indexOf(r);
3784 if (index < (activities.size() - 1)) {
3785 task.setFrontOfTask(); //设置frontOfTask属性,task的root running Activity为true
3786 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3787 // If the caller asked that this activity (and all above it)
3788 // be cleared when the task is reset, don't lose that information,
3789 // but propagate it up to the next activity.
3790 ActivityRecord next = activities.get(index+1);
3791 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3792 }
3793 }
3794
3795 r.pauseKeyDispatchingLocked();
3796
3797 adjustFocusedActivityStack(r, "finishActivity");
//调整focus activityStack(当前stack 调用topRunningActivityLocked为null,即当前stack中的所有task中的Activity没有正在running的)
3798
3799 finishActivityResultsLocked(r, resultCode, resultData);
//如果要finish的Activity有resultTo,传递结果给resultTo
3800
3801 final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
3802 final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
//endTask代表是否要销毁task(当要销毁的Activity在task中的index<=0)
3803 if (mResumedActivity == r) {
3804 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
3805 "Prepare close transition: finishing " + r);
3806 if (endTask) {
3807 mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
3808 task.taskId);
3809 }
3810 mWindowManager.prepareAppTransition(transit, false);
3811
3812 // Tell window manager to prepare for this one to be removed.
3813 r.setVisibility(false);
3814
3815 if (mPausingActivity == null) {
3816 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
3817 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
3818 "finish() => pause with userLeaving=false");
3819 startPausingLocked(false, false, null, pauseImmediately);
//调用startPausingLocked,finish之前需要先pause,注意resuming为null
3820 }
3821
3822 if (endTask) {
3823 mService.getLockTaskController().clearLockedTask(task);
3824 }
3825 } else if (!r.isState(PAUSING)) {
3826 // If the activity is PAUSING, we will complete the finish once
3827 // it is done pausing; else we can just directly finish it here.
3828 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
3829 if (r.visible) {
3830 prepareActivityHideTransitionAnimation(r, transit);
3831 }
3832
3833 final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
3834 : FINISH_AFTER_PAUSE;
3835 final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj,
3836 "finishActivityLocked") == null;
//如果要finish的Activity已经pause完成,则直接调用finishCurrentActivityLocked
3837
3838 // The following code is an optimization. When the last non-task overlay activity
3839 // is removed from the task, we remove the entire task from the stack. However,
3840 // since that is done after the scheduled destroy callback from the activity, that
3841 // call to change the visibility of the task overlay activities would be out of
3842 // sync with the activitiy visibility being set for this finishing activity above.
3843 // In this case, we can set the visibility of all the task overlay activities when
3844 // we detect the last one is finishing to keep them in sync.
3845 if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
3846 for (ActivityRecord taskOverlay : task.mActivities) {
3847 if (!taskOverlay.mTaskOverlay) {
3848 continue;
3849 }
3850 prepareActivityHideTransitionAnimation(taskOverlay, transit);
3851 }
3852 }
3853 return removedActivity;
3854 } else {
3855 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
3856 }
3857
3858 return false;
3859 } finally {
3860 mWindowManager.continueSurfaceLayout();
3861 }
3862 }
ActivityRecord#makeFinishingLocked
设置ActivityRecord的finishing属性
1402 void makeFinishingLocked() {
1403 if (finishing) {
1404 return;
1405 }
1406 finishing = true;
1407 if (stopped) {
1408 clearOptionsLocked();
1409 }
1410
1411 if (service != null) {
1412 service.mTaskChangeNotificationController.notifyTaskStackChanged();
1413 }
1414 }
ActivityStack#adjustFocusedActivityStack
3449 private void adjustFocusedActivityStack(ActivityRecord r, String reason) {
3450 if (!mStackSupervisor.isFocusedStack(this) ||
3451 ((mResumedActivity != r) && (mResumedActivity != null))) {
3452 return;
3453 }
3454
3455 final ActivityRecord next = topRunningActivityLocked();
3456 final String myReason = reason + " adjustFocus";
3457
3458 if (next == r) {
3459 mStackSupervisor.moveFocusableActivityStackToFrontLocked(
3460 mStackSupervisor.topRunningActivityLocked(), myReason);
3461 return;
3462 }
3463
3464 if (next != null && isFocusable()) {
//当stack中没有top running Activity的情况时才需要移动focus Activity Stack
3465 // Keep focus in stack if we have a top running activity and are focusable.
3466 return;
3467 }
3468
3469 // Task is not guaranteed to be non-null. For example, destroying the
3470 // {@link ActivityRecord} will disassociate the task from the activity.
3471 final TaskRecord task = r.getTask();
3472
3473 if (task == null) {
3474 throw new IllegalStateException("activity no longer associated with task:" + r);
3475 }
3476
3477 // Move focus to next focusable stack if possible.
3478 if (adjustFocusToNextFocusableStack(myReason)) {
//当前task中没有running的Activity了,那么需要将focus的ActivityStack移到下一个
3479 return;
3480 }
3481
3482 // Whatever...go home.
3483 mStackSupervisor.moveHomeStackTaskToTop(myReason);
3484 }
ActivityStack#topRunningActivityLocked
返回stack的top running Activity
837 ActivityRecord topRunningActivityLocked() {
838 return topRunningActivityLocked(false /* focusableOnly */);
839 }
848 private ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
849 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
850 ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
851 if (r != null && (!focusableOnly || r.isFocusable())) {
852 return r;
853 }
854 }
855 return null;
856 }
TaskRecord#topRunningActivityLocked
1068 ActivityRecord topRunningActivityLocked() {
1069 if (mStack != null) {
1070 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1071 ActivityRecord r = mActivities.get(activityNdx);
1072 if (!r.finishing && r.okToShowLocked()) {
1073 return r;
1074 }
1075 }
1076 }
1077 return null;
1078 }
finish Activity的逻辑后面再讲
网友评论