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