前言
前面大致整理了startActivity的相关流程,下面整理下Activity finish相关的流程
Activity finish流程
Activity#finish
首先客户端调用finish方法,触发finish的流程
/**
* Finishes the current activity and specifies whether to remove the task associated with this
* activity.
*/
private void finish(int finishTask) {
if (mParent == null) {
int resultCode;
Intent resultData;
synchronized (this) {
resultCode = mResultCode;
resultData = mResultData;
}
if (false) Log.v(TAG, "Finishing self: token=" + mToken);
try {
if (resultData != null) {
resultData.prepareToLeaveProcess(this);
}
if (ActivityManager.getService()
.finishActivity(mToken, resultCode, resultData, finishTask)) {
mFinished = true;
}
} catch (RemoteException e) {
// Empty
}
} else {
mParent.finishFromChild(this);
}
// Activity was launched when user tapped a link in the Autofill Save UI - Save UI must
// be restored now.
if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE,
mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
}
}
ActivityManagerService#finishActivity
/**
* This is the internal entry point for handling Activity.finish().
*
* @param token The Binder token referencing the Activity we want to finish.
* @param resultCode Result code, if any, from this Activity.
* @param resultData Result data (Intent), if any, from this Activity.
* @param finishTask Whether to finish the task associated with this Activity.
*
* @return Returns true if the activity successfully finished, or false if it is still running.
*/
@Override
public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
int finishTask) {
// Refuse possible leaked file descriptors
if (resultData != null && resultData.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return true;
}
// Keep track of the root activity of the task before we finish it
TaskRecord tr = r.getTask();
ActivityRecord rootR = tr.getRootActivity();
if (rootR == null) {
Slog.w(TAG, "Finishing task with all activities already finished");
}
// Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
// finish.
if (mLockTaskController.activityBlockedFromFinish(r)) {
return false;
}
if (mController != null) {
// Find the first activity that is not finishing.
ActivityRecord next = r.getStack().topRunningActivityLocked(token, 0);
if (next != null) {
// ask watcher if this is allowed
boolean resumeOK = true;
try {
resumeOK = mController.activityResuming(next.packageName);
} catch (RemoteException e) {
mController = null;
Watchdog.getInstance().setActivityController(null);
}
if (!resumeOK) {
Slog.i(TAG, "Not finishing activity because controller resumed");
return false;
}
}
}
final long origId = Binder.clearCallingIdentity();
try {
boolean res;
final boolean finishWithRootActivity =
finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
|| (finishWithRootActivity && r == rootR)) { //这里是finishTask with Activity或者with root Activity
// If requested, remove the task that is associated to this activity only if it
// was the root activity in the task. The result code and data is ignored
// because we don't support returning them across task boundaries. Also, to
// keep backwards compatibility we remove the task from recents when finishing
// task with root activity.
res = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
finishWithRootActivity, "finish-activity"); //因为finish Activity导致的remove task
if (!res) {
Slog.i(TAG, "Removing task failed to finish activity");
}
} else {
res = tr.getStack().requestFinishActivityLocked(token, resultCode,
resultData, "app-request", true); //调用ActiviyStack的requestFinishActivityLocked
if (!res) {
Slog.i(TAG, "Failed to finish by app-request");
}
}
return res;
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
ActivityStack#requestFinishActivityLocked
3583 /**
3584 * @return Returns true if the activity is being finished, false if for
3585 * some reason it is being left as-is.
3586 */
3587 final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3588 Intent resultData, String reason, boolean oomAdj) {
3589 ActivityRecord r = isInStackLocked(token);
3590 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES,
3591 "Finishing activity token=" + token + " r="
3592 + ", result=" + resultCode + ", data=" + resultData
3593 + ", reason=" + reason);
3594 if (r == null) {
3595 return false;
3596 }
3597
3598 finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
3599 return true;
3600 }
ActivityStack#finishActivityLocked
/**
* See {@link #finishActivityLocked(ActivityRecord, int, Intent, String, boolean, boolean)}
*/
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
String reason, boolean oomAdj) {
return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY);
}
/**
* @return Returns true if this activity has been removed from the history
* list, or false if it is still in the list and will be removed later.
*/
final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
String reason, boolean oomAdj, boolean pauseImmediately) {
if (r.finishing) {
Slog.w(TAG, "Duplicate finish request for " + r);
return false;
}
mWindowManager.deferSurfaceLayout();
try {
r.makeFinishingLocked(); //将Ativity对应的finishing属性置为true
final TaskRecord task = r.getTask();
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
r.app != null ? r.app.pid : 0, System.identityHashCode(r),
task.taskId, r.shortComponentName, reason); //打印event log
final ArrayList<ActivityRecord> activities = task.mActivities;
final int index = activities.indexOf(r);
if (index < (activities.size() - 1)) { //如果要finish的Activity不是task顶部的Activity
task.setFrontOfTask();
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
// If the caller asked that this activity (and all above it)
// be cleared when the task is reset, don't lose that information,
// but propagate it up to the next activity.
ActivityRecord next = activities.get(index+1);
next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
}
}
r.pauseKeyDispatchingLocked();
adjustFocusedActivityStack(r, "finishActivity"); //调整focus activityStack(当前stack 调用topRunningActivityLocked为null,即当前stack中的所有task中的Activity没有正在running的,那么此Activity不能再做前台,要移到后面)
finishActivityResultsLocked(r, resultCode, resultData); //如果要finish的Activity有resultTo,向其传递result
final boolean endTask = index <= 0 && !task.isClearingToReuseTask(); //是否要销毁task(当要销毁的Activity在task中的index<=0)
final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
if (mResumedActivity == r) {
if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare close transition: finishing " + r);
if (endTask) {
mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
task.taskId);
}
mWindowManager.prepareAppTransition(transit, false);
// Tell window manager to prepare for this one to be removed.
r.setVisibility(false);
if (mPausingActivity == null) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"finish() => pause with userLeaving=false");
startPausingLocked(false, false, null, pauseImmediately); //调用startPausingLocked,finish之前需要先pause,注意resuming为null
}
if (endTask) {
mService.getLockTaskController().clearLockedTask(task);
}
} else if (!r.isState(PAUSING)) { //这种情况是finish的不是resumed Activity的情况
// If the activity is PAUSING, we will complete the finish once
// it is done pausing; else we can just directly finish it here.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
if (r.visible) {
prepareActivityHideTransitionAnimation(r, transit);
}
final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
: FINISH_AFTER_PAUSE;
final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj,
"finishActivityLocked") == null; //也是调用finishCurrentActivityLocked
// The following code is an optimization. When the last non-task overlay activity
// is removed from the task, we remove the entire task from the stack. However,
// since that is done after the scheduled destroy callback from the activity, that
// call to change the visibility of the task overlay activities would be out of
// sync with the activitiy visibility being set for this finishing activity above.
// In this case, we can set the visibility of all the task overlay activities when
// we detect the last one is finishing to keep them in sync.
if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
for (ActivityRecord taskOverlay : task.mActivities) {
if (!taskOverlay.mTaskOverlay) {
continue;
}
prepareActivityHideTransitionAnimation(taskOverlay, transit);
}
}
return removedActivity;
} else {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
}
return false;
} finally {
mWindowManager.continueSurfaceLayout();
}
}
ActivityStack#adjustFocusedActivityStack
private void adjustFocusedActivityStack(ActivityRecord r, String reason) {
if (!mStackSupervisor.isFocusedStack(this) ||
((mResumedActivity != r) && (mResumedActivity != null))) {
return;
}
final ActivityRecord next = topRunningActivityLocked();
final String myReason = reason + " adjustFocus";
if (next == r) {
mStackSupervisor.moveFocusableActivityStackToFrontLocked(
mStackSupervisor.topRunningActivityLocked(), myReason);
return;
}
if (next != null && isFocusable()) { //当stack中没有top running Activity的情况时才需要移动focus Activity Stack
// Keep focus in stack if we have a top running activity and are focusable.
return;
}
// Task is not guaranteed to be non-null. For example, destroying the
// {@link ActivityRecord} will disassociate the task from the activity.
final TaskRecord task = r.getTask();
if (task == null) {
throw new IllegalStateException("activity no longer associated with task:" + r);
}
// Move focus to next focusable stack if possible.
if (adjustFocusToNextFocusableStack(myReason)) { //将focus焦点移到下一个focusable stack上
return;
}
// Whatever...go home.
mStackSupervisor.moveHomeStackTaskToTop(myReason);
}
调用了startPausingLocked完成要finish的Activity的pause操作,此时其状态为PAUSING,然后
调用activityPaused,completePauseLocked这里逻辑(可能pause超时,也可能未超时,都会调用到completePauseLocked):
ActivityStack#completePauseLocked
private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
ActivityRecord prev = mPausingActivity;
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
if (prev != null) {
prev.setWillCloseOrEnterPip(false);
final boolean wasStopping = prev.isState(STOPPING);
prev.setState(PAUSED, "completePausedLocked"); //变为paused状态
if (prev.finishing) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
"completedPausedLocked"); //如果是在finish的流程中的话,会调用到这里
}
...
}
...
//调用完 finishCurrentActivityLocked之后,还需要接着调用completePauseLocked,保证finish Activity之后有一个新的resumed Activity
if (resumeNext) {
final ActivityStack topStack = mStackSupervisor.getFocusedStack();
if (!topStack.shouldSleepOrShutDownActivities()) {
mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
} else {
checkReadyForSleep();
ActivityRecord top = topStack.topRunningActivityLocked();
if (top == null || (prev != null && top != prev)) {
// If there are no more activities available to run, do resume anyway to start
// something. Also if the top activity on the stack is not the just paused
// activity, we need to go ahead and resume it to ensure we complete an
// in-flight app switch.
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
}
}
ActivityStack#finishCurrentActivityLocked
finish top Activity时,先将其通过addToStopping加入到mStackSupervisor.mStoppingActivities队列中,后续会再次调用activityIdleInternalLocked中再次调用finishCurrentActivityLocked,从而走到destroyActivityLocked中
final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj,
String reason) {
// First things first: 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.
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(
true /* considerKeyguardState */); //next = MainActivity
if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
&& next != null && !next.nowVisible) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) {
addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */); //调用到这里,将被finish的Activity放到mstoppingActivties中,发送IDLE_NOW_MSG消息
}
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to STOPPING: "+ r + " (finish requested)");
if (mActivityPluginDelegate != null && getWindowingMode() != WINDOWING_MODE_UNDEFINED) {
mActivityPluginDelegate.activitySuspendNotification
(r.appInfo.packageName, getWindowingMode() == WINDOWING_MODE_FULLSCREEN, false);
}
r.setState(STOPPING, "finishCurrentActivityLocked"); //finish Activity变为stopping模式
if (oomAdj) {
mService.updateOomAdjLocked();
}
return r;
}
// make sure the record is cleaned out of other places.
mStackSupervisor.mStoppingActivities.remove(r);
mStackSupervisor.mGoingToSleepActivities.remove(r);
mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
final ActivityState prevState = r.getState();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
if (mActivityPluginDelegate != null && getWindowingMode() != WINDOWING_MODE_UNDEFINED) {
mActivityPluginDelegate.activitySuspendNotification
(r.appInfo.packageName, getWindowingMode() == WINDOWING_MODE_FULLSCREEN, false);
}
r.setState(FINISHING, "finishCurrentActivityLocked");
final boolean finishingActivityInNonFocusedStack
= r.getStack() != mStackSupervisor.getFocusedStack()
&& prevState == PAUSED && mode == FINISH_AFTER_VISIBLE;
if (mode == FINISH_IMMEDIATELY
|| (prevState == PAUSED
&& (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
|| finishingActivityInNonFocusedStack
|| prevState == STOPPING
|| prevState == STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
if (finishingActivityInNonFocusedStack) {
// Finishing activity that was in paused state and it was in not currently focused
// stack, need to make something visible in its place.
mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (activityRemoved) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
"destroyActivityLocked: finishCurrentActivityLocked r=" + r +
" destroy returned removed=" + activityRemoved);
return activityRemoved ? null : r;
}
// Need to go through the full pause cycle to get this
// activity into the stopped state and then finish it.
//第三种情况,加入到mStackSupervisor.mFinishingActivities队列;看注释是先pause,stop再finish,走完整个流程
if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r);
mStackSupervisor.mFinishingActivities.add(r);
r.resumeKeyDispatchingLocked();
mStackSupervisor.resumeFocusedStackTopActivityLocked();
return r;
}
刚刚把要finish的Activity加入到mStopping队列中了,通过activityIdleInternalLocked处理(有3种调用可能,如当新resume的Activity不在idle状态时,addToStopping中发送的IDLE_NOW_MSG消息也可以调用activityIdleInternalLocked)
ActivityStackSupervisor#activityIdleInternalLocked
当resume Activity进程的ActviityThread处于idle状态调用activityIdleInternalLocked时,其参数token不为null;当AMS的ActviityManager线程执行消息时,token的值为null
2015 // Checked.
2016 @GuardedBy("mService")
2017 final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
2018 boolean processPausingActivities, Configuration config) {
2019 if (DEBUG_ALL) Slog.v(TAG, "Activity idle: " + token);
2020
2021 ArrayList<ActivityRecord> finishes = null;
2022 ArrayList<UserState> startingUsers = null;
2023 int NS = 0;
2024 int NF = 0;
2025 boolean booting = false;
2026 boolean activityRemoved = false;
2027
2028 ActivityRecord r = ActivityRecord.forTokenLocked(token);
2029 if (r != null) {
2030 if (DEBUG_IDLE) Slog.d(TAG_IDLE, "activityIdleInternalLocked: Callers="
2031 + Debug.getCallers(4));
2032 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2033 r.finishLaunchTickingLocked();
2034 if (fromTimeout) {
2035 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
2036 }
2037
2038 // This is a hack to semi-deal with a race condition
2039 // in the client where it can be constructed with a
2040 // newer configuration from when we asked it to launch.
2041 // We'll update with whatever configuration it now says
2042 // it used to launch.
2043 if (config != null) {
2044 r.setLastReportedGlobalConfiguration(config);
2045 }
2046
2047 // We are now idle. If someone is waiting for a thumbnail from
2048 // us, we can now deliver.
2049 r.idle = true;
2050
2051 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
2052 if (isFocusedStack(r.getStack()) || fromTimeout) {
2053 booting = checkFinishBootingLocked();
2054 }
2055 }
2056
2057 if (allResumedActivitiesIdle()) {
2058 if (r != null) {
2059 mService.scheduleAppGcsLocked();
2060 }
2061
2062 if (mLaunchingActivity.isHeld()) {
2063 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
2064 if (VALIDATE_WAKE_LOCK_CALLER &&
2065 Binder.getCallingUid() != Process.myUid()) {
2066 throw new IllegalStateException("Calling must be system uid");
2067 }
2068 mLaunchingActivity.release();
2069 }
2070 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
2071 }
2072
2073 // Atomically retrieve all of the other things to do.
2074 final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
2075 true /* remove */, processPausingActivities);
2076 NS = stops != null ? stops.size() : 0;
2077 if ((NF = mFinishingActivities.size()) > 0) {
2078 finishes = new ArrayList<>(mFinishingActivities);
2079 mFinishingActivities.clear();
2080 }
2081
2082 if (mStartingUsers.size() > 0) {
2083 startingUsers = new ArrayList<>(mStartingUsers);
2084 mStartingUsers.clear();
2085 }
2086
2087 // Stop any activities that are scheduled to do so but have been
2088 // waiting for the next one to start.
2089 for (int i = 0; i < NS; i++) {
2090 r = stops.get(i);
2091 final ActivityStack stack = r.getStack();
2092 if (stack != null) {
2093 if (r.finishing) {
2094 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
2095 "activityIdleInternalLocked"); //再次调用finishCurrentActivityLocked方法
2096 } else {
2097 stack.stopActivityLocked(r);
2098 }
2099 }
2100 }
2101
2102 // Finish any activities that are scheduled to do so but have been
2103 // waiting for the next one to start.
2104 for (int i = 0; i < NF; i++) {
2105 r = finishes.get(i);
2106 final ActivityStack stack = r.getStack();
2107 if (stack != null) {
2108 activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
2109 }
2110 }
2111
2112 if (!booting) {
2113 // Complete user switch
2114 if (startingUsers != null) {
2115 for (int i = 0; i < startingUsers.size(); i++) {
2116 mService.mUserController.finishUserSwitch(startingUsers.get(i));
2117 }
2118 }
2119 }
2120
2121 mService.trimApplications();
2122 //dump();
2123 //mWindowManager.dump();
2124
2125 if (activityRemoved) {
2126 resumeFocusedStackTopActivityLocked();
2127 }
2128
2129 return r;
2130 }
第二次调用finishCurrentActivityLocked时会走到
if (mode == FINISH_IMMEDIATELY //这个条件就已经满足了
|| (prevState == PAUSED
&& (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
|| finishingActivityInNonFocusedStack
|| prevState == STOPPING
|| prevState == STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
//调用destroyActivityLocked方法
if (finishingActivityInNonFocusedStack) {
// Finishing activity that was in paused state and it was in not currently focused
// stack, need to make something visible in its place.
mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (activityRemoved) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
"destroyActivityLocked: finishCurrentActivityLocked r=" + r +
" destroy returned removed=" + activityRemoved);
return activityRemoved ? null : r;
}
ActivityStack#destroyActivityLocked
/**
* Destroy the current CLIENT SIDE instance of an activity. This may be
* called both when actually finishing an activity, or when performing
* a configuration switch where we destroy the current client-side object
* but then create a new client-side object for this same HistoryRecord.
*/
final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH,
"Removing activity from " + reason + ": token=" + r
+ ", app=" + (r.app != null ? r.app.processName : "(null)"));
if (r.isState(DESTROYING, DESTROYED)) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying."
+ "skipping request with reason:" + reason);
return false;
}
EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
r.app != null ? r.app.pid : 0, System.identityHashCode(r),
r.getTask().taskId, r.shortComponentName, reason);
boolean removedFromHistory = false;
cleanUpActivityLocked(r, false, false); //第一次调用cleanServices = false; setState = false;
final boolean hadApp = r.app != null;
if (hadApp) {
if (removeFromApp) { //将activity从其依赖的进程中删除
r.app.activities.remove(r);
if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
mService.mHeavyWeightProcess = null;
mService.mHandler.sendEmptyMessage(
ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
}
if (r.app.activities.isEmpty()) {
// Update any services we are bound to that might care about whether
// their client may have activities.
mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
// No longer have activities, so update LRU list and oom adj.
mService.updateLruProcessLocked(r.app, false, null);
mService.updateOomAdjLocked(); //进程中的app的Activity空了,要重新调整进程优先级
}
}
boolean skipDestroy = false;
try {
if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)); //执行DestroyActivityItem的excute
} catch (Exception e) {
// We can just ignore exceptions here... if the process
// has crashed, our death notification will clean things
// up.
//Slog.w(TAG, "Exception thrown during finish", e);
if (r.finishing) {
removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy");
removedFromHistory = true;
skipDestroy = true;
}
}
r.nowVisible = false; //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 (r.finishing && !skipDestroy) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYING: " + r
+ " (destroy requested)");
r.setState(DESTROYING,
"destroyActivityLocked. finishing and not skipping destroy"); //将Activity的state属性设为destorying
Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT); //为activity设置超时处理操作
} else {
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to DESTROYED: " + r + " (destroy skipped)");
r.setState(DESTROYED,
"destroyActivityLocked. not finishing or skipping destroy");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r);
r.app = null;
}
} else {
// remove this record from the history.
if (r.finishing) {
resumeTopActivityInnerLocked(r, reason + " hadNoApp");
removedFromHistory = true;
} else {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (no app)");
r.setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r);
r.app = null;
}
}
r.configChangeFlags = 0;
if (!mLRUActivities.remove(r) && hadApp) {
Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
}
return removedFromHistory;
}
ActivityStack#cleanUpActivityLocked
Perform the common clean-up of an activity record 两种情况下可能调用 1. destroyActivityLocked 2. Activity宿主进程消失(被杀)
/**
* Perform the common clean-up of an activity record. This is called both
* as part of destroyActivityLocked() (when destroying the client-side
* representation) and cleaning things up as a result of its hosting
* processing going away, in which case there is no remaining client-side
* state to destroy so only the cleanup here is needed.
*
* Note: Call before #removeActivityFromHistoryLocked.
*/
private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
onActivityRemovedFromStack(r);
r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
if (setState) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)");
r.setState(DESTROYED, "cleanupActivityLocked");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
r.app = null;
}
// Inform supervisor the activity has been removed.
mStackSupervisor.cleanupActivity(r);
// Remove any pending results.
if (r.finishing && r.pendingResults != null) {
for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
PendingIntentRecord rec = apr.get();
if (rec != null) {
mService.cancelIntentSenderLocked(rec, false);
}
}
r.pendingResults = null;
}
if (cleanServices) {
cleanUpActivityServicesLocked(r);
}
// Get rid of any pending idle timeouts.
removeTimeoutsForActivityLocked(r);
// Clean-up activities are no longer relaunching (e.g. app process died). Notify window
// manager so it can update its bookkeeping.
mWindowManager.notifyAppRelaunchesCleared(r.appToken);
}
ActivityStack#onActivityRemovedFromStack
当Activity从stack移除前都要调用
/**
* Remove any state associated with the {@link ActivityRecord}. This should be called whenever
* an activity moves away from the stack.
*/
void onActivityRemovedFromStack(ActivityRecord r) {
removeTimeoutsForActivityLocked(r);
if (mResumedActivity != null && mResumedActivity == r) {
setResumedActivity(null, "onActivityRemovedFromStack");
}
if (mPausingActivity != null && mPausingActivity == r) {
mPausingActivity = null;
}
}
DestroyActivityItem#execute
public class DestroyActivityItem extends ActivityLifecycleItem {
private boolean mFinished;
private int mConfigChanges;
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
client.handleDestroyActivity(token, mFinished, mConfigChanges,
false /* getNonConfigInstance */, "DestroyActivityItem");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
ActivityThread#handleDestroyActivity
@Override
public void handleDestroyActivity(IBinder token, boolean finishing, int configChanges,
boolean getNonConfigInstance, String reason) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance, reason);
if (r != null) {
cleanUpPendingRemoveWindows(r, finishing);
WindowManager wm = r.activity.getWindowManager();
View v = r.activity.mDecor;
if (v != null) {
if (r.activity.mVisibleFromServer) {
mNumVisibleActivities--;
}
IBinder wtoken = v.getWindowToken();
if (r.activity.mWindowAdded) {
if (r.mPreserveWindow) {
// Hold off on removing this until the new activity's
// window is being added.
r.mPendingRemoveWindow = r.window;
r.mPendingRemoveWindowManager = wm;
// We can only keep the part of the view hierarchy that we control,
// everything else must be removed, because it might not be able to
// behave properly when activity is relaunching.
r.window.clearContentView();
} else {
wm.removeViewImmediate(v);
}
}
if (wtoken != null && r.mPendingRemoveWindow == null) {
WindowManagerGlobal.getInstance().closeAll(wtoken,
r.activity.getClass().getName(), "Activity");
} else if (r.mPendingRemoveWindow != null) {
// We're preserving only one window, others should be closed so app views
// will be detached before the final tear down. It should be done now because
// some components (e.g. WebView) rely on detach callbacks to perform receiver
// unregister and other cleanup.
WindowManagerGlobal.getInstance().closeAllExceptView(token, v,
r.activity.getClass().getName(), "Activity");
}
r.activity.mDecor = null;
}
if (r.mPendingRemoveWindow == null) {
// If we are delaying the removal of the activity window, then
// we can't clean up all windows here. Note that we can't do
// so later either, which means any windows that aren't closed
// by the app will leak. Well we try to warning them a lot
// about leaking windows, because that is a bug, so if they are
// using this recreate facility then they get to live with leaks.
WindowManagerGlobal.getInstance().closeAll(token,
r.activity.getClass().getName(), "Activity");
}
// Mocked out contexts won't be participating in the normal
// process lifecycle, but if we're running with a proper
// ApplicationContext we need to have it tear down things
// cleanly.
Context c = r.activity.getBaseContext();
if (c instanceof ContextImpl) {
((ContextImpl) c).scheduleFinalCleanup(
r.activity.getClass().getName(), "Activity");
}
}
if (finishing) {
try {
ActivityManager.getService().activityDestroyed(token); //调用AMS的activityDestroyed
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
mSomeActivitiesChanged = true;
}
注意,当下方的activity重新resume时,还有机会调用activityIdleInternalLocked操作,但此时似乎没什么作用
ActivityManagerService#activityDestroyed
8347 @Override
8348 public final void activityDestroyed(IBinder token) {
8349 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token);
8350 synchronized (this) {
8351 ActivityStack stack = ActivityRecord.getStackLocked(token);
8352 if (stack != null) {
8353 stack.activityDestroyedLocked(token, "activityDestroyed");
8354 }
8355 }
8356 }
ActivityStack#activityDestroyedLocked
4468 final void activityDestroyedLocked(IBinder token, String reason) {
4469 final long origId = Binder.clearCallingIdentity();
4470 try {
4471 activityDestroyedLocked(ActivityRecord.forTokenLocked(token), reason);
4472 } finally {
4473 Binder.restoreCallingIdentity(origId);
4474 }
4475 }
4477 /**
4478 * This method is to only be called from the client via binder when the activity is destroyed
4479 * AND finished.
4480 */
4481 final void activityDestroyedLocked(ActivityRecord record, String reason) {
4482 if (record != null) {
4483 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, record);
4484 }
4485
4486 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + record);
4487
4488 if (isInStackLocked(record) != null) {
4489 if (record.isState(DESTROYING, DESTROYED)) {
4490 cleanUpActivityLocked(record, true, false); //再次调用cleanUpActivityLocked;第二次调用cleanServices = true;setState = false
4491 removeActivityFromHistoryLocked(record, reason);
4492 }
4493 }
4494
4495 mStackSupervisor.resumeFocusedStackTopActivityLocked();
//还会在调用一次resumeFocusedStackTopActivityLocked
4496 }
此时,cleanUpActivityLocked->cleanUpActivityServicesLocked
ActivityStack#cleanUpActivityServicesLocked
/**
* Perform clean-up of service connections in an activity record.
*/
private void cleanUpActivityServicesLocked(ActivityRecord r) {
// Throw away any services that have been bound by this activity.
if (r.connections != null) {
Iterator<ConnectionRecord> it = r.connections.iterator();
while (it.hasNext()) {
ConnectionRecord c = it.next();
mService.mServices.removeConnectionLocked(c, null, r);
}
r.connections = null;
}
}
ActivityStack#removeActivityFromHistoryLocked
private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
r.makeFinishingLocked();
if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
"Removing activity " + r + " from stack callers=" + Debug.getCallers(5));
r.takeFromHistory();
removeTimeoutsForActivityLocked(r);
if (DEBUG_STATES) Slog.v(TAG_STATES,
"Moving to DESTROYED: " + r + " (removed from history)");
r.setState(DESTROYED, "removeActivityFromHistoryLocked"); //设为destoryed属性
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
r.app = null; //依赖app进程赋为空
r.removeWindowContainer(); //将ActivityRecord的mWindowContainerController置为true
final TaskRecord task = r.getTask();
final boolean lastActivity = task != null ? task.removeActivity(r) : false; //如果要finish的Activity是task的root Activity
// If we are removing the last activity in the task, not including task overlay activities,
// then fall through into the block below to remove the entire task itself
final boolean onlyHasTaskOverlays = task != null
? task.onlyHasTaskOverlayActivities(false /* excludingFinishing */) : false;
if (lastActivity || onlyHasTaskOverlays) {
if (DEBUG_STACK) {
Slog.i(TAG_STACK,
"removeActivityFromHistoryLocked: last activity removed from " + this
+ " onlyHasTaskOverlays=" + onlyHasTaskOverlays);
}
// The following block can be executed multiple times if there is more than one overlay.
// {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
// of the task by id and exiting early if not found.
if (onlyHasTaskOverlays) {
// When destroying a task, tell the supervisor to remove it so that any activity it
// has can be cleaned up correctly. This is currently the only place where we remove
// a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
// state into removeTask(), we just clear the task here before the other residual
// work.
// TODO: If the callers to removeTask() changes such that we have multiple places
// where we are destroying the task, move this back into removeTask()
mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
!REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason);
}
// We must keep the task around until all activities are destroyed. The following
// statement will only execute once since overlays are also considered activities.
if (lastActivity) { //如果是最后一个activity,调用removeTask
removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING);
}
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
}
ActivityRecord#takeFromHistory
void takeFromHistory() {
if (this.inHistory) {
this.inHistory = false;
if (this.task != null && !this.finishing) {
--this.task.numActivities;
}
this.clearOptionsLocked();
}
}
ActivityStack#removeTimeoutsForActivityLocked
void removeTimeoutsForActivityLocked(ActivityRecord r) {
mStackSupervisor.removeTimeoutsForActivityLocked(r);
mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
r.finishLaunchTickingLocked();
}
ActivityStack#removeTask
/**
* Removes the input task from this stack.
* @param task to remove.
* @param reason for removal.
* @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
* {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
*/
void removeTask(TaskRecord task, String reason, int mode) {
for (ActivityRecord record : task.mActivities) {
onActivityRemovedFromStack(record);
}
final boolean removed = mTaskHistory.remove(task); //从stack中的mTaskHistory中将task移除
if (removed) {
EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId());
}
removeActivitiesFromLRUListLocked(task);
updateTaskMovement(task, true);
if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
// TODO: VI what about activity?
final boolean isVoiceSession = task.voiceSession != null;
if (isVoiceSession) {
try {
task.voiceSession.taskFinished(task.intent, task.taskId);
} catch (RemoteException e) {
}
}
if (task.autoRemoveFromRecents() || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
mStackSupervisor.mRecentTasks.remove(task);
}
task.removeWindowContainer();
}
if (mTaskHistory.isEmpty()) { //当stack中没有了task时
if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
// We only need to adjust focused stack if this stack is in focus and we are not in the
// process of moving the task to the top of the stack that will be focused.
if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
&& mStackSupervisor.isFocusedStack(this)) {
String myReason = reason + " leftTaskHistoryEmpty";
if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) {
mStackSupervisor.moveHomeStackToFront(myReason);
}
}
if (isAttached()) {
getDisplay().positionChildAtBottom(this); //将stack放到display底部
}
if (!isActivityTypeHome()) {
remove();
}
}
task.setStack(null);
// Notify if a task from the pinned stack is being removed (or moved depending on the mode)
if (inPinnedWindowingMode()) {
mService.mTaskChangeNotificationController.notifyActivityUnpinned();
}
}
ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked() {
return resumeFocusedStackTopActivityLocked(null, null, null);
}
ActivityStackSupervisor#resumeFocusedStackTopActivityLocked
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (!readyToResume()) {
return false;
}
// if resume one non-fullscreen task, also resume the other one
boolean resumed = false;
if (targetStack != null && isFocusedStack(targetStack)) {
if (target != null && target.getState() == RESUMED && mNeedScheduleIdle) {
scheduleIdleLocked();
mNeedScheduleIdle = false;
if (target.getTask().inMultiWindowMode()) {
return false;
}
}
resumed = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
} else {
ActivityStack recentsStack = getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS);
if (mLaunchRecentsFromGesture && recentsStack != null && !mHasResumeRecentsBehind
&& !mStopLaunchRecentsBehind) {
recentsStack.resumeTopActivityUncheckedLocked(null, null);
} else {
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.getState() != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.getState() == RESUMED) {
//此时下一个top Activity应该已经处于resumed的状态,直接返回false即可
if (!r.getTask().inMultiWindowMode()) {
mFocusedStack.executeAppTransition(targetOptions);
}
if (mNeedScheduleIdle) {
scheduleIdleLocked();
mNeedScheduleIdle = false;
}
return false;
}
}
}
// resume non-fullscreen task
if (mFocusedStack.topTask() != null && mFocusedStack.topTask().inMultiWindowMode()
&& !mService.isSleepingOrShuttingDownLocked()) {
ActivityStack multiWindowStack = null;
if (mFocusedStack.inSplitScreenPrimaryWindowingMode()) {
multiWindowStack = mFocusedStack.getDisplay().getTopStackInWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
} else if (mFocusedStack.inSplitScreenSecondaryWindowingMode()) {
multiWindowStack = mFocusedStack.getDisplay().getTopStackInWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
}
if (multiWindowStack != null
&& multiWindowStack.shouldBeVisible(null)) {
final ActivityRecord r = multiWindowStack.topRunningActivityLocked();
if (r != null && r.getState() != RESUMED && r.getTask().inMultiWindowMode()) {
multiWindowStack.resumeTopActivityUncheckedLocked(null, null);
}
}
}
return resumed;
}