android之AMS学习攻克

Activity相关学习-启动(2)

2019-01-06  本文已影响0人  weiinter105

前面说道准备工作和检查工作做完之后开始进行真正的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,条件可能有

  1. Intent component相同
  2. affinityIntent component相同
  3. 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的逻辑后面再讲

上一篇 下一篇

猜你喜欢

热点阅读