Display #0 (activities from top to bottom):
* Task{45dbacd #1 //标志1type=home ?? U=0 //标志2visible=true visibleRequested=true //标志3mode=fullscreen translucent=false sz=1}
* Task{c41a1a1 #8 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
mLastPausedActivity(上一次paused的activity): ActivityRecord{b9be218 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t8}
isSleeping=false
topResumedActivity(top Resumed的activity)=ActivityRecord{b9be218 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t8}
* Hist #0: ActivityRecord{b9be218 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t8}
(包名)packageName=com.android.launcher3 (进程名)processName=com.android.launcher3
launchedFromUid=0 launchedFromPackage=null launchedFromFeature=null userId=0
app=ProcessRecord{b1fce62 2666:com.android.launcher3/u0a107}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.launcher3/.uioverrides.QuickstepLauncher (has extras) }
(是否是根task)rootOfTask=true task=Task{c41a1a1 #8 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1}
taskAffinity=null
mActivityComponent=com.android.launcher3/.uioverrides.QuickstepLauncher
(apk路径)baseDir=/system_ext/priv-app/Launcher3QuickStep/Launcher3QuickStep.apk
(data数据路径)dataDir=/data/user/0/com.android.launcher3
stateNotNeeded=true componentSpecified=false mActivityType=home
compat={640dpi always-compat} labelRes=0x7f10007d icon=0x7f080250 theme=0x7f11000e
mLastReportedConfigurations:
(当前global config)mGlobalConfig={1.0 ?mcc?mnc [en_US] ldltr sw960dp w1776dp h876dp 640dpi xlrg long land vrheadset -touch -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 7104, 3840) mAppBounds=Rect(0, 0 - 7104, 3600) mMaxBounds=Rect(0, 0 - 7104, 3840) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} s.68 fontWeightAdjustment=0}
(上一次的config)mOverrideConfig={1.0 ?mcc?mnc [en_US] ldltr sw960dp w1776dp h876dp 640dpi xlrg long land vrheadset -touch -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 7104, 3840) mAppBounds=Rect(0, 0 - 7104, 3600) mMaxBounds=Rect(0, 0 - 7104, 3840) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s.3 fontWeightAdjustment=0}
(当前Configuration)CurrentConfiguration={1.0 ?mcc?mnc [en_US] ldltr sw960dp w1776dp h876dp 640dpi xlrg long land vrheadset -touch -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 - 7104, 3840) mAppBounds=Rect(0, 0 - 7104, 3600) mMaxBounds=Rect(0, 0 - 7104, 3840) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=home mAlwaysOnTop=undefined mRotation=ROTATION_0} s.3 fontWeightAdjustment=0}
RequestedOverrideConfiguration={0.0 ?mcc?mnc ?localeList ?layoutDir ?swdp ?wdp ?hdp ?density ?lsize ?long ?ldr ?wideColorGamut ?orien ?uimode ?night ?touch ?keyb/?/? ?nav/? winConfig={ mBounds=Rect(0, 0 - 0, 0) mAppBounds=null mMaxBounds=Rect(0, 0 - 0, 0) mWindowingMode=undefined mDisplayWindowingMode=undefined mActivityType=home mAlwaysOnTop=undefined mRotation=undefined} ?fontWeightAdjustment}
taskDescription: label="null" icon=null iconResource=/0 iconFilename=null primaryColor=fff0f0f3
(各布局颜色)backgroundColor=fff0f0f3 statusBarColor=0 navigationBarColor=0
backgroundColorFloating=fff0f0f3
launchFailed=false launchCount=0 lastLaunchTime=-2h20m41s36ms
mHaveState=false mIcicle=null
(当前activity状态)//标志4state=RESUMED stopped=false delayedResume=false finishing=false
keysPaused=false inHistory=true idle=true
occludesParent=true noDisplay=false immersive=false launchMode=2
frozenBeforeDestroy=false forceNewConfig=false
mActivityType=home
mImeInsetsFrozenUntilStartInput=false
windows=[Window{8097e4a u0 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher}]
windowType=2 hasVisible=true
mOccludesParent=true
mOrientation=SCREEN_ORIENTATION_UNSPECIFIED
mVisibleRequested=true mVisible=true mClientVisible=true reportedDrawn=true reportedVisible=true
mNumInterestingWindows=1 mNumDrawnWindows=1 allDrawn=true lastAllDrawn=true)
startingData=null firstWindowDrawn=true mIsExiting=false
nowVisible=true lastVisibleTime=-8s20ms
connections={ConnectionRecord{7a9ad43 u0 com.android.launcher3/com.android.quickstep.TouchInteractionService:@3e082f2}}
resizeMode=RESIZE_MODE_RESIZEABLE
mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
supportsSizeChanges=SIZE_CHANGES_UNSUPPORTED_METADATA
configChanges=0xdf3
neverSandboxDisplayApis=false
alwaysSandboxDisplayApis=false
areBoundsLetterboxed=false
ACTIVITY TYPE
标志1代表当前Activity的类型,Activity共有以下几种类型:
ACTIVITY TYPE | Value | 含义 |
---|---|---|
ACTIVITY_TYPE_UNDEFINED | 0 | 当前Activity type未定义 |
ACTIVITY_TYPE_STANDARD | 1 | 标准的Activity type,这个Activity没有特别的地方 |
ACTIVITY_TYPE_HOME | 2 | Home/Launcher activity type |
ACTIVITY_TYPE_RECENTS | 3 | Recents/Overview activity type,系统中只会存在一个这种类型的activity |
ACTIVITY_TYPE_ASSISTANT | 4 | Assistant activity type。语音助手 |
ACTIVITY_TYPE_DREAM | 5 | Dream activity type。手机屏保 |
visible
标志2代表当前activity是否可见。流程如下:
/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
boolean shouldBeVisible() { final Task rootTask = getRootTask(); if (rootTask == null) { return false; } final boolean behindFullscreenActivity = !rootTask.shouldBeVisible(null /* starting */) || rootTask.getOccludingActivityAbove(this) != null; return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */); }
/** @return {@code true} if this activity should be made visible. */ private boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) { updateVisibilityIgnoringKeyguard(behindFullscreenActivity); if (ignoringKeyguard) { return visibleIgnoringKeyguard; } return shouldBeVisibleUnchecked(); }
WINDOWING MODE
标志3 处代表的是当前Activity的window mode.
WINDOWING MODE | Value | 含义 |
---|---|---|
WINDOWING_MODE_UNDEFINED | 0 | 未定义的window mode |
WINDOWING_MODE_FULLSCREEN | 1 | 占用整个屏幕或父容器的区域的window mode |
WINDOWING_MODE_PINNED | 2 | 始终在顶部(始终可见)。对父容器中其他兄弟容器的 |
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY | 3 | 在分屏模式下的主容器 |
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY | 4 | 在分屏模式下的第二容器 |
WINDOWING_MODE_FREEFORM | 5 | 自由窗口,可以在父容器中自由调整大小 |
WINDOWING_MODE_MULTI_WINDOW | 6 | 通用多窗口,没有来自窗口管理器的表示属性 |
ActivityState
标志4代表当前Activity的状态,enum ActivityState内容如下:
ActivityState | 含义 |
---|---|
INITIALIZING | new ActivityRecord后的第一个状态, |
STARTED | 已经start |
RESUMED | 已经resumed完成 |
PAUSING | 正在pausing |
PAUSED | 已经pause完成 |
STOPPING | 正在stopping |
STOPPED | 已经stop完成 |
FINISHING | 正在finishing |
DESTROYING | 正在destroying |
DESTROYED | 已经destroy |
RESTARTING_PROCESS | 重新start |
Activity State的状态转变是由setState方法进行设置的,后面跟有原因。
/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
void setState(ActivityState state, String reason) { ProtoLog.v(WM_DEBUG_STATES, "State movement: %s from:%s to:%s reason:%s", this, getState(), state, reason); if (state == mState) {//这次和上次没变化 // No need to do anything if state doesn't change. ProtoLog.v(WM_DEBUG_STATES, "State unchanged from:%s", state); return; } mState = state; if (task != null) { task.onActivityStateChanged(this, state, reason); } // The WindowManager interprets the app stopping signal as // an indication that the Surface will eventually be destroyed. // This however isn't necessarily true if we are going to sleep. if (state == STOPPING && !isSleeping()) { if (getParent() == null) { Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: " + appToken); return; } } if (app != null) { mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */); } switch (state) { case RESUMED: mAtmService.updateBatteryStats(this, true); mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED); // Fall through. case STARTED: // Update process info while making an activity from invisible to visible, to make sure the process state is updated to foreground. if (app != null) { app.updateProcessInfo(false /* updateServiceConnectionActivities */, true /* activityChange */, true /* updateOomAdj */,true /* addPendingTopUid */); } final ContentCaptureManagerInternal contentCaptureService = LocalServices.getService(ContentCaptureManagerInternal.class); if (contentCaptureService != null) { contentCaptureService.notifyActivityEvent(mUserId, mActivityComponent, ActivityEvent.TYPE_ACTIVITY_STARTED); } break; case PAUSED: mAtmService.updateBatteryStats(this, false); mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED); break; case STOPPED: mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED); break; case DESTROYED: mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED); // Fall through. case DESTROYING: if (app != null && !app.hasActivities()) { // Update any services we are bound to that might care about whether their client may have activities. No longer have activities, so update LRU list and oom adj. app.updateProcessInfo(true /* updateServiceConnectionActivities */,false /* activityChange */, true /* updateOomAdj */, false /* addPendingTopUid */); } break; } }
1. setState STARTED
/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
/** * Make activity resumed or paused if needed. * @param activeActivity an activity that is resumed or just completed pause action. * We won't change the state of this activity. */ boolean makeActiveIfNeeded(ActivityRecord activeActivity) { ... } else if (shouldStartActivity()) { if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Start visible activity, " + this); } setState(STARTED, "makeActiveIfNeeded"); try { //执行动画 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, StartActivityItem.obtain(takeOptions())); } catch (Exception e) { Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e); } // The activity may be waiting for stop, but that is no longer appropriate if we are starting the activity again mTaskSupervisor.mStoppingActivities.remove(this); } return false; }
2. setState STARTED
frameworks/base/services/core/java/com/android/server/wm/Task.java
void minimalResumeActivityLocked(ActivityRecord r) { ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (starting new instance) " + "callers=%s", r, Debug.getCallers(5)); r.setState(RESUMED, "minimalResumeActivityLocked"); r.completeResumeLocked(); }
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options, boolean deferPause) {......
ActivityRecord next = topRunningActivity(true /* focusableOnly */);......
if (next.attachedToProcess()) { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped + " visibleRequested=" + next.mVisibleRequested);final boolean lastActivityTranslucent = lastFocusedRootTask != null && (lastFocusedRootTask.inMultiWindowMode() || (lastFocusedRootTask.mLastPausedActivity != null && !lastFocusedRootTask.mLastPausedActivity.occludesParent())); // This activity is now becoming visible. if (!next.mVisibleRequested || next.stopped || lastActivityTranslucent) { next.setVisibility(true); } // schedule launch ticks to collect information about slow apps. next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = lastFocusedRootTask == null ? null : lastFocusedRootTask.getResumedActivity(); final ActivityState lastState = next.getState(); mAtmService.updateCpuStats(); ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (in existing)", next); next.setState(RESUMED, "resumeTopActivityInnerLocked");......
try { ...... } catch (Exception e) { // Whoops, need to restart this activity! ProtoLog.v(WM_DEBUG_STATES, "Resume failed; resetting state to %s: " + "%s", lastState, next); next.setState(lastState, "resumeTopActivityInnerLocked"); // lastResumedActivity being non-null implies there is a lastStack present. if (lastResumedActivity != null) { lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); } ......
3. setState PAUSING
boolean makeActiveIfNeeded(ActivityRecord activeActivity) { ...... } else if (shouldPauseActivity(activeActivity)) { if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Pause visible activity, " + this); } // An activity must be in the {@link PAUSING} state for the system to validate // the move to {@link PAUSED}. setState(PAUSING, "makeActiveIfNeeded"); try { mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, PauseActivityItem.obtain(finishing, false /* userLeaving */,configChangeFlags, false /* dontReport */)); } catch (Exception e) { Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e); }
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, String reason) { ...... if (mPausingActivity != null) { Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity + " state=" + mPausingActivity.getState()); if (!shouldSleepActivities()) { // Avoid recursion among check for sleep and complete pause during sleeping. Because activity will be paused immediately after resume, just let pause be completed by the order of activity paused from clients. completePauseLocked(false, resuming); } } ActivityRecord prev = mResumedActivity; if (prev == null) { if (resuming == null) { Slog.wtf(TAG, "Trying to pause when nothing is resumed"); mRootWindowContainer.resumeFocusedTasksTopActivities(); } return false; } if (prev == resuming) { Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed"); return false; } ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev); mPausingActivity = prev; mLastPausedActivity = prev; if (prev.isNoHistory() && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) { mTaskSupervisor.mNoHistoryActivities.add(prev); } prev.setState(PAUSING, "startPausingLocked"); prev.getTask().touchActiveTime();......
4. setState PAUSED
void activityPaused(boolean timeout) { ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", appToken, timeout); if (task != null) { removePauseTimeout(); final ActivityRecord pausingActivity = task.getPausingActivity(); if (pausingActivity == this) { ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this, (timeout ? "(due to timeout)" : " (pause complete)")); mAtmService.deferWindowLayout(); try { task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */); } finally { mAtmService.continueWindowLayout(); } return; } else { EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this), shortComponentName, pausingActivity != null ? pausingActivity.shortComponentName : "(none)"); if (isState(PAUSING)) { setState(PAUSED, "activityPausedLocked"); if (finishing) { ProtoLog.v(WM_DEBUG_STATES, "Executing finish of failed to pause activity: %s", this); completeFinishing("activityPausedLocked"); } } } } mDisplayContent.handleActivitySizeCompatModeIfNeeded(this); mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); }
void relaunchActivityLocked(boolean preserveWindow) { if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) { configChangeFlags = 0; return; } // Do not waiting for translucent activity if it is going to relaunch. final Task rootTask = getRootTask(); if (rootTask != null && rootTask.mTranslucentActivityWaiting == this) { rootTask.checkTranslucentActivityWaiting(null); } final boolean andResume = shouldBeResumed(null /*activeActivity*/); List<ResultInfo> pendingResults = null; List<ReferrerIntent> pendingNewIntents = null; if (andResume) { pendingResults = results; pendingNewIntents = newIntents; } if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Relaunching: " + this + " with results=" + pendingResults + " newIntents=" + pendingNewIntents + " andResume=" + andResume + " preserveWindow=" + preserveWindow); if (andResume) { EventLogTags.writeWmRelaunchResumeActivity(mUserId, System.identityHashCode(this), task.mTaskId, shortComponentName); } else { EventLogTags.writeWmRelaunchActivity(mUserId, System.identityHashCode(this), task.mTaskId, shortComponentName); } startFreezingScreenLocked(0); try { ProtoLog.i(WM_DEBUG_STATES, "Moving to %s Relaunching %s callers=%s" , (andResume ? "RESUMED" : "PAUSED"), this, Debug.getCallers(6)); forceNewConfig = false; startRelaunching(); final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults, pendingNewIntents, configChangeFlags, new MergedConfiguration(getProcessGlobalConfiguration(), getMergedOverrideConfiguration()), preserveWindow); final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(isTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken); transaction.addCallback(callbackItem); transaction.setLifecycleStateRequest(lifecycleItem); mAtmService.getLifecycleManager().scheduleTransaction(transaction); // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only request resume if this activity is currently resumed, which implies we aren't sleeping. } catch (RemoteException e) { ProtoLog.i(WM_DEBUG_STATES, "Relaunch failed %s", e); } if (andResume) { ProtoLog.d(WM_DEBUG_STATES, "Resumed after relaunch %s", this); results = null; newIntents = null; mAtmService.getAppWarningsLocked().onResumeActivity(this); } else { removePauseTimeout(); setState(PAUSED, "relaunchActivityLocked"); } // The activity may be waiting for stop, but that is no longer appropriate for it. mTaskSupervisor.mStoppingActivities.remove(this); configChangeFlags = 0; deferRelaunchUntilPaused = false; preserveWindowOnDeferredRelaunch = false; }
void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { // Complete the pausing process of a pausing activity, so it doesn't make sense to // operate on non-leaf tasks. warnForNonLeafTask("completePauseLocked"); ActivityRecord prev = mPausingActivity; ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev); if (prev != null) { prev.setWillCloseOrEnterPip(false); final boolean wasStopping = prev.isState(STOPPING); prev.setState(PAUSED, "completePausedLocked"); ......
4. setState STOPPING
ActivityRecord completeFinishing(boolean updateVisibility, String reason) { if (!finishing || isState(RESUMED)) { throw new IllegalArgumentException( "Activity must be finishing and not resumed to complete, r=" + this + ", finishing=" + finishing + ", state=" + mState); } if (isState(PAUSING)) { // Activity is marked as finishing and will be processed once it completes. return this; } final boolean isCurrentVisible = mVisibleRequested || isState(PAUSED, STARTED); if (updateVisibility && isCurrentVisible) { boolean ensureVisibility = false; if (occludesParent(true /* includingFinishing */)) { // If the current activity is not opaque, we need to make sure the visibilities of activities be updated, they may be seen by users. ensureVisibility = true; } else if (mTaskSupervisor.getKeyguardController().isKeyguardLocked() && mTaskSupervisor.getKeyguardController().topActivityOccludesKeyguard(this)) { // Ensure activity visibilities and update lockscreen occluded/dismiss state when finishing the top activity that occluded keyguard. So that, the ActivityStack#mTopActivityOccludesKeyguard can be updated and the activity below won't be resumed. ensureVisibility = true; } if (ensureVisibility) { mDisplayContent.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, false /* preserveWindows */, true /* notifyClients */); } } boolean activityRemoved = false; // If this activity is currently visible, and the resumed activity is not yet visible, then hold off on finishing until the resumed one becomes visible. The activity that we are finishing may be over the lock screen. In this case, we do not want to consider activities that cannot be shown on the lock screen as running and should proceed with finishing the activity if there is no valid next top running activity. Note that if this finishing activity is floating task, we don't need to wait the next activity resume and can destroy it directly. // TODO(b/137329632): find the next activity directly underneath this one, not just anywhere final ActivityRecord next = getDisplayArea().topRunningActivity( true /* considerKeyguardState */); // isNextNotYetVisible is to check if the next activity is invisible, or it has been requested to be invisible but its windows haven't reported as invisible. If so, it implied that the current finishing activity should be added into stopping list rather than destroy immediately. final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.mVisibleRequested); // Clear last paused activity to ensure top activity can be resumed during sleeping. if (isNextNotYetVisible && mDisplayContent.isSleeping() && next == next.getRootTask().mLastPausedActivity) { next.getRootTask().mLastPausedActivity = null; } if (isCurrentVisible) { if (isNextNotYetVisible) { // Add this activity to the list of stopping activities. It will be processed and destroyed when the next activity reports idle. addToStopping(false /* scheduleIdle */, false /* idleDelayed */, "completeFinishing"); setState(STOPPING, "completeFinishing"); } else if (addToFinishingAndWaitForIdle()) { // We added this activity to the finishing list and something else is becoming resumed. The activity will complete finishing when the next activity reports idle. No need to do anything else here. } else { // Not waiting for the next one to become visible, and nothing else will be resumed in place of this activity - requesting destruction right away. activityRemoved = destroyIfPossible(reason); } } else { // Just need to make sure the next activities can be resumed (if needed) and is free to destroy this activity since it is currently not visible. addToFinishingAndWaitForIdle(); activityRemoved = destroyIfPossible(reason); } return activityRemoved ? null : this; }
void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { // Complete the pausing process of a pausing activity, so it doesn't make sense to operate on non-leaf tasks. warnForNonLeafTask("completePauseLocked"); ActivityRecord prev = mPausingActivity; ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev); if (prev != null) { prev.setWillCloseOrEnterPip(false); final boolean wasStopping = prev.isState(STOPPING); prev.setState(PAUSED, "completePausedLocked"); if (prev.finishing) { // We will update the activity visibility later, no need to do in // completeFinishing(). Updating visibility here might also making the next activities to be resumed, and could result in wrong app transition due to lack of previous activity information. ProtoLog.v(WM_DEBUG_STATES, "Executing finish of activity: %s", prev); prev = prev.completeFinishing(false /* updateVisibility */, "completePausedLocked"); } else if (prev.hasProcess()) { ProtoLog.v(WM_DEBUG_STATES, "Enqueue pending stop if needed: %s " + "wasStopping=%b visibleRequested=%b", prev, wasStopping, prev.mVisibleRequested); if (prev.deferRelaunchUntilPaused) { // Complete the deferred relaunch that was waiting for pause to complete. ProtoLog.v(WM_DEBUG_STATES, "Re-launching after pause: %s", prev); prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch); } else if (wasStopping) { // We are also stopping, the stop request must have gone soon after the pause. We can't clobber it, because the stop confirmation will not be handled.We don't need to schedule another stop, we only need to let it happen. prev.setState(STOPPING, "completePausedLocked"); } else if (!prev.mVisibleRequested || shouldSleepOrShutDownActivities()) {
void stopIfPossible() { if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this); final Task rootTask = getRootTask(); if (isNoHistory()) { if (!finishing) { if (!rootTask.shouldSleepActivities()) { ProtoLog.d(WM_DEBUG_STATES, "no-history finish of %s", this); if (finishIfPossible("stop-no-history", false /* oomAdj */) != FINISH_RESULT_CANCELLED) { resumeKeyDispatchingLocked(); return; } } else { ProtoLog.d(WM_DEBUG_STATES, "Not finishing noHistory %s on stop " + "because we're just sleeping", this); } } } if (!attachedToProcess()) { return; } resumeKeyDispatchingLocked(); try { stopped = false; ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPING: %s (stop requested)", this); setState(STOPPING, "stopIfPossible"); if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Stopping:" + this); } EventLogTags.writeWmStopActivity( mUserId, System.identityHashCode(this), shortComponentName); mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, StopActivityItem.obtain(configChangeFlags)); mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT); } catch (Exception e) {
// Maybe just ignore exceptions here... if the process has crashed, our death // notification will clean things up. Slog.w(TAG, "Exception thrown during pause", e); // Just in case, assume it to be stopped. stopped = true; ProtoLog.v(WM_DEBUG_STATES, "Stop failed; moving to STOPPED: %s", this); setState(STOPPED, "stopIfPossible"); if (deferRelaunchUntilPaused) { destroyImmediately("stop-except"); } }
4. setState STOPPED
有一个见3中最后一个
void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState, CharSequence description) { final boolean isStopping = mState == STOPPING; if (!isStopping && mState != RESTARTING_PROCESS) { Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this + " " + mState); removeStopTimeout(); return; } if (newPersistentState != null) { mPersistentState = newPersistentState; mAtmService.notifyTaskPersisterLocked(task, false); } if (newIcicle != null) { // If icicle is null, this is happening due to a timeout, so we haven't really saved the state. setSavedState(newIcicle); launchCount = 0; updateTaskDescription(description); } ProtoLog.i(WM_DEBUG_STATES, "Saving icicle of %s: %s", this, mIcicle); if (!stopped) { ProtoLog.v(WM_DEBUG_STATES, "Moving to STOPPED: %s (stop complete)", this); removeStopTimeout(); stopped = true; if (isStopping) { setState(STOPPED, "activityStoppedLocked"); } notifyAppStopped(); if (finishing) { abortAndClearOptionsAnimation(); } else { if (deferRelaunchUntilPaused) { destroyImmediately("stop-config"); mRootWindowContainer.resumeFocusedTasksTopActivities(); } else { mRootWindowContainer.updatePreviousProcess(this); } } mTaskSupervisor.checkReadyForSleepLocked(true /* allowDelay */); } }
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException {......
// TODO(lifecycler): Resume or pause requests are done as part of launch transaction, so updating the state should be done accordingly. if (andResume && readyToResume()) { // As part of the process of launching, ActivityThread also performs a resume. rootTask.minimalResumeActivityLocked(r); } else { // This activity is not starting in the resumed state... which should look like we asked it to pause+stop (but remain visible), and it has done so and reported back the current icicle and other state. ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s " + "(starting in paused state)", r); r.setState(PAUSED, "realStartActivityLocked"); mRootWindowContainer.executeAppTransitionForAllDisplay(); }
5. setState FINISHING
boolean destroyIfPossible(String reason) { setState(FINISHING, "destroyIfPossible"); ......boolean addToFinishingAndWaitForIdle() { ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending finish: %s", this); setState(FINISHING, "addToFinishingAndWaitForIdle"); ......
6. setState DESTROYING DESTROYED
boolean destroyImmediately(String reason) { if (DEBUG_SWITCH || DEBUG_CLEANUP) { Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this + ", app=" + (hasProcess() ? app.mName : "(null)")); } if (isState(DESTROYING, DESTROYED)) { ProtoLog.v(WM_DEBUG_STATES, "activity %s already destroying, skipping " + "request with reason:%s", this, reason); return false; } EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this), task.mTaskId, shortComponentName, reason); boolean removedFromHistory = false; cleanUp(false /* cleanServices */, false /* setState */); if (hasProcess()) { app.removeActivity(this, true /* keepAssociation */); if (!app.hasActivities()) { mAtmService.clearHeavyWeightProcessIfEquals(app); } boolean skipDestroy = false; try { if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this); mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, DestroyActivityItem.obtain(finishing, configChangeFlags)); } catch (Exception e) { // We can just ignore exceptions here... if the process has crashed, our death notification will clean things up. if (finishing) { removeFromHistory(reason + " exceptionInScheduleDestroy"); removedFromHistory = true; skipDestroy = true; } } nowVisible = false; // If the activity is finishing, we need to wait on removing it from the list to give it a chance to do its cleanup. During that time it may make calls back with its token so we need to be able to find it on the list and so we don't want to remove it from the list yet. Otherwise, we can just immediately put it in the destroyed state since we are not removing it from the list. if (finishing && !skipDestroy) { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYING: %s (destroy requested)", this); setState(DESTROYING, "destroyActivityLocked. finishing and not skipping destroy"); mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT); } else { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s " + "(destroy skipped)", this); setState(DESTROYED, "destroyActivityLocked. not finishing or skipping destroy"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this); detachFromProcess(); } } else { // Remove this record from the history. if (finishing) { removeFromHistory(reason + " hadNoApp"); removedFromHistory = true; } else { ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (no app)", this); setState(DESTROYED, "destroyActivityLocked. not finishing and had no app"); } } configChangeFlags = 0; return removedFromHistory; }
/** Note: call {@link #cleanUp(boolean, boolean)} before this method. */ void removeFromHistory(String reason) { finishActivityResults(Activity.RESULT_CANCELED,null /* resultData */, null /* resultGrants */); makeFinishingLocked(); ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Removing activity %s, reason= %s " + "callers=%s", this, reason, Debug.getCallers(5)); takeFromHistory(); removeTimeouts(); ProtoLog.v(WM_DEBUG_STATES, "Moving to DESTROYED: %s (removed from history)",this); setState(DESTROYED, "removeFromHistory"); if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this); detachFromProcess(); removeAppTokenFromDisplay(); cleanUpActivityServices(); removeUriPermissionsLocked(); }