Move activity finish methods to ActivityRecord

Methods dedicated to finishing activities in ActivityStack mostly
operate with internal ActivityRecord state and call ActivityRecord
methods, so it makes sense to move them there.

No change in functionality, only code being moved around.

Bug: 137329632
Test: Build and flash
Change-Id: Ic3555c3279a5e918925fc4bae3a4d2fa6b35fd74
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index cd72824..f1cd721 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1230,7 +1230,7 @@
                 final ActivityStack stack = mStacks.get(stackNdx);
                 // Always finish non-standard type stacks.
                 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
-                    stack.finishAllActivitiesLocked(true /* immediately */);
+                    stack.finishAllActivitiesImmediately();
                 } else {
                     // If default display is in split-window mode, set windowing mode of the stack
                     // to split-screen secondary. Otherwise, set the windowing mode to undefined by
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f0397df..26b1f7b 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -92,6 +92,8 @@
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
+import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
 
 import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
 import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
@@ -103,6 +105,7 @@
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
+import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
 import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
@@ -116,18 +119,29 @@
 import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
 import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
+import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -151,6 +165,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.Activity;
 import android.app.ActivityManager.TaskDescription;
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
@@ -194,6 +209,7 @@
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
 import android.service.voice.IVoiceInteractionSession;
+import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.MergedConfiguration;
@@ -215,11 +231,14 @@
 import com.android.server.AttributeCache;
 import com.android.server.AttributeCache.Entry;
 import com.android.server.am.AppTimeTracker;
+import com.android.server.am.EventLogTags;
 import com.android.server.am.PendingIntentRecord;
 import com.android.server.uri.UriPermissionOwner;
 import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
 import com.android.server.wm.ActivityStack.ActivityState;
 
+import com.google.android.collect.Sets;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -240,11 +259,16 @@
 final class ActivityRecord extends ConfigurationContainer {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
+    private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
+    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
+    private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
+    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
     private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
     private static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
+    private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
+    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
     private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
-    private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
 
     private static final String ATTR_ID = "id";
     private static final String TAG_INTENT = "intent";
@@ -1556,6 +1580,278 @@
         return true;
     }
 
+    /** Finish all activities in the task with the same affinity as this one. */
+    void finishActivityAffinity() {
+        final ArrayList<ActivityRecord> activities = getTaskRecord().mActivities;
+        for (int index = activities.indexOf(this); index >= 0; --index) {
+            final ActivityRecord cur = activities.get(index);
+            if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
+                break;
+            }
+            cur.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                    "request-affinity", true /* oomAdj */);
+        }
+    }
+
+    /**
+     * Sets the result for activity that started this one, clears the references to activities
+     * started for result from this one, and clears new intents.
+     */
+    void finishActivityResults(int resultCode, Intent resultData) {
+        // Send the result if needed
+        if (resultTo != null) {
+            if (DEBUG_RESULTS) {
+                Slog.v(TAG_RESULTS, "Adding result to " + resultTo
+                        + " who=" + resultWho + " req=" + requestCode
+                        + " res=" + resultCode + " data=" + resultData);
+            }
+            if (resultTo.mUserId != mUserId) {
+                if (resultData != null) {
+                    resultData.prepareToLeaveUser(mUserId);
+                }
+            }
+            if (info.applicationInfo.uid > 0) {
+                mAtmService.mUgmInternal.grantUriPermissionFromIntent(info.applicationInfo.uid,
+                        resultTo.packageName, resultData,
+                        resultTo.getUriPermissionsLocked(), resultTo.mUserId);
+            }
+            resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
+            resultTo = null;
+        } else if (DEBUG_RESULTS) {
+            Slog.v(TAG_RESULTS, "No result destination from " + this);
+        }
+
+        // Make sure this HistoryRecord is not holding on to other resources,
+        // because clients have remote IPC references to this object so we
+        // can't assume that will go away and want to avoid circular IPC refs.
+        results = null;
+        pendingResults = null;
+        newIntents = null;
+        setSavedState(null /* savedState */);
+    }
+
+    /**
+     * See {@link #finishActivityLocked(int, Intent, String, boolean, boolean)}
+     */
+    boolean finishActivityLocked(int resultCode, Intent resultData, String reason, boolean oomAdj) {
+        return finishActivityLocked(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.
+     */
+    boolean finishActivityLocked(int resultCode, Intent resultData, String reason, boolean oomAdj,
+            boolean pauseImmediately) {
+        if (finishing) {
+            Slog.w(TAG, "Duplicate finish request for " + this);
+            return false;
+        }
+
+        mAtmService.mWindowManager.deferSurfaceLayout();
+        try {
+            makeFinishingLocked();
+            final TaskRecord task = getTaskRecord();
+            EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
+                    mUserId, System.identityHashCode(this),
+                    task.taskId, shortComponentName, reason);
+            final ArrayList<ActivityRecord> activities = task.mActivities;
+            final int index = activities.indexOf(this);
+            if (index < (activities.size() - 1)) {
+                if ((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.
+                    final ActivityRecord next = activities.get(index + 1);
+                    next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+                }
+            }
+
+            pauseKeyDispatchingLocked();
+
+            final ActivityStack stack = getActivityStack();
+            stack.adjustFocusedActivityStack(this, "finishActivity");
+
+            finishActivityResults(resultCode, resultData);
+
+            final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
+            final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
+            if (stack.getResumedActivity() == this) {
+                if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
+                    Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
+                }
+                if (endTask) {
+                    mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
+                            task.getTaskInfo());
+                }
+                getDisplay().mDisplayContent.prepareAppTransition(transit, false);
+
+                // When finishing the activity preemptively take the snapshot before the app window
+                // is marked as hidden and any configuration changes take place
+                if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
+                    final ArraySet<Task> tasks = Sets.newArraySet(task.mTask);
+                    mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
+                    mAtmService.mWindowManager.mTaskSnapshotController
+                            .addSkipClosingAppSnapshotTasks(tasks);
+                }
+
+                // Tell window manager to prepare for this one to be removed.
+                setVisibility(false);
+
+                if (stack.mPausingActivity == null) {
+                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + this);
+                    if (DEBUG_USER_LEAVING) {
+                        Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
+                    }
+                    stack.startPausingLocked(false, false, null, pauseImmediately);
+                }
+
+                if (endTask) {
+                    mAtmService.getLockTaskController().clearLockedTask(task);
+                }
+            } else if (!isState(PAUSING)) {
+                // 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: " + this);
+                if (visible) {
+                    prepareActivityHideTransitionAnimation(transit);
+                }
+
+                final int finishMode = (visible || nowVisible) ? FINISH_AFTER_VISIBLE
+                        : FINISH_AFTER_PAUSE;
+                final boolean removedActivity = finishCurrentActivityLocked(finishMode, oomAdj,
+                        "finishActivityLocked") == null;
+
+                // 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 activity 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;
+                        }
+                        taskOverlay.prepareActivityHideTransitionAnimation(transit);
+                    }
+                }
+                return removedActivity;
+            } else {
+                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
+            }
+
+            return false;
+        } finally {
+            mAtmService.mWindowManager.continueSurfaceLayout();
+        }
+    }
+
+    private void prepareActivityHideTransitionAnimation(int transit) {
+        final DisplayContent dc = getDisplay().mDisplayContent;
+        dc.prepareAppTransition(transit, false);
+        setVisibility(false);
+        dc.executeAppTransition();
+    }
+
+    static final int FINISH_IMMEDIATELY = 0;
+    private static final int FINISH_AFTER_PAUSE = 1;
+    static final int FINISH_AFTER_VISIBLE = 2;
+
+    ActivityRecord finishCurrentActivityLocked(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.
+        // Note that if this finishing activity is floating task, we don't need to wait the
+        // next activity resume and can destroy it directly.
+        final ActivityStack stack = getActivityStack();
+        final ActivityDisplay display = getDisplay();
+        final ActivityRecord next = display.topRunningActivity(true /* considerKeyguardState */);
+        final boolean isFloating = getConfiguration().windowConfiguration.tasksAreFloating();
+
+        if (mode == FINISH_AFTER_VISIBLE && (visible || nowVisible)
+                && next != null && !next.nowVisible && !isFloating) {
+            if (!mStackSupervisor.mStoppingActivities.contains(this)) {
+                stack.addToStopping(this, false /* scheduleIdle */, false /* idleDelayed */,
+                        "finishCurrentActivityLocked");
+            }
+            if (DEBUG_STATES) {
+                Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (finish requested)");
+            }
+            setState(STOPPING, "finishCurrentActivityLocked");
+            if (oomAdj) {
+                mAtmService.updateOomAdj();
+            }
+            return this;
+        }
+
+        // make sure the record is cleaned out of other places.
+        mStackSupervisor.mStoppingActivities.remove(this);
+        mStackSupervisor.mGoingToSleepActivities.remove(this);
+        final ActivityState prevState = getState();
+        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + this);
+
+        setState(FINISHING, "finishCurrentActivityLocked");
+
+        // Don't destroy activity immediately if the display contains home stack, although there is
+        // no next activity at the moment but another home activity should be started later. Keep
+        // this activity alive until next home activity is resumed then user won't see a temporary
+        // black screen.
+        final boolean noRunningStack = next == null && display.topRunningActivity() == null
+                && display.getHomeStack() == null;
+        final boolean noFocusedStack = stack != display.getFocusedStack();
+        final boolean finishingInNonFocusedStackOrNoRunning = mode == FINISH_AFTER_VISIBLE
+                && prevState == PAUSED && (noFocusedStack || noRunningStack);
+
+        if (mode == FINISH_IMMEDIATELY
+                || (prevState == PAUSED && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
+                || finishingInNonFocusedStackOrNoRunning
+                || prevState == STARTED
+                || prevState == STOPPING
+                || prevState == STOPPED
+                || prevState == ActivityState.INITIALIZING) {
+            makeFinishingLocked();
+            boolean activityRemoved = stack.destroyActivityLocked(this, true /* removeFromApp */,
+                    "finish-imm:" + reason);
+
+            if (finishingInNonFocusedStackOrNoRunning) {
+                // Finishing activity that was in paused state and it was in not currently focused
+                // stack, need to make something visible in its place. Also if the display does not
+                // have running activity, the configuration may need to be updated for restoring
+                // original orientation of the display.
+                mRootActivityContainer.ensureVisibilityAndConfig(next, getDisplayId(),
+                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
+            }
+            if (activityRemoved) {
+                mRootActivityContainer.resumeFocusedStacksTopActivities();
+            }
+            if (DEBUG_CONTAINERS) {
+                Slog.d(TAG_CONTAINERS, "destroyActivityLocked: finishCurrentActivityLocked r="
+                        + this + " destroy returned removed=" + activityRemoved);
+            }
+            return activityRemoved ? null : this;
+        }
+
+        // Need to go through the full pause cycle to get this
+        // activity into the stopped state and then finish it.
+        if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + this);
+        mStackSupervisor.mFinishingActivities.add(this);
+        resumeKeyDispatchingLocked();
+        mRootActivityContainer.resumeFocusedStacksTopActivities();
+        // If activity was not paused at this point - explicitly pause it to start finishing
+        // process. Finishing will be completed once it reports pause back.
+        if (isState(RESUMED) && stack.mPausingActivity != null) {
+            stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
+                    next /* resuming */, false /* dontWait */);
+        }
+        return this;
+    }
+
     void makeFinishingLocked() {
         if (finishing) {
             return;
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index ccc2dfe..81d8fa9 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -56,9 +56,10 @@
 import static com.android.server.am.ActivityStackProto.TASKS;
 import static com.android.server.wm.ActivityDisplay.POSITION_BOTTOM;
 import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
+import static com.android.server.wm.ActivityRecord.FINISH_AFTER_VISIBLE;
+import static com.android.server.wm.ActivityRecord.FINISH_IMMEDIATELY;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
@@ -92,7 +93,6 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
@@ -164,8 +164,6 @@
 import com.android.server.am.EventLogTags;
 import com.android.server.am.PendingIntentRecord;
 
-import com.google.android.collect.Sets;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
@@ -186,7 +184,6 @@
     private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
     private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
     private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
-    private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
     private static final String TAG_STACK = TAG + POSTFIX_STACK;
     private static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
@@ -1779,7 +1776,7 @@
                     if (r.finishing) {
                         if (DEBUG_PAUSE) Slog.v(TAG,
                                 "Executing finish of failed to pause activity: " + r);
-                        finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false,
+                        r.finishCurrentActivityLocked(FINISH_AFTER_VISIBLE, false,
                                 "activityPausedLocked");
                     }
                 }
@@ -1798,7 +1795,7 @@
             prev.setState(PAUSED, "completePausedLocked");
             if (prev.finishing) {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
-                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
+                prev = prev.finishCurrentActivityLocked(FINISH_AFTER_VISIBLE, false /* oomAdj */,
                         "completePausedLocked");
             } else if (prev.hasProcess()) {
                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
@@ -3454,8 +3451,8 @@
                     }
                     if (DEBUG_TASKS) Slog.w(TAG_TASKS,
                             "resetTaskIntendedTask: calling finishActivity on " + p);
-                    if (finishActivityLocked(
-                            p, Activity.RESULT_CANCELED, null, "reset-task", false)) {
+                    if (p.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                            "reset-task", false /* oomAdj */)) {
                         end--;
                         srcPos--;
                     }
@@ -3539,8 +3536,8 @@
                         if (p.finishing) {
                             continue;
                         }
-                        finishActivityLocked(
-                                p, Activity.RESULT_CANCELED, null, "move-affinity", false);
+                        p.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                                "move-affinity", false /* oomAdj */);
                     }
                 } else {
                     if (taskInsertionPoint < 0) {
@@ -3569,13 +3566,13 @@
                     // instance of the same activity?  Then we drop the instance
                     // below so it remains singleTop.
                     if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
-                        ArrayList<ActivityRecord> taskActivities = task.mActivities;
-                        int targetNdx = taskActivities.indexOf(target);
+                        final ArrayList<ActivityRecord> taskActivities = task.mActivities;
+                        final int targetNdx = taskActivities.indexOf(target);
                         if (targetNdx > 0) {
-                            ActivityRecord p = taskActivities.get(targetNdx - 1);
+                            final ActivityRecord p = taskActivities.get(targetNdx - 1);
                             if (p.intent.getComponent().equals(target.intent.getComponent())) {
-                                finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
-                                        false);
+                                p.finishActivityLocked(Activity.RESULT_CANCELED,
+                                        null /* resultData */, "replace", false /* oomAdj */);
                             }
                         }
                     }
