Android(安卓)P ActivityManagerService(六) startActivity的第四小部分
ActivityStarter中,生成ActivityRecord之后startActivity方法;
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { int result = START_CANCELED; try { mService.mWindowManager.deferSurfaceLayout(); result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, outActivity); } finally { // If we are not able to proceed, disassociate the activity from the task. Leaving an // activity in an incomplete state can lead to issues, such as performing operations // without a window container. final ActivityStack stack = mStartActivity.getStack(); if (!ActivityManager.isStartResultSuccessful(result) && stack != null) { stack.finishActivityLocked(mStartActivity, RESULT_CANCELED, null /* intentResultData */, "startActivity", true /* oomAdj */); } mService.mWindowManager.continueSurfaceLayout(); } postStartActivityProcessing(r, result, mTargetStack); return result;}
在AMS的初始化中,SystemServer的startOtherServices方法内,AMS通过setWindowManager方法获得了WindowManagerService;即这里的mService.mWindowManager;
public void setWindowManager(WindowManagerService wm) { synchronized (this) { mWindowManager = wm; mStackSupervisor.setWindowManager(wm); mLockTaskController.setWindowManager(wm); }}
WindowManagerService的deferSurfaceLayout方法;通知暂停布局;
/** * Starts deferring layout passes. Useful when doing multiple changes but to optimize * performance, only one layout pass should be done. This can be called multiple times, and * layouting will be resumed once the last caller has called {@link #continueSurfaceLayout} */public void deferSurfaceLayout() { synchronized (mWindowMap) { mWindowPlacerLocked.deferLayout(); }}
continueSurfaceLayout方法;恢复暂停的布局;
/** * Resumes layout passes after deferring them. See {@link #deferSurfaceLayout()} */public void continueSurfaceLayout() { synchronized (mWindowMap) { mWindowPlacerLocked.continueLayout(); }}
这两个方法中间,是启动Activity的关键方法;startActivityUnchecked;Unchecked这个词很关键,表示再也不会像之前一样,检查个300行代码了;然后这个启动的代码,也有260行之多;
// Note: This method should only be called from {@link startActivity}.private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask, ActivityRecord[] outActivity) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor); computeLaunchingTaskFlags(); computeSourceStack(); mIntent.setFlags(mLaunchFlags); ActivityRecord reusedActivity = getReusableIntentActivity(); int preferredWindowingMode = WINDOWING_MODE_UNDEFINED; int preferredLaunchDisplayId = DEFAULT_DISPLAY; if (mOptions != null) { preferredWindowingMode = mOptions.getLaunchWindowingMode(); preferredLaunchDisplayId = mOptions.getLaunchDisplayId(); } // windowing mode and preferred launch display values from {@link LaunchParams} take // priority over those specified in {@link ActivityOptions}. if (!mLaunchParams.isEmpty()) { if (mLaunchParams.hasPreferredDisplay()) { preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId; } if (mLaunchParams.hasWindowingMode()) { preferredWindowingMode = mLaunchParams.mWindowingMode; } } if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and // the device would otherwise leave the locked task. if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(), (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } // True if we are clearing top and resetting of a standard (default) launch mode // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished. final boolean clearTopAndResetStandardLaunchMode = (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)) == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) && mLaunchMode == LAUNCH_MULTIPLE; // If mStartActivity does not have a task associated with it, associate it with the // reused activity's task. Do not do so if we're clearing top and resetting for a // standard launchMode activity. if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) { mStartActivity.setTask(reusedActivity.getTask()); } if (reusedActivity.getTask().intent == null) { // This task was started because of movement of the activity based on affinity... // Now that we are actually launching it, we can assign the base intent. reusedActivity.getTask().setIntent(mStartActivity); } // This code path leads to delivering a new intent, we want to make sure we schedule it // as the first operation, in case the activity will be resumed as a result of later // operations. if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 || isDocumentLaunchesIntoExisting(mLaunchFlags) || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) { final TaskRecord task = reusedActivity.getTask(); // In this situation we want to remove all activities from the task up to the one // being started. In most cases this means we are resetting the task to its initial // state. final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity, mLaunchFlags); // The above code can remove {@code reusedActivity} from the task, leading to the // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The // task reference is needed in the call below to // {@link setTargetStackAndMoveToFrontIfNeeded}. if (reusedActivity.getTask() == null) { reusedActivity.setTask(task); } if (top != null) { if (top.frontOfTask) { // Activity aliases may mean we use different intents for the top activity, // so make sure the task now has the identity of the new intent. top.getTask().setIntent(mStartActivity); } deliverNewIntent(top); } } mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity); reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity); final ActivityRecord outResult = outActivity != null && outActivity.length > 0 ? outActivity[0] : null; // When there is a reused activity and the current result is a trampoline activity, // set the reused activity as the result. if (outResult != null && (outResult.finishing || outResult.noDisplay)) { outActivity[0] = reusedActivity; } if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do anything // if that is the case, so this is it! And for paranoia, make sure we have // correctly resumed the top activity. resumeTargetStackIfNeeded(); return START_RETURN_INTENT_TO_CALLER; } if (reusedActivity != null) { setTaskFromIntentActivity(reusedActivity); if (!mAddingToTask && mReuseTask == null) { // We didn't do anything... but it was needed (a.k.a., client don't use that // intent!) And for paranoia, make sure we have correctly resumed the top activity. resumeTargetStackIfNeeded(); if (outActivity != null && outActivity.length > 0) { outActivity[0] = reusedActivity; } return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP; } } } if (mStartActivity.packageName == null) { final ActivityStack sourceStack = mStartActivity.resultTo != null ? mStartActivity.resultTo.getStack() : null; if (sourceStack != null) { sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo, mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null /* data */); } ActivityOptions.abort(mOptions); return START_CLASS_NOT_FOUND; } // If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. final ActivityStack topStack = mSupervisor.mFocusedStack; final ActivityRecord topFocused = topStack.getTopActivity(); final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop); final boolean dontStart = top != null && mStartActivity.resultTo == null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId && top.app != null && top.app.thread != null && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)); if (dontStart) { // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { mSupervisor.resumeFocusedStackTopActivityLocked(); } ActivityOptions.abort(mOptions); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do // anything if that is the case, so this is it! return START_RETURN_INTENT_TO_CALLER; } deliverNewIntent(top); // Don't use mStartActivity.task to show the toast. We're not starting a new activity // but reusing 'top'. Fields in mStartActivity may not be fully initialized. mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode, preferredLaunchDisplayId, topStack); return START_DELIVERED_TO_TOP; } boolean newTask = false; final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null; // Should this be considered a new task? int result = START_SUCCESS; if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack); } else if (mSourceRecord != null) { result = setTaskFromSourceRecord(); } else if (mInTask != null) { result = setTaskFromInTask(); } else { // This not being started from an existing activity, and not part of a new task... // just put it in the top task, though these days this case should never happen. setTaskToCurrentTopOrCreateNewTask(); } if (result != START_SUCCESS) { return result; } mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName, mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId); mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent, mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid)); if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.getTask().taskId); } ActivityStack.logStartActivity( EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask()); mTargetStack.mLastPausedActivity = null; mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity); mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetStack.isFocusable() || (topTaskActivity != null && topTaskActivity.mTaskOverlay && mStartActivity != topTaskActivity)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mService.mWindowManager.executeAppTransition(); } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); } } else if (mStartActivity != null) { mSupervisor.mRecentTasks.add(mStartActivity.getTask()); } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode, preferredLaunchDisplayId, mTargetStack); return START_SUCCESS;}
代码太长;只能一段段分开看;
1. 启动参数的初始化;里面是对一个参数和Flag的设置;
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor);
2. 计算LaunchingTask和一些LaunchMode;
computeLaunchingTaskFlags();
3. 拿到mSourceStack;这里会对正在关闭的source做特殊处理;
computeSourceStack();
4. 设置LaunchFlags;FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_MULTIPLE_TASK等Flags;
mIntent.setFlags(mLaunchFlags);
5. 判断是否应将新Activity插入现有task;如果不是,则返回null;如果是,则返回包含要添加新Activity的task的ActivityRecord;
ActivityRecord reusedActivity = getReusableIntentActivity();
6. window mode和dispaly id;window mode定义在WindowConfiguration,包括WINDOWING_MODE_UNDEFINED、WINDOWING_MODE_FULLSCREEN、WINDOWING_MODE_PINNED等;display id相关定义在Display中,每个dispay都有一个唯一的id;
int preferredWindowingMode = WINDOWING_MODE_UNDEFINED;int preferredLaunchDisplayId = DEFAULT_DISPLAY;if (mOptions != null) { preferredWindowingMode = mOptions.getLaunchWindowingMode(); preferredLaunchDisplayId = mOptions.getLaunchDisplayId();}// windowing mode and preferred launch display values from {@link LaunchParams} take// priority over those specified in {@link ActivityOptions}.if (!mLaunchParams.isEmpty()) { if (mLaunchParams.hasPreferredDisplay()) { preferredLaunchDisplayId = mLaunchParams.mPreferredDisplayId; } if (mLaunchParams.hasWindowingMode()) { preferredWindowingMode = mLaunchParams.mWindowingMode; }}
7. 重用Activity;符合条件就直接重用;不走后面的代码;
if (reusedActivity != null) { // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but // still needs to be a lock task mode violation since the task gets cleared out and // the device would otherwise leave the locked task. if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(), (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) { Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode"); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } // True if we are clearing top and resetting of a standard (default) launch mode // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished. final boolean clearTopAndResetStandardLaunchMode = (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)) == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) && mLaunchMode == LAUNCH_MULTIPLE; // If mStartActivity does not have a task associated with it, associate it with the // reused activity's task. Do not do so if we're clearing top and resetting for a // standard launchMode activity. if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) { mStartActivity.setTask(reusedActivity.getTask()); } if (reusedActivity.getTask().intent == null) { // This task was started because of movement of the activity based on affinity... // Now that we are actually launching it, we can assign the base intent. reusedActivity.getTask().setIntent(mStartActivity); } // This code path leads to delivering a new intent, we want to make sure we schedule it // as the first operation, in case the activity will be resumed as a result of later // operations. if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0 || isDocumentLaunchesIntoExisting(mLaunchFlags) || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) { final TaskRecord task = reusedActivity.getTask(); // In this situation we want to remove all activities from the task up to the one // being started. In most cases this means we are resetting the task to its initial // state. final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity, mLaunchFlags); // The above code can remove {@code reusedActivity} from the task, leading to the // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The // task reference is needed in the call below to // {@link setTargetStackAndMoveToFrontIfNeeded}. if (reusedActivity.getTask() == null) { reusedActivity.setTask(task); } if (top != null) { if (top.frontOfTask) { // Activity aliases may mean we use different intents for the top activity, // so make sure the task now has the identity of the new intent. top.getTask().setIntent(mStartActivity); } deliverNewIntent(top); } } mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity); reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity); final ActivityRecord outResult = outActivity != null && outActivity.length > 0 ? outActivity[0] : null; // When there is a reused activity and the current result is a trampoline activity, // set the reused activity as the result. if (outResult != null && (outResult.finishing || outResult.noDisplay)) { outActivity[0] = reusedActivity; } if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do anything // if that is the case, so this is it! And for paranoia, make sure we have // correctly resumed the top activity. resumeTargetStackIfNeeded(); return START_RETURN_INTENT_TO_CALLER; } if (reusedActivity != null) { setTaskFromIntentActivity(reusedActivity); if (!mAddingToTask && mReuseTask == null) { // We didn't do anything... but it was needed (a.k.a., client don't use that // intent!) And for paranoia, make sure we have correctly resumed the top activity. resumeTargetStackIfNeeded(); if (outActivity != null && outActivity.length > 0) { outActivity[0] = reusedActivity; } return mMovedToFront ? START_TASK_TO_FRONT : START_DELIVERED_TO_TOP; } }}
8. 检查class not found;
if (mStartActivity.packageName == null) { final ActivityStack sourceStack = mStartActivity.resultTo != null ? mStartActivity.resultTo.getStack() : null; if (sourceStack != null) { sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo, mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED, null /* data */); } ActivityOptions.abort(mOptions); return START_CLASS_NOT_FOUND;}
9. 对SINGLE_TOP做的CASE处理;
// If the activity being launched is the same as the one currently at the top, then// we need to check if it should only be launched once.final ActivityStack topStack = mSupervisor.mFocusedStack;final ActivityRecord topFocused = topStack.getTopActivity();final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);final boolean dontStart = top != null && mStartActivity.resultTo == null && top.realActivity.equals(mStartActivity.realActivity) && top.userId == mStartActivity.userId && top.app != null && top.app.thread != null && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));if (dontStart) { // For paranoia, make sure we have correctly resumed the top activity. topStack.mLastPausedActivity = null; if (mDoResume) { mSupervisor.resumeFocusedStackTopActivityLocked(); } ActivityOptions.abort(mOptions); if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) { // We don't need to start a new activity, and the client said not to do // anything if that is the case, so this is it! return START_RETURN_INTENT_TO_CALLER; } deliverNewIntent(top); // Don't use mStartActivity.task to show the toast. We're not starting a new activity // but reusing 'top'. Fields in mStartActivity may not be fully initialized. mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode, preferredLaunchDisplayId, topStack); return START_DELIVERED_TO_TOP;}
10. 根据情况选择task,并将其带到前台;如果是new task,就需要创建新的;
boolean newTask = false;final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null;// Should this be considered a new task?int result = START_SUCCESS;if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) { newTask = true; result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);} else if (mSourceRecord != null) { result = setTaskFromSourceRecord();} else if (mInTask != null) { result = setTaskFromInTask();} else { // This not being started from an existing activity, and not part of a new task... // just put it in the top task, though these days this case should never happen. setTaskToCurrentTopOrCreateNewTask();}if (result != START_SUCCESS) { return result;}
11. 给予UriPermission;
mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName, mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
12. emmm
mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent, mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));
13. 打LOG
if (newTask) { EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId, mStartActivity.getTask().taskId);}ActivityStack.logStartActivity( EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
14. 将mLastPausedActivity 置为null;
mTargetStack.mLastPausedActivity = null;
/** * This is the last activity that we put into the paused state. This is * used to determine if we need to do an activity transition while sleeping, * when we normally hold the top activity paused. */ActivityRecord mLastPausedActivity = null;
15. emmmm
mSupervisor.sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);
16. 启动Activity
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition, mOptions);
17. Resume
if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetStack.isFocusable() || (topTaskActivity != null && topTaskActivity.mTaskOverlay && mStartActivity != topTaskActivity)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mService.mWindowManager.executeAppTransition(); } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityUnchecked"); } mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions); }} else if (mStartActivity != null) { mSupervisor.mRecentTasks.add(mStartActivity.getTask());}
18. 更新stack的userId
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
/** * Update the last used stack id for non-current user (current user's last * used stack is the focused stack) */void updateUserStackLocked(int userId, ActivityStack stack) { if (userId != mCurrentUser) { mUserStackInFront.put(userId, stack != null ? stack.getStackId() : mHomeStack.mStackId); }}
19. 处理分屏
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode, preferredLaunchDisplayId, mTargetStack);
startActivityUnchecked的内容很多;后面再摘取有趣的部分深入的阅读;
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, mOptions);
targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);mFocusedStack.resumeTopActivityUncheckedLocked(null, null);private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)
mStackSupervisor.startSpecificActivityLocked(next, true, true);final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException
更多相关文章
- android判断一个应用是不是系统应用
- Android实现定时器的方法
- Android(安卓)PackageManager 卸载包的方法
- Android在子线程中更新UI(二)
- android中如何获取视频时长
- Android(安卓)Audio代码分析14 - testPlaybackHeadPositionIncre
- Android重写view时onAttachedToWindow () 和 onDetachedFromWind
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用