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

Activity相关学习-启动(3)

作者: weiinter105 | 来源:发表于2019-01-07 14:40 被阅读0次

    上一回讲到复用task,Activity的部分

    流程

    复用部分逻辑

    1259        if (reusedActivity != null) {
    1260            // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
    1261            // still needs to be a lock task mode violation since the task gets cleared out and
    1262            // the device would otherwise leave the locked task.
    1263            if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
    1264                    (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
    1265                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
    1266                Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
    1267                return START_RETURN_LOCK_TASK_MODE_VIOLATION;
    1268            }
    1269
    1270            // True if we are clearing top and resetting of a standard (default) launch mode
    1271            // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
    1272            final boolean clearTopAndResetStandardLaunchMode =
    1273                    (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
    1274                            == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
    1275                    && mLaunchMode == LAUNCH_MULTIPLE;
    1276
    1277            // If mStartActivity does not have a task associated with it, associate it with the
    1278            // reused activity's task. Do not do so if we're clearing top and resetting for a
    1279            // standard launchMode activity.
    1280            if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
    1281                mStartActivity.setTask(reusedActivity.getTask());
    1282            }
    1283
    1284            if (reusedActivity.getTask().intent == null) {
    1285                // This task was started because of movement of the activity based on affinity...
    1286                // Now that we are actually launching it, we can assign the base intent.
    1287                reusedActivity.getTask().setIntent(mStartActivity);
    1288            }
    1289
    1290            // This code path leads to delivering a new intent, we want to make sure we schedule it
    1291            // as the first operation, in case the activity will be resumed as a result of later
    1292            // operations.
    1293            if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
    1294                    || isDocumentLaunchesIntoExisting(mLaunchFlags)
    1295                    || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
    1296                final TaskRecord task = reusedActivity.getTask();
    1297
    1298                // In this situation we want to remove all activities from the task up to the one
    1299                // being started. In most cases this means we are resetting the task to its initial
    1300                // state.
    1301                final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
    1302                        mLaunchFlags); //将要复用的Activity上面的ActivityRecord都清除
                            //如果没有找到要复用的Activity,说明是第一次创建,则返回null
                           //注意,前面是task复用,这里如果top也不为null,那么就是ActivityRecord也复用了
    1303
    1304                // The above code can remove {@code reusedActivity} from the task, leading to the
    1305                // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
    1306                // task reference is needed in the call below to
    1307                // {@link setTargetStackAndMoveToFrontIfNeeded}.
    1308                if (reusedActivity.getTask() == null) {
    1309                    reusedActivity.setTask(task);
    1310                }
    1311
    1312                if (top != null) { //如果找到了复用的Activity
    1313                    if (top.frontOfTask) { //且复用的Activity是root Activity
    1314                        // Activity aliases may mean we use different intents for the top activity,
    1315                        // so make sure the task now has the identity of the new intent.
    1316                        top.getTask().setIntent(mStartActivity); //重新设置task的Intent属性
    1317                    }
    1318                    deliverNewIntent(top); //调用Activity的omNewIntent方法
    1319                }
    1320            }
    
    1322            mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);
    1323
    1324            reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity); 
                       //将复用task及其ActivityStack移到前台(如果必要的话) ;比如,使sourceTask和StartActivity的task不同,但是StartActivity指定的task已经存在了,可以复用(sourceTask和StartActivity的task不同,这也就是NEW_TASK这个flag的意思,可以找到可复用task的top running Activity,若没找到返回null),将其移到前台来即可;
    1325
    1326            final ActivityRecord outResult =
    1327                    outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
    1328
    1329            // When there is a reused activity and the current result is a trampoline activity,
    1330            // set the reused activity as the result.
    1331            if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
    1332                outActivity[0] = reusedActivity;
    1333            }
    1334
    1335            if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
    1336                // We don't need to start a new activity, and the client said not to do anything
    1337                // if that is the case, so this is it!  And for paranoia, make sure we have
    1338                // correctly resumed the top activity.
    1339                resumeTargetStackIfNeeded(); 
    1340                return START_RETURN_INTENT_TO_CALLER;
    1341            }
    1342
    1343            if (reusedActivity != null) {
    1344                setTaskFromIntentActivity(reusedActivity);
    1345
    1346                if (!mAddingToTask && mReuseTask == null) {
                            //mAddingToTask为false,且在复用的逻辑中,那么说明task中有复用Activity
    1347                    // We didn't do anything...  but it was needed (a.k.a., client don't use that
    1348                    // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
    1349                   //按理说前面已经将Activity之上的全部清空了,保险起见,再调用一次resume的逻辑
    1350                    resumeTargetStackIfNeeded();//其实就是调用
                              //如同一个栈中A->B->A,A是singleTask模式,那么task,Activity均可复用,这里就是先将B pause,然后A resume,最后B finish;介绍大致流程resumeFocusedStackTopActivityLocked
    1351                    if (outActivity != null && outActivity.length > 0) {
    1352                        outActivity[0] = reusedActivity;
    1353                    }
    1354
    1355                    return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP; //mMovedToFront 代表是否将ActivityStack移到了前台,如果本来就在前台,则为false
    1356                }
    1357            }
    1358        }
    

    ActivityStarter#deliverNewIntent

    2092    private void deliverNewIntent(ActivityRecord activity) {
    2093        if (mIntentDelivered) {
    2094            return;
    2095        }
    2096
    2097        ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
    2098        activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
    2099                mStartActivity.launchedFromPackage);
    2100        mIntentDelivered = true;
    2101    }
    

    ActivityRecord#deliverNewIntentLocked

    1464    /**
    1465     * Deliver a new Intent to an existing activity, so that its onNewIntent()
    1466     * method will be called at the proper time.
    1467     */
    1468    final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
    1469        // The activity now gets access to the data associated with this Intent.
    1470        service.grantUriPermissionFromIntentLocked(callingUid, packageName,
    1471                intent, getUriPermissionsLocked(), userId);
    1472        final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
    1473        boolean unsent = true;
    1474        final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
    1475
    1476        // We want to immediately deliver the intent to the activity if:
    1477        // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
    1478        //   the user to see the visual effects caused by the intent delivery now.
    1479        // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
                //当Activity处于paused或者resumed状态(用户还可见时,调用Activity的onNewIntent)
    1480        if ((mState == RESUMED || mState == PAUSED
    1481                || isTopActivityWhileSleeping) && app != null && app.thread != null) {
    1482            try {
    1483                ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
    1484                ar.add(rintent);
    1485                service.getLifecycleManager().scheduleTransaction(app.thread, appToken,
    1486                        NewIntentItem.obtain(ar, mState == PAUSED));
    1487                unsent = false; //调用onNewIntent
    1488            } catch (RemoteException e) {
    1489                Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
    1490            } catch (NullPointerException e) {
    1491                Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
    1492            }
    1493        }
    1494        if (unsent) {
                       //将intent加入到ActivityRecord中的newIntents队列
    1495            addNewIntentLocked(rintent);
    1496        }
    1497    }
    

    如何调用Activity相关的声明周期函数呢?大致逻辑如下

    ClientLifecycleManager#scheduleTransaction
    56    /**
    57     * Schedule a single lifecycle request or callback to client activity.
    58     * @param client Target client.
    59     * @param activityToken Target activity token.
    60     * @param stateRequest A request to move target activity to a desired lifecycle state.
    61     * @throws RemoteException
    62     *
    63     * @see ClientTransactionItem
    64     */
    65    void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,
    66            @NonNull ActivityLifecycleItem stateRequest) throws RemoteException {
    67        final ClientTransaction clientTransaction = transactionWithState(client, activityToken,
    68                stateRequest);
    69        scheduleTransaction(clientTransaction);
    70    }
    
    38    /**
    39     * Schedule a transaction, which may consist of multiple callbacks and a lifecycle request.
    40     * @param transaction A sequence of client transaction items.
    41     * @throws RemoteException
    42     *
    43     * @see ClientTransaction
    44     */
    45    void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    46        final IApplicationThread client = transaction.getClient();
    47        transaction.schedule();
    48        if (!(client instanceof Binder)) {
    49            // If client is not an instance of Binder - it's a remote call and at this point it is
    50            // safe to recycle the object. All objects used for local calls will be recycled after
    51            // the transaction is executed on client in ActivityThread.
    52            transaction.recycle();
    53        }
    54    }
    55
    
    ClientTransaction#schedule
    118    /**
    119     * Schedule the transaction after it was initialized. It will be send to client and all its
    120     * individual parts will be applied in the following sequence:
    121     * 1. The client calls {@link #preExecute(ClientTransactionHandler)}, which triggers all work
    122     *    that needs to be done before actually scheduling the transaction for callbacks and
    123     *    lifecycle state request.
    124     * 2. The transaction message is scheduled.
    125     * 3. The client calls {@link TransactionExecutor#execute(ClientTransaction)}, which executes
    126     *    all callbacks and necessary lifecycle transitions.
    127     */
    128    public void schedule() throws RemoteException {
    129        mClient.scheduleTransaction(this);
    130    }
    
    53    /** Target client. */
    54    private IApplicationThread mClient;
    

    我们同样注意到

    public final class ActivityThread extends ClientTransactionHandler 
    

    ClientTransactionHandler#scheduleTransaction
    42    /** Prepare and schedule transaction for execution. */
    43    void scheduleTransaction(ClientTransaction transaction) {
    44        transaction.preExecute(this);
    45        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
    46    }
    
    ActivityThread#handleMessage
    1809                case EXECUTE_TRANSACTION:
    1810                    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    1811                    mTransactionExecutor.execute(transaction);
    1812                    if (isSystem()) {
    1813                        // Client transactions inside system process are recycled on the client side
    1814                        // instead of ClientLifecycleManager to avoid being cleared before this
    1815                        // message is handled.
    1816                        transaction.recycle();
    1817                    }
    
    TransactionExecutor#execute
        /**
         * Resolve transaction.
         * First all callbacks will be executed in the order they appear in the list. If a callback
         * requires a certain pre- or post-execution state, the client will be transitioned accordingly.
         * Then the client will cycle to the final lifecycle state if provided. Otherwise, it will
         * either remain in the initial state, or last state needed by a callback.
         */
        public void execute(ClientTransaction transaction) {
            final IBinder token = transaction.getActivityToken();
            log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
    
            executeCallbacks(transaction);
    
            executeLifecycleState(transaction);
            mPendingActions.clear();
            log("End resolving transaction");
        }
    
    TransactionExecutor#executeLifecycleState
        private void executeLifecycleState(ClientTransaction transaction) {
            final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
            if (lifecycleItem == null) {
                // No lifecycle request, return early.
                return;
            }
            log("Resolving lifecycle state: " + lifecycleItem);
    
            final IBinder token = transaction.getActivityToken();
            final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
    
            if (r == null) {
                // Ignore requests for non-existent client records for now.
                return;
            }
    
            // Cycle to the state right before the final requested state.
            cycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */);
    
            // Execute the final transition with proper parameters.
            lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
            lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
        }
    

    执行对应ActivityLifecycleItem的excute,如

    NewIntentItem#execute
        @Override
        public void execute(ClientTransactionHandler client, IBinder token,
                PendingTransactionActions pendingActions) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
            client.handleNewIntent(token, mIntents, mPause);
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    
    ActivityThread#handleNewIntent
    3142    @Override
    3143    public void handleNewIntent(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
    3144        performNewIntents(token, intents, andPause);
    3145    }
    
    
    3115    void performNewIntents(IBinder token, List<ReferrerIntent> intents, boolean andPause) {
    3116        final ActivityClientRecord r = mActivities.get(token);
    3117        if (r == null) {
    3118            return;
    3119        }
    3120
    3121        final boolean resumed = !r.paused;
    3122        if (resumed) {
    3123            r.activity.mTemporaryPause = true;
    3124            mInstrumentation.callActivityOnPause(r.activity);
    3125        }
    3126        checkAndBlockForNetworkAccess();
    3127        deliverNewIntents(r, intents);
    3128        if (resumed) {
    3129            r.activity.performResume(false, "performNewIntents");
    3130            r.activity.mTemporaryPause = false;
    3131        }
    3132
    3133        if (r.paused && andPause) {
    3134            // In this case the activity was in the paused state when we delivered the intent,
    3135            // to guarantee onResume gets called after onNewIntent we temporarily resume the
    3136            // activity and pause again as the caller wanted.
    3137            performResumeActivity(token, false, "performNewIntents");
    3138            performPauseActivityIfNeeded(r, "performNewIntents");
    3139        }
    3140    }
    

    以上全是在Activity的服务端执行的逻辑

    回到task,Activity复用的逻辑

    ActivityStarter#setTargetStackAndMoveToFrontIfNeeded

    保证复用的task,stack在前台

    1855    /**
    1856     * Figure out which task and activity to bring to front when we have found an existing matching
    1857     * activity record in history. May also clear the task if needed.
    1858     * @param intentActivity Existing matching activity.
    1859     * @return {@link ActivityRecord} brought to front.
    1860     */
    1861    private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
    1862        mTargetStack = intentActivity.getStack(); //得到reusedActivity相应的stack
    1863        mTargetStack.mLastPausedActivity = null;
    1864        // If the target task is not in the front, then we need to bring it to the front...
    1865        // except...  well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
    1866        // the same behavior as if a new instance was being started, which means not bringing it
    1867        // to the front if the caller is not itself in the front.
    1868        final ActivityStack focusStack = mSupervisor.getFocusedStack();
    1869        ActivityRecord curTop = (focusStack == null)
    1870                ? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
    1871
    1872        final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
    1873        if (topTask != null
    1874                && (topTask != intentActivity.getTask() || topTask != focusStack.topTask())
    1875                && !mAvoidMoveToFront) { //针对task需要移动到前台的情况
                       //要复用的task不是当前focus stack的top task
    1876            mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
    1877            if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
    1878                    mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
    1879                // We really do want to push this one into the user's face, right now.
    1880                if (mLaunchTaskBehind && mSourceRecord != null) {
    1881                    intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
    1882                }
    1883
    1884                // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
    1885                // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
    1886                // So no point resuming any of the activities here, it just wastes one extra
    1887                // resuming, plus enter AND exit transitions.
    1888                // Here we only want to bring the target stack forward. Transition will be applied
    1889                // to the new activity that's started after the old ones are gone.
    1890                final boolean willClearTask =
    1891                        (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
    1892                            == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
    1893                if (!willClearTask) {
    1894                    final ActivityStack launchStack = getLaunchStack(
    1895                            mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
                            //getLaunchStack返回The stack to use for the launch or INVALID_STACK_ID.
    1896                    final TaskRecord intentTask = intentActivity.getTask();
    1897                    if (launchStack == null || launchStack == mTargetStack) {
    1898                        // We only want to move to the front, if we aren't going to launch on a
    1899                        // different stack. If we launch on a different stack, we will put the
    1900                        // task on top there.
                                //将要复用的task放到stack前面,并将改ActivityStack也设为focus
    1901                        mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
    1902                                mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
    1903                        mMovedToFront = true;
    1904                    } else if (launchStack.inSplitScreenWindowingMode()) {
    1905                        if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
    1906                            // If we want to launch adjacent and mTargetStack is not the computed
    1907                            // launch stack - move task to top of computed stack.
    1908                            intentTask.reparent(launchStack, ON_TOP,
    1909                                    REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
    1910                                    "launchToSide");
    1911                        } else {
    1912                            // TODO: This should be reevaluated in MW v2.
    1913                            // We choose to move task to front instead of launching it adjacent
    1914                            // when specific stack was requested explicitly and it appeared to be
    1915                            // adjacent stack, but FLAG_ACTIVITY_LAUNCH_ADJACENT was not set.
    1916                            mTargetStack.moveTaskToFrontLocked(intentTask,
    1917                                    mNoAnimation, mOptions, mStartActivity.appTimeTracker,
    1918                                    "bringToFrontInsteadOfAdjacentLaunch");
    1919                        }
    1920                        mMovedToFront = launchStack != launchStack.getDisplay()
    1921                                .getTopStackInWindowingMode(launchStack.getWindowingMode());
    1922                    } else if (launchStack.mDisplayId != mTargetStack.mDisplayId) {
    1923                        // Target and computed stacks are on different displays and we've
    1924                        // found a matching task - move the existing instance to that display and
    1925                        // move it to front.
    1926                        intentActivity.getTask().reparent(launchStack, ON_TOP,
    1927                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
    1928                                "reparentToDisplay");
    1929                        mMovedToFront = true;
    1930                    } else if (launchStack.isActivityTypeHome()
    1931                            && !mTargetStack.isActivityTypeHome()) {
    1932                        // It is possible for the home activity to be in another stack initially.
    1933                        // For example, the activity may have been initially started with an intent
    1934                        // which placed it in the fullscreen stack. To ensure the proper handling of
    1935                        // the activity based on home stack assumptions, we must move it over.
    1936                        intentActivity.getTask().reparent(launchStack, ON_TOP,
    1937                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
    1938                                "reparentingHome");
    1939                        mMovedToFront = true;
    1940                    }
    1941                    mOptions = null;
    1942
    1943                    // We are moving a task to the front, use starting window to hide initial drawn
    1944                    // delay.
    1945                    intentActivity.showStartingWindow(null /* prev */, false /* newTask */,
    1946                            true /* taskSwitch */);
    1947                }
    1948            }
    1949        }
    1950        // Need to update mTargetStack because if task was moved out of it, the original stack may
    1951        // be destroyed.
    1952        mTargetStack = intentActivity.getStack();
    1953        if (!mMovedToFront && mDoResume) {
    1954            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
    1955                    + " from " + intentActivity);
    1956            mTargetStack.moveToFront("intentActivityFound");
    1957        }
    1958
    1959        mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
    1960                WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
    1961
    1962        // If the caller has requested that the target task be reset, then do so.
    1963        if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
    1964            return mTargetStack.resetTaskIfNeededLocked(intentActivity, mStartActivity);
    1965        }
    1966        return intentActivity;
    1967    }
    

    ActivityStack#moveTaskToFrontLocked

    4651    final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
    4652            AppTimeTracker timeTracker, String reason) {
    4653        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
    4654
    4655        final ActivityStack topStack = getDisplay().getTopStack();
    4656        final ActivityRecord topActivity = topStack != null ? topStack.getTopActivity() : null;
    4657        final int numTasks = mTaskHistory.size();
    4658        final int index = mTaskHistory.indexOf(tr);
    4659        if (numTasks == 0 || index < 0)  {
    4660            // nothing to do!
    4661            if (noAnimation) {
    4662                ActivityOptions.abort(options);
    4663            } else {
    4664                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
    4665            }
    4666            return;
    4667        }
    4668
    4669        if (timeTracker != null) {
    4670            // The caller wants a time tracker associated with this task.
    4671            for (int i = tr.mActivities.size() - 1; i >= 0; i--) {
    4672                tr.mActivities.get(i).appTimeTracker = timeTracker;
    4673            }
    4674        }
    4675
    4676        try {
    4677            // Defer updating the IME target since the new IME target will try to get computed
    4678            // before updating all closing and opening apps, which can cause the ime target to
    4679            // get calculated incorrectly.
    4680            getDisplay().deferUpdateImeTarget();
    4681
    4682            // Shift all activities with this task up to the top
    4683            // of the stack, keeping them in the same internal order.
    4684            insertTaskAtTop(tr, null); //将task放到当前ActivityStack的top位置
    4685
    4686            // Don't refocus if invisible to current user
    4687            final ActivityRecord top = tr.getTopActivity();
    4688            if (top == null || !top.okToShowLocked()) {
    4689                if (top != null) {
    4690                    mStackSupervisor.mRecentTasks.add(top.getTask());
    4691                }
    4692                ActivityOptions.abort(options);
    4693                return;
    4694            }
    4695
    4696            // Set focus to the top running activity of this stack.
                       //得到当前stack的top running Activity
    4697            final ActivityRecord r = topRunningActivityLocked();
                      //然后调用到这里,将当前栈设置为focus
    4698            mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason); 
    4699
    4700            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
    4701            if (noAnimation) {
    4702                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
    4703                if (r != null) {
    4704                    mStackSupervisor.mNoAnimActivities.add(r);
    4705                }
    4706                ActivityOptions.abort(options);
    4707            } else {
    4708                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
    4709            }
    4710            // If a new task is moved to the front, then mark the existing top activity as
    4711            // supporting
    4712
    4713            // picture-in-picture while paused only if the task would not be considered an oerlay
    4714            // on top
    4715            // of the current activity (eg. not fullscreen, or the assistant)
    4716            if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
    4717                    options)) {
    4718                topActivity.supportsEnterPipOnTaskSwitch = true;
    4719            }
    4720
    4721            mStackSupervisor.resumeFocusedStackTopActivityLocked();
                    //然后调用到这里,在resumeTopActivityInnerLocked中的pauseBackStacks,将上一个stack中的Activity pause
                   //resumeFocusedStackTopActivityLocked可以等到后面再说
    4722            EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
    4723
    4724            mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
    4725        } finally {
    4726            getDisplay().continueUpdateImeTarget();
    4727        }
    4728    }
    
    ActivityStackSupervisor#moveFocusableActivityStackToFrontLocked

    将ActivityRecord所在stack移到前台,并设置为focus

    3411    /** Move activity with its stack to front and make the stack focused. */
    3412    boolean moveFocusableActivityStackToFrontLocked(ActivityRecord r, String reason) {
    3413        if (r == null || !r.isFocusable()) {
    3414            if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
    3415                    "moveActivityStackToFront: unfocusable r=" + r);
    3416            return false;
    3417        }
    3418
    3419        final TaskRecord task = r.getTask();
    3420        final ActivityStack stack = r.getStack();
    3421        if (stack == null) {
    3422            Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: r="
    3423                    + r + " task=" + task);
    3424            return false;
    3425        }
    3426
    3427        if (stack == mFocusedStack && stack.topRunningActivityLocked() == r) {
    3428            if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
    3429                    "moveActivityStackToFront: already on top, r=" + r);
    3430            return false;
    3431        }
    3432
    3433        if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
    3434                "moveActivityStackToFront: r=" + r);
    3435
    3436        stack.moveToFront(reason, task);
    3437        return true;
    3438    }
    
    ActivityStack#moveToFront
    1022    /**
    1023     * @param reason The reason for moving the stack to the front.
    1024     * @param task If non-null, the task will be moved to the top of the stack.
    1025     * */
    1026    void moveToFront(String reason, TaskRecord task) {
    1027        if (!isAttached()) {
    1028            return;
    1029        }
    1030
    1031        final ActivityDisplay display = getDisplay();
    1032
    1033        if (inSplitScreenSecondaryWindowingMode()) {
    1034            // If the stack is in split-screen seconardy mode, we need to make sure we move the
    1035            // primary split-screen stack forward in the case it is currently behind a fullscreen
    1036            // stack so both halves of the split-screen appear on-top and the fullscreen stack isn't
    1037            // cutting between them.
    1038            // TODO(b/70677280): This is a workaround until we can fix as part of b/70677280.
    1039            final ActivityStack topFullScreenStack =
    1040                    display.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
    1041            if (topFullScreenStack != null) {
    1042                final ActivityStack primarySplitScreenStack = display.getSplitScreenPrimaryStack();
    1043                if (display.getIndexOf(topFullScreenStack)
    1044                        > display.getIndexOf(primarySplitScreenStack)) {
    1045                    primarySplitScreenStack.moveToFront(reason + " splitScreenToTop");
    1046                }
    1047            }
    1048        }
    1049
    1050        if (!isActivityTypeHome() && returnsToHomeStack()) {
    1051            // Make sure the home stack is behind this stack since that is where we should return to
    1052            // when this stack is no longer visible.
    1053            mStackSupervisor.moveHomeStackToFront(reason + " returnToHome");
    1054        }
    1055
    1056        display.positionChildAtTop(this);
    1057        mStackSupervisor.setFocusStackUnchecked(reason, this);//将当前的ActivityStack设置为focus
    1058        if (task != null) {
    1059            insertTaskAtTop(task, null); //task放到stack的top位置
    1060            return;
    1061        }
    1062    }
    
    ActivityStackSupervisor#setFocusStackUnchecked
    713    /** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
    714    void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
    715        if (!focusCandidate.isFocusable()) {
    716            // The focus candidate isn't focusable. Move focus to the top stack that is focusable.
    717            focusCandidate = getNextFocusableStackLocked(focusCandidate, false /* ignoreCurrent */);
    718        }
    719
    720        if (focusCandidate != mFocusedStack) {
    721            mLastFocusedStack = mFocusedStack;
    722            mFocusedStack = focusCandidate;
    723
    724            EventLogTags.writeAmFocusedStack(
    725                    mCurrentUser, mFocusedStack == null ? -1 : mFocusedStack.getStackId(),
    726                    mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), reason);
    727        }
    728
    729        final ActivityRecord r = topRunningActivityLocked();
    730        if (mService.mBooting || !mService.mBooted) {
    731            if (r != null && r.idle) {
    732                checkFinishBootingLocked();
    733            }
    734        }
    735    }
    

    回到复用的逻辑

    ActivityStarter#setTaskFromIntentActivity

    setTaskFromIntentActivity也是针对task复用而言的;这个是用来设置复用task相关的一些属性的;注意mAddingToTask,个人理解,当mAddingToTask的值为true时,代表要创建新的Activity添加到复用task中

    2130    private void setTaskFromIntentActivity(ActivityRecord intentActivity) {
    2131        if ((mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
    2132                == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) {
    2133            // The caller has requested to completely replace any existing task with its new
    2134            // activity. Well that should not be too hard...
    2135            // Note: we must persist the {@link TaskRecord} first as intentActivity could be
    2136            // removed from calling performClearTaskLocked (For example, if it is being brought out
    2137            // of history or if it is finished immediately), thus disassociating the task. Also note
    2138            // that mReuseTask is reset as a result of {@link TaskRecord#performClearTaskLocked}
    2139            // launching another activity.
    2140            // TODO(b/36119896):  We shouldn't trigger activity launches in this path since we are
    2141            // already launching one.
    2142            final TaskRecord task = intentActivity.getTask();
    2143            task.performClearTaskLocked();
    2144            mReuseTask = task;
    2145            mReuseTask.setIntent(mStartActivity);
    2146        } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
    2147                || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
    2148            ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
    2149                    mLaunchFlags);
    2150            if (top == null) {
                        //比如这里,虽然复用task,但是在task中找不到复用的ActivityRecord;如要启动的flag包含NEW_TASK;但是这个Activity是第一次启动
                       //则mAddingToTask为true,代表要创建new Activity放到复用task中
              
    2151                // A special case: we need to start the activity because it is not currently
    2152                // running, and the caller has asked to clear the current task to have this
    2153                // activity at the top.
    2154                mAddingToTask = true;
    2155
    2156                // We are no longer placing the activity in the task we previously thought we were.
    2157                mStartActivity.setTask(null);
                        //注意这里将StartActivity的task置空,后续还会通过setTaskFromSourceRecord()赋值
    2158                // Now pretend like this activity is being started by the top of its task, so it
    2159                // is put in the right place.
    2160                mSourceRecord = intentActivity;
                            //mSourceRecord的值赋值为intentActivity
    2161                final TaskRecord task = mSourceRecord.getTask();
    2162                if (task != null && task.getStack() == null) {
    2163                    // Target stack got cleared when we all activities were removed above.
    2164                    // Go ahead and reset it.
    2165                    mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
    2166                            mLaunchFlags, mOptions);
    2167                    mTargetStack.addTask(task,
    2168                            !mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
    2169                }
    2170            }
    2171        } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
    2172            // In this case the top activity on the task is the same as the one being launched,
    2173            // so we take that as a request to bring the task to the foreground. If the top
    2174            // activity in the task is the root activity, deliver this new intent to it if it
    2175            // desires.
    2176            if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
    2177                        || LAUNCH_SINGLE_TOP == mLaunchMode)
    2178                    && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
    2179                if (intentActivity.frontOfTask) {
    2180                    intentActivity.getTask().setIntent(mStartActivity);
    2181                }
    2182                deliverNewIntent(intentActivity);
    2183            } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
    2184                // In this case we are launching the root activity of the task, but with a
    2185                // different intent. We should start a new instance on top.
    2186                mAddingToTask = true;
    2187                mSourceRecord = intentActivity;
    2188            }
    2189        } else if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
    2190            // In this case an activity is being launched in to an existing task, without
    2191            // resetting that task. This is typically the situation of launching an activity
    2192            // from a notification or shortcut. We want to place the new activity on top of the
    2193            // current task.
    2194            mAddingToTask = true;
    2195            mSourceRecord = intentActivity;
    2196        } else if (!intentActivity.getTask().rootWasReset) {
    2197            // In this case we are launching into an existing task that has not yet been started
    2198            // from its front door. The current task has been brought to the front. Ideally,
    2199            // we'd probably like to place this new task at the bottom of its stack, but that's
    2200            // a little hard to do with the current organization of the code so for now we'll
    2201            // just drop it.
    2202            intentActivity.getTask().setIntent(mStartActivity);
    2203        }
    2204    }
    

    ActivityStarter#resumeTargetStackIfNeeded

    上面说道resumeTargetStackIfNeeded,这也只是在复用task的时候才会调用的
    A->B->A A为singleTask模式的大致流程

    1477            if (reusedActivity != null) {
    1478                setTaskFromIntentActivity(reusedActivity);
    1479
    1480                if (!mAddingToTask && mReuseTask == null) {
    1481                    // We didn't do anything...  but it was needed (a.k.a., client don't use that
    1482                    // intent!)  And for paranoia, make sure we have correctly resumed the top activity.
    1483                   //mAddingToTask = false,不用创建新的Activity,那么就是复用原来的
    1484                    resumeTargetStackIfNeeded(); //调用resumeTargetStackIfNeeded
    1485                    if (outActivity != null && outActivity.length > 0) {
    1486                        outActivity[0] = reusedActivity;
    1487                    }
    1488
    1489                    return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP;
    1490                }
    1491            }
    
    2206    private void resumeTargetStackIfNeeded() {
    2207        if (mDoResume) {
    2208            mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
    2209        } else {
    2210            ActivityOptions.abort(mOptions);
    2211        }
    2212        mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
    2213    }
    
    ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
    2307    boolean resumeFocusedStackTopActivityLocked(
    2308            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    2309
    2310        if (!readyToResume()) {
    2311            return false;
    2312        }
    2313
    2315        // if resume one non-fullscreen task, also resume the other one
    2316        boolean resumed = false;
    2317        if (targetStack != null && isFocusedStack(targetStack)) {
    2321
    2331            if (target != null && target.getState() == RESUMED && mNeedScheduleIdle) {
    2332                scheduleIdleLocked();
    2333                mNeedScheduleIdle = false;
    2334                if (target.getTask().inMultiWindowMode()) {
    2335                    return false;
    2336                }
    2337            }
    2338            resumed = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    2339        } else {
    2340            ActivityStack recentsStack = getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS);
    2341            if (mLaunchRecentsFromGesture && recentsStack != null && !mHasResumeRecentsBehind
    2342                    && !mStopLaunchRecentsBehind) {
    2343                recentsStack.resumeTopActivityUncheckedLocked(null, null);
    2344            } else {
    2345                final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    2346                if (r == null || r.getState() != RESUMED) {
    2347                    mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    2348                } else if (r.getState() == RESUMED) {
    2349                    if (!r.getTask().inMultiWindowMode()) {
    2350                        mFocusedStack.executeAppTransition(targetOptions);
    2351                    }
    2352                    if (mNeedScheduleIdle) {
    2353                        scheduleIdleLocked();
    2354                        mNeedScheduleIdle = false;
    2355                    }
    2356                    return false;
    2357                }
    2358            }
    2359        }
    2360        // resume non-fullscreen task
    2361        if (mFocusedStack.topTask() != null && mFocusedStack.topTask().inMultiWindowMode()
    2362                && !mService.isSleepingOrShuttingDownLocked()) {
    2364            ActivityStack multiWindowStack = null;
    2365            if (mFocusedStack.inSplitScreenPrimaryWindowingMode()) {
    2366                multiWindowStack = mFocusedStack.getDisplay().getTopStackInWindowingMode(
    2367                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
    2368            } else if (mFocusedStack.inSplitScreenSecondaryWindowingMode()) {
    2369                multiWindowStack = mFocusedStack.getDisplay().getTopStackInWindowingMode(
    2370                        WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
    2371            }
    2372
    2373            if (multiWindowStack != null
    2374                    && multiWindowStack.shouldBeVisible(null)) {
    2375                final ActivityRecord r = multiWindowStack.topRunningActivityLocked();
    2376                if (r != null && r.getState() != RESUMED && r.getTask().inMultiWindowMode()) {
    2377                    multiWindowStack.resumeTopActivityUncheckedLocked(null, null);
    2378                }
    2379            }
    2380        }
    2381        return resumed;
    2382        // END
    2383    }
    

    ActivityStack#resumeTopActivityUncheckedLocked

    2397    /**
    2398     * Ensure that the top activity in the stack is resumed.
    2399     *
    2400     * @param prev The previously resumed activity, for when in the process
    2401     * of pausing; can be null to call from elsewhere.
    2402     * @param options Activity options.
    2403     *
    2404     * @return Returns true if something is being resumed, or false if
    2405     * nothing happened.
    2406     *
    2407     * NOTE: It is not safe to call this method directly as it can cause an activity in a
    2408     *       non-focused stack to be resumed.
    2409     *       Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the
    2410     *       right activity for the current system state.
    2411     */
    2412    @GuardedBy("mService")
    2413    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    2414        if (mStackSupervisor.inResumeTopActivity) {
    2415            // Don't even start recursing.
    2416            return false;
    2417        }
    2418
    2419        boolean result = false;
    2420        try {
    2421            // Protect against recursion.
    2422            mStackSupervisor.inResumeTopActivity = true;
    2423            result = resumeTopActivityInnerLocked(prev, options);
    2424
    2425            // When resuming the top activity, it may be necessary to pause the top activity (for
    2426            // example, returning to the lock screen. We suppress the normal pause logic in
    2427            // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
    2428            // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
    2429            // to ensure any necessary pause logic occurs. In the case where the Activity will be
    2430            // shown regardless of the lock screen, the call to
    2431            // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
    2432            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
    2433            if (next == null || !next.canTurnScreenOn()) {
    2434                checkReadyForSleep();
    2435            }
    2436        } finally {
    2437            mStackSupervisor.inResumeTopActivity = false;
    2438        }
    2439
    2440        return result;
    2441    }
    

    调用resumeTopActivityInnerLocked,这个逻辑比较复杂,放在下面的文章中讲

    相关文章

      网友评论

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

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