@@ -3678,7 +3675,7 @@
         return false;
     }
 
-    private void adjustFocusedActivityStack(ActivityRecord r, String reason) {
+    void adjustFocusedActivityStack(ActivityRecord r, String reason) {
         if (!mRootActivityContainer.isTopDisplayFocusedStack(this) ||
                 ((mResumedActivity != r) && (mResumedActivity != null))) {
             return;
@@ -3830,7 +3827,7 @@
             return false;
         }
 
-        finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
+        r.finishActivityLocked(resultCode, resultData, reason, oomAdj);
         return true;
     }
 
@@ -3842,8 +3839,8 @@
                 if (r.resultTo == self && r.requestCode == requestCode) {
                     if ((r.resultWho == null && resultWho == null) ||
                         (r.resultWho != null && r.resultWho.equals(resultWho))) {
-                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub",
-                                false);
+                        r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                                "request-sub", false /* oomAdj */);
                     }
                 }
             }
@@ -3873,7 +3870,8 @@
         int activityNdx = task.mActivities.indexOf(r);
         getDisplay().mDisplayContent.prepareAppTransition(
                 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
-        finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
+        r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */, reason,
+                false /* oomAdj */);
         finishedTask = task;
         // Also terminate any activities below it that aren't yet
         // stopped, to avoid a situation where one will get
