1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
20import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
21import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
22import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
25import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
26import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
27import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
28import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
29import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
30import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
31import static android.app.WindowConfiguration.activityTypeToString;
32import static android.app.WindowConfiguration.windowingModeToString;
33import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
34import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
35import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
36import static android.view.Display.DEFAULT_DISPLAY;
37import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
38import static android.view.Display.INVALID_DISPLAY;
39
40import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
41import static com.android.server.am.ActivityDisplay.POSITION_TOP;
42import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
43import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
44import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
45import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP;
46import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
47import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
48import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
49import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
50import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
51import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
52import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
53import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
54import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
55import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TRANSITION;
56import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
58import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
59import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_APP;
60import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
61import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS;
62import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
63import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
65import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
66import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
67import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
68import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
70import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TRANSITION;
71import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
72import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
73import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
74import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
75import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
76import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
77import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
78import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
79import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
80import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
81import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
82import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
83import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
84import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
85import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
86import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
87import static com.android.server.am.ActivityStackProto.BOUNDS;
88import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
89import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
90import static com.android.server.am.ActivityStackProto.FULLSCREEN;
91import static com.android.server.am.ActivityStackProto.ID;
92import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
93import static com.android.server.am.ActivityStackProto.TASKS;
94import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
95import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
96import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
97import static android.view.WindowManager.TRANSIT_NONE;
98import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
99import static android.view.WindowManager.TRANSIT_TASK_OPEN;
100import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
101import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
102import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
103
104import static java.lang.Integer.MAX_VALUE;
105
106import android.app.Activity;
107import android.app.ActivityManager;
108import android.app.ActivityOptions;
109import android.app.AppGlobals;
110import android.app.IActivityController;
111import android.app.ResultInfo;
112import android.app.WindowConfiguration.ActivityType;
113import android.app.WindowConfiguration.WindowingMode;
114import android.app.servertransaction.ActivityResultItem;
115import android.app.servertransaction.ClientTransaction;
116import android.app.servertransaction.NewIntentItem;
117import android.app.servertransaction.WindowVisibilityItem;
118import android.app.servertransaction.DestroyActivityItem;
119import android.app.servertransaction.PauseActivityItem;
120import android.app.servertransaction.ResumeActivityItem;
121import android.app.servertransaction.StopActivityItem;
122import android.content.ComponentName;
123import android.content.Intent;
124import android.content.pm.ActivityInfo;
125import android.content.pm.ApplicationInfo;
126import android.content.res.Configuration;
127import android.graphics.Rect;
128import android.net.Uri;
129import android.os.Binder;
130import android.os.Debug;
131import android.os.Handler;
132import android.os.IBinder;
133import android.os.Looper;
134import android.os.Message;
135import android.os.RemoteException;
136import android.os.SystemClock;
137import android.os.UserHandle;
138import android.service.voice.IVoiceInteractionSession;
139import android.util.ArraySet;
140import android.util.EventLog;
141import android.util.IntArray;
142import android.util.Log;
143import android.util.Slog;
144import android.util.SparseArray;
145import android.util.proto.ProtoOutputStream;
146import android.view.Display;
147
148import com.android.internal.annotations.GuardedBy;
149import com.android.internal.annotations.VisibleForTesting;
150import com.android.internal.app.IVoiceInteractor;
151import com.android.internal.os.BatteryStatsImpl;
152import com.android.server.Watchdog;
153import com.android.server.am.ActivityManagerService.ItemMatcher;
154import com.android.server.wm.ConfigurationContainer;
155import com.android.server.wm.StackWindowController;
156import com.android.server.wm.StackWindowListener;
157import com.android.server.wm.WindowManagerService;
158
159import java.io.FileDescriptor;
160import java.io.PrintWriter;
161import java.lang.ref.WeakReference;
162import java.util.ArrayList;
163import java.util.Iterator;
164import java.util.List;
165import java.util.Objects;
166import java.util.Set;
167
168/**
169 * State and management of a single stack of activities.
170 */
171class ActivityStack<T extends StackWindowController> extends ConfigurationContainer
172        implements StackWindowListener {
173    private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM;
174    private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
175    private static final String TAG_APP = TAG + POSTFIX_APP;
176    private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
177    private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
178    private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
179    private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
180    private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
181    private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
182    private static final String TAG_STACK = TAG + POSTFIX_STACK;
183    private static final String TAG_STATES = TAG + POSTFIX_STATES;
184    private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
185    private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
186    private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
187    private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
188    private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
189
190    // Ticks during which we check progress while waiting for an app to launch.
191    static final int LAUNCH_TICK = 500;
192
193    // How long we wait until giving up on the last activity to pause.  This
194    // is short because it directly impacts the responsiveness of starting the
195    // next activity.
196    private static final int PAUSE_TIMEOUT = 500;
197
198    // How long we wait for the activity to tell us it has stopped before
199    // giving up.  This is a good amount of time because we really need this
200    // from the application in order to get its saved state. Once the stop
201    // is complete we may start destroying client resources triggering
202    // crashes if the UI thread was hung. We put this timeout one second behind
203    // the ANR timeout so these situations will generate ANR instead of
204    // Surface lost or other errors.
205    private static final int STOP_TIMEOUT = 11 * 1000;
206
207    // How long we wait until giving up on an activity telling us it has
208    // finished destroying itself.
209    private static final int DESTROY_TIMEOUT = 10 * 1000;
210
211    // Set to false to disable the preview that is shown while a new activity
212    // is being started.
213    private static final boolean SHOW_APP_STARTING_PREVIEW = true;
214
215    // How long to wait for all background Activities to redraw following a call to
216    // convertToTranslucent().
217    private static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
218
219    // How many activities have to be scheduled to stop to force a stop pass.
220    private static final int MAX_STOPPING_TO_FORCE = 3;
221
222    @Override
223    protected int getChildCount() {
224        return mTaskHistory.size();
225    }
226
227    @Override
228    protected ConfigurationContainer getChildAt(int index) {
229        return mTaskHistory.get(index);
230    }
231
232    @Override
233    protected ConfigurationContainer getParent() {
234        return getDisplay();
235    }
236
237    @Override
238    protected void onParentChanged() {
239        super.onParentChanged();
240        mStackSupervisor.updateUIDsPresentOnDisplay();
241    }
242
243    enum ActivityState {
244        INITIALIZING,
245        RESUMED,
246        PAUSING,
247        PAUSED,
248        STOPPING,
249        STOPPED,
250        FINISHING,
251        DESTROYING,
252        DESTROYED
253    }
254
255    @VisibleForTesting
256    /* The various modes for the method {@link #removeTask}. */
257    // Task is being completely removed from all stacks in the system.
258    protected static final int REMOVE_TASK_MODE_DESTROYING = 0;
259    // Task is being removed from this stack so we can add it to another stack. In the case we are
260    // moving we don't want to perform some operations on the task like removing it from window
261    // manager or recents.
262    static final int REMOVE_TASK_MODE_MOVING = 1;
263    // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new
264    // stack and the new stack will be on top of all stacks.
265    static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
266
267    // The height/width divide used when fitting a task within a bounds with method
268    // {@link #fitWithinBounds}.
269    // We always want the task to to be visible in the bounds without affecting its size when
270    // fitting. To make sure this is the case, we don't adjust the task left or top side pass
271    // the input bounds right or bottom side minus the width or height divided by this value.
272    private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
273
274    final ActivityManagerService mService;
275    private final WindowManagerService mWindowManager;
276    T mWindowContainerController;
277
278    /**
279     * The back history of all previous (and possibly still
280     * running) activities.  It contains #TaskRecord objects.
281     */
282    private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
283
284    /**
285     * List of running activities, sorted by recent usage.
286     * The first entry in the list is the least recently used.
287     * It contains HistoryRecord objects.
288     */
289    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
290
291    /**
292     * When we are in the process of pausing an activity, before starting the
293     * next one, this variable holds the activity that is currently being paused.
294     */
295    ActivityRecord mPausingActivity = null;
296
297    /**
298     * This is the last activity that we put into the paused state.  This is
299     * used to determine if we need to do an activity transition while sleeping,
300     * when we normally hold the top activity paused.
301     */
302    ActivityRecord mLastPausedActivity = null;
303
304    /**
305     * Activities that specify No History must be removed once the user navigates away from them.
306     * If the device goes to sleep with such an activity in the paused state then we save it here
307     * and finish it later if another activity replaces it on wakeup.
308     */
309    ActivityRecord mLastNoHistoryActivity = null;
310
311    /**
312     * Current activity that is resumed, or null if there is none.
313     */
314    ActivityRecord mResumedActivity = null;
315
316    // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
317    // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
318    // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
319    // Activity in mTranslucentActivityWaiting is notified via
320    // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
321    // background activity being drawn then the same call will be made with a true value.
322    ActivityRecord mTranslucentActivityWaiting = null;
323    ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>();
324
325    /**
326     * Set when we know we are going to be calling updateConfiguration()
327     * soon, so want to skip intermediate config checks.
328     */
329    boolean mConfigWillChange;
330
331    /**
332     * When set, will force the stack to report as invisible.
333     */
334    boolean mForceHidden = false;
335
336    private boolean mUpdateBoundsDeferred;
337    private boolean mUpdateBoundsDeferredCalled;
338    private final Rect mDeferredBounds = new Rect();
339    private final Rect mDeferredTaskBounds = new Rect();
340    private final Rect mDeferredTaskInsetBounds = new Rect();
341
342    int mCurrentUser;
343
344    final int mStackId;
345    /** The attached Display's unique identifier, or -1 if detached */
346    int mDisplayId;
347
348    private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
349    private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
350    private final Rect mTmpRect2 = new Rect();
351    private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic();
352
353    /** List for processing through a set of activities */
354    private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
355
356    /** Run all ActivityStacks through this */
357    protected final ActivityStackSupervisor mStackSupervisor;
358
359    private boolean mTopActivityOccludesKeyguard;
360    private ActivityRecord mTopDismissingKeyguardActivity;
361
362    static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
363    static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
364    static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
365    static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
366    static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
367    static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
368
369    private static class ScheduleDestroyArgs {
370        final ProcessRecord mOwner;
371        final String mReason;
372        ScheduleDestroyArgs(ProcessRecord owner, String reason) {
373            mOwner = owner;
374            mReason = reason;
375        }
376    }
377
378    final Handler mHandler;
379
380    private class ActivityStackHandler extends Handler {
381
382        ActivityStackHandler(Looper looper) {
383            super(looper);
384        }
385
386        @Override
387        public void handleMessage(Message msg) {
388            switch (msg.what) {
389                case PAUSE_TIMEOUT_MSG: {
390                    ActivityRecord r = (ActivityRecord)msg.obj;
391                    // We don't at this point know if the activity is fullscreen,
392                    // so we need to be conservative and assume it isn't.
393                    Slog.w(TAG, "Activity pause timeout for " + r);
394                    synchronized (mService) {
395                        if (r.app != null) {
396                            mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
397                        }
398                        activityPausedLocked(r.appToken, true);
399                    }
400                } break;
401                case LAUNCH_TICK_MSG: {
402                    ActivityRecord r = (ActivityRecord)msg.obj;
403                    synchronized (mService) {
404                        if (r.continueLaunchTickingLocked()) {
405                            mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
406                        }
407                    }
408                } break;
409                case DESTROY_TIMEOUT_MSG: {
410                    ActivityRecord r = (ActivityRecord)msg.obj;
411                    // We don't at this point know if the activity is fullscreen,
412                    // so we need to be conservative and assume it isn't.
413                    Slog.w(TAG, "Activity destroy timeout for " + r);
414                    synchronized (mService) {
415                        activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout");
416                    }
417                } break;
418                case STOP_TIMEOUT_MSG: {
419                    ActivityRecord r = (ActivityRecord)msg.obj;
420                    // We don't at this point know if the activity is fullscreen,
421                    // so we need to be conservative and assume it isn't.
422                    Slog.w(TAG, "Activity stop timeout for " + r);
423                    synchronized (mService) {
424                        if (r.isInHistory()) {
425                            r.activityStoppedLocked(null /* icicle */,
426                                    null /* persistentState */, null /* description */);
427                        }
428                    }
429                } break;
430                case DESTROY_ACTIVITIES_MSG: {
431                    ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
432                    synchronized (mService) {
433                        destroyActivitiesLocked(args.mOwner, args.mReason);
434                    }
435                } break;
436                case TRANSLUCENT_TIMEOUT_MSG: {
437                    synchronized (mService) {
438                        notifyActivityDrawnLocked(null);
439                    }
440                } break;
441            }
442        }
443    }
444
445    int numActivities() {
446        int count = 0;
447        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
448            count += mTaskHistory.get(taskNdx).mActivities.size();
449        }
450        return count;
451    }
452
453    ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
454            int windowingMode, int activityType, boolean onTop) {
455        mStackSupervisor = supervisor;
456        mService = supervisor.mService;
457        mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
458        mWindowManager = mService.mWindowManager;
459        mStackId = stackId;
460        mCurrentUser = mService.mUserController.getCurrentUserId();
461        mTmpRect2.setEmpty();
462        // Set display id before setting activity and window type to make sure it won't affect
463        // stacks on a wrong display.
464        mDisplayId = display.mDisplayId;
465        setActivityType(activityType);
466        setWindowingMode(windowingMode);
467        mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
468                mTmpRect2);
469        postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
470    }
471
472    T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
473        return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds,
474                mStackSupervisor.mWindowManager);
475    }
476
477    T getWindowContainerController() {
478        return mWindowContainerController;
479    }
480
481    /**
482     * This should be called when an activity in a child task changes state. This should only
483     * be called from
484     * {@link TaskRecord#onActivityStateChanged(ActivityRecord, ActivityState, String)}.
485     * @param record The {@link ActivityRecord} whose state has changed.
486     * @param state The new state.
487     * @param reason The reason for the change.
488     */
489    void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
490        if (record == mResumedActivity && state != RESUMED) {
491            setResumedActivity(null, reason + " - onActivityStateChanged");
492        }
493
494        if (state == RESUMED) {
495            if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
496                    + reason);
497            setResumedActivity(record, reason + " - onActivityStateChanged");
498            mService.setResumedActivityUncheckLocked(record, reason);
499            mStackSupervisor.mRecentTasks.add(record.getTask());
500        }
501    }
502
503    @Override
504    public void onConfigurationChanged(Configuration newParentConfig) {
505        final int prevWindowingMode = getWindowingMode();
506        super.onConfigurationChanged(newParentConfig);
507        final ActivityDisplay display = getDisplay();
508        if (display != null && prevWindowingMode != getWindowingMode()) {
509            display.onStackWindowingModeChanged(this);
510        }
511    }
512
513    @Override
514    public void setWindowingMode(int windowingMode) {
515        setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
516                false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */);
517    }
518
519    void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents,
520            boolean enteringSplitScreenMode, boolean deferEnsuringVisibility) {
521        final boolean creating = mWindowContainerController == null;
522        final int currentMode = getWindowingMode();
523        final ActivityDisplay display = getDisplay();
524        final TaskRecord topTask = topTask();
525        final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
526        mTmpOptions.setLaunchWindowingMode(preferredWindowingMode);
527
528        // Need to make sure windowing mode is supported. If we in the process of creating the stack
529        // no need to resolve the windowing mode again as it is already resolved to the right mode.
530        int windowingMode = creating
531                ? preferredWindowingMode
532                : display.resolveWindowingMode(
533                        null /* ActivityRecord */, mTmpOptions, topTask, getActivityType());
534        if (splitScreenStack == this && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
535            // Resolution to split-screen secondary for the primary split-screen stack means we want
536            // to go fullscreen.
537            windowingMode = WINDOWING_MODE_FULLSCREEN;
538        }
539
540        final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack();
541
542        // Don't send non-resizeable notifications if the windowing mode changed was a side effect
543        // of us entering split-screen mode.
544        final boolean sendNonResizeableNotification = !enteringSplitScreenMode;
545        // Take any required action due to us not supporting the preferred windowing mode.
546        if (alreadyInSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
547                && sendNonResizeableNotification && isActivityTypeStandardOrUndefined()) {
548            final boolean preferredSplitScreen =
549                    preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
550                    || preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
551            if (preferredSplitScreen || creating) {
552                // Looks like we can't launch in split screen mode or the stack we are launching
553                // doesn't support split-screen mode, go ahead an dismiss split-screen and display a
554                // warning toast about it.
555                mService.mTaskChangeNotificationController.notifyActivityDismissingDockedStack();
556                display.getSplitScreenPrimaryStack().setWindowingMode(WINDOWING_MODE_FULLSCREEN,
557                        false /* animate */, false /* showRecents */,
558                        false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */);
559            }
560        }
561
562        if (currentMode == windowingMode) {
563            // You are already in the window mode silly...
564            return;
565        }
566
567        final WindowManagerService wm = mService.mWindowManager;
568        final ActivityRecord topActivity = getTopActivity();
569
570        if (sendNonResizeableNotification && windowingMode != WINDOWING_MODE_FULLSCREEN
571                && topActivity != null && topActivity.isNonResizableOrForcedResizable()
572                && !topActivity.noDisplay) {
573            // Inform the user that they are starting an app that may not work correctly in
574            // multi-window mode.
575            final String packageName = topActivity.appInfo.packageName;
576            mService.mTaskChangeNotificationController.notifyActivityForcedResizable(
577                    topTask.taskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName);
578        }
579
580        wm.deferSurfaceLayout();
581        try {
582            if (!animate && topActivity != null) {
583                mStackSupervisor.mNoAnimActivities.add(topActivity);
584            }
585            super.setWindowingMode(windowingMode);
586
587            if (creating) {
588                // Nothing else to do if we don't have a window container yet. E.g. call from ctor.
589                return;
590            }
591
592            if (windowingMode == WINDOWING_MODE_PINNED || currentMode == WINDOWING_MODE_PINNED) {
593                // TODO: Need to remove use of PinnedActivityStack for this to be supported.
594                // NOTE: Need to ASS.scheduleUpdatePictureInPictureModeIfNeeded() in
595                // setWindowModeUnchecked() when this support is added. See TaskRecord.reparent()
596                throw new IllegalArgumentException(
597                        "Changing pinned windowing mode not currently supported");
598            }
599
600            if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && splitScreenStack != null) {
601                // We already have a split-screen stack in this display, so just move the tasks over.
602                // TODO: Figure-out how to do all the stuff in
603                // AMS.setTaskWindowingModeSplitScreenPrimary
604                throw new IllegalArgumentException("Setting primary split-screen windowing mode"
605                        + " while there is already one isn't currently supported");
606                //return;
607            }
608
609            mTmpRect2.setEmpty();
610            if (windowingMode != WINDOWING_MODE_FULLSCREEN) {
611                mWindowContainerController.getRawBounds(mTmpRect2);
612                if (windowingMode == WINDOWING_MODE_FREEFORM) {
613                    if (topTask != null) {
614                        // TODO: Can we consolidate this and other sites that call this methods?
615                        Rect bounds = topTask().getLaunchBounds();
616                        if (bounds != null) {
617                            mTmpRect2.set(bounds);
618                        }
619                    }
620                }
621            }
622
623            if (!Objects.equals(getOverrideBounds(), mTmpRect2)) {
624                resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */);
625            }
626        } finally {
627            if (showRecents && !alreadyInSplitScreenMode && mDisplayId == DEFAULT_DISPLAY
628                    && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
629                // Make sure recents stack exist when creating a dock stack as it normally needs to
630                // be on the other side of the docked stack and we make visibility decisions based
631                // on that.
632                // TODO: This is only here to help out with the case where recents stack doesn't
633                // exist yet. For that case the initial size of the split-screen stack will be the
634                // the one where the home stack is visible since recents isn't visible yet, but the
635                // divider will be off. I think we should just make the initial bounds that of home
636                // so that the divider matches and remove this logic.
637                // TODO: This is currently only called when entering split-screen while in another
638                // task, and from the tests
639                // TODO (b/78247419): Check if launcher and overview are same then move home stack
640                // instead of recents stack. Then fix the rotation animation from fullscreen to
641                // minimized mode
642                final ActivityStack recentStack = display.getOrCreateStack(
643                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS,
644                        true /* onTop */);
645                recentStack.moveToFront("setWindowingMode");
646                // If task moved to docked stack - show recents if needed.
647                mService.mWindowManager.showRecentApps();
648            }
649            wm.continueSurfaceLayout();
650        }
651
652        if (!deferEnsuringVisibility) {
653            mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS);
654            mStackSupervisor.resumeFocusedStackTopActivityLocked();
655        }
656    }
657
658    @Override
659    public boolean isCompatible(int windowingMode, int activityType) {
660        // TODO: Should we just move this to ConfigurationContainer?
661        if (activityType == ACTIVITY_TYPE_UNDEFINED) {
662            // Undefined activity types end up in a standard stack once the stack is created on a
663            // display, so they should be considered compatible.
664            activityType = ACTIVITY_TYPE_STANDARD;
665        }
666        final ActivityDisplay display = getDisplay();
667        if (display != null && activityType == ACTIVITY_TYPE_STANDARD
668                    && windowingMode == WINDOWING_MODE_UNDEFINED) {
669            // Standard activity types will mostly take on the windowing mode of the display if one
670            // isn't specified, so look-up a compatible stack based on the display's windowing mode.
671            windowingMode = display.getWindowingMode();
672        }
673        return super.isCompatible(windowingMode, activityType);
674    }
675
676    /** Adds the stack to specified display and calls WindowManager to do the same. */
677    void reparent(ActivityDisplay activityDisplay, boolean onTop) {
678        // TODO: We should probably resolve the windowing mode for the stack on the new display here
679        // so that it end up in a compatible mode in the new display. e.g. split-screen secondary.
680        removeFromDisplay();
681        // Reparent the window container before we try to update the position when adding it to
682        // the new display below
683        mTmpRect2.setEmpty();
684        mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop);
685        postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
686        adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */);
687        mStackSupervisor.resumeFocusedStackTopActivityLocked();
688        // Update visibility of activities before notifying WM. This way it won't try to resize
689        // windows that are no longer visible.
690        mStackSupervisor.ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
691                !PRESERVE_WINDOWS);
692    }
693
694    /**
695     * Updates internal state after adding to new display.
696     * @param activityDisplay New display to which this stack was attached.
697     * @param bounds Updated bounds.
698     */
699    private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) {
700        mDisplayId = activityDisplay.mDisplayId;
701        setBounds(bounds);
702        onParentChanged();
703
704        activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
705        if (inSplitScreenPrimaryWindowingMode()) {
706            // If we created a docked stack we want to resize it so it resizes all other stacks
707            // in the system.
708            mStackSupervisor.resizeDockedStackLocked(
709                    getOverrideBounds(), null, null, null, null, PRESERVE_WINDOWS);
710        }
711    }
712
713    /**
714     * Updates the inner state of the stack to remove it from its current parent, so it can be
715     * either destroyed completely or re-parented.
716     */
717    private void removeFromDisplay() {
718        final ActivityDisplay display = getDisplay();
719        if (display != null) {
720            display.removeChild(this);
721        }
722        mDisplayId = INVALID_DISPLAY;
723    }
724
725    /** Removes the stack completely. Also calls WindowManager to do the same on its side. */
726    void remove() {
727        removeFromDisplay();
728        mWindowContainerController.removeContainer();
729        mWindowContainerController = null;
730        onParentChanged();
731    }
732
733    ActivityDisplay getDisplay() {
734        return mStackSupervisor.getActivityDisplay(mDisplayId);
735    }
736
737    /**
738     * @see #getStackDockedModeBounds(Rect, Rect, Rect, boolean)
739     */
740    void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
741            Rect outTempTaskBounds, boolean ignoreVisibility) {
742        mWindowContainerController.getStackDockedModeBounds(currentTempTaskBounds,
743                outStackBounds, outTempTaskBounds, ignoreVisibility);
744    }
745
746    void prepareFreezingTaskBounds() {
747        mWindowContainerController.prepareFreezingTaskBounds();
748    }
749
750    void getWindowContainerBounds(Rect outBounds) {
751        if (mWindowContainerController != null) {
752            mWindowContainerController.getBounds(outBounds);
753            return;
754        }
755        outBounds.setEmpty();
756    }
757
758    void getBoundsForNewConfiguration(Rect outBounds) {
759        mWindowContainerController.getBoundsForNewConfiguration(outBounds);
760    }
761
762    void positionChildWindowContainerAtTop(TaskRecord child) {
763        mWindowContainerController.positionChildAtTop(child.getWindowContainerController(),
764                true /* includingParents */);
765    }
766
767    /**
768     * Returns whether to defer the scheduling of the multi-window mode.
769     */
770    boolean deferScheduleMultiWindowModeChanged() {
771        return false;
772    }
773
774    /**
775     * Defers updating the bounds of the stack. If the stack was resized/repositioned while
776     * deferring, the bounds will update in {@link #continueUpdateBounds()}.
777     */
778    void deferUpdateBounds() {
779        if (!mUpdateBoundsDeferred) {
780            mUpdateBoundsDeferred = true;
781            mUpdateBoundsDeferredCalled = false;
782        }
783    }
784
785    /**
786     * Continues updating bounds after updates have been deferred. If there was a resize attempt
787     * between {@link #deferUpdateBounds()} and {@link #continueUpdateBounds()}, the stack will
788     * be resized to that bounds.
789     */
790    void continueUpdateBounds() {
791        final boolean wasDeferred = mUpdateBoundsDeferred;
792        mUpdateBoundsDeferred = false;
793        if (wasDeferred && mUpdateBoundsDeferredCalled) {
794            resize(mDeferredBounds.isEmpty() ? null : mDeferredBounds,
795                    mDeferredTaskBounds.isEmpty() ? null : mDeferredTaskBounds,
796                    mDeferredTaskInsetBounds.isEmpty() ? null : mDeferredTaskInsetBounds);
797        }
798    }
799
800    boolean updateBoundsAllowed(Rect bounds, Rect tempTaskBounds,
801            Rect tempTaskInsetBounds) {
802        if (!mUpdateBoundsDeferred) {
803            return true;
804        }
805        if (bounds != null) {
806            mDeferredBounds.set(bounds);
807        } else {
808            mDeferredBounds.setEmpty();
809        }
810        if (tempTaskBounds != null) {
811            mDeferredTaskBounds.set(tempTaskBounds);
812        } else {
813            mDeferredTaskBounds.setEmpty();
814        }
815        if (tempTaskInsetBounds != null) {
816            mDeferredTaskInsetBounds.set(tempTaskInsetBounds);
817        } else {
818            mDeferredTaskInsetBounds.setEmpty();
819        }
820        mUpdateBoundsDeferredCalled = true;
821        return false;
822    }
823
824    @Override
825    public int setBounds(Rect bounds) {
826        return super.setBounds(!inMultiWindowMode() ? null : bounds);
827    }
828
829    ActivityRecord topRunningActivityLocked() {
830        return topRunningActivityLocked(false /* focusableOnly */);
831    }
832
833    void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
834        outActivities.clear();
835        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
836            mTaskHistory.get(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities);
837        }
838    }
839
840    private ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
841        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
842            ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
843            if (r != null && (!focusableOnly || r.isFocusable())) {
844                return r;
845            }
846        }
847        return null;
848    }
849
850    ActivityRecord topRunningNonOverlayTaskActivity() {
851        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
852            final TaskRecord task = mTaskHistory.get(taskNdx);
853            final ArrayList<ActivityRecord> activities = task.mActivities;
854            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
855                final ActivityRecord r = activities.get(activityNdx);
856                if (!r.finishing && !r.mTaskOverlay) {
857                    return r;
858                }
859            }
860        }
861        return null;
862    }
863
864    ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
865        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
866            final TaskRecord task = mTaskHistory.get(taskNdx);
867            final ArrayList<ActivityRecord> activities = task.mActivities;
868            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
869                ActivityRecord r = activities.get(activityNdx);
870                if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) {
871                    return r;
872                }
873            }
874        }
875        return null;
876    }
877
878    /**
879     * This is a simplified version of topRunningActivityLocked that provides a number of
880     * optional skip-over modes.  It is intended for use with the ActivityController hook only.
881     *
882     * @param token If non-null, any history records matching this token will be skipped.
883     * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
884     *
885     * @return Returns the HistoryRecord of the next activity on the stack.
886     */
887    final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
888        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
889            TaskRecord task = mTaskHistory.get(taskNdx);
890            if (task.taskId == taskId) {
891                continue;
892            }
893            ArrayList<ActivityRecord> activities = task.mActivities;
894            for (int i = activities.size() - 1; i >= 0; --i) {
895                final ActivityRecord r = activities.get(i);
896                // Note: the taskId check depends on real taskId fields being non-zero
897                if (!r.finishing && (token != r.appToken) && r.okToShowLocked()) {
898                    return r;
899                }
900            }
901        }
902        return null;
903    }
904
905    ActivityRecord getTopActivity() {
906        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
907            final ActivityRecord r = mTaskHistory.get(taskNdx).getTopActivity();
908            if (r != null) {
909                return r;
910            }
911        }
912        return null;
913    }
914
915    final TaskRecord topTask() {
916        final int size = mTaskHistory.size();
917        if (size > 0) {
918            return mTaskHistory.get(size - 1);
919        }
920        return null;
921    }
922
923    private TaskRecord bottomTask() {
924        if (mTaskHistory.isEmpty()) {
925            return null;
926        }
927        return mTaskHistory.get(0);
928    }
929
930    TaskRecord taskForIdLocked(int id) {
931        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
932            final TaskRecord task = mTaskHistory.get(taskNdx);
933            if (task.taskId == id) {
934                return task;
935            }
936        }
937        return null;
938    }
939
940    ActivityRecord isInStackLocked(IBinder token) {
941        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
942        return isInStackLocked(r);
943    }
944
945    ActivityRecord isInStackLocked(ActivityRecord r) {
946        if (r == null) {
947            return null;
948        }
949        final TaskRecord task = r.getTask();
950        final ActivityStack stack = r.getStack();
951        if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
952            if (stack != this) Slog.w(TAG,
953                    "Illegal state! task does not point to stack it is in.");
954            return r;
955        }
956        return null;
957    }
958
959    boolean isInStackLocked(TaskRecord task) {
960        return mTaskHistory.contains(task);
961    }
962
963    /** Checks if there are tasks with specific UID in the stack. */
964    boolean isUidPresent(int uid) {
965        for (TaskRecord task : mTaskHistory) {
966            for (ActivityRecord r : task.mActivities) {
967                if (r.getUid() == uid) {
968                    return true;
969                }
970            }
971        }
972        return false;
973    }
974
975    /** Get all UIDs that are present in the stack. */
976    void getPresentUIDs(IntArray presentUIDs) {
977        for (TaskRecord task : mTaskHistory) {
978            for (ActivityRecord r : task.mActivities) {
979                presentUIDs.add(r.getUid());
980            }
981        }
982    }
983
984    final void removeActivitiesFromLRUListLocked(TaskRecord task) {
985        for (ActivityRecord r : task.mActivities) {
986            mLRUActivities.remove(r);
987        }
988    }
989
990    final boolean updateLRUListLocked(ActivityRecord r) {
991        final boolean hadit = mLRUActivities.remove(r);
992        mLRUActivities.add(r);
993        return hadit;
994    }
995
996    final boolean isHomeOrRecentsStack() {
997        return isActivityTypeHome() || isActivityTypeRecents();
998    }
999
1000    final boolean isOnHomeDisplay() {
1001        return mDisplayId == DEFAULT_DISPLAY;
1002    }
1003
1004    private boolean returnsToHomeStack() {
1005        return !inMultiWindowMode()
1006                && !mTaskHistory.isEmpty()
1007                && mTaskHistory.get(0).returnsToHomeStack();
1008    }
1009
1010    void moveToFront(String reason) {
1011        moveToFront(reason, null);
1012    }
1013
1014    /**
1015     * @param reason The reason for moving the stack to the front.
1016     * @param task If non-null, the task will be moved to the top of the stack.
1017     * */
1018    void moveToFront(String reason, TaskRecord task) {
1019        if (!isAttached()) {
1020            return;
1021        }
1022
1023        final ActivityDisplay display = getDisplay();
1024
1025        if (inSplitScreenSecondaryWindowingMode()) {
1026            // If the stack is in split-screen seconardy mode, we need to make sure we move the
1027            // primary split-screen stack forward in the case it is currently behind a fullscreen
1028            // stack so both halves of the split-screen appear on-top and the fullscreen stack isn't
1029            // cutting between them.
1030            // TODO(b/70677280): This is a workaround until we can fix as part of b/70677280.
1031            final ActivityStack topFullScreenStack =
1032                    display.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
1033            if (topFullScreenStack != null) {
1034                final ActivityStack primarySplitScreenStack = display.getSplitScreenPrimaryStack();
1035                if (display.getIndexOf(topFullScreenStack)
1036                        > display.getIndexOf(primarySplitScreenStack)) {
1037                    primarySplitScreenStack.moveToFront(reason + " splitScreenToTop");
1038                }
1039            }
1040        }
1041
1042        if (!isActivityTypeHome() && returnsToHomeStack()) {
1043            // Make sure the home stack is behind this stack since that is where we should return to
1044            // when this stack is no longer visible.
1045            mStackSupervisor.moveHomeStackToFront(reason + " returnToHome");
1046        }
1047
1048        display.positionChildAtTop(this);
1049        mStackSupervisor.setFocusStackUnchecked(reason, this);
1050        if (task != null) {
1051            insertTaskAtTop(task, null);
1052            return;
1053        }
1054    }
1055
1056    /**
1057     * @param reason The reason for moving the stack to the back.
1058     * @param task If non-null, the task will be moved to the bottom of the stack.
1059     **/
1060    void moveToBack(String reason, TaskRecord task) {
1061        if (!isAttached()) {
1062            return;
1063        }
1064
1065        /**
1066         * The intent behind moving a primary split screen stack to the back is usually to hide
1067         * behind the home stack. Exit split screen in this case.
1068         */
1069        if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
1070            setWindowingMode(WINDOWING_MODE_FULLSCREEN);
1071        }
1072
1073        getDisplay().positionChildAtBottom(this);
1074        mStackSupervisor.setFocusStackUnchecked(reason, getDisplay().getTopStack());
1075        if (task != null) {
1076            insertTaskAtBottom(task);
1077            return;
1078        }
1079    }
1080
1081    boolean isFocusable() {
1082        final ActivityRecord r = topRunningActivityLocked();
1083        return mStackSupervisor.isFocusable(this, r != null && r.isFocusable());
1084    }
1085
1086    final boolean isAttached() {
1087        return getParent() != null;
1088    }
1089
1090    /**
1091     * Returns the top activity in any existing task matching the given Intent in the input result.
1092     * Returns null if no such task is found.
1093     */
1094    void findTaskLocked(ActivityRecord target, FindTaskResult result) {
1095        Intent intent = target.intent;
1096        ActivityInfo info = target.info;
1097        ComponentName cls = intent.getComponent();
1098        if (info.targetActivity != null) {
1099            cls = new ComponentName(info.packageName, info.targetActivity);
1100        }
1101        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
1102        boolean isDocument = intent != null & intent.isDocument();
1103        // If documentData is non-null then it must match the existing task data.
1104        Uri documentData = isDocument ? intent.getData() : null;
1105
1106        if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
1107        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1108            final TaskRecord task = mTaskHistory.get(taskNdx);
1109            if (task.voiceSession != null) {
1110                // We never match voice sessions; those always run independently.
1111                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
1112                continue;
1113            }
1114            if (task.userId != userId) {
1115                // Looking for a different task.
1116                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user");
1117                continue;
1118            }
1119
1120            // Overlays should not be considered as the task's logical top activity.
1121            final ActivityRecord r = task.getTopActivity(false /* includeOverlays */);
1122            if (r == null || r.finishing || r.userId != userId ||
1123                    r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1124                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
1125                continue;
1126            }
1127            if (!r.hasCompatibleActivityType(target)) {
1128                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type");
1129                continue;
1130            }
1131
1132            final Intent taskIntent = task.intent;
1133            final Intent affinityIntent = task.affinityIntent;
1134            final boolean taskIsDocument;
1135            final Uri taskDocumentData;
1136            if (taskIntent != null && taskIntent.isDocument()) {
1137                taskIsDocument = true;
1138                taskDocumentData = taskIntent.getData();
1139            } else if (affinityIntent != null && affinityIntent.isDocument()) {
1140                taskIsDocument = true;
1141                taskDocumentData = affinityIntent.getData();
1142            } else {
1143                taskIsDocument = false;
1144                taskDocumentData = null;
1145            }
1146
1147            if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
1148                    + taskIntent.getComponent().flattenToShortString()
1149                    + "/aff=" + r.getTask().rootAffinity + " to new cls="
1150                    + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
1151            // TODO Refactor to remove duplications. Check if logic can be simplified.
1152            if (taskIntent != null && taskIntent.getComponent() != null &&
1153                    taskIntent.getComponent().compareTo(cls) == 0 &&
1154                    Objects.equals(documentData, taskDocumentData)) {
1155                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
1156                //dump();
1157                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
1158                        "For Intent " + intent + " bringing to top: " + r.intent);
1159                result.r = r;
1160                result.matchedByRootAffinity = false;
1161                break;
1162            } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
1163                    affinityIntent.getComponent().compareTo(cls) == 0 &&
1164                    Objects.equals(documentData, taskDocumentData)) {
1165                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
1166                //dump();
1167                if (DEBUG_TASKS) Slog.d(TAG_TASKS,
1168                        "For Intent " + intent + " bringing to top: " + r.intent);
1169                result.r = r;
1170                result.matchedByRootAffinity = false;
1171                break;
1172            } else if (!isDocument && !taskIsDocument
1173                    && result.r == null && task.rootAffinity != null) {
1174                if (task.rootAffinity.equals(target.taskAffinity)) {
1175                    if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!");
1176                    // It is possible for multiple tasks to have the same root affinity especially
1177                    // if they are in separate stacks. We save off this candidate, but keep looking
1178                    // to see if there is a better candidate.
1179                    result.r = r;
1180                    result.matchedByRootAffinity = true;
1181                }
1182            } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task);
1183        }
1184    }
1185
1186    /**
1187     * Returns the first activity (starting from the top of the stack) that
1188     * is the same as the given activity.  Returns null if no such activity
1189     * is found.
1190     */
1191    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
1192                                      boolean compareIntentFilters) {
1193        ComponentName cls = intent.getComponent();
1194        if (info.targetActivity != null) {
1195            cls = new ComponentName(info.packageName, info.targetActivity);
1196        }
1197        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
1198
1199        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1200            final TaskRecord task = mTaskHistory.get(taskNdx);
1201            final ArrayList<ActivityRecord> activities = task.mActivities;
1202
1203            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1204                ActivityRecord r = activities.get(activityNdx);
1205                if (!r.okToShowLocked()) {
1206                    continue;
1207                }
1208                if (!r.finishing && r.userId == userId) {
1209                    if (compareIntentFilters) {
1210                        if (r.intent.filterEquals(intent)) {
1211                            return r;
1212                        }
1213                    } else {
1214                        if (r.intent.getComponent().equals(cls)) {
1215                            return r;
1216                        }
1217                    }
1218                }
1219            }
1220        }
1221
1222        return null;
1223    }
1224
1225    /*
1226     * Move the activities around in the stack to bring a user to the foreground.
1227     */
1228    final void switchUserLocked(int userId) {
1229        if (mCurrentUser == userId) {
1230            return;
1231        }
1232        mCurrentUser = userId;
1233
1234        // Move userId's tasks to the top.
1235        int index = mTaskHistory.size();
1236        for (int i = 0; i < index; ) {
1237            final TaskRecord task = mTaskHistory.get(i);
1238
1239            if (task.okToShowLocked()) {
1240                if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUserLocked: stack=" + getStackId() +
1241                        " moving " + task + " to top");
1242                mTaskHistory.remove(i);
1243                mTaskHistory.add(task);
1244                --index;
1245                // Use same value for i.
1246            } else {
1247                ++i;
1248            }
1249        }
1250    }
1251
1252    void minimalResumeActivityLocked(ActivityRecord r) {
1253        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)"
1254                + " callers=" + Debug.getCallers(5));
1255        r.setState(RESUMED, "minimalResumeActivityLocked");
1256        r.completeResumeLocked();
1257        mStackSupervisor.getLaunchTimeTracker().setLaunchTime(r);
1258        if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
1259                "Launch completed; removing icicle of " + r.icicle);
1260    }
1261
1262    private void clearLaunchTime(ActivityRecord r) {
1263        // Make sure that there is no activity waiting for this to launch.
1264        if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
1265            r.displayStartTime = r.fullyDrawnStartTime = 0;
1266        } else {
1267            mStackSupervisor.removeTimeoutsForActivityLocked(r);
1268            mStackSupervisor.scheduleIdleTimeoutLocked(r);
1269        }
1270    }
1271
1272    void awakeFromSleepingLocked() {
1273        // Ensure activities are no longer sleeping.
1274        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1275            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1276            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1277                activities.get(activityNdx).setSleeping(false);
1278            }
1279        }
1280        if (mPausingActivity != null) {
1281            Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause");
1282            activityPausedLocked(mPausingActivity.appToken, true);
1283        }
1284    }
1285
1286    void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
1287        final String packageName = aInfo.packageName;
1288        final int userId = UserHandle.getUserId(aInfo.uid);
1289
1290        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1291            final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1292            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1293                final ActivityRecord ar = activities.get(activityNdx);
1294
1295                if ((userId == ar.userId) && packageName.equals(ar.packageName)) {
1296                    ar.updateApplicationInfo(aInfo);
1297                }
1298            }
1299        }
1300    }
1301
1302    void checkReadyForSleep() {
1303        if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) {
1304            mStackSupervisor.checkReadyForSleepLocked(true /* allowDelay */);
1305        }
1306    }
1307
1308    /**
1309     * Tries to put the activities in the stack to sleep.
1310     *
1311     * If the stack is not in a state where its activities can be put to sleep, this function will
1312     * start any necessary actions to move the stack into such a state. It is expected that this
1313     * function get called again when those actions complete.
1314     *
1315     * @param shuttingDown true when the called because the device is shutting down.
1316     * @return true if the stack finished going to sleep, false if the stack only started the
1317     * process of going to sleep (checkReadyForSleep will be called when that process finishes).
1318     */
1319    boolean goToSleepIfPossible(boolean shuttingDown) {
1320        boolean shouldSleep = true;
1321
1322        if (mResumedActivity != null) {
1323            // Still have something resumed; can't sleep until it is paused.
1324            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity);
1325            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
1326                    "Sleep => pause with userLeaving=false");
1327
1328            startPausingLocked(false, true, null, false);
1329            shouldSleep = false ;
1330        } else if (mPausingActivity != null) {
1331            // Still waiting for something to pause; can't sleep yet.
1332            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity);
1333            shouldSleep = false;
1334        }
1335
1336        if (!shuttingDown) {
1337            if (containsActivityFromStack(mStackSupervisor.mStoppingActivities)) {
1338                // Still need to tell some activities to stop; can't sleep yet.
1339                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop "
1340                        + mStackSupervisor.mStoppingActivities.size() + " activities");
1341
1342                mStackSupervisor.scheduleIdleLocked();
1343                shouldSleep = false;
1344            }
1345
1346            if (containsActivityFromStack(mStackSupervisor.mGoingToSleepActivities)) {
1347                // Still need to tell some activities to sleep; can't sleep yet.
1348                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep "
1349                        + mStackSupervisor.mGoingToSleepActivities.size() + " activities");
1350                shouldSleep = false;
1351            }
1352        }
1353
1354        if (shouldSleep) {
1355            goToSleep();
1356        }
1357
1358        return shouldSleep;
1359    }
1360
1361    void goToSleep() {
1362        // Ensure visibility without updating configuration, as activities are about to sleep.
1363        ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */,
1364                !PRESERVE_WINDOWS);
1365
1366        // Make sure any paused or stopped but visible activities are now sleeping.
1367        // This ensures that the activity's onStop() is called.
1368        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1369            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1370            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1371                final ActivityRecord r = activities.get(activityNdx);
1372                if (r.isState(STOPPING, STOPPED, PAUSED, PAUSING)) {
1373                    r.setSleeping(true);
1374                }
1375            }
1376        }
1377    }
1378
1379    private boolean containsActivityFromStack(List<ActivityRecord> rs) {
1380        for (ActivityRecord r : rs) {
1381            if (r.getStack() == this) {
1382                return true;
1383            }
1384        }
1385        return false;
1386    }
1387
1388    /**
1389     * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
1390     * this directly impacts the responsiveness seen by the user.
1391     */
1392    private void schedulePauseTimeout(ActivityRecord r) {
1393        final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1394        msg.obj = r;
1395        r.pauseTime = SystemClock.uptimeMillis();
1396        mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1397        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
1398    }
1399
1400    /**
1401     * Start pausing the currently resumed activity.  It is an error to call this if there
1402     * is already an activity being paused or there is no resumed activity.
1403     *
1404     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
1405     * @param uiSleeping True if this is happening with the user interface going to sleep (the
1406     * screen turning off).
1407     * @param resuming The activity we are currently trying to resume or null if this is not being
1408     *                 called as part of resuming the top activity, so we shouldn't try to instigate
1409     *                 a resume here if not null.
1410     * @param pauseImmediately True if the caller does not want to wait for the activity callback to
1411     *                         complete pausing.
1412     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
1413     * it to tell us when it is done.
1414     */
1415    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
1416            ActivityRecord resuming, boolean pauseImmediately) {
1417        if (mPausingActivity != null) {
1418            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
1419                    + " state=" + mPausingActivity.getState());
1420            if (!shouldSleepActivities()) {
1421                // Avoid recursion among check for sleep and complete pause during sleeping.
1422                // Because activity will be paused immediately after resume, just let pause
1423                // be completed by the order of activity paused from clients.
1424                completePauseLocked(false, resuming);
1425            }
1426        }
1427        ActivityRecord prev = mResumedActivity;
1428
1429        if (prev == null) {
1430            if (resuming == null) {
1431                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
1432                mStackSupervisor.resumeFocusedStackTopActivityLocked();
1433            }
1434            return false;
1435        }
1436
1437        if (prev == resuming) {
1438            Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
1439            return false;
1440        }
1441
1442        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
1443        else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
1444        mPausingActivity = prev;
1445        mLastPausedActivity = prev;
1446        mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
1447                || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
1448        prev.setState(PAUSING, "startPausingLocked");
1449        prev.getTask().touchActiveTime();
1450        clearLaunchTime(prev);
1451
1452        mStackSupervisor.getLaunchTimeTracker().stopFullyDrawnTraceIfNeeded(getWindowingMode());
1453
1454        mService.updateCpuStats();
1455
1456        if (prev.app != null && prev.app.thread != null) {
1457            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
1458            try {
1459                EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
1460                        prev.shortComponentName, "userLeaving=" + userLeaving);
1461                mService.updateUsageStats(prev, false);
1462
1463                mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
1464                        PauseActivityItem.obtain(prev.finishing, userLeaving,
1465                                prev.configChangeFlags, pauseImmediately));
1466            } catch (Exception e) {
1467                // Ignore exception, if process died other code will cleanup.
1468                Slog.w(TAG, "Exception thrown during pause", e);
1469                mPausingActivity = null;
1470                mLastPausedActivity = null;
1471                mLastNoHistoryActivity = null;
1472            }
1473        } else {
1474            mPausingActivity = null;
1475            mLastPausedActivity = null;
1476            mLastNoHistoryActivity = null;
1477        }
1478
1479        // If we are not going to sleep, we want to ensure the device is
1480        // awake until the next activity is started.
1481        if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
1482            mStackSupervisor.acquireLaunchWakelock();
1483        }
1484
1485        if (mPausingActivity != null) {
1486            // Have the window manager pause its key dispatching until the new
1487            // activity has started.  If we're pausing the activity just because
1488            // the screen is being turned off and the UI is sleeping, don't interrupt
1489            // key dispatch; the same activity will pick it up again on wakeup.
1490            if (!uiSleeping) {
1491                prev.pauseKeyDispatchingLocked();
1492            } else if (DEBUG_PAUSE) {
1493                 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
1494            }
1495
1496            if (pauseImmediately) {
1497                // If the caller said they don't want to wait for the pause, then complete
1498                // the pause now.
1499                completePauseLocked(false, resuming);
1500                return false;
1501
1502            } else {
1503                schedulePauseTimeout(prev);
1504                return true;
1505            }
1506
1507        } else {
1508            // This activity failed to schedule the
1509            // pause, so just treat it as being paused now.
1510            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
1511            if (resuming == null) {
1512                mStackSupervisor.resumeFocusedStackTopActivityLocked();
1513            }
1514            return false;
1515        }
1516    }
1517
1518    final void activityPausedLocked(IBinder token, boolean timeout) {
1519        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
1520            "Activity paused: token=" + token + ", timeout=" + timeout);
1521
1522        final ActivityRecord r = isInStackLocked(token);
1523        if (r != null) {
1524            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
1525            if (mPausingActivity == r) {
1526                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
1527                        + (timeout ? " (due to timeout)" : " (pause complete)"));
1528                mService.mWindowManager.deferSurfaceLayout();
1529                try {
1530                    completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
1531                } finally {
1532                    mService.mWindowManager.continueSurfaceLayout();
1533                }
1534                return;
1535            } else {
1536                EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
1537                        r.userId, System.identityHashCode(r), r.shortComponentName,
1538                        mPausingActivity != null
1539                            ? mPausingActivity.shortComponentName : "(none)");
1540                if (r.isState(PAUSING)) {
1541                    r.setState(PAUSED, "activityPausedLocked");
1542                    if (r.finishing) {
1543                        if (DEBUG_PAUSE) Slog.v(TAG,
1544                                "Executing finish of failed to pause activity: " + r);
1545                        finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false,
1546                                "activityPausedLocked");
1547                    }
1548                }
1549            }
1550        }
1551        mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1552    }
1553
1554    private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
1555        ActivityRecord prev = mPausingActivity;
1556        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
1557
1558        if (prev != null) {
1559            prev.setWillCloseOrEnterPip(false);
1560            final boolean wasStopping = prev.isState(STOPPING);
1561            prev.setState(PAUSED, "completePausedLocked");
1562            if (prev.finishing) {
1563                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
1564                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
1565                        "completedPausedLocked");
1566            } else if (prev.app != null) {
1567                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
1568                        + " wasStopping=" + wasStopping + " visible=" + prev.visible);
1569                if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {
1570                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
1571                            "Complete pause, no longer waiting: " + prev);
1572                }
1573                if (prev.deferRelaunchUntilPaused) {
1574                    // Complete the deferred relaunch that was waiting for pause to complete.
1575                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
1576                    prev.relaunchActivityLocked(false /* andResume */,
1577                            prev.preserveWindowOnDeferredRelaunch);
1578                } else if (wasStopping) {
1579                    // We are also stopping, the stop request must have gone soon after the pause.
1580                    // We can't clobber it, because the stop confirmation will not be handled.
1581                    // We don't need to schedule another stop, we only need to let it happen.
1582                    prev.setState(STOPPING, "completePausedLocked");
1583                } else if (!prev.visible || shouldSleepOrShutDownActivities()) {
1584                    // Clear out any deferred client hide we might currently have.
1585                    prev.setDeferHidingClient(false);
1586                    // If we were visible then resumeTopActivities will release resources before
1587                    // stopping.
1588                    addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
1589                }
1590            } else {
1591                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
1592                prev = null;
1593            }
1594            // It is possible the activity was freezing the screen before it was paused.
1595            // In that case go ahead and remove the freeze this activity has on the screen
1596            // since it is no longer visible.
1597            if (prev != null) {
1598                prev.stopFreezingScreenLocked(true /*force*/);
1599            }
1600            mPausingActivity = null;
1601        }
1602
1603        if (resumeNext) {
1604            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
1605            if (!topStack.shouldSleepOrShutDownActivities()) {
1606                mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
1607            } else {
1608                checkReadyForSleep();
1609                ActivityRecord top = topStack.topRunningActivityLocked();
1610                if (top == null || (prev != null && top != prev)) {
1611                    // If there are no more activities available to run, do resume anyway to start
1612                    // something. Also if the top activity on the stack is not the just paused
1613                    // activity, we need to go ahead and resume it to ensure we complete an
1614                    // in-flight app switch.
1615                    mStackSupervisor.resumeFocusedStackTopActivityLocked();
1616                }
1617            }
1618        }
1619
1620        if (prev != null) {
1621            prev.resumeKeyDispatchingLocked();
1622
1623            if (prev.app != null && prev.cpuTimeAtResume > 0
1624                    && mService.mBatteryStatsService.isOnBattery()) {
1625                long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
1626                        - prev.cpuTimeAtResume;
1627                if (diff > 0) {
1628                    BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1629                    synchronized (bsi) {
1630                        BatteryStatsImpl.Uid.Proc ps =
1631                                bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1632                                        prev.info.packageName);
1633                        if (ps != null) {
1634                            ps.addForegroundTimeLocked(diff);
1635                        }
1636                    }
1637                }
1638            }
1639            prev.cpuTimeAtResume = 0; // reset it
1640        }
1641
1642        // Notify when the task stack has changed, but only if visibilities changed (not just
1643        // focus). Also if there is an active pinned stack - we always want to notify it about
1644        // task stack changes, because its positioning may depend on it.
1645        if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
1646                || getDisplay().hasPinnedStack()) {
1647            mService.mTaskChangeNotificationController.notifyTaskStackChanged();
1648            mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
1649        }
1650
1651        mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS);
1652    }
1653
1654    void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
1655        if (!mStackSupervisor.mStoppingActivities.contains(r)) {
1656            mStackSupervisor.mStoppingActivities.add(r);
1657        }
1658
1659        // If we already have a few activities waiting to stop, then give up
1660        // on things going idle and start clearing them out. Or if r is the
1661        // last of activity of the last task the stack will be empty and must
1662        // be cleared immediately.
1663        boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
1664                || (r.frontOfTask && mTaskHistory.size() <= 1);
1665        if (scheduleIdle || forceIdle) {
1666            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle="
1667                    + forceIdle + "immediate=" + !idleDelayed);
1668            if (!idleDelayed) {
1669                mStackSupervisor.scheduleIdleLocked();
1670            } else {
1671                mStackSupervisor.scheduleIdleTimeoutLocked(r);
1672            }
1673        } else {
1674            checkReadyForSleep();
1675        }
1676    }
1677
1678    /**
1679     * Returns true if the stack is translucent and can have other contents visible behind it if
1680     * needed. A stack is considered translucent if it don't contain a visible or
1681     * starting (about to be visible) activity that is fullscreen (opaque).
1682     * @param starting The currently starting activity or null if there is none.
1683     */
1684    @VisibleForTesting
1685    boolean isStackTranslucent(ActivityRecord starting) {
1686        if (!isAttached() || mForceHidden) {
1687            return true;
1688        }
1689        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1690            final TaskRecord task = mTaskHistory.get(taskNdx);
1691            final ArrayList<ActivityRecord> activities = task.mActivities;
1692            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1693                final ActivityRecord r = activities.get(activityNdx);
1694
1695                if (r.finishing) {
1696                    // We don't factor in finishing activities when determining translucency since
1697                    // they will be gone soon.
1698                    continue;
1699                }
1700
1701                if (!r.visibleIgnoringKeyguard && r != starting) {
1702                    // Also ignore invisible activities that are not the currently starting
1703                    // activity (about to be visible).
1704                    continue;
1705                }
1706
1707                if (r.fullscreen || r.hasWallpaper) {
1708                    // Stack isn't translucent if it has at least one fullscreen activity
1709                    // that is visible.
1710                    return false;
1711                }
1712            }
1713        }
1714        return true;
1715    }
1716
1717    boolean isTopStackOnDisplay() {
1718        return getDisplay().isTopStack(this);
1719    }
1720
1721    boolean isTopActivityVisible() {
1722        final ActivityRecord topActivity = getTopActivity();
1723        return topActivity != null && topActivity.visible;
1724    }
1725
1726    /**
1727     * Returns true if the stack should be visible.
1728     *
1729     * @param starting The currently starting activity or null if there is none.
1730     */
1731    boolean shouldBeVisible(ActivityRecord starting) {
1732        if (!isAttached() || mForceHidden) {
1733            return false;
1734        }
1735        if (mStackSupervisor.isFocusedStack(this)) {
1736            return true;
1737        }
1738
1739        final ActivityRecord top = topRunningActivityLocked();
1740        if (top == null && isInStackLocked(starting) == null && !isTopStackOnDisplay()) {
1741            // Shouldn't be visible if you don't have any running activities, not starting one, and
1742            // not the top stack on display.
1743            return false;
1744        }
1745
1746        final ActivityDisplay display = getDisplay();
1747        boolean gotSplitScreenStack = false;
1748        boolean gotOpaqueSplitScreenPrimary = false;
1749        boolean gotOpaqueSplitScreenSecondary = false;
1750        final int windowingMode = getWindowingMode();
1751        final boolean isAssistantType = isActivityTypeAssistant();
1752        for (int i = display.getChildCount() - 1; i >= 0; --i) {
1753            final ActivityStack other = display.getChildAt(i);
1754            if (other == this) {
1755                // Should be visible if there is no other stack occluding it.
1756                return true;
1757            }
1758
1759            final int otherWindowingMode = other.getWindowingMode();
1760
1761            if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
1762                // In this case the home stack isn't resizeable even though we are in split-screen
1763                // mode. We still want the primary splitscreen stack to be visible as there will be
1764                // a slight hint of it in the status bar area above the non-resizeable home
1765                // activity. In addition, if the fullscreen assistant is over primary splitscreen
1766                // stack, the stack should still be visible in the background as long as the recents
1767                // animation is running.
1768                final int activityType = other.getActivityType();
1769                if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
1770                    if (activityType == ACTIVITY_TYPE_HOME
1771                            || (activityType == ACTIVITY_TYPE_ASSISTANT
1772                                    && mWindowManager.getRecentsAnimationController() != null)) {
1773                       return true;
1774                    }
1775                }
1776                if (other.isStackTranslucent(starting)) {
1777                    // Can be visible behind a translucent fullscreen stack.
1778                    continue;
1779                }
1780                return false;
1781            } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
1782                    && !gotOpaqueSplitScreenPrimary) {
1783                gotSplitScreenStack = true;
1784                gotOpaqueSplitScreenPrimary =
1785                        !other.isStackTranslucent(starting);
1786                if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
1787                        && gotOpaqueSplitScreenPrimary) {
1788                    // Can not be visible behind another opaque stack in split-screen-primary mode.
1789                    return false;
1790                }
1791            } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1792                    && !gotOpaqueSplitScreenSecondary) {
1793                gotSplitScreenStack = true;
1794                gotOpaqueSplitScreenSecondary =
1795                        !other.isStackTranslucent(starting);
1796                if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1797                        && gotOpaqueSplitScreenSecondary) {
1798                    // Can not be visible behind another opaque stack in split-screen-secondary mode.
1799                    return false;
1800                }
1801            }
1802            if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
1803                // Can not be visible if we are in split-screen windowing mode and both halves of
1804                // the screen are opaque.
1805                return false;
1806            }
1807            if (isAssistantType && gotSplitScreenStack) {
1808                // Assistant stack can't be visible behind split-screen. In addition to this not
1809                // making sense, it also works around an issue here we boost the z-order of the
1810                // assistant window surfaces in window manager whenever it is visible.
1811                return false;
1812            }
1813        }
1814
1815        // Well, nothing is stopping you from being visible...
1816        return true;
1817    }
1818
1819    final int rankTaskLayers(int baseLayer) {
1820        int layer = 0;
1821        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1822            final TaskRecord task = mTaskHistory.get(taskNdx);
1823            ActivityRecord r = task.topRunningActivityLocked();
1824            if (r == null || r.finishing || !r.visible) {
1825                task.mLayerRank = -1;
1826            } else {
1827                task.mLayerRank = baseLayer + layer++;
1828            }
1829        }
1830        return layer;
1831    }
1832
1833    /**
1834     * Make sure that all activities that need to be visible in the stack (that is, they
1835     * currently can be seen by the user) actually are and update their configuration.
1836     */
1837    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
1838            boolean preserveWindows) {
1839        ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
1840                true /* notifyClients */);
1841    }
1842
1843    /**
1844     * Ensure visibility with an option to also update the configuration of visible activities.
1845     * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
1846     * @see ActivityStackSupervisor#ensureActivitiesVisibleLocked(ActivityRecord, int, boolean)
1847     */
1848    // TODO: Should be re-worked based on the fact that each task as a stack in most cases.
1849    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
1850            boolean preserveWindows, boolean notifyClients) {
1851        mTopActivityOccludesKeyguard = false;
1852        mTopDismissingKeyguardActivity = null;
1853        mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
1854        try {
1855            ActivityRecord top = topRunningActivityLocked();
1856            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
1857                    + " configChanges=0x" + Integer.toHexString(configChanges));
1858            if (top != null) {
1859                checkTranslucentActivityWaiting(top);
1860            }
1861
1862            // If the top activity is not fullscreen, then we need to
1863            // make sure any activities under it are now visible.
1864            boolean aboveTop = top != null;
1865            final boolean stackShouldBeVisible = shouldBeVisible(starting);
1866            boolean behindFullscreenActivity = !stackShouldBeVisible;
1867            boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
1868                    && (isInStackLocked(starting) == null);
1869            final boolean isTopNotPinnedStack =
1870                    isAttached() && getDisplay().isTopNotPinnedStack(this);
1871            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1872                final TaskRecord task = mTaskHistory.get(taskNdx);
1873                final ArrayList<ActivityRecord> activities = task.mActivities;
1874                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1875                    final ActivityRecord r = activities.get(activityNdx);
1876                    if (r.finishing) {
1877                        continue;
1878                    }
1879                    final boolean isTop = r == top;
1880                    if (aboveTop && !isTop) {
1881                        continue;
1882                    }
1883                    aboveTop = false;
1884
1885                    // Check whether activity should be visible without Keyguard influence
1886                    final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard(
1887                            behindFullscreenActivity);
1888                    r.visibleIgnoringKeyguard = visibleIgnoringKeyguard;
1889
1890                    // Now check whether it's really visible depending on Keyguard state.
1891                    final boolean reallyVisible = checkKeyguardVisibility(r,
1892                            visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
1893                    if (visibleIgnoringKeyguard) {
1894                        behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible,
1895                                behindFullscreenActivity, r);
1896                    }
1897                    if (reallyVisible) {
1898                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
1899                                + " finishing=" + r.finishing + " state=" + r.getState());
1900                        // First: if this is not the current activity being started, make
1901                        // sure it matches the current configuration.
1902                        if (r != starting && notifyClients) {
1903                            r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows,
1904                                    true /* ignoreStopState */);
1905                        }
1906
1907                        if (r.app == null || r.app.thread == null) {
1908                            if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
1909                                    resumeNextActivity, r)) {
1910                                if (activityNdx >= activities.size()) {
1911                                    // Record may be removed if its process needs to restart.
1912                                    activityNdx = activities.size() - 1;
1913                                } else {
1914                                    resumeNextActivity = false;
1915                                }
1916                            }
1917                        } else if (r.visible) {
1918                            // If this activity is already visible, then there is nothing to do here.
1919                            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
1920                                    "Skipping: already visible at " + r);
1921
1922                            if (r.mClientVisibilityDeferred && notifyClients) {
1923                                r.makeClientVisible();
1924                            }
1925
1926                            if (r.handleAlreadyVisible()) {
1927                                resumeNextActivity = false;
1928                            }
1929                        } else {
1930                            r.makeVisibleIfNeeded(starting, notifyClients);
1931                        }
1932                        // Aggregate current change flags.
1933                        configChanges |= r.configChangeFlags;
1934                    } else {
1935                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
1936                                + " finishing=" + r.finishing + " state=" + r.getState()
1937                                + " stackShouldBeVisible=" + stackShouldBeVisible
1938                                + " behindFullscreenActivity=" + behindFullscreenActivity
1939                                + " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
1940                        makeInvisible(r);
1941                    }
1942                }
1943                final int windowingMode = getWindowingMode();
1944                if (windowingMode == WINDOWING_MODE_FREEFORM) {
1945                    // The visibility of tasks and the activities they contain in freeform stack are
1946                    // determined individually unlike other stacks where the visibility or fullscreen
1947                    // status of an activity in a previous task affects other.
1948                    behindFullscreenActivity = !stackShouldBeVisible;
1949                } else if (isActivityTypeHome()) {
1950                    if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
1951                            + " stackShouldBeVisible=" + stackShouldBeVisible
1952                            + " behindFullscreenActivity=" + behindFullscreenActivity);
1953                    // No other task in the home stack should be visible behind the home activity.
1954                    // Home activities is usually a translucent activity with the wallpaper behind
1955                    // them. However, when they don't have the wallpaper behind them, we want to
1956                    // show activities in the next application stack behind them vs. another
1957                    // task in the home stack like recents.
1958                    behindFullscreenActivity = true;
1959                }
1960            }
1961
1962            if (mTranslucentActivityWaiting != null &&
1963                    mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
1964                // Nothing is getting drawn or everything was already visible, don't wait for timeout.
1965                notifyActivityDrawnLocked(null);
1966            }
1967        } finally {
1968            mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate();
1969        }
1970    }
1971
1972    void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
1973        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1974            mTaskHistory.get(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch);
1975        }
1976    }
1977
1978    /**
1979     * @return true if the top visible activity wants to occlude the Keyguard, false otherwise
1980     */
1981    boolean topActivityOccludesKeyguard() {
1982        return mTopActivityOccludesKeyguard;
1983    }
1984
1985    /**
1986     * Returns true if this stack should be resized to match the bounds specified by
1987     * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack.
1988     */
1989    boolean resizeStackWithLaunchBounds() {
1990        return inPinnedWindowingMode();
1991    }
1992
1993    @Override
1994    public boolean supportsSplitScreenWindowingMode() {
1995        final TaskRecord topTask = topTask();
1996        return super.supportsSplitScreenWindowingMode()
1997                && (topTask == null || topTask.supportsSplitScreenWindowingMode());
1998    }
1999
2000    /** @return True if the resizing of the primary-split-screen stack affects this stack size. */
2001    boolean affectedBySplitScreenResize() {
2002        if (!supportsSplitScreenWindowingMode()) {
2003            return false;
2004        }
2005        final int windowingMode = getWindowingMode();
2006        return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED;
2007    }
2008
2009    /**
2010     * @return the top most visible activity that wants to dismiss Keyguard
2011     */
2012    ActivityRecord getTopDismissingKeyguardActivity() {
2013        return mTopDismissingKeyguardActivity;
2014    }
2015
2016    /**
2017     * Checks whether {@param r} should be visible depending on Keyguard state and updates
2018     * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if
2019     * necessary.
2020     *
2021     * @return true if {@param r} is visible taken Keyguard state into account, false otherwise
2022     */
2023    boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) {
2024        final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
2025        final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController()
2026                .isKeyguardOrAodShowing(displayId);
2027        final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked();
2028        final boolean showWhenLocked = r.canShowWhenLocked();
2029        final boolean dismissKeyguard = r.hasDismissKeyguardWindows();
2030        if (shouldBeVisible) {
2031            if (dismissKeyguard && mTopDismissingKeyguardActivity == null) {
2032                mTopDismissingKeyguardActivity = r;
2033            }
2034
2035            // Only the top activity may control occluded, as we can't occlude the Keyguard if the
2036            // top app doesn't want to occlude it.
2037            if (isTop) {
2038                mTopActivityOccludesKeyguard |= showWhenLocked;
2039            }
2040
2041            final boolean canShowWithKeyguard = canShowWithInsecureKeyguard()
2042                    && mStackSupervisor.getKeyguardController().canDismissKeyguard();
2043            if (canShowWithKeyguard) {
2044                return true;
2045            }
2046        }
2047        if (keyguardOrAodShowing) {
2048            // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
2049            // right away and AOD isn't visible.
2050            return shouldBeVisible && mStackSupervisor.getKeyguardController()
2051                    .canShowActivityWhileKeyguardShowing(r, dismissKeyguard);
2052        } else if (keyguardLocked) {
2053            return shouldBeVisible && mStackSupervisor.getKeyguardController().canShowWhileOccluded(
2054                    dismissKeyguard, showWhenLocked);
2055        } else {
2056            return shouldBeVisible;
2057        }
2058    }
2059
2060    /**
2061     * Check if the display to which this stack is attached has
2062     * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
2063     */
2064    private boolean canShowWithInsecureKeyguard() {
2065        final ActivityDisplay activityDisplay = getDisplay();
2066        if (activityDisplay == null) {
2067            throw new IllegalStateException("Stack is not attached to any display, stackId="
2068                    + mStackId);
2069        }
2070
2071        final int flags = activityDisplay.mDisplay.getFlags();
2072        return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
2073    }
2074
2075    private void checkTranslucentActivityWaiting(ActivityRecord top) {
2076        if (mTranslucentActivityWaiting != top) {
2077            mUndrawnActivitiesBelowTopTranslucent.clear();
2078            if (mTranslucentActivityWaiting != null) {
2079                // Call the callback with a timeout indication.
2080                notifyActivityDrawnLocked(null);
2081                mTranslucentActivityWaiting = null;
2082            }
2083            mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
2084        }
2085    }
2086
2087    private boolean makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges,
2088            boolean isTop, boolean andResume, ActivityRecord r) {
2089        // We need to make sure the app is running if it's the top, or it is just made visible from
2090        // invisible. If the app is already visible, it must have died while it was visible. In this
2091        // case, we'll show the dead window but will not restart the app. Otherwise we could end up
2092        // thrashing.
2093        if (isTop || !r.visible) {
2094            // This activity needs to be visible, but isn't even running...
2095            // get it started and resume if no other stack in this stack is resumed.
2096            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r);
2097            if (r != starting) {
2098                r.startFreezingScreenLocked(r.app, configChanges);
2099            }
2100            if (!r.visible || r.mLaunchTaskBehind) {
2101                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r);
2102                r.setVisible(true);
2103            }
2104            if (r != starting) {
2105                mStackSupervisor.startSpecificActivityLocked(r, andResume, false);
2106                return true;
2107            }
2108        }
2109        return false;
2110    }
2111
2112    // TODO: Should probably be moved into ActivityRecord.
2113    private void makeInvisible(ActivityRecord r) {
2114        if (!r.visible) {
2115            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r);
2116            return;
2117        }
2118        // Now for any activities that aren't visible to the user, make sure they no longer are
2119        // keeping the screen frozen.
2120        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.getState());
2121        try {
2122            final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
2123                    "makeInvisible", true /* beforeStopping */);
2124            // Defer telling the client it is hidden if it can enter Pip and isn't current paused,
2125            // stopped or stopping. This gives it a chance to enter Pip in onPause().
2126            // TODO: There is still a question surrounding activities in multi-window mode that want
2127            // to enter Pip after they are paused, but are still visible. I they should be okay to
2128            // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and
2129            // the current contract for "auto-Pip" is that the app should enter it before onPause
2130            // returns. Just need to confirm this reasoning makes sense.
2131            final boolean deferHidingClient = canEnterPictureInPicture
2132                    && !r.isState(STOPPING, STOPPED, PAUSED);
2133            r.setDeferHidingClient(deferHidingClient);
2134            r.setVisible(false);
2135
2136            switch (r.getState()) {
2137                case STOPPING:
2138                case STOPPED:
2139                    if (r.app != null && r.app.thread != null) {
2140                        if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
2141                                "Scheduling invisibility: " + r);
2142                        mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
2143                                WindowVisibilityItem.obtain(false /* showWindow */));
2144                    }
2145
2146                    // Reset the flag indicating that an app can enter picture-in-picture once the
2147                    // activity is hidden
2148                    r.supportsEnterPipOnTaskSwitch = false;
2149                    break;
2150
2151                case INITIALIZING:
2152                case RESUMED:
2153                case PAUSING:
2154                case PAUSED:
2155                    addToStopping(r, true /* scheduleIdle */,
2156                            canEnterPictureInPicture /* idleDelayed */);
2157                    break;
2158
2159                default:
2160                    break;
2161            }
2162        } catch (Exception e) {
2163            // Just skip on any failure; we'll make it visible when it next restarts.
2164            Slog.w(TAG, "Exception thrown making hidden: " + r.intent.getComponent(), e);
2165        }
2166    }
2167
2168    private boolean updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity,
2169            ActivityRecord r) {
2170        if (r.fullscreen) {
2171            if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r
2172                        + " stackInvisible=" + stackInvisible
2173                        + " behindFullscreenActivity=" + behindFullscreenActivity);
2174            // At this point, nothing else needs to be shown in this task.
2175            behindFullscreenActivity = true;
2176        }
2177        return behindFullscreenActivity;
2178    }
2179
2180    void convertActivityToTranslucent(ActivityRecord r) {
2181        mTranslucentActivityWaiting = r;
2182        mUndrawnActivitiesBelowTopTranslucent.clear();
2183        mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
2184    }
2185
2186    void clearOtherAppTimeTrackers(AppTimeTracker except) {
2187        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2188            final TaskRecord task = mTaskHistory.get(taskNdx);
2189            final ArrayList<ActivityRecord> activities = task.mActivities;
2190            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2191                final ActivityRecord r = activities.get(activityNdx);
2192                if ( r.appTimeTracker != except) {
2193                    r.appTimeTracker = null;
2194                }
2195            }
2196        }
2197    }
2198
2199    /**
2200     * Called as activities below the top translucent activity are redrawn. When the last one is
2201     * redrawn notify the top activity by calling
2202     * {@link Activity#onTranslucentConversionComplete}.
2203     *
2204     * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
2205     * occurred and the activity will be notified immediately.
2206     */
2207    void notifyActivityDrawnLocked(ActivityRecord r) {
2208        if ((r == null)
2209                || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
2210                        mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
2211            // The last undrawn activity below the top has just been drawn. If there is an
2212            // opaque activity at the top, notify it that it can become translucent safely now.
2213            final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
2214            mTranslucentActivityWaiting = null;
2215            mUndrawnActivitiesBelowTopTranslucent.clear();
2216            mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
2217
2218            if (waitingActivity != null) {
2219                mWindowManager.setWindowOpaque(waitingActivity.appToken, false);
2220                if (waitingActivity.app != null && waitingActivity.app.thread != null) {
2221                    try {
2222                        waitingActivity.app.thread.scheduleTranslucentConversionComplete(
2223                                waitingActivity.appToken, r != null);
2224                    } catch (RemoteException e) {
2225                    }
2226                }
2227            }
2228        }
2229    }
2230
2231    /** If any activities below the top running one are in the INITIALIZING state and they have a
2232     * starting window displayed then remove that starting window. It is possible that the activity
2233     * in this state will never resumed in which case that starting window will be orphaned. */
2234    void cancelInitializingActivities() {
2235        final ActivityRecord topActivity = topRunningActivityLocked();
2236        boolean aboveTop = true;
2237        // We don't want to clear starting window for activities that aren't behind fullscreen
2238        // activities as we need to display their starting window until they are done initializing.
2239        boolean behindFullscreenActivity = false;
2240
2241        if (!shouldBeVisible(null)) {
2242            // The stack is not visible, so no activity in it should be displaying a starting
2243            // window. Mark all activities below top and behind fullscreen.
2244            aboveTop = false;
2245            behindFullscreenActivity = true;
2246        }
2247
2248        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2249            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2250            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2251                final ActivityRecord r = activities.get(activityNdx);
2252                if (aboveTop) {
2253                    if (r == topActivity) {
2254                        aboveTop = false;
2255                    }
2256                    behindFullscreenActivity |= r.fullscreen;
2257                    continue;
2258                }
2259
2260                r.removeOrphanedStartingWindow(behindFullscreenActivity);
2261                behindFullscreenActivity |= r.fullscreen;
2262            }
2263        }
2264    }
2265
2266    /**
2267     * Ensure that the top activity in the stack is resumed.
2268     *
2269     * @param prev The previously resumed activity, for when in the process
2270     * of pausing; can be null to call from elsewhere.
2271     * @param options Activity options.
2272     *
2273     * @return Returns true if something is being resumed, or false if
2274     * nothing happened.
2275     *
2276     * NOTE: It is not safe to call this method directly as it can cause an activity in a
2277     *       non-focused stack to be resumed.
2278     *       Use {@link ActivityStackSupervisor#resumeFocusedStackTopActivityLocked} to resume the
2279     *       right activity for the current system state.
2280     */
2281    @GuardedBy("mService")
2282    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
2283        if (mStackSupervisor.inResumeTopActivity) {
2284            // Don't even start recursing.
2285            return false;
2286        }
2287
2288        boolean result = false;
2289        try {
2290            // Protect against recursion.
2291            mStackSupervisor.inResumeTopActivity = true;
2292            result = resumeTopActivityInnerLocked(prev, options);
2293
2294            // When resuming the top activity, it may be necessary to pause the top activity (for
2295            // example, returning to the lock screen. We suppress the normal pause logic in
2296            // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
2297            // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
2298            // to ensure any necessary pause logic occurs. In the case where the Activity will be
2299            // shown regardless of the lock screen, the call to
2300            // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
2301            final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
2302            if (next == null || !next.canTurnScreenOn()) {
2303                checkReadyForSleep();
2304            }
2305        } finally {
2306            mStackSupervisor.inResumeTopActivity = false;
2307        }
2308
2309        return result;
2310    }
2311
2312    /**
2313     * Returns the currently resumed activity.
2314     */
2315    protected ActivityRecord getResumedActivity() {
2316        return mResumedActivity;
2317    }
2318
2319    private void setResumedActivity(ActivityRecord r, String reason) {
2320        if (mResumedActivity == r) {
2321            return;
2322        }
2323
2324        if (DEBUG_STACK) Slog.d(TAG_STACK, "setResumedActivity stack:" + this + " + from: "
2325                + mResumedActivity + " to:" + r + " reason:" + reason);
2326        mResumedActivity = r;
2327    }
2328
2329    @GuardedBy("mService")
2330    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
2331        if (!mService.mBooting && !mService.mBooted) {
2332            // Not ready yet!
2333            return false;
2334        }
2335
2336        // Find the next top-most activity to resume in this stack that is not finishing and is
2337        // focusable. If it is not focusable, we will fall into the case below to resume the
2338        // top activity in the next focusable task.
2339        final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
2340
2341        final boolean hasRunningActivity = next != null;
2342
2343        // TODO: Maybe this entire condition can get removed?
2344        if (hasRunningActivity && !isAttached()) {
2345            return false;
2346        }
2347
2348        mStackSupervisor.cancelInitializingActivities();
2349
2350        // Remember how we'll process this pause/resume situation, and ensure
2351        // that the state is reset however we wind up proceeding.
2352        boolean userLeaving = mStackSupervisor.mUserLeaving;
2353        mStackSupervisor.mUserLeaving = false;
2354
2355        if (!hasRunningActivity) {
2356            // There are no activities left in the stack, let's look somewhere else.
2357            return resumeTopActivityInNextFocusableStack(prev, options, "noMoreActivities");
2358        }
2359
2360        next.delayedResume = false;
2361
2362        // If the top activity is the resumed one, nothing to do.
2363        if (mResumedActivity == next && next.isState(RESUMED)
2364                && mStackSupervisor.allResumedActivitiesComplete()) {
2365            // Make sure we have executed any pending transitions, since there
2366            // should be nothing left to do at this point.
2367            executeAppTransition(options);
2368            if (DEBUG_STATES) Slog.d(TAG_STATES,
2369                    "resumeTopActivityLocked: Top activity resumed " + next);
2370            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2371            return false;
2372        }
2373
2374        // If we are sleeping, and there is no resumed activity, and the top
2375        // activity is paused, well that is the state we want.
2376        if (shouldSleepOrShutDownActivities()
2377                && mLastPausedActivity == next
2378                && mStackSupervisor.allPausedActivitiesComplete()) {
2379            // Make sure we have executed any pending transitions, since there
2380            // should be nothing left to do at this point.
2381            executeAppTransition(options);
2382            if (DEBUG_STATES) Slog.d(TAG_STATES,
2383                    "resumeTopActivityLocked: Going to sleep and all paused");
2384            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2385            return false;
2386        }
2387
2388        // Make sure that the user who owns this activity is started.  If not,
2389        // we will just leave it as is because someone should be bringing
2390        // another user's activities to the top of the stack.
2391        if (!mService.mUserController.hasStartedUserState(next.userId)) {
2392            Slog.w(TAG, "Skipping resume of top activity " + next
2393                    + ": user " + next.userId + " is stopped");
2394            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2395            return false;
2396        }
2397
2398        // The activity may be waiting for stop, but that is no longer
2399        // appropriate for it.
2400        mStackSupervisor.mStoppingActivities.remove(next);
2401        mStackSupervisor.mGoingToSleepActivities.remove(next);
2402        next.sleeping = false;
2403        mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(next);
2404
2405        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
2406
2407        // If we are currently pausing an activity, then don't do anything until that is done.
2408        if (!mStackSupervisor.allPausedActivitiesComplete()) {
2409            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
2410                    "resumeTopActivityLocked: Skip resume: some activity pausing.");
2411            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2412            return false;
2413        }
2414
2415        mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
2416
2417        boolean lastResumedCanPip = false;
2418        ActivityRecord lastResumed = null;
2419        final ActivityStack lastFocusedStack = mStackSupervisor.getLastStack();
2420        if (lastFocusedStack != null && lastFocusedStack != this) {
2421            // So, why aren't we using prev here??? See the param comment on the method. prev doesn't
2422            // represent the last resumed activity. However, the last focus stack does if it isn't null.
2423            lastResumed = lastFocusedStack.mResumedActivity;
2424            if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) {
2425                // The user isn't leaving if this stack is the multi-window mode and the last
2426                // focused stack should still be visible.
2427                if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false"
2428                        + " next=" + next + " lastResumed=" + lastResumed);
2429                userLeaving = false;
2430            }
2431            lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
2432                    "resumeTopActivity", userLeaving /* beforeStopping */);
2433        }
2434        // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
2435        // to be paused, while at the same time resuming the new resume activity only if the
2436        // previous activity can't go into Pip since we want to give Pip activities a chance to
2437        // enter Pip before resuming the next activity.
2438        final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
2439                && !lastResumedCanPip;
2440
2441        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
2442        if (mResumedActivity != null) {
2443            if (DEBUG_STATES) Slog.d(TAG_STATES,
2444                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
2445            pausing |= startPausingLocked(userLeaving, false, next, false);
2446        }
2447        if (pausing && !resumeWhilePausing) {
2448            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
2449                    "resumeTopActivityLocked: Skip resume: need to start pausing");
2450            // At this point we want to put the upcoming activity's process
2451            // at the top of the LRU list, since we know we will be needing it
2452            // very soon and it would be a waste to let it get killed if it
2453            // happens to be sitting towards the end.
2454            if (next.app != null && next.app.thread != null) {
2455                mService.updateLruProcessLocked(next.app, true, null);
2456            }
2457            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2458            if (lastResumed != null) {
2459                lastResumed.setWillCloseOrEnterPip(true);
2460            }
2461            return true;
2462        } else if (mResumedActivity == next && next.isState(RESUMED)
2463                && mStackSupervisor.allResumedActivitiesComplete()) {
2464            // It is possible for the activity to be resumed when we paused back stacks above if the
2465            // next activity doesn't have to wait for pause to complete.
2466            // So, nothing else to-do except:
2467            // Make sure we have executed any pending transitions, since there
2468            // should be nothing left to do at this point.
2469            executeAppTransition(options);
2470            if (DEBUG_STATES) Slog.d(TAG_STATES,
2471                    "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next);
2472            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2473            return true;
2474        }
2475
2476        // If the most recent activity was noHistory but was only stopped rather
2477        // than stopped+finished because the device went to sleep, we need to make
2478        // sure to finish it as we're making a new activity topmost.
2479        if (shouldSleepActivities() && mLastNoHistoryActivity != null &&
2480                !mLastNoHistoryActivity.finishing) {
2481            if (DEBUG_STATES) Slog.d(TAG_STATES,
2482                    "no-history finish of " + mLastNoHistoryActivity + " on new resume");
2483            requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
2484                    null, "resume-no-history", false);
2485            mLastNoHistoryActivity = null;
2486        }
2487
2488        if (prev != null && prev != next) {
2489            if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
2490                    && next != null && !next.nowVisible) {
2491                mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev);
2492                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
2493                        "Resuming top, waiting visible to hide: " + prev);
2494            } else {
2495                // The next activity is already visible, so hide the previous
2496                // activity's windows right now so we can show the new one ASAP.
2497                // We only do this if the previous is finishing, which should mean
2498                // it is on top of the one being resumed so hiding it quickly
2499                // is good.  Otherwise, we want to do the normal route of allowing
2500                // the resumed activity to be shown so we can decide if the
2501                // previous should actually be hidden depending on whether the
2502                // new one is found to be full-screen or not.
2503                if (prev.finishing) {
2504                    prev.setVisibility(false);
2505                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
2506                            "Not waiting for visible to hide: " + prev + ", waitingVisible="
2507                            + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
2508                            + ", nowVisible=" + next.nowVisible);
2509                } else {
2510                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
2511                            "Previous already visible but still waiting to hide: " + prev
2512                            + ", waitingVisible="
2513                            + mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(prev)
2514                            + ", nowVisible=" + next.nowVisible);
2515                }
2516            }
2517        }
2518
2519        // Launching this app's activity, make sure the app is no longer
2520        // considered stopped.
2521        try {
2522            AppGlobals.getPackageManager().setPackageStoppedState(
2523                    next.packageName, false, next.userId); /* TODO: Verify if correct userid */
2524        } catch (RemoteException e1) {
2525        } catch (IllegalArgumentException e) {
2526            Slog.w(TAG, "Failed trying to unstop package "
2527                    + next.packageName + ": " + e);
2528        }
2529
2530        // We are starting up the next activity, so tell the window manager
2531        // that the previous one will be hidden soon.  This way it can know
2532        // to ignore it when computing the desired screen orientation.
2533        boolean anim = true;
2534        if (prev != null) {
2535            if (prev.finishing) {
2536                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
2537                        "Prepare close transition: prev=" + prev);
2538                if (mStackSupervisor.mNoAnimActivities.contains(prev)) {
2539                    anim = false;
2540                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
2541                } else {
2542                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
2543                            ? TRANSIT_ACTIVITY_CLOSE
2544                            : TRANSIT_TASK_CLOSE, false);
2545                }
2546                prev.setVisibility(false);
2547            } else {
2548                if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
2549                        "Prepare open transition: prev=" + prev);
2550                if (mStackSupervisor.mNoAnimActivities.contains(next)) {
2551                    anim = false;
2552                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
2553                } else {
2554                    mWindowManager.prepareAppTransition(prev.getTask() == next.getTask()
2555                            ? TRANSIT_ACTIVITY_OPEN
2556                            : next.mLaunchTaskBehind
2557                                    ? TRANSIT_TASK_OPEN_BEHIND
2558                                    : TRANSIT_TASK_OPEN, false);
2559                }
2560            }
2561        } else {
2562            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
2563            if (mStackSupervisor.mNoAnimActivities.contains(next)) {
2564                anim = false;
2565                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
2566            } else {
2567                mWindowManager.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
2568            }
2569        }
2570
2571        if (anim) {
2572            next.applyOptionsLocked();
2573        } else {
2574            next.clearOptionsLocked();
2575        }
2576
2577        mStackSupervisor.mNoAnimActivities.clear();
2578
2579        ActivityStack lastStack = mStackSupervisor.getLastStack();
2580        if (next.app != null && next.app.thread != null) {
2581            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next
2582                    + " stopped=" + next.stopped + " visible=" + next.visible);
2583
2584            // If the previous activity is translucent, force a visibility update of
2585            // the next activity, so that it's added to WM's opening app list, and
2586            // transition animation can be set up properly.
2587            // For example, pressing Home button with a translucent activity in focus.
2588            // Launcher is already visible in this case. If we don't add it to opening
2589            // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a
2590            // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation.
2591            final boolean lastActivityTranslucent = lastStack != null
2592                    && (lastStack.inMultiWindowMode()
2593                    || (lastStack.mLastPausedActivity != null
2594                    && !lastStack.mLastPausedActivity.fullscreen));
2595
2596            // The contained logic must be synchronized, since we are both changing the visibility
2597            // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will
2598            // ultimately cause the client code to schedule a layout. Since layouts retrieve the
2599            // current {@link Configuration}, we must ensure that the below code updates it before
2600            // the layout can occur.
2601            synchronized(mWindowManager.getWindowManagerLock()) {
2602                // This activity is now becoming visible.
2603                if (!next.visible || next.stopped || lastActivityTranslucent) {
2604                    next.setVisibility(true);
2605                }
2606
2607                // schedule launch ticks to collect information about slow apps.
2608                next.startLaunchTickingLocked();
2609
2610                ActivityRecord lastResumedActivity =
2611                        lastStack == null ? null :lastStack.mResumedActivity;
2612                final ActivityState lastState = next.getState();
2613
2614                mService.updateCpuStats();
2615
2616                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next
2617                        + " (in existing)");
2618
2619                next.setState(RESUMED, "resumeTopActivityInnerLocked");
2620
2621                mService.updateLruProcessLocked(next.app, true, null);
2622                updateLRUListLocked(next);
2623                mService.updateOomAdjLocked();
2624
2625                // Have the window manager re-evaluate the orientation of
2626                // the screen based on the new activity order.
2627                boolean notUpdated = true;
2628
2629                if (mStackSupervisor.isFocusedStack(this)) {
2630                    // We have special rotation behavior when here is some active activity that
2631                    // requests specific orientation or Keyguard is locked. Make sure all activity
2632                    // visibilities are set correctly as well as the transition is updated if needed
2633                    // to get the correct rotation behavior. Otherwise the following call to update
2634                    // the orientation may cause incorrect configurations delivered to client as a
2635                    // result of invisible window resize.
2636                    // TODO: Remove this once visibilities are set correctly immediately when
2637                    // starting an activity.
2638                    notUpdated = !mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
2639                            true /* markFrozenIfConfigChanged */, false /* deferResume */);
2640                }
2641
2642                if (notUpdated) {
2643                    // The configuration update wasn't able to keep the existing
2644                    // instance of the activity, and instead started a new one.
2645                    // We should be all done, but let's just make sure our activity
2646                    // is still at the top and schedule another run if something
2647                    // weird happened.
2648                    ActivityRecord nextNext = topRunningActivityLocked();
2649                    if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES,
2650                            "Activity config changed during resume: " + next
2651                                    + ", new next: " + nextNext);
2652                    if (nextNext != next) {
2653                        // Do over!
2654                        mStackSupervisor.scheduleResumeTopActivities();
2655                    }
2656                    if (!next.visible || next.stopped) {
2657                        next.setVisibility(true);
2658                    }
2659                    next.completeResumeLocked();
2660                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2661                    return true;
2662                }
2663
2664                try {
2665                    final ClientTransaction transaction = ClientTransaction.obtain(next.app.thread,
2666                            next.appToken);
2667                    // Deliver all pending results.
2668                    ArrayList<ResultInfo> a = next.results;
2669                    if (a != null) {
2670                        final int N = a.size();
2671                        if (!next.finishing && N > 0) {
2672                            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
2673                                    "Delivering results to " + next + ": " + a);
2674                            transaction.addCallback(ActivityResultItem.obtain(a));
2675                        }
2676                    }
2677
2678                    if (next.newIntents != null) {
2679                        transaction.addCallback(NewIntentItem.obtain(next.newIntents,
2680                                false /* andPause */));
2681                    }
2682
2683                    // Well the app will no longer be stopped.
2684                    // Clear app token stopped state in window manager if needed.
2685                    next.notifyAppResumed(next.stopped);
2686
2687                    EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
2688                            System.identityHashCode(next), next.getTask().taskId,
2689                            next.shortComponentName);
2690
2691                    next.sleeping = false;
2692                    mService.getAppWarningsLocked().onResumeActivity(next);
2693                    mService.showAskCompatModeDialogLocked(next);
2694                    next.app.pendingUiClean = true;
2695                    next.app.forceProcessStateUpTo(mService.mTopProcessState);
2696                    next.clearOptionsLocked();
2697                    transaction.setLifecycleStateRequest(
2698                            ResumeActivityItem.obtain(next.app.repProcState,
2699                                    mService.isNextTransitionForward()));
2700                    mService.getLifecycleManager().scheduleTransaction(transaction);
2701
2702                    if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed "
2703                            + next);
2704                } catch (Exception e) {
2705                    // Whoops, need to restart this activity!
2706                    if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to "
2707                            + lastState + ": " + next);
2708                    next.setState(lastState, "resumeTopActivityInnerLocked");
2709
2710                    // lastResumedActivity being non-null implies there is a lastStack present.
2711                    if (lastResumedActivity != null) {
2712                        lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked");
2713                    }
2714
2715                    Slog.i(TAG, "Restarting because process died: " + next);
2716                    if (!next.hasBeenLaunched) {
2717                        next.hasBeenLaunched = true;
2718                    } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null
2719                            && lastStack.isTopStackOnDisplay()) {
2720                        next.showStartingWindow(null /* prev */, false /* newTask */,
2721                                false /* taskSwitch */);
2722                    }
2723                    mStackSupervisor.startSpecificActivityLocked(next, true, false);
2724                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2725                    return true;
2726                }
2727            }
2728
2729            // From this point on, if something goes wrong there is no way
2730            // to recover the activity.
2731            try {
2732                next.completeResumeLocked();
2733            } catch (Exception e) {
2734                // If any exception gets thrown, toss away this
2735                // activity and try the next one.
2736                Slog.w(TAG, "Exception thrown during resume of " + next, e);
2737                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
2738                        "resume-exception", true);
2739                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2740                return true;
2741            }
2742        } else {
2743            // Whoops, need to restart this activity!
2744            if (!next.hasBeenLaunched) {
2745                next.hasBeenLaunched = true;
2746            } else {
2747                if (SHOW_APP_STARTING_PREVIEW) {
2748                    next.showStartingWindow(null /* prev */, false /* newTask */,
2749                            false /* taskSwich */);
2750                }
2751                if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
2752            }
2753            if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
2754            mStackSupervisor.startSpecificActivityLocked(next, true, true);
2755        }
2756
2757        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2758        return true;
2759    }
2760
2761    private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
2762            ActivityOptions options, String reason) {
2763        if (adjustFocusToNextFocusableStack(reason)) {
2764            // Try to move focus to the next visible stack with a running activity if this
2765            // stack is not covering the entire screen or is on a secondary display (with no home
2766            // stack).
2767            return mStackSupervisor.resumeFocusedStackTopActivityLocked(
2768                    mStackSupervisor.getFocusedStack(), prev, null);
2769        }
2770
2771        // Let's just start up the Launcher...
2772        ActivityOptions.abort(options);
2773        if (DEBUG_STATES) Slog.d(TAG_STATES,
2774                "resumeTopActivityInNextFocusableStack: " + reason + ", go home");
2775        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2776        // Only resume home if on home display
2777        return isOnHomeDisplay() &&
2778                mStackSupervisor.resumeHomeStackTask(prev, reason);
2779    }
2780
2781    private TaskRecord getNextTask(TaskRecord targetTask) {
2782        final int index = mTaskHistory.indexOf(targetTask);
2783        if (index >= 0) {
2784            final int numTasks = mTaskHistory.size();
2785            for (int i = index + 1; i < numTasks; ++i) {
2786                TaskRecord task = mTaskHistory.get(i);
2787                if (task.userId == targetTask.userId) {
2788                    return task;
2789                }
2790            }
2791        }
2792        return null;
2793    }
2794
2795    /** Returns the position the input task should be placed in this stack. */
2796    int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition,
2797            ActivityRecord starting) {
2798
2799        int maxPosition = mTaskHistory.size();
2800        if ((starting != null && starting.okToShowLocked())
2801                || (starting == null && task.okToShowLocked())) {
2802            // If the task or starting activity can be shown, then whatever position is okay.
2803            return Math.min(suggestedPosition, maxPosition);
2804        }
2805
2806        // The task can't be shown, put non-current user tasks below current user tasks.
2807        while (maxPosition > 0) {
2808            final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1);
2809            if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId)
2810                    || tmpTask.topRunningActivityLocked() == null) {
2811                break;
2812            }
2813            maxPosition--;
2814        }
2815
2816        return  Math.min(suggestedPosition, maxPosition);
2817    }
2818
2819    /**
2820     * Used from {@link ActivityStack#positionTask(TaskRecord, int)}.
2821     * @see ActivityManagerService#positionTaskInStack(int, int, int).
2822     */
2823    private void insertTaskAtPosition(TaskRecord task, int position) {
2824        if (position >= mTaskHistory.size()) {
2825            insertTaskAtTop(task, null);
2826            return;
2827        } else if (position <= 0) {
2828            insertTaskAtBottom(task);
2829            return;
2830        }
2831        position = getAdjustedPositionForTask(task, position, null /* starting */);
2832        mTaskHistory.remove(task);
2833        mTaskHistory.add(position, task);
2834        mWindowContainerController.positionChildAt(task.getWindowContainerController(), position);
2835        updateTaskMovement(task, true);
2836    }
2837
2838    private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
2839        // TODO: Better place to put all the code below...may be addTask...
2840        mTaskHistory.remove(task);
2841        // Now put task at top.
2842        final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
2843        mTaskHistory.add(position, task);
2844        updateTaskMovement(task, true);
2845        mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
2846                true /* includingParents */);
2847    }
2848
2849    private void insertTaskAtBottom(TaskRecord task) {
2850        // Unlike insertTaskAtPosition, this will also position parents of the windowcontroller.
2851        mTaskHistory.remove(task);
2852        final int position = getAdjustedPositionForTask(task, 0, null);
2853        mTaskHistory.add(position, task);
2854        updateTaskMovement(task, true);
2855        mWindowContainerController.positionChildAtBottom(task.getWindowContainerController(),
2856                true /* includingParents */);
2857    }
2858
2859    void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
2860            boolean newTask, boolean keepCurTransition, ActivityOptions options) {
2861        TaskRecord rTask = r.getTask();
2862        final int taskId = rTask.taskId;
2863        // mLaunchTaskBehind tasks get placed at the back of the task stack.
2864        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
2865            // Last activity in task had been removed or ActivityManagerService is reusing task.
2866            // Insert or replace.
2867            // Might not even be in.
2868            insertTaskAtTop(rTask, r);
2869        }
2870        TaskRecord task = null;
2871        if (!newTask) {
2872            // If starting in an existing task, find where that is...
2873            boolean startIt = true;
2874            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2875                task = mTaskHistory.get(taskNdx);
2876                if (task.getTopActivity() == null) {
2877                    // All activities in task are finishing.
2878                    continue;
2879                }
2880                if (task == rTask) {
2881                    // Here it is!  Now, if this is not yet visible to the
2882                    // user, then just add it without starting; it will
2883                    // get started when the user navigates back to it.
2884                    if (!startIt) {
2885                        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
2886                                + task, new RuntimeException("here").fillInStackTrace());
2887                        r.createWindowContainer();
2888                        ActivityOptions.abort(options);
2889                        return;
2890                    }
2891                    break;
2892                } else if (task.numFullscreen > 0) {
2893                    startIt = false;
2894                }
2895            }
2896        }
2897
2898        // Place a new activity at top of stack, so it is next to interact with the user.
2899
2900        // If we are not placing the new activity frontmost, we do not want to deliver the
2901        // onUserLeaving callback to the actual frontmost activity
2902        final TaskRecord activityTask = r.getTask();
2903        if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
2904            mStackSupervisor.mUserLeaving = false;
2905            if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
2906                    "startActivity() behind front, mUserLeaving=false");
2907        }
2908
2909        task = activityTask;
2910
2911        // Slot the activity into the history stack and proceed
2912        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
2913                new RuntimeException("here").fillInStackTrace());
2914        // TODO: Need to investigate if it is okay for the controller to already be created by the
2915        // time we get to this point. I think it is, but need to double check.
2916        // Use test in b/34179495 to trace the call path.
2917        if (r.getWindowContainerController() == null) {
2918            r.createWindowContainer();
2919        }
2920        task.setFrontOfTask();
2921
2922        if (!isHomeOrRecentsStack() || numActivities() > 0) {
2923            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
2924                    "Prepare open transition: starting " + r);
2925            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2926                mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
2927                mStackSupervisor.mNoAnimActivities.add(r);
2928            } else {
2929                int transit = TRANSIT_ACTIVITY_OPEN;
2930                if (newTask) {
2931                    if (r.mLaunchTaskBehind) {
2932                        transit = TRANSIT_TASK_OPEN_BEHIND;
2933                    } else {
2934                        // If a new task is being launched, then mark the existing top activity as
2935                        // supporting picture-in-picture while pausing only if the starting activity
2936                        // would not be considered an overlay on top of the current activity
2937                        // (eg. not fullscreen, or the assistant)
2938                        if (canEnterPipOnTaskSwitch(focusedTopActivity,
2939                                null /* toFrontTask */, r, options)) {
2940                            focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
2941                        }
2942                        transit = TRANSIT_TASK_OPEN;
2943                    }
2944                }
2945                mWindowManager.prepareAppTransition(transit, keepCurTransition);
2946                mStackSupervisor.mNoAnimActivities.remove(r);
2947            }
2948            boolean doShow = true;
2949            if (newTask) {
2950                // Even though this activity is starting fresh, we still need
2951                // to reset it to make sure we apply affinities to move any
2952                // existing activities from other tasks in to it.
2953                // If the caller has requested that the target task be
2954                // reset, then do so.
2955                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2956                    resetTaskIfNeededLocked(r, r);
2957                    doShow = topRunningNonDelayedActivityLocked(null) == r;
2958                }
2959            } else if (options != null && options.getAnimationType()
2960                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
2961                doShow = false;
2962            }
2963            if (r.mLaunchTaskBehind) {
2964                // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
2965                // tell WindowManager that r is visible even though it is at the back of the stack.
2966                r.setVisibility(true);
2967                ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
2968            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
2969                // Figure out if we are transitioning from another activity that is
2970                // "has the same starting icon" as the next one.  This allows the
2971                // window manager to keep the previous window it had previously
2972                // created, if it still had one.
2973                TaskRecord prevTask = r.getTask();
2974                ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
2975                if (prev != null) {
2976                    // We don't want to reuse the previous starting preview if:
2977                    // (1) The current activity is in a different task.
2978                    if (prev.getTask() != prevTask) {
2979                        prev = null;
2980                    }
2981                    // (2) The current activity is already displayed.
2982                    else if (prev.nowVisible) {
2983                        prev = null;
2984                    }
2985                }
2986                r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
2987            }
2988        } else {
2989            // If this is the first activity, don't do any fancy animations,
2990            // because there is nothing for it to animate on top of.
2991            ActivityOptions.abort(options);
2992        }
2993    }
2994
2995    /**
2996     * @return Whether the switch to another task can trigger the currently running activity to
2997     * enter PiP while it is pausing (if supported). Only one of {@param toFrontTask} or
2998     * {@param toFrontActivity} should be set.
2999     */
3000    private boolean canEnterPipOnTaskSwitch(ActivityRecord pipCandidate,
3001            TaskRecord toFrontTask, ActivityRecord toFrontActivity, ActivityOptions opts) {
3002        if (opts != null && opts.disallowEnterPictureInPictureWhileLaunching()) {
3003            // Ensure the caller has requested not to trigger auto-enter PiP
3004            return false;
3005        }
3006        if (pipCandidate == null || pipCandidate.inPinnedWindowingMode()) {
3007            // Ensure that we do not trigger entering PiP an activity on the pinned stack
3008            return false;
3009        }
3010        final ActivityStack targetStack = toFrontTask != null
3011                ? toFrontTask.getStack() : toFrontActivity.getStack();
3012        if (targetStack != null && targetStack.isActivityTypeAssistant()) {
3013            // Ensure the task/activity being brought forward is not the assistant
3014            return false;
3015        }
3016        return true;
3017    }
3018
3019    private boolean isTaskSwitch(ActivityRecord r,
3020            ActivityRecord topFocusedActivity) {
3021        return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask();
3022    }
3023
3024    /**
3025     * Perform a reset of the given task, if needed as part of launching it.
3026     * Returns the new HistoryRecord at the top of the task.
3027     */
3028    /**
3029     * Helper method for #resetTaskIfNeededLocked.
3030     * We are inside of the task being reset...  we'll either finish this activity, push it out
3031     * for another task, or leave it as-is.
3032     * @param task The task containing the Activity (taskTop) that might be reset.
3033     * @param forceReset
3034     * @return An ActivityOptions that needs to be processed.
3035     */
3036    private ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
3037        ActivityOptions topOptions = null;
3038
3039        int replyChainEnd = -1;
3040        boolean canMoveOptions = true;
3041
3042        // We only do this for activities that are not the root of the task (since if we finish
3043        // the root, we may no longer have the task!).
3044        final ArrayList<ActivityRecord> activities = task.mActivities;
3045        final int numActivities = activities.size();
3046        final int rootActivityNdx = task.findEffectiveRootIndex();
3047        for (int i = numActivities - 1; i > rootActivityNdx; --i ) {
3048            ActivityRecord target = activities.get(i);
3049            if (target.frontOfTask)
3050                break;
3051
3052            final int flags = target.info.flags;
3053            final boolean finishOnTaskLaunch =
3054                    (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
3055            final boolean allowTaskReparenting =
3056                    (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
3057            final boolean clearWhenTaskReset =
3058                    (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
3059
3060            if (!finishOnTaskLaunch
3061                    && !clearWhenTaskReset
3062                    && target.resultTo != null) {
3063                // If this activity is sending a reply to a previous
3064                // activity, we can't do anything with it now until
3065                // we reach the start of the reply chain.
3066                // XXX note that we are assuming the result is always
3067                // to the previous activity, which is almost always
3068                // the case but we really shouldn't count on.
3069                if (replyChainEnd < 0) {
3070                    replyChainEnd = i;
3071                }
3072            } else if (!finishOnTaskLaunch
3073                    && !clearWhenTaskReset
3074                    && allowTaskReparenting
3075                    && target.taskAffinity != null
3076                    && !target.taskAffinity.equals(task.affinity)) {
3077                // If this activity has an affinity for another
3078                // task, then we need to move it out of here.  We will
3079                // move it as far out of the way as possible, to the
3080                // bottom of the activity stack.  This also keeps it
3081                // correctly ordered with any activities we previously
3082                // moved.
3083                final TaskRecord targetTask;
3084                final ActivityRecord bottom =
3085                        !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
3086                                mTaskHistory.get(0).mActivities.get(0) : null;
3087                if (bottom != null && target.taskAffinity != null
3088                        && target.taskAffinity.equals(bottom.getTask().affinity)) {
3089                    // If the activity currently at the bottom has the
3090                    // same task affinity as the one we are moving,
3091                    // then merge it into the same task.
3092                    targetTask = bottom.getTask();
3093                    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
3094                            + " out to bottom task " + targetTask);
3095                } else {
3096                    targetTask = createTaskRecord(
3097                            mStackSupervisor.getNextTaskIdForUserLocked(target.userId),
3098                            target.info, null, null, null, false);
3099                    targetTask.affinityIntent = target.intent;
3100                    if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
3101                            + " out to new task " + targetTask);
3102                }
3103
3104                boolean noOptions = canMoveOptions;
3105                final int start = replyChainEnd < 0 ? i : replyChainEnd;
3106                for (int srcPos = start; srcPos >= i; --srcPos) {
3107                    final ActivityRecord p = activities.get(srcPos);
3108                    if (p.finishing) {
3109                        continue;
3110                    }
3111
3112                    canMoveOptions = false;
3113                    if (noOptions && topOptions == null) {
3114                        topOptions = p.takeOptionsLocked();
3115                        if (topOptions != null) {
3116                            noOptions = false;
3117                        }
3118                    }
3119                    if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
3120                            "Removing activity " + p + " from task=" + task + " adding to task="
3121                            + targetTask + " Callers=" + Debug.getCallers(4));
3122                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
3123                            "Pushing next activity " + p + " out to target's task " + target);
3124                    p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded");
3125                }
3126
3127                mWindowContainerController.positionChildAtBottom(
3128                        targetTask.getWindowContainerController(), false /* includingParents */);
3129                replyChainEnd = -1;
3130            } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
3131                // If the activity should just be removed -- either
3132                // because it asks for it, or the task should be
3133                // cleared -- then finish it and anything that is
3134                // part of its reply chain.
3135                int end;
3136                if (clearWhenTaskReset) {
3137                    // In this case, we want to finish this activity
3138                    // and everything above it, so be sneaky and pretend
3139                    // like these are all in the reply chain.
3140                    end = activities.size() - 1;
3141                } else if (replyChainEnd < 0) {
3142                    end = i;
3143                } else {
3144                    end = replyChainEnd;
3145                }
3146                boolean noOptions = canMoveOptions;
3147                for (int srcPos = i; srcPos <= end; srcPos++) {
3148                    ActivityRecord p = activities.get(srcPos);
3149                    if (p.finishing) {
3150                        continue;
3151                    }
3152                    canMoveOptions = false;
3153                    if (noOptions && topOptions == null) {
3154                        topOptions = p.takeOptionsLocked();
3155                        if (topOptions != null) {
3156                            noOptions = false;
3157                        }
3158                    }
3159                    if (DEBUG_TASKS) Slog.w(TAG_TASKS,
3160                            "resetTaskIntendedTask: calling finishActivity on " + p);
3161                    if (finishActivityLocked(
3162                            p, Activity.RESULT_CANCELED, null, "reset-task", false)) {
3163                        end--;
3164                        srcPos--;
3165                    }
3166                }
3167                replyChainEnd = -1;
3168            } else {
3169                // If we were in the middle of a chain, well the
3170                // activity that started it all doesn't want anything
3171                // special, so leave it all as-is.
3172                replyChainEnd = -1;
3173            }
3174        }
3175
3176        return topOptions;
3177    }
3178
3179    /**
3180     * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given
3181     * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop.
3182     * @param affinityTask The task we are looking for an affinity to.
3183     * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
3184     * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
3185     * @param forceReset Flag passed in to resetTaskIfNeededLocked.
3186     */
3187    private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task,
3188            boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
3189        int replyChainEnd = -1;
3190        final int taskId = task.taskId;
3191        final String taskAffinity = task.affinity;
3192
3193        final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
3194        final int numActivities = activities.size();
3195        final int rootActivityNdx = affinityTask.findEffectiveRootIndex();
3196
3197        // Do not operate on or below the effective root Activity.
3198        for (int i = numActivities - 1; i > rootActivityNdx; --i) {
3199            ActivityRecord target = activities.get(i);
3200            if (target.frontOfTask)
3201                break;
3202
3203            final int flags = target.info.flags;
3204            boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
3205            boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
3206
3207            if (target.resultTo != null) {
3208                // If this activity is sending a reply to a previous
3209                // activity, we can't do anything with it now until
3210                // we reach the start of the reply chain.
3211                // XXX note that we are assuming the result is always
3212                // to the previous activity, which is almost always
3213                // the case but we really shouldn't count on.
3214                if (replyChainEnd < 0) {
3215                    replyChainEnd = i;
3216                }
3217            } else if (topTaskIsHigher
3218                    && allowTaskReparenting
3219                    && taskAffinity != null
3220                    && taskAffinity.equals(target.taskAffinity)) {
3221                // This activity has an affinity for our task. Either remove it if we are
3222                // clearing or move it over to our task.  Note that
3223                // we currently punt on the case where we are resetting a
3224                // task that is not at the top but who has activities above
3225                // with an affinity to it...  this is really not a normal
3226                // case, and we will need to later pull that task to the front
3227                // and usually at that point we will do the reset and pick
3228                // up those remaining activities.  (This only happens if
3229                // someone starts an activity in a new task from an activity
3230                // in a task that is not currently on top.)
3231                if (forceReset || finishOnTaskLaunch) {
3232                    final int start = replyChainEnd >= 0 ? replyChainEnd : i;
3233                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
3234                            "Finishing task at index " + start + " to " + i);
3235                    for (int srcPos = start; srcPos >= i; --srcPos) {
3236                        final ActivityRecord p = activities.get(srcPos);
3237                        if (p.finishing) {
3238                            continue;
3239                        }
3240                        finishActivityLocked(
3241                                p, Activity.RESULT_CANCELED, null, "move-affinity", false);
3242                    }
3243                } else {
3244                    if (taskInsertionPoint < 0) {
3245                        taskInsertionPoint = task.mActivities.size();
3246
3247                    }
3248
3249                    final int start = replyChainEnd >= 0 ? replyChainEnd : i;
3250                    if (DEBUG_TASKS) Slog.v(TAG_TASKS,
3251                            "Reparenting from task=" + affinityTask + ":" + start + "-" + i
3252                            + " to task=" + task + ":" + taskInsertionPoint);
3253                    for (int srcPos = start; srcPos >= i; --srcPos) {
3254                        final ActivityRecord p = activities.get(srcPos);
3255                        p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked");
3256
3257                        if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
3258                                "Removing and adding activity " + p + " to stack at " + task
3259                                + " callers=" + Debug.getCallers(3));
3260                        if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p
3261                                + " from " + srcPos + " in to resetting task " + task);
3262                    }
3263                    mWindowContainerController.positionChildAtTop(
3264                            task.getWindowContainerController(), true /* includingParents */);
3265
3266                    // Now we've moved it in to place...  but what if this is
3267                    // a singleTop activity and we have put it on top of another
3268                    // instance of the same activity?  Then we drop the instance
3269                    // below so it remains singleTop.
3270                    if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
3271                        ArrayList<ActivityRecord> taskActivities = task.mActivities;
3272                        int targetNdx = taskActivities.indexOf(target);
3273                        if (targetNdx > 0) {
3274                            ActivityRecord p = taskActivities.get(targetNdx - 1);
3275                            if (p.intent.getComponent().equals(target.intent.getComponent())) {
3276                                finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
3277                                        false);
3278                            }
3279                        }
3280                    }
3281                }
3282
3283                replyChainEnd = -1;
3284            }
3285        }
3286        return taskInsertionPoint;
3287    }
3288
3289    final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
3290            ActivityRecord newActivity) {
3291        final boolean forceReset =
3292                (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
3293        final TaskRecord task = taskTop.getTask();
3294
3295        /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
3296         * for remaining tasks. Used for later tasks to reparent to task. */
3297        boolean taskFound = false;
3298
3299        /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */
3300        ActivityOptions topOptions = null;
3301
3302        // Preserve the location for reparenting in the new task.
3303        int reparentInsertionPoint = -1;
3304
3305        for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
3306            final TaskRecord targetTask = mTaskHistory.get(i);
3307
3308            if (targetTask == task) {
3309                topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
3310                taskFound = true;
3311            } else {
3312                reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
3313                        taskFound, forceReset, reparentInsertionPoint);
3314            }
3315        }
3316
3317        int taskNdx = mTaskHistory.indexOf(task);
3318        if (taskNdx >= 0) {
3319            do {
3320                taskTop = mTaskHistory.get(taskNdx--).getTopActivity();
3321            } while (taskTop == null && taskNdx >= 0);
3322        }
3323
3324        if (topOptions != null) {
3325            // If we got some ActivityOptions from an activity on top that
3326            // was removed from the task, propagate them to the new real top.
3327            if (taskTop != null) {
3328                taskTop.updateOptionsLocked(topOptions);
3329            } else {
3330                topOptions.abort();
3331            }
3332        }
3333
3334        return taskTop;
3335    }
3336
3337    void sendActivityResultLocked(int callingUid, ActivityRecord r,
3338            String resultWho, int requestCode, int resultCode, Intent data) {
3339
3340        if (callingUid > 0) {
3341            mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3342                    data, r.getUriPermissionsLocked(), r.userId);
3343        }
3344
3345        if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
3346                + " : who=" + resultWho + " req=" + requestCode
3347                + " res=" + resultCode + " data=" + data);
3348        if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3349            try {
3350                ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3351                list.add(new ResultInfo(resultWho, requestCode,
3352                        resultCode, data));
3353                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
3354                        ActivityResultItem.obtain(list));
3355                return;
3356            } catch (Exception e) {
3357                Slog.w(TAG, "Exception thrown sending result to " + r, e);
3358            }
3359        }
3360
3361        r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3362    }
3363
3364    /** Returns true if the task is one of the task finishing on-top of the top running task. */
3365    private boolean isATopFinishingTask(TaskRecord task) {
3366        for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
3367            final TaskRecord current = mTaskHistory.get(i);
3368            final ActivityRecord r = current.topRunningActivityLocked();
3369            if (r != null) {
3370                // We got a top running activity, so there isn't a top finishing task...
3371                return false;
3372            }
3373            if (current == task) {
3374                return true;
3375            }
3376        }
3377        return false;
3378    }
3379
3380    private void adjustFocusedActivityStack(ActivityRecord r, String reason) {
3381        if (!mStackSupervisor.isFocusedStack(this) ||
3382                ((mResumedActivity != r) && (mResumedActivity != null))) {
3383            return;
3384        }
3385
3386        final ActivityRecord next = topRunningActivityLocked();
3387        final String myReason = reason + " adjustFocus";
3388
3389        if (next == r) {
3390            mStackSupervisor.moveFocusableActivityStackToFrontLocked(
3391                    mStackSupervisor.topRunningActivityLocked(), myReason);
3392            return;
3393        }
3394
3395        if (next != null && isFocusable()) {
3396            // Keep focus in stack if we have a top running activity and are focusable.
3397            return;
3398        }
3399
3400        // Task is not guaranteed to be non-null. For example, destroying the
3401        // {@link ActivityRecord} will disassociate the task from the activity.
3402        final TaskRecord task = r.getTask();
3403
3404        if (task == null) {
3405            throw new IllegalStateException("activity no longer associated with task:" + r);
3406        }
3407
3408        // Move focus to next focusable stack if possible.
3409        if (adjustFocusToNextFocusableStack(myReason)) {
3410            return;
3411        }
3412
3413        // Whatever...go home.
3414        mStackSupervisor.moveHomeStackTaskToTop(myReason);
3415    }
3416
3417    /** Find next proper focusable stack and make it focused. */
3418    boolean adjustFocusToNextFocusableStack(String reason) {
3419        return adjustFocusToNextFocusableStack(reason, false /* allowFocusSelf */);
3420    }
3421
3422    /**
3423     * Find next proper focusable stack and make it focused.
3424     * @param allowFocusSelf Is the focus allowed to remain on the same stack.
3425     */
3426    private boolean adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) {
3427        final ActivityStack stack =
3428                mStackSupervisor.getNextFocusableStackLocked(this, !allowFocusSelf);
3429        final String myReason = reason + " adjustFocusToNextFocusableStack";
3430        if (stack == null) {
3431            return false;
3432        }
3433
3434        final ActivityRecord top = stack.topRunningActivityLocked();
3435
3436        if (stack.isActivityTypeHome() && (top == null || !top.visible)) {
3437            // If we will be focusing on the home stack next and its current top activity isn't
3438            // visible, then use the move the home stack task to top to make the activity visible.
3439            return mStackSupervisor.moveHomeStackTaskToTop(reason);
3440        }
3441
3442        stack.moveToFront(myReason);
3443        return true;
3444    }
3445
3446    final void stopActivityLocked(ActivityRecord r) {
3447        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r);
3448        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3449                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3450            if (!r.finishing) {
3451                if (!shouldSleepActivities()) {
3452                    if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r);
3453                    if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
3454                            "stop-no-history", false)) {
3455                        // If {@link requestFinishActivityLocked} returns {@code true},
3456                        // {@link adjustFocusedActivityStack} would have been already called.
3457                        r.resumeKeyDispatchingLocked();
3458                        return;
3459                    }
3460                } else {
3461                    if (DEBUG_STATES) Slog.d(TAG_STATES, "Not finishing noHistory " + r
3462                            + " on stop because we're just sleeping");
3463                }
3464            }
3465        }
3466
3467        if (r.app != null && r.app.thread != null) {
3468            adjustFocusedActivityStack(r, "stopActivity");
3469            r.resumeKeyDispatchingLocked();
3470            try {
3471                r.stopped = false;
3472                if (DEBUG_STATES) Slog.v(TAG_STATES,
3473                        "Moving to STOPPING: " + r + " (stop requested)");
3474                r.setState(STOPPING, "stopActivityLocked");
3475                if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
3476                        "Stopping visible=" + r.visible + " for " + r);
3477                if (!r.visible) {
3478                    r.setVisible(false);
3479                }
3480                EventLogTags.writeAmStopActivity(
3481                        r.userId, System.identityHashCode(r), r.shortComponentName);
3482                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
3483                        StopActivityItem.obtain(r.visible, r.configChangeFlags));
3484                if (shouldSleepOrShutDownActivities()) {
3485                    r.setSleeping(true);
3486                }
3487                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
3488                mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
3489            } catch (Exception e) {
3490                // Maybe just ignore exceptions here...  if the process
3491                // has crashed, our death notification will clean things
3492                // up.
3493                Slog.w(TAG, "Exception thrown during pause", e);
3494                // Just in case, assume it to be stopped.
3495                r.stopped = true;
3496                if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r);
3497                r.setState(STOPPED, "stopActivityLocked");
3498                if (r.deferRelaunchUntilPaused) {
3499                    destroyActivityLocked(r, true, "stop-except");
3500                }
3501            }
3502        }
3503    }
3504
3505    /**
3506     * @return Returns true if the activity is being finished, false if for
3507     * some reason it is being left as-is.
3508     */
3509    final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3510            Intent resultData, String reason, boolean oomAdj) {
3511        ActivityRecord r = isInStackLocked(token);
3512        if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES,
3513                "Finishing activity token=" + token + " r="
3514                + ", result=" + resultCode + ", data=" + resultData
3515                + ", reason=" + reason);
3516        if (r == null) {
3517            return false;
3518        }
3519
3520        finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
3521        return true;
3522    }
3523
3524    final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
3525        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3526            ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3527            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3528                ActivityRecord r = activities.get(activityNdx);
3529                if (r.resultTo == self && r.requestCode == requestCode) {
3530                    if ((r.resultWho == null && resultWho == null) ||
3531                        (r.resultWho != null && r.resultWho.equals(resultWho))) {
3532                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub",
3533                                false);
3534                    }
3535                }
3536            }
3537        }
3538        mService.updateOomAdjLocked();
3539    }
3540
3541    /**
3542     * Finish the topmost activity that belongs to the crashed app. We may also finish the activity
3543     * that requested launch of the crashed one to prevent launch-crash loop.
3544     * @param app The app that crashed.
3545     * @param reason Reason to perform this action.
3546     * @return The task that was finished in this stack, {@code null} if top running activity does
3547     *         not belong to the crashed app.
3548     */
3549    final TaskRecord finishTopCrashedActivityLocked(ProcessRecord app, String reason) {
3550        ActivityRecord r = topRunningActivityLocked();
3551        TaskRecord finishedTask = null;
3552        if (r == null || r.app != app) {
3553            return null;
3554        }
3555        Slog.w(TAG, "  Force finishing activity "
3556                + r.intent.getComponent().flattenToShortString());
3557        finishedTask = r.getTask();
3558        int taskNdx = mTaskHistory.indexOf(finishedTask);
3559        final TaskRecord task = finishedTask;
3560        int activityNdx = task.mActivities.indexOf(r);
3561        mWindowManager.prepareAppTransition(TRANSIT_CRASHING_ACTIVITY_CLOSE,
3562                false /* alwaysKeepCurrent */);
3563        finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
3564        finishedTask = task;
3565        // Also terminate any activities below it that aren't yet
3566        // stopped, to avoid a situation where one will get
3567        // re-start our crashing activity once it gets resumed again.
3568        --activityNdx;
3569        if (activityNdx < 0) {
3570            do {
3571                --taskNdx;
3572                if (taskNdx < 0) {
3573                    break;
3574                }
3575                activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1;
3576            } while (activityNdx < 0);
3577        }
3578        if (activityNdx >= 0) {
3579            r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
3580            if (r.isState(RESUMED, PAUSING, PAUSED)) {
3581                if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
3582                    Slog.w(TAG, "  Force finishing activity "
3583                            + r.intent.getComponent().flattenToShortString());
3584                    finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false);
3585                }
3586            }
3587        }
3588        return finishedTask;
3589    }
3590
3591    final void finishVoiceTask(IVoiceInteractionSession session) {
3592        IBinder sessionBinder = session.asBinder();
3593        boolean didOne = false;
3594        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3595            TaskRecord tr = mTaskHistory.get(taskNdx);
3596            if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
3597                for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
3598                    ActivityRecord r = tr.mActivities.get(activityNdx);
3599                    if (!r.finishing) {
3600                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice",
3601                                false);
3602                        didOne = true;
3603                    }
3604                }
3605            } else {
3606                // Check if any of the activities are using voice
3607                for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
3608                    ActivityRecord r = tr.mActivities.get(activityNdx);
3609                    if (r.voiceSession != null
3610                            && r.voiceSession.asBinder() == sessionBinder) {
3611                        // Inform of cancellation
3612                        r.clearVoiceSessionLocked();
3613                        try {
3614                            r.app.thread.scheduleLocalVoiceInteractionStarted((IBinder) r.appToken,
3615                                    null);
3616                        } catch (RemoteException re) {
3617                            // Ok
3618                        }
3619                        mService.finishRunningVoiceLocked();
3620                        break;
3621                    }
3622                }
3623            }
3624        }
3625
3626        if (didOne) {
3627            mService.updateOomAdjLocked();
3628        }
3629    }
3630
3631    final boolean finishActivityAffinityLocked(ActivityRecord r) {
3632        ArrayList<ActivityRecord> activities = r.getTask().mActivities;
3633        for (int index = activities.indexOf(r); index >= 0; --index) {
3634            ActivityRecord cur = activities.get(index);
3635            if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
3636                break;
3637            }
3638            finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
3639        }
3640        return true;
3641    }
3642
3643    private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
3644        // send the result
3645        ActivityRecord resultTo = r.resultTo;
3646        if (resultTo != null) {
3647            if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo
3648                    + " who=" + r.resultWho + " req=" + r.requestCode
3649                    + " res=" + resultCode + " data=" + resultData);
3650            if (resultTo.userId != r.userId) {
3651                if (resultData != null) {
3652                    resultData.prepareToLeaveUser(r.userId);
3653                }
3654            }
3655            if (r.info.applicationInfo.uid > 0) {
3656                mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3657                        resultTo.packageName, resultData,
3658                        resultTo.getUriPermissionsLocked(), resultTo.userId);
3659            }
3660            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3661                                     resultData);
3662            r.resultTo = null;
3663        }
3664        else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r);
3665
3666        // Make sure this HistoryRecord is not holding on to other resources,
3667        // because clients have remote IPC references to this object so we
3668        // can't assume that will go away and want to avoid circular IPC refs.
3669        r.results = null;
3670        r.pendingResults = null;
3671        r.newIntents = null;
3672        r.icicle = null;
3673    }
3674
3675    /**
3676     * See {@link #finishActivityLocked(ActivityRecord, int, Intent, String, boolean, boolean)}
3677     */
3678    final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
3679            String reason, boolean oomAdj) {
3680        return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY);
3681    }
3682
3683    /**
3684     * @return Returns true if this activity has been removed from the history
3685     * list, or false if it is still in the list and will be removed later.
3686     */
3687    final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
3688            String reason, boolean oomAdj, boolean pauseImmediately) {
3689        if (r.finishing) {
3690            Slog.w(TAG, "Duplicate finish request for " + r);
3691            return false;
3692        }
3693
3694        mWindowManager.deferSurfaceLayout();
3695        try {
3696            r.makeFinishingLocked();
3697            final TaskRecord task = r.getTask();
3698            EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3699                    r.userId, System.identityHashCode(r),
3700                    task.taskId, r.shortComponentName, reason);
3701            final ArrayList<ActivityRecord> activities = task.mActivities;
3702            final int index = activities.indexOf(r);
3703            if (index < (activities.size() - 1)) {
3704                task.setFrontOfTask();
3705                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3706                    // If the caller asked that this activity (and all above it)
3707                    // be cleared when the task is reset, don't lose that information,
3708                    // but propagate it up to the next activity.
3709                    ActivityRecord next = activities.get(index+1);
3710                    next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3711                }
3712            }
3713
3714            r.pauseKeyDispatchingLocked();
3715
3716            adjustFocusedActivityStack(r, "finishActivity");
3717
3718            finishActivityResultsLocked(r, resultCode, resultData);
3719
3720            final boolean endTask = index <= 0 && !task.isClearingToReuseTask();
3721            final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
3722            if (mResumedActivity == r) {
3723                if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
3724                        "Prepare close transition: finishing " + r);
3725                if (endTask) {
3726                    mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(
3727                            task.taskId);
3728                }
3729                mWindowManager.prepareAppTransition(transit, false);
3730
3731                // Tell window manager to prepare for this one to be removed.
3732                r.setVisibility(false);
3733
3734                if (mPausingActivity == null) {
3735                    if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
3736                    if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
3737                            "finish() => pause with userLeaving=false");
3738                    startPausingLocked(false, false, null, pauseImmediately);
3739                }
3740
3741                if (endTask) {
3742                    mService.getLockTaskController().clearLockedTask(task);
3743                }
3744            } else if (!r.isState(PAUSING)) {
3745                // If the activity is PAUSING, we will complete the finish once
3746                // it is done pausing; else we can just directly finish it here.
3747                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
3748                if (r.visible) {
3749                    prepareActivityHideTransitionAnimation(r, transit);
3750                }
3751
3752                final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE
3753                        : FINISH_AFTER_PAUSE;
3754                final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj,
3755                        "finishActivityLocked") == null;
3756
3757                // The following code is an optimization. When the last non-task overlay activity
3758                // is removed from the task, we remove the entire task from the stack. However,
3759                // since that is done after the scheduled destroy callback from the activity, that
3760                // call to change the visibility of the task overlay activities would be out of
3761                // sync with the activitiy visibility being set for this finishing activity above.
3762                // In this case, we can set the visibility of all the task overlay activities when
3763                // we detect the last one is finishing to keep them in sync.
3764                if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
3765                    for (ActivityRecord taskOverlay : task.mActivities) {
3766                        if (!taskOverlay.mTaskOverlay) {
3767                            continue;
3768                        }
3769                        prepareActivityHideTransitionAnimation(taskOverlay, transit);
3770                    }
3771                }
3772                return removedActivity;
3773            } else {
3774                if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
3775            }
3776
3777            return false;
3778        } finally {
3779            mWindowManager.continueSurfaceLayout();
3780        }
3781    }
3782
3783    private void prepareActivityHideTransitionAnimation(ActivityRecord r, int transit) {
3784        mWindowManager.prepareAppTransition(transit, false);
3785        r.setVisibility(false);
3786        mWindowManager.executeAppTransition();
3787        if (!mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(r)) {
3788            mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(r);
3789        }
3790    }
3791
3792    static final int FINISH_IMMEDIATELY = 0;
3793    static final int FINISH_AFTER_PAUSE = 1;
3794    static final int FINISH_AFTER_VISIBLE = 2;
3795
3796    final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj,
3797            String reason) {
3798        // First things first: if this activity is currently visible,
3799        // and the resumed activity is not yet visible, then hold off on
3800        // finishing until the resumed one becomes visible.
3801
3802        // The activity that we are finishing may be over the lock screen. In this case, we do not
3803        // want to consider activities that cannot be shown on the lock screen as running and should
3804        // proceed with finishing the activity if there is no valid next top running activity.
3805        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(
3806                true /* considerKeyguardState */);
3807
3808        if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible)
3809                && next != null && !next.nowVisible) {
3810            if (!mStackSupervisor.mStoppingActivities.contains(r)) {
3811                addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */);
3812            }
3813            if (DEBUG_STATES) Slog.v(TAG_STATES,
3814                    "Moving to STOPPING: "+ r + " (finish requested)");
3815            r.setState(STOPPING, "finishCurrentActivityLocked");
3816            if (oomAdj) {
3817                mService.updateOomAdjLocked();
3818            }
3819            return r;
3820        }
3821
3822        // make sure the record is cleaned out of other places.
3823        mStackSupervisor.mStoppingActivities.remove(r);
3824        mStackSupervisor.mGoingToSleepActivities.remove(r);
3825        mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
3826        final ActivityState prevState = r.getState();
3827        if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
3828
3829        r.setState(FINISHING, "finishCurrentActivityLocked");
3830        final boolean finishingActivityInNonFocusedStack
3831                = r.getStack() != mStackSupervisor.getFocusedStack()
3832                && prevState == PAUSED && mode == FINISH_AFTER_VISIBLE;
3833
3834        if (mode == FINISH_IMMEDIATELY
3835                || (prevState == PAUSED
3836                    && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
3837                || finishingActivityInNonFocusedStack
3838                || prevState == STOPPING
3839                || prevState == STOPPED
3840                || prevState == ActivityState.INITIALIZING) {
3841            r.makeFinishingLocked();
3842            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
3843
3844            if (finishingActivityInNonFocusedStack) {
3845                // Finishing activity that was in paused state and it was in not currently focused
3846                // stack, need to make something visible in its place.
3847                mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
3848                        false /* markFrozenIfConfigChanged */, true /* deferResume */);
3849            }
3850            if (activityRemoved) {
3851                mStackSupervisor.resumeFocusedStackTopActivityLocked();
3852            }
3853            if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS,
3854                    "destroyActivityLocked: finishCurrentActivityLocked r=" + r +
3855                    " destroy returned removed=" + activityRemoved);
3856            return activityRemoved ? null : r;
3857        }
3858
3859        // Need to go through the full pause cycle to get this
3860        // activity into the stopped state and then finish it.
3861        if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r);
3862        mStackSupervisor.mFinishingActivities.add(r);
3863        r.resumeKeyDispatchingLocked();
3864        mStackSupervisor.resumeFocusedStackTopActivityLocked();
3865        return r;
3866    }
3867
3868    void finishAllActivitiesLocked(boolean immediately) {
3869        boolean noActivitiesInStack = true;
3870        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3871            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3872            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3873                final ActivityRecord r = activities.get(activityNdx);
3874                noActivitiesInStack = false;
3875                if (r.finishing && !immediately) {
3876                    continue;
3877                }
3878                Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately");
3879                finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
3880                        "finishAllActivitiesLocked");
3881            }
3882        }
3883        if (noActivitiesInStack) {
3884            remove();
3885        }
3886    }
3887
3888    /** @return true if the stack behind this one is a standard activity type. */
3889    boolean inFrontOfStandardStack() {
3890        final ActivityDisplay display = getDisplay();
3891        if (display == null) {
3892            return false;
3893        }
3894        final int index = display.getIndexOf(this);
3895        if (index == 0) {
3896            return false;
3897        }
3898        final ActivityStack stackBehind = display.getChildAt(index - 1);
3899        return stackBehind.isActivityTypeStandard();
3900    }
3901
3902    boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
3903        // Basic case: for simple app-centric recents, we need to recreate
3904        // the task if the affinity has changed.
3905        if (srec == null || srec.getTask().affinity == null ||
3906                !srec.getTask().affinity.equals(destAffinity)) {
3907            return true;
3908        }
3909        // Document-centric case: an app may be split in to multiple documents;
3910        // they need to re-create their task if this current activity is the root
3911        // of a document, unless simply finishing it will return them to the the
3912        // correct app behind.
3913        final TaskRecord task = srec.getTask();
3914        if (srec.frontOfTask && task.getBaseIntent() != null && task.getBaseIntent().isDocument()) {
3915            // Okay, this activity is at the root of its task.  What to do, what to do...
3916            if (!inFrontOfStandardStack()) {
3917                // Finishing won't return to an application, so we need to recreate.
3918                return true;
3919            }
3920            // We now need to get the task below it to determine what to do.
3921            int taskIdx = mTaskHistory.indexOf(task);
3922            if (taskIdx <= 0) {
3923                Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
3924                return false;
3925            }
3926            final TaskRecord prevTask = mTaskHistory.get(taskIdx);
3927            if (!task.affinity.equals(prevTask.affinity)) {
3928                // These are different apps, so need to recreate.
3929                return true;
3930            }
3931        }
3932        return false;
3933    }
3934
3935    final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
3936            Intent resultData) {
3937        final TaskRecord task = srec.getTask();
3938        final ArrayList<ActivityRecord> activities = task.mActivities;
3939        final int start = activities.indexOf(srec);
3940        if (!mTaskHistory.contains(task) || (start < 0)) {
3941            return false;
3942        }
3943        int finishTo = start - 1;
3944        ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo);
3945        boolean foundParentInTask = false;
3946        final ComponentName dest = destIntent.getComponent();
3947        if (start > 0 && dest != null) {
3948            for (int i = finishTo; i >= 0; i--) {
3949                ActivityRecord r = activities.get(i);
3950                if (r.info.packageName.equals(dest.getPackageName()) &&
3951                        r.info.name.equals(dest.getClassName())) {
3952                    finishTo = i;
3953                    parent = r;
3954                    foundParentInTask = true;
3955                    break;
3956                }
3957            }
3958        }
3959
3960        IActivityController controller = mService.mController;
3961        if (controller != null) {
3962            ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
3963            if (next != null) {
3964                // ask watcher if this is allowed
3965                boolean resumeOK = true;
3966                try {
3967                    resumeOK = controller.activityResuming(next.packageName);
3968                } catch (RemoteException e) {
3969                    mService.mController = null;
3970                    Watchdog.getInstance().setActivityController(null);
3971                }
3972
3973                if (!resumeOK) {
3974                    return false;
3975                }
3976            }
3977        }
3978        final long origId = Binder.clearCallingIdentity();
3979        for (int i = start; i > finishTo; i--) {
3980            ActivityRecord r = activities.get(i);
3981            requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true);
3982            // Only return the supplied result for the first activity finished
3983            resultCode = Activity.RESULT_CANCELED;
3984            resultData = null;
3985        }
3986
3987        if (parent != null && foundParentInTask) {
3988            final int parentLaunchMode = parent.info.launchMode;
3989            final int destIntentFlags = destIntent.getFlags();
3990            if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
3991                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
3992                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
3993                    (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3994                parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent,
3995                        srec.packageName);
3996            } else {
3997                try {
3998                    ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
3999                            destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
4000                            srec.userId);
4001                    // TODO(b/64750076): Check if calling pid should really be -1.
4002                    final int res = mService.getActivityStartController()
4003                            .obtainStarter(destIntent, "navigateUpTo")
4004                            .setCaller(srec.app.thread)
4005                            .setActivityInfo(aInfo)
4006                            .setResultTo(parent.appToken)
4007                            .setCallingPid(-1)
4008                            .setCallingUid(parent.launchedFromUid)
4009                            .setCallingPackage(parent.launchedFromPackage)
4010                            .setRealCallingPid(-1)
4011                            .setRealCallingUid(parent.launchedFromUid)
4012                            .setComponentSpecified(true)
4013                            .execute();
4014                    foundParentInTask = res == ActivityManager.START_SUCCESS;
4015                } catch (RemoteException e) {
4016                    foundParentInTask = false;
4017                }
4018                requestFinishActivityLocked(parent.appToken, resultCode,
4019                        resultData, "navigate-top", true);
4020            }
4021        }
4022        Binder.restoreCallingIdentity(origId);
4023        return foundParentInTask;
4024    }
4025
4026    /**
4027     * Remove any state associated with the {@link ActivityRecord}. This should be called whenever
4028     * an activity moves away from the stack.
4029     */
4030    void onActivityRemovedFromStack(ActivityRecord r) {
4031        removeTimeoutsForActivityLocked(r);
4032
4033        if (mResumedActivity != null && mResumedActivity == r) {
4034            setResumedActivity(null, "onActivityRemovedFromStack");
4035        }
4036        if (mPausingActivity != null && mPausingActivity == r) {
4037            mPausingActivity = null;
4038        }
4039    }
4040
4041    void onActivityAddedToStack(ActivityRecord r) {
4042        if(r.getState() == RESUMED) {
4043            setResumedActivity(r, "onActivityAddedToStack");
4044        }
4045    }
4046
4047    /**
4048     * Perform the common clean-up of an activity record.  This is called both
4049     * as part of destroyActivityLocked() (when destroying the client-side
4050     * representation) and cleaning things up as a result of its hosting
4051     * processing going away, in which case there is no remaining client-side
4052     * state to destroy so only the cleanup here is needed.
4053     *
4054     * Note: Call before #removeActivityFromHistoryLocked.
4055     */
4056    private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
4057        onActivityRemovedFromStack(r);
4058
4059        r.deferRelaunchUntilPaused = false;
4060        r.frozenBeforeDestroy = false;
4061
4062        if (setState) {
4063            if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)");
4064            r.setState(DESTROYED, "cleanupActivityLocked");
4065            if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
4066            r.app = null;
4067        }
4068
4069        // Inform supervisor the activity has been removed.
4070        mStackSupervisor.cleanupActivity(r);
4071
4072
4073        // Remove any pending results.
4074        if (r.finishing && r.pendingResults != null) {
4075            for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
4076                PendingIntentRecord rec = apr.get();
4077                if (rec != null) {
4078                    mService.cancelIntentSenderLocked(rec, false);
4079                }
4080            }
4081            r.pendingResults = null;
4082        }
4083
4084        if (cleanServices) {
4085            cleanUpActivityServicesLocked(r);
4086        }
4087
4088        // Get rid of any pending idle timeouts.
4089        removeTimeoutsForActivityLocked(r);
4090        // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
4091        // manager so it can update its bookkeeping.
4092        mWindowManager.notifyAppRelaunchesCleared(r.appToken);
4093    }
4094
4095    void removeTimeoutsForActivityLocked(ActivityRecord r) {
4096        mStackSupervisor.removeTimeoutsForActivityLocked(r);
4097        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4098        mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
4099        mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4100        r.finishLaunchTickingLocked();
4101    }
4102
4103    private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) {
4104        finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
4105        r.makeFinishingLocked();
4106        if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
4107                "Removing activity " + r + " from stack callers=" + Debug.getCallers(5));
4108
4109        r.takeFromHistory();
4110        removeTimeoutsForActivityLocked(r);
4111        if (DEBUG_STATES) Slog.v(TAG_STATES,
4112                "Moving to DESTROYED: " + r + " (removed from history)");
4113        r.setState(DESTROYED, "removeActivityFromHistoryLocked");
4114        if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
4115        r.app = null;
4116        r.removeWindowContainer();
4117        final TaskRecord task = r.getTask();
4118        final boolean lastActivity = task != null ? task.removeActivity(r) : false;
4119        // If we are removing the last activity in the task, not including task overlay activities,
4120        // then fall through into the block below to remove the entire task itself
4121        final boolean onlyHasTaskOverlays = task != null
4122                ? task.onlyHasTaskOverlayActivities(false /* excludingFinishing */) : false;
4123
4124        if (lastActivity || onlyHasTaskOverlays) {
4125            if (DEBUG_STACK) {
4126                Slog.i(TAG_STACK,
4127                        "removeActivityFromHistoryLocked: last activity removed from " + this
4128                                + " onlyHasTaskOverlays=" + onlyHasTaskOverlays);
4129            }
4130
4131            // The following block can be executed multiple times if there is more than one overlay.
4132            // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
4133            // of the task by id and exiting early if not found.
4134            if (onlyHasTaskOverlays) {
4135                // When destroying a task, tell the supervisor to remove it so that any activity it
4136                // has can be cleaned up correctly. This is currently the only place where we remove
4137                // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
4138                // state into removeTask(), we just clear the task here before the other residual
4139                // work.
4140                // TODO: If the callers to removeTask() changes such that we have multiple places
4141                //       where we are destroying the task, move this back into removeTask()
4142                mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
4143                        !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason);
4144            }
4145
4146            // We must keep the task around until all activities are destroyed. The following
4147            // statement will only execute once since overlays are also considered activities.
4148            if (lastActivity) {
4149                removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING);
4150            }
4151        }
4152        cleanUpActivityServicesLocked(r);
4153        r.removeUriPermissionsLocked();
4154    }
4155
4156    /**
4157     * Perform clean-up of service connections in an activity record.
4158     */
4159    private void cleanUpActivityServicesLocked(ActivityRecord r) {
4160        // Throw away any services that have been bound by this activity.
4161        if (r.connections != null) {
4162            Iterator<ConnectionRecord> it = r.connections.iterator();
4163            while (it.hasNext()) {
4164                ConnectionRecord c = it.next();
4165                mService.mServices.removeConnectionLocked(c, null, r);
4166            }
4167            r.connections = null;
4168        }
4169    }
4170
4171    final void scheduleDestroyActivities(ProcessRecord owner, String reason) {
4172        Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
4173        msg.obj = new ScheduleDestroyArgs(owner, reason);
4174        mHandler.sendMessage(msg);
4175    }
4176
4177    private void destroyActivitiesLocked(ProcessRecord owner, String reason) {
4178        boolean lastIsOpaque = false;
4179        boolean activityRemoved = false;
4180        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4181            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4182            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4183                final ActivityRecord r = activities.get(activityNdx);
4184                if (r.finishing) {
4185                    continue;
4186                }
4187                if (r.fullscreen) {
4188                    lastIsOpaque = true;
4189                }
4190                if (owner != null && r.app != owner) {
4191                    continue;
4192                }
4193                if (!lastIsOpaque) {
4194                    continue;
4195                }
4196                if (r.isDestroyable()) {
4197                    if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r
4198                            + " in state " + r.getState()
4199                            + " resumed=" + mResumedActivity
4200                            + " pausing=" + mPausingActivity + " for reason " + reason);
4201                    if (destroyActivityLocked(r, true, reason)) {
4202                        activityRemoved = true;
4203                    }
4204                }
4205            }
4206        }
4207        if (activityRemoved) {
4208            mStackSupervisor.resumeFocusedStackTopActivityLocked();
4209        }
4210    }
4211
4212    final boolean safelyDestroyActivityLocked(ActivityRecord r, String reason) {
4213        if (r.isDestroyable()) {
4214            if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
4215                    "Destroying " + r + " in state " + r.getState() + " resumed=" + mResumedActivity
4216                    + " pausing=" + mPausingActivity + " for reason " + reason);
4217            return destroyActivityLocked(r, true, reason);
4218        }
4219        return false;
4220    }
4221
4222    final int releaseSomeActivitiesLocked(ProcessRecord app, ArraySet<TaskRecord> tasks,
4223            String reason) {
4224        // Iterate over tasks starting at the back (oldest) first.
4225        if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app);
4226        int maxTasks = tasks.size() / 4;
4227        if (maxTasks < 1) {
4228            maxTasks = 1;
4229        }
4230        int numReleased = 0;
4231        for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) {
4232            final TaskRecord task = mTaskHistory.get(taskNdx);
4233            if (!tasks.contains(task)) {
4234                continue;
4235            }
4236            if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Looking for activities to release in " + task);
4237            int curNum = 0;
4238            final ArrayList<ActivityRecord> activities = task.mActivities;
4239            for (int actNdx = 0; actNdx < activities.size(); actNdx++) {
4240                final ActivityRecord activity = activities.get(actNdx);
4241                if (activity.app == app && activity.isDestroyable()) {
4242                    if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + activity
4243                            + " in state " + activity.getState() + " resumed=" + mResumedActivity
4244                            + " pausing=" + mPausingActivity + " for reason " + reason);
4245                    destroyActivityLocked(activity, true, reason);
4246                    if (activities.get(actNdx) != activity) {
4247                        // Was removed from list, back up so we don't miss the next one.
4248                        actNdx--;
4249                    }
4250                    curNum++;
4251                }
4252            }
4253            if (curNum > 0) {
4254                numReleased += curNum;
4255                maxTasks--;
4256                if (mTaskHistory.get(taskNdx) != task) {
4257                    // The entire task got removed, back up so we don't miss the next one.
4258                    taskNdx--;
4259                }
4260            }
4261        }
4262        if (DEBUG_RELEASE) Slog.d(TAG_RELEASE,
4263                "Done releasing: did " + numReleased + " activities");
4264        return numReleased;
4265    }
4266
4267    /**
4268     * Destroy the current CLIENT SIDE instance of an activity.  This may be
4269     * called both when actually finishing an activity, or when performing
4270     * a configuration switch where we destroy the current client-side object
4271     * but then create a new client-side object for this same HistoryRecord.
4272     */
4273    final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
4274        if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH,
4275                "Removing activity from " + reason + ": token=" + r
4276                        + ", app=" + (r.app != null ? r.app.processName : "(null)"));
4277
4278        if (r.isState(DESTROYING, DESTROYED)) {
4279            if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying."
4280                    + "skipping request with reason:" + reason);
4281            return false;
4282        }
4283
4284        EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
4285                r.userId, System.identityHashCode(r),
4286                r.getTask().taskId, r.shortComponentName, reason);
4287
4288        boolean removedFromHistory = false;
4289
4290        cleanUpActivityLocked(r, false, false);
4291
4292        final boolean hadApp = r.app != null;
4293
4294        if (hadApp) {
4295            if (removeFromApp) {
4296                r.app.activities.remove(r);
4297                if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4298                    mService.mHeavyWeightProcess = null;
4299                    mService.mHandler.sendEmptyMessage(
4300                            ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
4301                }
4302                if (r.app.activities.isEmpty()) {
4303                    // Update any services we are bound to that might care about whether
4304                    // their client may have activities.
4305                    mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
4306                    // No longer have activities, so update LRU list and oom adj.
4307                    mService.updateLruProcessLocked(r.app, false, null);
4308                    mService.updateOomAdjLocked();
4309                }
4310            }
4311
4312            boolean skipDestroy = false;
4313
4314            try {
4315                if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r);
4316                mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
4317                        DestroyActivityItem.obtain(r.finishing, r.configChangeFlags));
4318            } catch (Exception e) {
4319                // We can just ignore exceptions here...  if the process
4320                // has crashed, our death notification will clean things
4321                // up.
4322                //Slog.w(TAG, "Exception thrown during finish", e);
4323                if (r.finishing) {
4324                    removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy");
4325                    removedFromHistory = true;
4326                    skipDestroy = true;
4327                }
4328            }
4329
4330            r.nowVisible = false;
4331
4332            // If the activity is finishing, we need to wait on removing it
4333            // from the list to give it a chance to do its cleanup.  During
4334            // that time it may make calls back with its token so we need to
4335            // be able to find it on the list and so we don't want to remove
4336            // it from the list yet.  Otherwise, we can just immediately put
4337            // it in the destroyed state since we are not removing it from the
4338            // list.
4339            if (r.finishing && !skipDestroy) {
4340                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYING: " + r
4341                        + " (destroy requested)");
4342                r.setState(DESTROYING,
4343                        "destroyActivityLocked. finishing and not skipping destroy");
4344                Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
4345                mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4346            } else {
4347                if (DEBUG_STATES) Slog.v(TAG_STATES,
4348                        "Moving to DESTROYED: " + r + " (destroy skipped)");
4349                r.setState(DESTROYED,
4350                        "destroyActivityLocked. not finishing or skipping destroy");
4351                if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r);
4352                r.app = null;
4353            }
4354        } else {
4355            // remove this record from the history.
4356            if (r.finishing) {
4357                removeActivityFromHistoryLocked(r, reason + " hadNoApp");
4358                removedFromHistory = true;
4359            } else {
4360                if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (no app)");
4361                r.setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
4362                if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r);
4363                r.app = null;
4364            }
4365        }
4366
4367        r.configChangeFlags = 0;
4368
4369        if (!mLRUActivities.remove(r) && hadApp) {
4370            Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4371        }
4372
4373        return removedFromHistory;
4374    }
4375
4376    final void activityDestroyedLocked(IBinder token, String reason) {
4377        final long origId = Binder.clearCallingIdentity();
4378        try {
4379            activityDestroyedLocked(ActivityRecord.forTokenLocked(token), reason);
4380        } finally {
4381            Binder.restoreCallingIdentity(origId);
4382        }
4383    }
4384
4385    /**
4386     * This method is to only be called from the client via binder when the activity is destroyed
4387     * AND finished.
4388     */
4389    final void activityDestroyedLocked(ActivityRecord record, String reason) {
4390        if (record != null) {
4391            mHandler.removeMessages(DESTROY_TIMEOUT_MSG, record);
4392        }
4393
4394        if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + record);
4395
4396        if (isInStackLocked(record) != null) {
4397            if (record.isState(DESTROYING, DESTROYED)) {
4398                cleanUpActivityLocked(record, true, false);
4399                removeActivityFromHistoryLocked(record, reason);
4400            }
4401        }
4402
4403        mStackSupervisor.resumeFocusedStackTopActivityLocked();
4404    }
4405
4406    private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
4407            ProcessRecord app, String listName) {
4408        int i = list.size();
4409        if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4410            "Removing app " + app + " from list " + listName + " with " + i + " entries");
4411        while (i > 0) {
4412            i--;
4413            ActivityRecord r = list.get(i);
4414            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r);
4415            if (r.app == app) {
4416                if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!");
4417                list.remove(i);
4418                removeTimeoutsForActivityLocked(r);
4419            }
4420        }
4421    }
4422
4423    private boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
4424        removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
4425        removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
4426                "mStoppingActivities");
4427        removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
4428                "mGoingToSleepActivities");
4429        removeHistoryRecordsForAppLocked(mStackSupervisor.mActivitiesWaitingForVisibleActivity, app,
4430                "mActivitiesWaitingForVisibleActivity");
4431        removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
4432                "mFinishingActivities");
4433
4434        boolean hasVisibleActivities = false;
4435
4436        // Clean out the history list.
4437        int i = numActivities();
4438        if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4439                "Removing app " + app + " from history with " + i + " entries");
4440        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4441            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4442            mTmpActivities.clear();
4443            mTmpActivities.addAll(activities);
4444
4445            while (!mTmpActivities.isEmpty()) {
4446                final int targetIndex = mTmpActivities.size() - 1;
4447                final ActivityRecord r = mTmpActivities.remove(targetIndex);
4448                if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
4449                        "Record #" + targetIndex + " " + r + ": app=" + r.app);
4450
4451                if (r.app == app) {
4452                    if (r.visible) {
4453                        hasVisibleActivities = true;
4454                    }
4455                    final boolean remove;
4456                    if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4457                        // Don't currently have state for the activity, or
4458                        // it is finishing -- always remove it.
4459                        remove = true;
4460                    } else if (!r.visible && r.launchCount > 2 &&
4461                            r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
4462                        // We have launched this activity too many times since it was
4463                        // able to run, so give up and remove it.
4464                        // (Note if the activity is visible, we don't remove the record.
4465                        // We leave the dead window on the screen but the process will
4466                        // not be restarted unless user explicitly tap on it.)
4467                        remove = true;
4468                    } else {
4469                        // The process may be gone, but the activity lives on!
4470                        remove = false;
4471                    }
4472                    if (remove) {
4473                        if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
4474                                "Removing activity " + r + " from stack at " + i
4475                                + ": haveState=" + r.haveState
4476                                + " stateNotNeeded=" + r.stateNotNeeded
4477                                + " finishing=" + r.finishing
4478                                + " state=" + r.getState() + " callers=" + Debug.getCallers(5));
4479                        if (!r.finishing) {
4480                            Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
4481                            EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
4482                                    r.userId, System.identityHashCode(r),
4483                                    r.getTask().taskId, r.shortComponentName,
4484                                    "proc died without state saved");
4485                            if (r.getState() == RESUMED) {
4486                                mService.updateUsageStats(r, false);
4487                            }
4488                        }
4489                    } else {
4490                        // We have the current state for this activity, so
4491                        // it can be restarted later when needed.
4492                        if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
4493                        if (DEBUG_APP) Slog.v(TAG_APP,
4494                                "Clearing app during removeHistory for activity " + r);
4495                        r.app = null;
4496                        // Set nowVisible to previous visible state. If the app was visible while
4497                        // it died, we leave the dead window on screen so it's basically visible.
4498                        // This is needed when user later tap on the dead window, we need to stop
4499                        // other apps when user transfers focus to the restarted activity.
4500                        r.nowVisible = r.visible;
4501                        if (!r.haveState) {
4502                            if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE,
4503                                    "App died, clearing saved state of " + r);
4504                            r.icicle = null;
4505                        }
4506                    }
4507                    cleanUpActivityLocked(r, true, true);
4508                    if (remove) {
4509                        removeActivityFromHistoryLocked(r, "appDied");
4510                    }
4511                }
4512            }
4513        }
4514
4515        return hasVisibleActivities;
4516    }
4517
4518    private void updateTransitLocked(int transit, ActivityOptions options) {
4519        if (options != null) {
4520            ActivityRecord r = topRunningActivityLocked();
4521            if (r != null && !r.isState(RESUMED)) {
4522                r.updateOptionsLocked(options);
4523            } else {
4524                ActivityOptions.abort(options);
4525            }
4526        }
4527        mWindowManager.prepareAppTransition(transit, false);
4528    }
4529
4530    private void updateTaskMovement(TaskRecord task, boolean toFront) {
4531        if (task.isPersistable) {
4532            task.mLastTimeMoved = System.currentTimeMillis();
4533            // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
4534            // recently will be most negative, tasks sent to the bottom before that will be less
4535            // negative. Similarly for recent tasks moved to the top which will be most positive.
4536            if (!toFront) {
4537                task.mLastTimeMoved *= -1;
4538            }
4539        }
4540        mStackSupervisor.invalidateTaskLayers();
4541    }
4542
4543    void moveHomeStackTaskToTop() {
4544        if (!isActivityTypeHome()) {
4545            throw new IllegalStateException("Calling moveHomeStackTaskToTop() on non-home stack: "
4546                    + this);
4547        }
4548        final int top = mTaskHistory.size() - 1;
4549        if (top >= 0) {
4550            final TaskRecord task = mTaskHistory.get(top);
4551            if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK,
4552                    "moveHomeStackTaskToTop: moving " + task);
4553            mTaskHistory.remove(top);
4554            mTaskHistory.add(top, task);
4555            updateTaskMovement(task, true);
4556        }
4557    }
4558
4559    final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
4560            AppTimeTracker timeTracker, String reason) {
4561        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
4562
4563        final ActivityStack topStack = getDisplay().getTopStack();
4564        final ActivityRecord topActivity = topStack != null ? topStack.getTopActivity() : null;
4565        final int numTasks = mTaskHistory.size();
4566        final int index = mTaskHistory.indexOf(tr);
4567        if (numTasks == 0 || index < 0)  {
4568            // nothing to do!
4569            if (noAnimation) {
4570                ActivityOptions.abort(options);
4571            } else {
4572                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
4573            }
4574            return;
4575        }
4576
4577        if (timeTracker != null) {
4578            // The caller wants a time tracker associated with this task.
4579            for (int i = tr.mActivities.size() - 1; i >= 0; i--) {
4580                tr.mActivities.get(i).appTimeTracker = timeTracker;
4581            }
4582        }
4583
4584        try {
4585            // Defer updating the IME target since the new IME target will try to get computed
4586            // before updating all closing and opening apps, which can cause the ime target to
4587            // get calculated incorrectly.
4588            getDisplay().deferUpdateImeTarget();
4589
4590            // Shift all activities with this task up to the top
4591            // of the stack, keeping them in the same internal order.
4592            insertTaskAtTop(tr, null);
4593
4594            // Don't refocus if invisible to current user
4595            final ActivityRecord top = tr.getTopActivity();
4596            if (top == null || !top.okToShowLocked()) {
4597                if (top != null) {
4598                    mStackSupervisor.mRecentTasks.add(top.getTask());
4599                }
4600                ActivityOptions.abort(options);
4601                return;
4602            }
4603
4604            // Set focus to the top running activity of this stack.
4605            final ActivityRecord r = topRunningActivityLocked();
4606            mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
4607
4608            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
4609            if (noAnimation) {
4610                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
4611                if (r != null) {
4612                    mStackSupervisor.mNoAnimActivities.add(r);
4613                }
4614                ActivityOptions.abort(options);
4615            } else {
4616                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options);
4617            }
4618            // If a new task is moved to the front, then mark the existing top activity as
4619            // supporting
4620
4621            // picture-in-picture while paused only if the task would not be considered an oerlay
4622            // on top
4623            // of the current activity (eg. not fullscreen, or the assistant)
4624            if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */,
4625                    options)) {
4626                topActivity.supportsEnterPipOnTaskSwitch = true;
4627            }
4628
4629            mStackSupervisor.resumeFocusedStackTopActivityLocked();
4630            EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
4631
4632            mService.mTaskChangeNotificationController.notifyTaskMovedToFront(tr.taskId);
4633        } finally {
4634            getDisplay().continueUpdateImeTarget();
4635        }
4636    }
4637
4638    /**
4639     * Worker method for rearranging history stack. Implements the function of moving all
4640     * activities for a specific task (gathering them if disjoint) into a single group at the
4641     * bottom of the stack.
4642     *
4643     * If a watcher is installed, the action is preflighted and the watcher has an opportunity
4644     * to premeptively cancel the move.
4645     *
4646     * @param taskId The taskId to collect and move to the bottom.
4647     * @return Returns true if the move completed, false if not.
4648     */
4649    final boolean moveTaskToBackLocked(int taskId) {
4650        final TaskRecord tr = taskForIdLocked(taskId);
4651        if (tr == null) {
4652            Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
4653            return false;
4654        }
4655        Slog.i(TAG, "moveTaskToBack: " + tr);
4656
4657        // In LockTask mode, moving a locked task to the back of the stack may expose unlocked
4658        // ones. Therefore we need to check if this operation is allowed.
4659        if (!mService.getLockTaskController().canMoveTaskToBack(tr)) {
4660            return false;
4661        }
4662
4663        // If we have a watcher, preflight the move before committing to it.  First check
4664        // for *other* available tasks, but if none are available, then try again allowing the
4665        // current task to be selected.
4666        if (isTopStackOnDisplay() && mService.mController != null) {
4667            ActivityRecord next = topRunningActivityLocked(null, taskId);
4668            if (next == null) {
4669                next = topRunningActivityLocked(null, 0);
4670            }
4671            if (next != null) {
4672                // ask watcher if this is allowed
4673                boolean moveOK = true;
4674                try {
4675                    moveOK = mService.mController.activityResuming(next.packageName);
4676                } catch (RemoteException e) {
4677                    mService.mController = null;
4678                    Watchdog.getInstance().setActivityController(null);
4679                }
4680                if (!moveOK) {
4681                    return false;
4682                }
4683            }
4684        }
4685
4686        if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId);
4687
4688        mTaskHistory.remove(tr);
4689        mTaskHistory.add(0, tr);
4690        updateTaskMovement(tr, false);
4691
4692        mWindowManager.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
4693        moveToBack("moveTaskToBackLocked", tr);
4694
4695        if (inPinnedWindowingMode()) {
4696            mStackSupervisor.removeStack(this);
4697            return true;
4698        }
4699
4700        mStackSupervisor.resumeFocusedStackTopActivityLocked();
4701        return true;
4702    }
4703
4704    static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
4705        final Uri data = r.intent.getData();
4706        final String strData = data != null ? data.toSafeString() : null;
4707
4708        EventLog.writeEvent(tag,
4709                r.userId, System.identityHashCode(r), task.taskId,
4710                r.shortComponentName, r.intent.getAction(),
4711                r.intent.getType(), strData, r.intent.getFlags());
4712    }
4713
4714    /**
4715     * Ensures all visible activities at or below the input activity have the right configuration.
4716     */
4717    void ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow) {
4718        if (start == null || !start.visible) {
4719            return;
4720        }
4721
4722        final TaskRecord startTask = start.getTask();
4723        boolean behindFullscreen = false;
4724        boolean updatedConfig = false;
4725
4726        for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) {
4727            final TaskRecord task = mTaskHistory.get(taskIndex);
4728            final ArrayList<ActivityRecord> activities = task.mActivities;
4729            int activityIndex =
4730                    (start.getTask() == task) ? activities.indexOf(start) : activities.size() - 1;
4731            for (; activityIndex >= 0; --activityIndex) {
4732                final ActivityRecord r = activities.get(activityIndex);
4733                updatedConfig |= r.ensureActivityConfiguration(0 /* globalChanges */,
4734                        preserveWindow);
4735                if (r.fullscreen) {
4736                    behindFullscreen = true;
4737                    break;
4738                }
4739            }
4740            if (behindFullscreen) {
4741                break;
4742            }
4743        }
4744        if (updatedConfig) {
4745            // Ensure the resumed state of the focus activity if we updated the configuration of
4746            // any activity.
4747            mStackSupervisor.resumeFocusedStackTopActivityLocked();
4748        }
4749    }
4750
4751    // TODO: Figure-out a way to consolidate with resize() method below.
4752    @Override
4753    public void requestResize(Rect bounds) {
4754        mService.resizeStack(mStackId, bounds, true /* allowResizeInDockedMode */,
4755                false /* preserveWindows */, false /* animate */, -1 /* animationDuration */);
4756    }
4757
4758    // TODO: Can only be called from special methods in ActivityStackSupervisor.
4759    // Need to consolidate those calls points into this resize method so anyone can call directly.
4760    void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) {
4761        if (!updateBoundsAllowed(bounds, tempTaskBounds, tempTaskInsetBounds)) {
4762            return;
4763        }
4764
4765        // Update override configurations of all tasks in the stack.
4766        final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
4767        final Rect insetBounds = tempTaskInsetBounds != null ? tempTaskInsetBounds : taskBounds;
4768
4769        mTmpBounds.clear();
4770        mTmpInsetBounds.clear();
4771
4772        synchronized (mWindowManager.getWindowManagerLock()) {
4773            for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
4774                final TaskRecord task = mTaskHistory.get(i);
4775                if (task.isResizeable()) {
4776                    if (inFreeformWindowingMode()) {
4777                        // TODO: Can be removed now since each freeform task is in its own stack.
4778                        // For freeform stack we don't adjust the size of the tasks to match that
4779                        // of the stack, but we do try to make sure the tasks are still contained
4780                        // with the bounds of the stack.
4781                        mTmpRect2.set(task.getOverrideBounds());
4782                        fitWithinBounds(mTmpRect2, bounds);
4783                        task.updateOverrideConfiguration(mTmpRect2);
4784                    } else {
4785                        task.updateOverrideConfiguration(taskBounds, insetBounds);
4786                    }
4787                }
4788
4789                mTmpBounds.put(task.taskId, task.getOverrideBounds());
4790                if (tempTaskInsetBounds != null) {
4791                    mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds);
4792                }
4793            }
4794
4795            mWindowContainerController.resize(bounds, mTmpBounds, mTmpInsetBounds);
4796            setBounds(bounds);
4797        }
4798    }
4799
4800    void onPipAnimationEndResize() {
4801        mWindowContainerController.onPipAnimationEndResize();
4802    }
4803
4804
4805    /**
4806     * Adjust bounds to stay within stack bounds.
4807     *
4808     * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
4809     * that keep them unchanged, but be contained within the stack bounds.
4810     *
4811     * @param bounds Bounds to be adjusted.
4812     * @param stackBounds Bounds within which the other bounds should remain.
4813     */
4814    private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
4815        if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
4816            return;
4817        }
4818
4819        if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
4820            final int maxRight = stackBounds.right
4821                    - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
4822            int horizontalDiff = stackBounds.left - bounds.left;
4823            if ((horizontalDiff < 0 && bounds.left >= maxRight)
4824                    || (bounds.left + horizontalDiff >= maxRight)) {
4825                horizontalDiff = maxRight - bounds.left;
4826            }
4827            bounds.left += horizontalDiff;
4828            bounds.right += horizontalDiff;
4829        }
4830
4831        if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
4832            final int maxBottom = stackBounds.bottom
4833                    - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
4834            int verticalDiff = stackBounds.top - bounds.top;
4835            if ((verticalDiff < 0 && bounds.top >= maxBottom)
4836                    || (bounds.top + verticalDiff >= maxBottom)) {
4837                verticalDiff = maxBottom - bounds.top;
4838            }
4839            bounds.top += verticalDiff;
4840            bounds.bottom += verticalDiff;
4841        }
4842    }
4843
4844    boolean willActivityBeVisibleLocked(IBinder token) {
4845        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4846            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4847            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4848                final ActivityRecord r = activities.get(activityNdx);
4849                if (r.appToken == token) {
4850                    return true;
4851                }
4852                if (r.fullscreen && !r.finishing) {
4853                    return false;
4854                }
4855            }
4856        }
4857        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
4858        if (r == null) {
4859            return false;
4860        }
4861        if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false,"
4862                + " would have returned true for r=" + r);
4863        return !r.finishing;
4864    }
4865
4866    void closeSystemDialogsLocked() {
4867        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4868            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4869            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4870                final ActivityRecord r = activities.get(activityNdx);
4871                if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4872                    finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true);
4873                }
4874            }
4875        }
4876    }
4877
4878    boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses,
4879            boolean doit, boolean evenPersistent, int userId) {
4880        boolean didSomething = false;
4881        TaskRecord lastTask = null;
4882        ComponentName homeActivity = null;
4883        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4884            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4885            mTmpActivities.clear();
4886            mTmpActivities.addAll(activities);
4887
4888            while (!mTmpActivities.isEmpty()) {
4889                ActivityRecord r = mTmpActivities.remove(0);
4890                final boolean sameComponent =
4891                        (r.packageName.equals(packageName) && (filterByClasses == null
4892                                || filterByClasses.contains(r.realActivity.getClassName())))
4893                        || (packageName == null && r.userId == userId);
4894                if ((userId == UserHandle.USER_ALL || r.userId == userId)
4895                        && (sameComponent || r.getTask() == lastTask)
4896                        && (r.app == null || evenPersistent || !r.app.persistent)) {
4897                    if (!doit) {
4898                        if (r.finishing) {
4899                            // If this activity is just finishing, then it is not
4900                            // interesting as far as something to stop.
4901                            continue;
4902                        }
4903                        return true;
4904                    }
4905                    if (r.isActivityTypeHome()) {
4906                        if (homeActivity != null && homeActivity.equals(r.realActivity)) {
4907                            Slog.i(TAG, "Skip force-stop again " + r);
4908                            continue;
4909                        } else {
4910                            homeActivity = r.realActivity;
4911                        }
4912                    }
4913                    didSomething = true;
4914                    Slog.i(TAG, "  Force finishing activity " + r);
4915                    if (sameComponent) {
4916                        if (r.app != null) {
4917                            r.app.removed = true;
4918                        }
4919                        r.app = null;
4920                    }
4921                    lastTask = r.getTask();
4922                    finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
4923                            true);
4924                }
4925            }
4926        }
4927        return didSomething;
4928    }
4929
4930    /**
4931     * @return The set of running tasks through {@param tasksOut} that are available to the caller.
4932     *         If {@param ignoreActivityType} or {@param ignoreWindowingMode} are not undefined,
4933     *         then skip running tasks that match those types.
4934     */
4935    void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType,
4936            @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed) {
4937        boolean focusedStack = mStackSupervisor.getFocusedStack() == this;
4938        boolean topTask = true;
4939        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4940            final TaskRecord task = mTaskHistory.get(taskNdx);
4941            if (task.getTopActivity() == null) {
4942                // Skip if there are no activities in the task
4943                continue;
4944            }
4945            if (!allowed && !task.isActivityTypeHome() && task.effectiveUid != callingUid) {
4946                // Skip if the caller can't fetch this task
4947                continue;
4948            }
4949            if (ignoreActivityType != ACTIVITY_TYPE_UNDEFINED
4950                    && task.getActivityType() == ignoreActivityType) {
4951                // Skip ignored activity type
4952                continue;
4953            }
4954            if (ignoreWindowingMode != WINDOWING_MODE_UNDEFINED
4955                    && task.getWindowingMode() == ignoreWindowingMode) {
4956                // Skip ignored windowing mode
4957                continue;
4958            }
4959            if (focusedStack && topTask) {
4960                // For the focused stack top task, update the last stack active time so that it can
4961                // be used to determine the order of the tasks (it may not be set for newly created
4962                // tasks)
4963                task.lastActiveTime = SystemClock.elapsedRealtime();
4964                topTask = false;
4965            }
4966            tasksOut.add(task);
4967        }
4968    }
4969
4970    void unhandledBackLocked() {
4971        final int top = mTaskHistory.size() - 1;
4972        if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
4973        if (top >= 0) {
4974            final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
4975            int activityTop = activities.size() - 1;
4976            if (activityTop >= 0) {
4977                finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
4978                        "unhandled-back", true);
4979            }
4980        }
4981    }
4982
4983    /**
4984     * Reset local parameters because an app's activity died.
4985     * @param app The app of the activity that died.
4986     * @return result from removeHistoryRecordsForAppLocked.
4987     */
4988    boolean handleAppDiedLocked(ProcessRecord app) {
4989        if (mPausingActivity != null && mPausingActivity.app == app) {
4990            if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
4991                    "App died while pausing: " + mPausingActivity);
4992            mPausingActivity = null;
4993        }
4994        if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
4995            mLastPausedActivity = null;
4996            mLastNoHistoryActivity = null;
4997        }
4998
4999        return removeHistoryRecordsForAppLocked(app);
5000    }
5001
5002    void handleAppCrashLocked(ProcessRecord app) {
5003        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5004            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5005            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
5006                final ActivityRecord r = activities.get(activityNdx);
5007                if (r.app == app) {
5008                    Slog.w(TAG, "  Force finishing activity "
5009                            + r.intent.getComponent().flattenToShortString());
5010                    // Force the destroy to skip right to removal.
5011                    r.app = null;
5012                    mWindowManager.prepareAppTransition(TRANSIT_CRASHING_ACTIVITY_CLOSE,
5013                            false /* alwaysKeepCurrent */);
5014                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false,
5015                            "handleAppCrashedLocked");
5016                }
5017            }
5018        }
5019    }
5020
5021    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
5022            boolean dumpClient, String dumpPackage, boolean needSep) {
5023
5024        if (mTaskHistory.isEmpty()) {
5025            return false;
5026        }
5027        final String prefix = "    ";
5028        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5029            final TaskRecord task = mTaskHistory.get(taskNdx);
5030            if (needSep) {
5031                pw.println("");
5032            }
5033            pw.println(prefix + "Task id #" + task.taskId);
5034            pw.println(prefix + "mBounds=" + task.getOverrideBounds());
5035            pw.println(prefix + "mMinWidth=" + task.mMinWidth);
5036            pw.println(prefix + "mMinHeight=" + task.mMinHeight);
5037            pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
5038            pw.println(prefix + "* " + task);
5039            task.dump(pw, prefix + "  ");
5040            ActivityStackSupervisor.dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
5041                    prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task);
5042        }
5043        return true;
5044    }
5045
5046    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
5047        ArrayList<ActivityRecord> activities = new ArrayList<>();
5048
5049        if ("all".equals(name)) {
5050            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5051                activities.addAll(mTaskHistory.get(taskNdx).mActivities);
5052            }
5053        } else if ("top".equals(name)) {
5054            final int top = mTaskHistory.size() - 1;
5055            if (top >= 0) {
5056                final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
5057                int listTop = list.size() - 1;
5058                if (listTop >= 0) {
5059                    activities.add(list.get(listTop));
5060                }
5061            }
5062        } else {
5063            ItemMatcher matcher = new ItemMatcher();
5064            matcher.build(name);
5065
5066            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5067                for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
5068                    if (matcher.match(r1, r1.intent.getComponent())) {
5069                        activities.add(r1);
5070                    }
5071                }
5072            }
5073        }
5074
5075        return activities;
5076    }
5077
5078    ActivityRecord restartPackage(String packageName) {
5079        ActivityRecord starting = topRunningActivityLocked();
5080
5081        // All activities that came from the package must be
5082        // restarted as if there was a config change.
5083        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5084            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
5085            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
5086                final ActivityRecord a = activities.get(activityNdx);
5087                if (a.info.packageName.equals(packageName)) {
5088                    a.forceNewConfig = true;
5089                    if (starting != null && a == starting && a.visible) {
5090                        a.startFreezingScreenLocked(starting.app,
5091                                CONFIG_SCREEN_LAYOUT);
5092                    }
5093                }
5094            }
5095        }
5096
5097        return starting;
5098    }
5099
5100    /**
5101     * Removes the input task from this stack.
5102     * @param task to remove.
5103     * @param reason for removal.
5104     * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
5105     *             {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
5106     */
5107    void removeTask(TaskRecord task, String reason, int mode) {
5108        for (ActivityRecord record : task.mActivities) {
5109            onActivityRemovedFromStack(record);
5110        }
5111
5112        final boolean removed = mTaskHistory.remove(task);
5113
5114        if (removed) {
5115            EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId());
5116        }
5117
5118        removeActivitiesFromLRUListLocked(task);
5119        updateTaskMovement(task, true);
5120
5121        if (mode == REMOVE_TASK_MODE_DESTROYING && task.mActivities.isEmpty()) {
5122            // TODO: VI what about activity?
5123            final boolean isVoiceSession = task.voiceSession != null;
5124            if (isVoiceSession) {
5125                try {
5126                    task.voiceSession.taskFinished(task.intent, task.taskId);
5127                } catch (RemoteException e) {
5128                }
5129            }
5130            if (task.autoRemoveFromRecents() || isVoiceSession) {
5131                // Task creator asked to remove this when done, or this task was a voice
5132                // interaction, so it should not remain on the recent tasks list.
5133                mStackSupervisor.mRecentTasks.remove(task);
5134            }
5135
5136            task.removeWindowContainer();
5137        }
5138
5139        if (mTaskHistory.isEmpty()) {
5140            if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
5141            // We only need to adjust focused stack if this stack is in focus and we are not in the
5142            // process of moving the task to the top of the stack that will be focused.
5143            if (isOnHomeDisplay() && mode != REMOVE_TASK_MODE_MOVING_TO_TOP
5144                    && mStackSupervisor.isFocusedStack(this)) {
5145                String myReason = reason + " leftTaskHistoryEmpty";
5146                if (!inMultiWindowMode() || !adjustFocusToNextFocusableStack(myReason)) {
5147                    mStackSupervisor.moveHomeStackToFront(myReason);
5148                }
5149            }
5150            if (isAttached()) {
5151                getDisplay().positionChildAtBottom(this);
5152            }
5153            if (!isActivityTypeHome()) {
5154                remove();
5155            }
5156        }
5157
5158        task.setStack(null);
5159
5160        // Notify if a task from the pinned stack is being removed (or moved depending on the mode)
5161        if (inPinnedWindowingMode()) {
5162            mService.mTaskChangeNotificationController.notifyActivityUnpinned();
5163        }
5164    }
5165
5166    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
5167            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
5168            boolean toTop) {
5169        return createTaskRecord(taskId, info, intent, voiceSession, voiceInteractor, toTop,
5170                null /*activity*/, null /*source*/, null /*options*/);
5171    }
5172
5173    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
5174            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
5175            boolean toTop, ActivityRecord activity, ActivityRecord source,
5176            ActivityOptions options) {
5177        final TaskRecord task = TaskRecord.create(
5178                mService, taskId, info, intent, voiceSession, voiceInteractor);
5179        // add the task to stack first, mTaskPositioner might need the stack association
5180        addTask(task, toTop, "createTaskRecord");
5181        final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
5182        final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
5183                .isKeyguardOrAodShowing(displayId);
5184        if (!mStackSupervisor.getLaunchParamsController()
5185                .layoutTask(task, info.windowLayout, activity, source, options)
5186                && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
5187            task.updateOverrideConfiguration(getOverrideBounds());
5188        }
5189        task.createWindowContainer(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
5190        return task;
5191    }
5192
5193    ArrayList<TaskRecord> getAllTasks() {
5194        return new ArrayList<>(mTaskHistory);
5195    }
5196
5197    void addTask(final TaskRecord task, final boolean toTop, String reason) {
5198        addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
5199        if (toTop) {
5200            // TODO: figure-out a way to remove this call.
5201            mWindowContainerController.positionChildAtTop(task.getWindowContainerController(),
5202                    true /* includingParents */);
5203        }
5204    }
5205
5206    // TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
5207    // with the fall-out...
5208    void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
5209            String reason) {
5210        // TODO: Is this remove really needed? Need to look into the call path for the other addTask
5211        mTaskHistory.remove(task);
5212        position = getAdjustedPositionForTask(task, position, null /* starting */);
5213        final boolean toTop = position >= mTaskHistory.size();
5214        final ActivityStack prevStack = preAddTask(task, reason, toTop);
5215
5216        mTaskHistory.add(position, task);
5217        task.setStack(this);
5218
5219        updateTaskMovement(task, toTop);
5220
5221        postAddTask(task, prevStack, schedulePictureInPictureModeChange);
5222    }
5223
5224    void positionChildAt(TaskRecord task, int index) {
5225
5226        if (task.getStack() != this) {
5227            throw new IllegalArgumentException("AS.positionChildAt: task=" + task
5228                    + " is not a child of stack=" + this + " current parent=" + task.getStack());
5229        }
5230
5231        task.updateOverrideConfigurationForStack(this);
5232
5233        final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
5234        final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
5235        insertTaskAtPosition(task, index);
5236        task.setStack(this);
5237        postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */);
5238
5239        if (wasResumed) {
5240            if (mResumedActivity != null) {
5241                Log.wtf(TAG, "mResumedActivity was already set when moving mResumedActivity from"
5242                        + " other stack to this stack mResumedActivity=" + mResumedActivity
5243                        + " other mResumedActivity=" + topRunningActivity);
5244            }
5245            topRunningActivity.setState(RESUMED, "positionChildAt");
5246        }
5247
5248        // The task might have already been running and its visibility needs to be synchronized with
5249        // the visibility of the stack / windows.
5250        ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
5251        mStackSupervisor.resumeFocusedStackTopActivityLocked();
5252    }
5253
5254    private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
5255        final ActivityStack prevStack = task.getStack();
5256        if (prevStack != null && prevStack != this) {
5257            prevStack.removeTask(task, reason,
5258                    toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
5259        }
5260        return prevStack;
5261    }
5262
5263    /**
5264     * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
5265     *            change. Callers may set this to false if they are explicitly scheduling PiP mode
5266     *            changes themselves, like during the PiP animation
5267     */
5268    private void postAddTask(TaskRecord task, ActivityStack prevStack,
5269            boolean schedulePictureInPictureModeChange) {
5270        if (schedulePictureInPictureModeChange && prevStack != null) {
5271            mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
5272        } else if (task.voiceSession != null) {
5273            try {
5274                task.voiceSession.taskStarted(task.intent, task.taskId);
5275            } catch (RemoteException e) {
5276            }
5277        }
5278    }
5279
5280    void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume,
5281            boolean setPause, String reason) {
5282        if (!moveToFront) {
5283            return;
5284        }
5285
5286        // If the activity owns the last resumed activity, transfer that together,
5287        // so that we don't resume the same activity again in the new stack.
5288        // Apps may depend on onResume()/onPause() being called in pairs.
5289        if (setResume) {
5290            r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded");
5291            updateLRUListLocked(r);
5292        }
5293        // If the activity was previously pausing, then ensure we transfer that as well
5294        if (setPause) {
5295            mPausingActivity = r;
5296            schedulePauseTimeout(r);
5297        }
5298        // Move the stack in which we are placing the activity to the front. The call will also
5299        // make sure the activity focus is set.
5300        moveToFront(reason);
5301    }
5302
5303    public int getStackId() {
5304        return mStackId;
5305    }
5306
5307    @Override
5308    public String toString() {
5309        return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
5310                + " stackId=" + mStackId + " type=" + activityTypeToString(getActivityType())
5311                + " mode=" + windowingModeToString(getWindowingMode())
5312                + " visible=" + shouldBeVisible(null /* starting */)
5313                + " translucent=" + isStackTranslucent(null /* starting */)
5314                + ", "
5315                + mTaskHistory.size() + " tasks}";
5316    }
5317
5318    void onLockTaskPackagesUpdated() {
5319        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5320            mTaskHistory.get(taskNdx).setLockTaskAuth();
5321        }
5322    }
5323
5324    void executeAppTransition(ActivityOptions options) {
5325        mWindowManager.executeAppTransition();
5326        ActivityOptions.abort(options);
5327    }
5328
5329    boolean shouldSleepActivities() {
5330        final ActivityDisplay display = getDisplay();
5331
5332        // Do not sleep activities in this stack if we're marked as focused and the keyguard
5333        // is in the process of going away.
5334        if (mStackSupervisor.getFocusedStack() == this
5335                && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
5336            return false;
5337        }
5338
5339        return display != null ? display.isSleeping() : mService.isSleepingLocked();
5340    }
5341
5342    boolean shouldSleepOrShutDownActivities() {
5343        return shouldSleepActivities() || mService.isShuttingDownLocked();
5344    }
5345
5346    public void writeToProto(ProtoOutputStream proto, long fieldId) {
5347        final long token = proto.start(fieldId);
5348        super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
5349        proto.write(ID, mStackId);
5350        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5351            final TaskRecord task = mTaskHistory.get(taskNdx);
5352            task.writeToProto(proto, TASKS);
5353        }
5354        if (mResumedActivity != null) {
5355            mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
5356        }
5357        proto.write(DISPLAY_ID, mDisplayId);
5358        if (!matchParentBounds()) {
5359            final Rect bounds = getOverrideBounds();
5360            bounds.writeToProto(proto, BOUNDS);
5361        }
5362
5363        // TODO: Remove, no longer needed with windowingMode.
5364        proto.write(FULLSCREEN, matchParentBounds());
5365        proto.end(token);
5366    }
5367}
5368