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 
17 package com.android.server.am;
18 
19 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
26 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
27 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
28 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
29 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
31 import static android.app.WindowConfiguration.activityTypeToString;
32 import static android.app.WindowConfiguration.windowingModeToString;
33 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
34 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
35 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
36 import static android.view.Display.DEFAULT_DISPLAY;
37 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
38 import static android.view.Display.INVALID_DISPLAY;
39 
40 import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
41 import static com.android.server.am.ActivityDisplay.POSITION_TOP;
42 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
43 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
44 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
45 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP;
46 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
47 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
48 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
49 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
50 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
51 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
52 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
53 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
54 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
55 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TRANSITION;
56 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_USER_LEAVING;
57 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
58 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
59 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_APP;
60 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
61 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS;
62 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
63 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
64 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RESULTS;
65 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
66 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
67 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
68 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
69 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
70 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TRANSITION;
71 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_USER_LEAVING;
72 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
73 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
74 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
75 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
76 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
77 import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
78 import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
79 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
80 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
81 import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
82 import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
83 import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
84 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
85 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
86 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
87 import static com.android.server.am.ActivityStackProto.BOUNDS;
88 import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER;
89 import static com.android.server.am.ActivityStackProto.DISPLAY_ID;
90 import static com.android.server.am.ActivityStackProto.FULLSCREEN;
91 import static com.android.server.am.ActivityStackProto.ID;
92 import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY;
93 import static com.android.server.am.ActivityStackProto.TASKS;
94 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
95 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
96 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
97 import static android.view.WindowManager.TRANSIT_NONE;
98 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
99 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
100 import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
101 import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
102 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
103 
104 import static java.lang.Integer.MAX_VALUE;
105 
106 import android.app.Activity;
107 import android.app.ActivityManager;
108 import android.app.ActivityOptions;
109 import android.app.AppGlobals;
110 import android.app.IActivityController;
111 import android.app.ResultInfo;
112 import android.app.WindowConfiguration.ActivityType;
113 import android.app.WindowConfiguration.WindowingMode;
114 import android.app.servertransaction.ActivityResultItem;
115 import android.app.servertransaction.ClientTransaction;
116 import android.app.servertransaction.NewIntentItem;
117 import android.app.servertransaction.WindowVisibilityItem;
118 import android.app.servertransaction.DestroyActivityItem;
119 import android.app.servertransaction.PauseActivityItem;
120 import android.app.servertransaction.ResumeActivityItem;
121 import android.app.servertransaction.StopActivityItem;
122 import android.content.ComponentName;
123 import android.content.Intent;
124 import android.content.pm.ActivityInfo;
125 import android.content.pm.ApplicationInfo;
126 import android.content.res.Configuration;
127 import android.graphics.Rect;
128 import android.net.Uri;
129 import android.os.Binder;
130 import android.os.Debug;
131 import android.os.Handler;
132 import android.os.IBinder;
133 import android.os.Looper;
134 import android.os.Message;
135 import android.os.RemoteException;
136 import android.os.SystemClock;
137 import android.os.UserHandle;
138 import android.service.voice.IVoiceInteractionSession;
139 import android.util.ArraySet;
140 import android.util.EventLog;
141 import android.util.IntArray;
142 import android.util.Log;
143 import android.util.Slog;
144 import android.util.SparseArray;
145 import android.util.proto.ProtoOutputStream;
146 import android.view.Display;
147 
148 import com.android.internal.annotations.GuardedBy;
149 import com.android.internal.annotations.VisibleForTesting;
150 import com.android.internal.app.IVoiceInteractor;
151 import com.android.internal.os.BatteryStatsImpl;
152 import com.android.server.Watchdog;
153 import com.android.server.am.ActivityManagerService.ItemMatcher;
154 import com.android.server.wm.ConfigurationContainer;
155 import com.android.server.wm.StackWindowController;
156 import com.android.server.wm.StackWindowListener;
157 import com.android.server.wm.WindowManagerService;
158 
159 import java.io.FileDescriptor;
160 import java.io.PrintWriter;
161 import java.lang.ref.WeakReference;
162 import java.util.ArrayList;
163 import java.util.Iterator;
164 import java.util.List;
165 import java.util.Objects;
166 import java.util.Set;
167 
168 /**
169  * State and management of a single stack of activities.
170  */
171 class 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
getChildCount()223     protected int getChildCount() {
224         return mTaskHistory.size();
225     }
226 
227     @Override
getChildAt(int index)228     protected ConfigurationContainer getChildAt(int index) {
229         return mTaskHistory.get(index);
230     }
231 
232     @Override
getParent()233     protected ConfigurationContainer getParent() {
234         return getDisplay();
235     }
236 
237     @Override
onParentChanged()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;
ScheduleDestroyArgs(ProcessRecord owner, String reason)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 
ActivityStackHandler(Looper looper)382         ActivityStackHandler(Looper looper) {
383             super(looper);
384         }
385 
386         @Override
handleMessage(Message msg)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 
numActivities()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 
ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, int windowingMode, int activityType, boolean onTop)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 
createStackWindowController(int displayId, boolean onTop, Rect outBounds)472     T createStackWindowController(int displayId, boolean onTop, Rect outBounds) {
473         return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds,
474                 mStackSupervisor.mWindowManager);
475     }
476 
getWindowContainerController()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      */
onActivityStateChanged(ActivityRecord record, ActivityState state, String reason)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
onConfigurationChanged(Configuration newParentConfig)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
setWindowingMode(int windowingMode)514     public void setWindowingMode(int windowingMode) {
515         setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
516                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */);
517     }
518 
setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility)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
isCompatible(int windowingMode, int activityType)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. */
reparent(ActivityDisplay activityDisplay, boolean onTop)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      */
postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop)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      */
removeFromDisplay()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. */
remove()726     void remove() {
727         removeFromDisplay();
728         mWindowContainerController.removeContainer();
729         mWindowContainerController = null;
730         onParentChanged();
731     }
732 
getDisplay()733     ActivityDisplay getDisplay() {
734         return mStackSupervisor.getActivityDisplay(mDisplayId);
735     }
736 
737     /**
738      * @see #getStackDockedModeBounds(Rect, Rect, Rect, boolean)
739      */
getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds, boolean ignoreVisibility)740     void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
741             Rect outTempTaskBounds, boolean ignoreVisibility) {
742         mWindowContainerController.getStackDockedModeBounds(currentTempTaskBounds,
743                 outStackBounds, outTempTaskBounds, ignoreVisibility);
744     }
745 
prepareFreezingTaskBounds()746     void prepareFreezingTaskBounds() {
747         mWindowContainerController.prepareFreezingTaskBounds();
748     }
749 
getWindowContainerBounds(Rect outBounds)750     void getWindowContainerBounds(Rect outBounds) {
751         if (mWindowContainerController != null) {
752             mWindowContainerController.getBounds(outBounds);
753             return;
754         }
755         outBounds.setEmpty();
756     }
757 
getBoundsForNewConfiguration(Rect outBounds)758     void getBoundsForNewConfiguration(Rect outBounds) {
759         mWindowContainerController.getBoundsForNewConfiguration(outBounds);
760     }
761 
positionChildWindowContainerAtTop(TaskRecord child)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      */
deferScheduleMultiWindowModeChanged()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      */
deferUpdateBounds()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      */
continueUpdateBounds()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 
updateBoundsAllowed(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds)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
setBounds(Rect bounds)825     public int setBounds(Rect bounds) {
826         return super.setBounds(!inMultiWindowMode() ? null : bounds);
827     }
828 
topRunningActivityLocked()829     ActivityRecord topRunningActivityLocked() {
830         return topRunningActivityLocked(false /* focusableOnly */);
831     }
832 
getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities)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 
topRunningActivityLocked(boolean focusableOnly)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 
topRunningNonOverlayTaskActivity()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 
topRunningNonDelayedActivityLocked(ActivityRecord notTop)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      */
topRunningActivityLocked(IBinder token, int taskId)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 
getTopActivity()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 
topTask()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 
bottomTask()923     private TaskRecord bottomTask() {
924         if (mTaskHistory.isEmpty()) {
925             return null;
926         }
927         return mTaskHistory.get(0);
928     }
929 
taskForIdLocked(int id)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 
isInStackLocked(IBinder token)940     ActivityRecord isInStackLocked(IBinder token) {
941         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
942         return isInStackLocked(r);
943     }
944 
isInStackLocked(ActivityRecord r)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 
isInStackLocked(TaskRecord task)959     boolean isInStackLocked(TaskRecord task) {
960         return mTaskHistory.contains(task);
961     }
962 
963     /** Checks if there are tasks with specific UID in the stack. */
isUidPresent(int uid)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. */
getPresentUIDs(IntArray presentUIDs)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 
removeActivitiesFromLRUListLocked(TaskRecord task)984     final void removeActivitiesFromLRUListLocked(TaskRecord task) {
985         for (ActivityRecord r : task.mActivities) {
986             mLRUActivities.remove(r);
987         }
988     }
989 
updateLRUListLocked(ActivityRecord r)990     final boolean updateLRUListLocked(ActivityRecord r) {
991         final boolean hadit = mLRUActivities.remove(r);
992         mLRUActivities.add(r);
993         return hadit;
994     }
995 
isHomeOrRecentsStack()996     final boolean isHomeOrRecentsStack() {
997         return isActivityTypeHome() || isActivityTypeRecents();
998     }
999 
isOnHomeDisplay()1000     final boolean isOnHomeDisplay() {
1001         return mDisplayId == DEFAULT_DISPLAY;
1002     }
1003 
returnsToHomeStack()1004     private boolean returnsToHomeStack() {
1005         return !inMultiWindowMode()
1006                 && !mTaskHistory.isEmpty()
1007                 && mTaskHistory.get(0).returnsToHomeStack();
1008     }
1009 
moveToFront(String reason)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      * */
moveToFront(String reason, TaskRecord task)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      **/
moveToBack(String reason, TaskRecord task)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 
isFocusable()1081     boolean isFocusable() {
1082         final ActivityRecord r = topRunningActivityLocked();
1083         return mStackSupervisor.isFocusable(this, r != null && r.isFocusable());
1084     }
1085 
isAttached()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      */
findTaskLocked(ActivityRecord target, FindTaskResult result)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      */
findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters)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      */
switchUserLocked(int userId)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 
minimalResumeActivityLocked(ActivityRecord r)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 
clearLaunchTime(ActivityRecord r)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 
awakeFromSleepingLocked()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 
updateActivityApplicationInfoLocked(ApplicationInfo aInfo)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 
checkReadyForSleep()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      */
goToSleepIfPossible(boolean shuttingDown)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 
goToSleep()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 
containsActivityFromStack(List<ActivityRecord> rs)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      */
schedulePauseTimeout(ActivityRecord r)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      */
startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately)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 
activityPausedLocked(IBinder token, boolean timeout)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 
completePauseLocked(boolean resumeNext, ActivityRecord resuming)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 
addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed)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
isStackTranslucent(ActivityRecord starting)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 
isTopStackOnDisplay()1717     boolean isTopStackOnDisplay() {
1718         return getDisplay().isTopStack(this);
1719     }
1720 
isTopActivityVisible()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      */
shouldBeVisible(ActivityRecord starting)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 
rankTaskLayers(int baseLayer)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      */
ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows)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.
ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)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 
addStartingWindowsForVisibleActivities(boolean taskSwitch)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      */
topActivityOccludesKeyguard()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      */
resizeStackWithLaunchBounds()1989     boolean resizeStackWithLaunchBounds() {
1990         return inPinnedWindowingMode();
1991     }
1992 
1993     @Override
supportsSplitScreenWindowingMode()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. */
affectedBySplitScreenResize()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      */
getTopDismissingKeyguardActivity()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      */
checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop)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      */
canShowWithInsecureKeyguard()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 
checkTranslucentActivityWaiting(ActivityRecord top)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 
makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, boolean isTop, boolean andResume, ActivityRecord r)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.
makeInvisible(ActivityRecord r)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 
updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity, ActivityRecord r)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 
convertActivityToTranslucent(ActivityRecord r)2180     void convertActivityToTranslucent(ActivityRecord r) {
2181         mTranslucentActivityWaiting = r;
2182         mUndrawnActivitiesBelowTopTranslucent.clear();
2183         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
2184     }
2185 
clearOtherAppTimeTrackers(AppTimeTracker except)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      */
notifyActivityDrawnLocked(ActivityRecord r)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. */
cancelInitializingActivities()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")
resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options)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      */
getResumedActivity()2315     protected ActivityRecord getResumedActivity() {
2316         return mResumedActivity;
2317     }
2318 
setResumedActivity(ActivityRecord r, String reason)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")
resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)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 
resumeTopActivityInNextFocusableStack(ActivityRecord prev, ActivityOptions options, String reason)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 
getNextTask(TaskRecord targetTask)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. */
getAdjustedPositionForTask(TaskRecord task, int suggestedPosition, ActivityRecord starting)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      */
insertTaskAtPosition(TaskRecord task, int position)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 
insertTaskAtTop(TaskRecord task, ActivityRecord starting)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 
insertTaskAtBottom(TaskRecord task)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 
startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, boolean newTask, boolean keepCurTransition, ActivityOptions options)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      */
canEnterPipOnTaskSwitch(ActivityRecord pipCandidate, TaskRecord toFrontTask, ActivityRecord toFrontActivity, ActivityOptions opts)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 
isTaskSwitch(ActivityRecord r, ActivityRecord topFocusedActivity)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      */
resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset)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      */
resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint)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 
resetTaskIfNeededLocked(ActivityRecord taskTop, ActivityRecord newActivity)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 
sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data)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. */
isATopFinishingTask(TaskRecord 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 
adjustFocusedActivityStack(ActivityRecord r, String reason)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. */
adjustFocusToNextFocusableStack(String reason)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      */
adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf)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 
stopActivityLocked(ActivityRecord r)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      */
requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason, boolean oomAdj)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 
finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode)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      */
finishTopCrashedActivityLocked(ProcessRecord app, String reason)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 
finishVoiceTask(IVoiceInteractionSession session)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 
finishActivityAffinityLocked(ActivityRecord r)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 
finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData)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      */
finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj)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      */
finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj, boolean pauseImmediately)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 
prepareActivityHideTransitionAnimation(ActivityRecord r, int transit)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 
finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj, String reason)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 
finishAllActivitiesLocked(boolean immediately)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. */
inFrontOfStandardStack()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 
shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity)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 
navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, Intent resultData)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      */
onActivityRemovedFromStack(ActivityRecord r)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 
onActivityAddedToStack(ActivityRecord r)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      */
cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState)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 
removeTimeoutsForActivityLocked(ActivityRecord r)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 
removeActivityFromHistoryLocked(ActivityRecord r, String reason)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      */
cleanUpActivityServicesLocked(ActivityRecord r)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 
scheduleDestroyActivities(ProcessRecord owner, String reason)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 
destroyActivitiesLocked(ProcessRecord owner, String reason)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 
safelyDestroyActivityLocked(ActivityRecord r, String reason)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 
releaseSomeActivitiesLocked(ProcessRecord app, ArraySet<TaskRecord> tasks, String reason)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      */
destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason)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 
activityDestroyedLocked(IBinder token, String reason)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      */
activityDestroyedLocked(ActivityRecord record, String reason)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 
removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, ProcessRecord app, String listName)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 
removeHistoryRecordsForAppLocked(ProcessRecord app)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 
updateTransitLocked(int transit, ActivityOptions options)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 
updateTaskMovement(TaskRecord task, boolean toFront)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 
moveHomeStackTaskToTop()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 
moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker, String reason)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      */
moveTaskToBackLocked(int taskId)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 
logStartActivity(int tag, ActivityRecord r, TaskRecord task)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      */
ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow)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
requestResize(Rect bounds)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.
resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds)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 
onPipAnimationEndResize()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      */
fitWithinBounds(Rect bounds, Rect stackBounds)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 
willActivityBeVisibleLocked(IBinder token)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 
closeSystemDialogsLocked()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 
finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, boolean doit, boolean evenPersistent, int userId)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      */
getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed)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 
unhandledBackLocked()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      */
handleAppDiedLocked(ProcessRecord app)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 
handleAppCrashLocked(ProcessRecord app)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 
dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, boolean needSep)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 
getDumpActivitiesLocked(String name)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 
restartPackage(String packageName)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      */
removeTask(TaskRecord task, String reason, int mode)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 
createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop)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 
createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity, ActivityRecord source, ActivityOptions options)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 
getAllTasks()5193     ArrayList<TaskRecord> getAllTasks() {
5194         return new ArrayList<>(mTaskHistory);
5195     }
5196 
addTask(final TaskRecord task, final boolean toTop, String reason)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...
addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange, String reason)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 
positionChildAt(TaskRecord task, int index)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 
preAddTask(TaskRecord task, String reason, boolean toTop)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      */
postAddTask(TaskRecord task, ActivityStack prevStack, boolean schedulePictureInPictureModeChange)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 
moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, boolean setPause, String reason)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 
getStackId()5303     public int getStackId() {
5304         return mStackId;
5305     }
5306 
5307     @Override
toString()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 
onLockTaskPackagesUpdated()5318     void onLockTaskPackagesUpdated() {
5319         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5320             mTaskHistory.get(taskNdx).setLockTaskAuth();
5321         }
5322     }
5323 
executeAppTransition(ActivityOptions options)5324     void executeAppTransition(ActivityOptions options) {
5325         mWindowManager.executeAppTransition();
5326         ActivityOptions.abort(options);
5327     }
5328 
shouldSleepActivities()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 
shouldSleepOrShutDownActivities()5342     boolean shouldSleepOrShutDownActivities() {
5343         return shouldSleepActivities() || mService.isShuttingDownLocked();
5344     }
5345 
writeToProto(ProtoOutputStream proto, long fieldId)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