@@ -3894,7 +3892,8 @@
                 if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
                     Slog.w(TAG, "  Force finishing activity "
                             + r.intent.getComponent().flattenToShortString());
-                    finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
+                    r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */, reason,
+                            false /* oomAdj */);
                 }
             }
         }
@@ -3910,8 +3909,8 @@
                 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
                     ActivityRecord r = tr.mActivities.get(activityNdx);
                     if (!r.finishing) {
-                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice",
-                                false);
+                        r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                                "finish-voice", false /* oomAdj */);
                         didOne = true;
                     }
                 }
@@ -3940,279 +3939,17 @@
         }
     }
 
-    final boolean finishActivityAffinityLocked(ActivityRecord r) {
-        ArrayList<ActivityRecord> activities = r.getTaskRecord().mActivities;
-        for (int index = activities.indexOf(r); index >= 0; --index) {
-            ActivityRecord cur = activities.get(index);
-            if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
-                break;
-            }
-            finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
-        }
-        return true;
-    }
-
-    private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
-        // send the result
-        ActivityRecord resultTo = r.resultTo;
-        if (resultTo != null) {
-            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo
-                    + " who=" + r.resultWho + " req=" + r.requestCode
-                    + " res=" + resultCode + " data=" + resultData);
-            if (resultTo.mUserId != r.mUserId) {
-                if (resultData != null) {
-                    resultData.prepareToLeaveUser(r.mUserId);
-                }
-            }
-            if (r.info.applicationInfo.uid > 0) {
-                mService.mUgmInternal.grantUriPermissionFromIntent(r.info.applicationInfo.uid,
-                        resultTo.packageName, resultData,
-                        resultTo.getUriPermissionsLocked(), resultTo.mUserId);
-            }
-            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData);
-            r.resultTo = null;
-        }
-        else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
-
-        // Make sure this HistoryRecord is not holding on to other resources,
-        // because clients have remote IPC references to this object so we
-        // can't assume that will go away and want to avoid circular IPC refs.
-        r.results = null;
-        r.pendingResults = null;
-        r.newIntents = null;
-        r.setSavedState(null /* savedState */);
-    }
-
-    /**
-     * 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();
-            final TaskRecord task = r.getTaskRecord();
-            EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
-                    r.mUserId, System.identityHashCode(r),
-                    task.taskId, r.shortComponentName, reason);
-            final ArrayList<ActivityRecord> activities = task.mActivities;
-            final int index = activities.indexOf(r);
-            if (index < (activities.size() - 1)) {
-                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");
-
-            finishActivityResultsLocked(r, resultCode, resultData);
-
-            final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
-            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.getTaskChangeNotificationController().notifyTaskRemovalStarted(
-                            task.getTaskInfo());
-                }
-                getDisplay().mDisplayContent.prepareAppTransition(transit, false);
-
-                // When finishing the activity pre-emptively take the snapshot before the app window
-                // is marked as hidden and any configuration changes take place
-                if (mWindowManager.mTaskSnapshotController != null) {
-                    final ArraySet<Task> tasks = Sets.newArraySet(task.mTask);
-                    mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
-                    mWindowManager.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(tasks);
-                }
-
-                // 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);
-                }
-
-                if (endTask) {
-                    mService.getLockTaskController().clearLockedTask(task);
-                }
-            } else if (!r.isState(PAUSING)) {
-                // 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;
-
-                // 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();
-        }
-    }
-
-    private void prepareActivityHideTransitionAnimation(ActivityRecord r, int transit) {
-        final DisplayContent dc = getDisplay().mDisplayContent;
-        dc.prepareAppTransition(transit, false);
-        r.setVisibility(false);
-        dc.executeAppTransition();
-    }
-
-    static final int FINISH_IMMEDIATELY = 0;
-    static final int FINISH_AFTER_PAUSE = 1;
-    static final int FINISH_AFTER_VISIBLE = 2;
-
-    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.
-        // Note that if this finishing activity is floating task, we don't need to wait the
-        // next activity resume and can destroy it directly.
-        final ActivityDisplay display = getDisplay();
-        final ActivityRecord next = display.topRunningActivity(true /* considerKeyguardState */);
-        final boolean isFloating = r.getConfiguration().windowConfiguration.tasksAreFloating();
-
-        if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
-                && next != null && !next.nowVisible && !isFloating) {
-            if (!mStackSupervisor.mStoppingActivities.contains(r)) {
-                addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */,
-                        "finishCurrentActivityLocked");
-            }
-            if (DEBUG_STATES) Slog.v(TAG_STATES,
-                    "Moving to STOPPING: "+ r + " (finish requested)");
-            r.setState(STOPPING, "finishCurrentActivityLocked");
-            if (oomAdj) {
-                mService.updateOomAdj();
-            }
-            return r;
-        }
-
-        // make sure the record is cleaned out of other places.
-        mStackSupervisor.mStoppingActivities.remove(r);
-        mStackSupervisor.mGoingToSleepActivities.remove(r);
-        final ActivityState prevState = r.getState();
-        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
-
-        r.setState(FINISHING, "finishCurrentActivityLocked");
-
-        // Don't destroy activity immediately if the display contains home stack, although there is
-        // no next activity at the moment but another home activity should be started later. Keep
-        // this activity alive until next home activity is resumed then user won't see a temporary
-        // black screen.
-        final boolean noRunningStack = next == null && display.topRunningActivity() == null
-                && display.getHomeStack() == null;
-        final boolean noFocusedStack = r.getActivityStack() != display.getFocusedStack();
-        final boolean finishingInNonFocusedStackOrNoRunning = mode == FINISH_AFTER_VISIBLE
-                && prevState == PAUSED && (noFocusedStack || noRunningStack);
-
-        if (mode == FINISH_IMMEDIATELY
-                || (prevState == PAUSED
-                    && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
-                || finishingInNonFocusedStackOrNoRunning
-                || prevState == STARTED
-                || prevState == STOPPING
-                || prevState == STOPPED
-                || prevState == ActivityState.INITIALIZING) {
-            r.makeFinishingLocked();
-            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
-
-            if (finishingInNonFocusedStackOrNoRunning) {
-                // Finishing activity that was in paused state and it was in not currently focused
-                // stack, need to make something visible in its place. Also if the display does not
-                // have running activity, the configuration may need to be updated for restoring
-                // original orientation of the display.
-                mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId,
-                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
-            }
-            if (activityRemoved) {
-                mRootActivityContainer.resumeFocusedStacksTopActivities();
-            }
-            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.
-        if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r);
-        mStackSupervisor.mFinishingActivities.add(r);
-        r.resumeKeyDispatchingLocked();
-        mRootActivityContainer.resumeFocusedStacksTopActivities();
-        // If activity was not paused at this point - explicitly pause it to start finishing
-        // process. Finishing will be completed once it reports pause back.
-        if (r.isState(RESUMED) && mPausingActivity != null) {
-            startPausingLocked(false /* userLeaving */, false /* uiSleeping */, next /* resuming */,
-                    false /* dontWait */);
-        }
-        return r;
-    }
-
-    void finishAllActivitiesLocked(boolean immediately) {
+    /** Finish all activities in the stack without waiting. */
+    void finishAllActivitiesImmediately() {
         boolean noActivitiesInStack = true;
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 final ActivityRecord r = activities.get(activityNdx);
                 noActivitiesInStack = false;
-                if (r.finishing && !immediately) {
-                    continue;
-                }
-                Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately");
-                finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
-                        "finishAllActivitiesLocked");
+                Slog.d(TAG, "finishAllActivitiesImmediatelyLocked: finishing " + r);
+                r.finishCurrentActivityLocked(FINISH_IMMEDIATELY, false /* oomAdj */,
+                        "finishAllActivitiesImmediatelyLocked");
             }
         }
         if (noActivitiesInStack) {
@@ -4439,7 +4176,7 @@
     }
 
     private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
