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