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