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