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