-        finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
+        r.finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
         r.makeFinishingLocked();
         if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
                 "Removing activity " + r + " from stack callers=" + Debug.getCallers(5));
@@ -5177,7 +4914,7 @@
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
                 final ActivityRecord r = activities.get(activityNdx);
                 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
-                    finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true);
+                    r.finishActivityLocked(Activity.RESULT_CANCELED, null, "close-sys", true);
                 }
             }
         }
@@ -5221,8 +4958,7 @@
                     didSomething = true;
                     Slog.i(TAG, "  Force finishing activity " + r);
                     lastTask = r.getTaskRecord();
-                    finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
-                            true);
+                    r.finishActivityLocked(Activity.RESULT_CANCELED, null, "force-stop", true);
                 }
             }
         }
@@ -5276,7 +5012,7 @@
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
             int activityTop = activities.size() - 1;
             if (activityTop >= 0) {
-                finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
+                activities.get(activityTop).finishActivityLocked(Activity.RESULT_CANCELED, null,
                         "unhandled-back", true);
             }
         }
@@ -5313,7 +5049,7 @@
                     r.app = null;
                     getDisplay().mDisplayContent.prepareAppTransition(
                             TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
-                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
+                    r.finishCurrentActivityLocked(FINISH_IMMEDIATELY, false /* oomAdj */,
                             "handleAppCrashedLocked");
                 }
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 1314bfd..038f8e9 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1340,8 +1340,8 @@
             final ActivityStack stack = r.getActivityStack();
             if (stack != null) {
                 if (r.finishing) {
-                    stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
-                            "activityIdleInternalLocked");
+                    r.finishCurrentActivityLocked(ActivityRecord.FINISH_IMMEDIATELY,
+                            false /* oomAdj */, "activityIdleInternalLocked");
                 } else {
                     stack.stopActivityLocked(r);
                 }
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 0a8f870..a334ed8 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1416,7 +1416,7 @@
                 // performing operations without a window container.
                 final ActivityStack stack = mStartActivity.getActivityStack();
                 if (stack != null) {
-                    stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
+                    mStartActivity.finishActivityLocked(RESULT_CANCELED,
                             null /* intentResultData */, "startActivity", true /* oomAdj */);
                 }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c37ced5..03af388 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1646,7 +1646,8 @@
                 if (getLockTaskController().activityBlockedFromFinish(r)) {
                     return false;
                 }
