美文网首页android之AMS学习攻克
Activity相关学习-启动(2)

Activity相关学习-启动(2)

作者: weiinter105 | 来源:发表于2019-01-06 00:03 被阅读0次

    前面说道准备工作和检查工作做完之后开始进行真正的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的逻辑后面再讲

    相关文章

      网友评论

        本文标题:Activity相关学习-启动(2)

        本文链接:https://www.haomeiwen.com/subject/llqjrqtx.html