-                return task.getStack().finishActivityAffinityLocked(r);
+                r.finishActivityAffinity();
+                return true;
             } finally {
                 Binder.restoreCallingIdentity(origId);
             }
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index d1c0c07..23515d8 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -1418,8 +1418,8 @@
                 mActivities.remove(activityNdx);
                 --activityNdx;
                 --numActivities;
-            } else if (mStack.finishActivityLocked(r, Activity.RESULT_CANCELED, null,
-                    reason, false, pauseImmediately)) {
+            } else if (r.finishActivityLocked(Activity.RESULT_CANCELED, null,
+                    reason, false /* oomAdj */, pauseImmediately)) {
                 --activityNdx;
                 --numActivities;
             }
@@ -1473,8 +1473,8 @@
                     if (opts != null) {
                         ret.updateOptionsLocked(opts);
                     }
-                    if (mStack != null && mStack.finishActivityLocked(
-                            r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
+                    if (r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                            "clear-task-stack", false /* oomAdj */)) {
                         --activityNdx;
                         --numActivities;
                     }
@@ -1487,10 +1487,8 @@
                         && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
                         && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
                     if (!ret.finishing) {
-                        if (mStack != null) {
-                            mStack.finishActivityLocked(
-                                    ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
-                        }
+                        ret.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                                "clear-task-top", false /* oomAdj */);
                         return null;
                     }
                 }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index e65712c..f74e2c0 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -629,8 +629,8 @@
         for (int i = 0; i < activities.size(); i++) {
             final ActivityRecord r = activities.get(i);
             if (!r.finishing && r.isInStackLocked()) {
-                r.getActivityStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
-                        null, "finish-heavy", true);
+                r.finishActivityLocked(Activity.RESULT_CANCELED, null /* resultData */,
+                        "finish-heavy", true /* oomAdj */);
             }
         }
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 0bf7446..e5278d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.Activity.RESULT_CANCELED;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -969,7 +970,7 @@
         homeStask.removeTask(homeTask, "testAdjustFocusedStack", REMOVE_TASK_MODE_DESTROYING);
 
         // Finish the only activity.
-        mStack.finishActivityLocked(topActivity, 0 /* resultCode */, null /* resultData */,
+        topActivity.finishActivityLocked(RESULT_CANCELED /* resultCode */, null /* resultData */,
                 "testAdjustFocusedStack", false /* oomAdj */);
         // Although home stack is empty, it should still be the focused stack.
         assertEquals(homeStask, mDefaultDisplay.getFocusedStack());
@@ -1014,7 +1015,7 @@
         assertNotNull(activity);
         activity.setState(PAUSED, "finishCurrentActivity");
         activity.makeFinishingLocked();
-        stack.finishCurrentActivityLocked(activity, ActivityStack.FINISH_AFTER_VISIBLE,
+        activity.finishCurrentActivityLocked(ActivityRecord.FINISH_AFTER_VISIBLE,
                 false /* oomAdj */, "finishCurrentActivity");
         return activity;
     }