ActivityStack.java revision 92fe44e966b9622c24a6810aaf9c2d8e2b1f9d92
175f0d3110b04346b901771f96ce15cdbe907278fYang Ni/* 275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Copyright (C) 2010 The Android Open Source Project 375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * 475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Licensed under the Apache License, Version 2.0 (the "License"); 575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * you may not use this file except in compliance with the License. 675f0d3110b04346b901771f96ce15cdbe907278fYang Ni * You may obtain a copy of the License at 775f0d3110b04346b901771f96ce15cdbe907278fYang Ni * 875f0d3110b04346b901771f96ce15cdbe907278fYang Ni * http://www.apache.org/licenses/LICENSE-2.0 975f0d3110b04346b901771f96ce15cdbe907278fYang Ni * 1075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Unless required by applicable law or agreed to in writing, software 1175f0d3110b04346b901771f96ce15cdbe907278fYang Ni * distributed under the License is distributed on an "AS IS" BASIS, 1275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * See the License for the specific language governing permissions and 1475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * limitations under the License. 1575f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 1675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 1775f0d3110b04346b901771f96ce15cdbe907278fYang Nipackage com.android.server.am; 1875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 1975f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 2075f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 2175f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; 2275f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static android.app.ActivityManager.StackId.HOME_STACK_ID; 2375f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static android.app.ActivityManager.StackId.PINNED_STACK_ID; 2475f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; 2575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 2675f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static com.android.server.am.ActivityManagerDebugConfig.*; 2775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 2875f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; 2975f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; 3075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 3175f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static com.android.server.am.ActivityStackSupervisor.MOVING; 3275f0d3110b04346b901771f96ce15cdbe907278fYang Niimport static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; 3375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 3475f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.graphics.Rect; 3575f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.util.ArraySet; 3675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 3775f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.internal.app.IVoiceInteractor; 3875f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.internal.content.ReferrerIntent; 3975f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.internal.os.BatteryStatsImpl; 4075f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.server.Watchdog; 4175f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.server.am.ActivityManagerService.ItemMatcher; 4275f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.server.am.ActivityStackSupervisor.ActivityContainer; 4375f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.server.wm.AppTransition; 4475f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.server.wm.TaskGroup; 4575f0d3110b04346b901771f96ce15cdbe907278fYang Niimport com.android.server.wm.WindowManagerService; 4675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 4775f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.Activity; 4875f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.ActivityManager; 4975f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.ActivityManager.StackId; 5075f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.ActivityOptions; 5175f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.AppGlobals; 5275f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.IActivityController; 5375f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.ResultInfo; 5475f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.app.ActivityManager.RunningTaskInfo; 5575f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.content.ComponentName; 5675f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.content.Intent; 5775f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.content.pm.ActivityInfo; 5875f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.content.pm.PackageManager; 5975f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.content.res.Configuration; 6075f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.graphics.Bitmap; 6175f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.net.Uri; 6275f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.Binder; 6375f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.Bundle; 6475f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.Debug; 6575f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.Handler; 6675f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.IBinder; 6775f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.Looper; 6875f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.Message; 6975f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.PersistableBundle; 7075f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.RemoteException; 7175f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.SystemClock; 7275f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.Trace; 7375f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.os.UserHandle; 7475f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.service.voice.IVoiceInteractionSession; 7575f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.util.EventLog; 7675f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.util.Slog; 7775f0d3110b04346b901771f96ce15cdbe907278fYang Niimport android.view.Display; 7875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 7975f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.io.FileDescriptor; 8075f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.io.PrintWriter; 8175f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.lang.ref.WeakReference; 8275f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.util.ArrayList; 8375f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.util.Iterator; 8475f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.util.List; 8575f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.util.Objects; 8675f0d3110b04346b901771f96ce15cdbe907278fYang Niimport java.util.Set; 8775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 8875f0d3110b04346b901771f96ce15cdbe907278fYang Ni/** 8975f0d3110b04346b901771f96ce15cdbe907278fYang Ni * State and management of a single stack of activities. 9075f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 9175f0d3110b04346b901771f96ce15cdbe907278fYang Nifinal class ActivityStack { 9275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 9375f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_AM; 9475f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; 9575f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_APP = TAG + POSTFIX_APP; 9675f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP; 9775f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION; 9875f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS; 9975f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE; 10075f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; 10175f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS; 10275f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE; 10375f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_SCREENSHOTS = TAG + POSTFIX_SCREENSHOTS; 10475f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_STACK = TAG + POSTFIX_STACK; 10575f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_STATES = TAG + POSTFIX_STATES; 10675f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; 10775f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_TASKS = TAG + POSTFIX_TASKS; 10875f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION; 10975f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; 11075f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; 11175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 11275f0d3110b04346b901771f96ce15cdbe907278fYang Ni private static final boolean VALIDATE_TOKENS = false; 11375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 11475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Ticks during which we check progress while waiting for an app to launch. 11575f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int LAUNCH_TICK = 500; 11675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 11775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // How long we wait until giving up on the last activity to pause. This 11875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // is short because it directly impacts the responsiveness of starting the 11975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // next activity. 12075f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int PAUSE_TIMEOUT = 500; 12175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 12275f0d3110b04346b901771f96ce15cdbe907278fYang Ni // How long we wait for the activity to tell us it has stopped before 12375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // giving up. This is a good amount of time because we really need this 12475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // from the application in order to get its saved state. 12575f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int STOP_TIMEOUT = 10 * 1000; 12675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 12775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // How long we wait until giving up on an activity telling us it has 12875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // finished destroying itself. 12975f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int DESTROY_TIMEOUT = 10 * 1000; 13075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 13175f0d3110b04346b901771f96ce15cdbe907278fYang Ni // How long until we reset a task when the user returns to it. Currently 13275f0d3110b04346b901771f96ce15cdbe907278fYang Ni // disabled. 13375f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final long ACTIVITY_INACTIVE_RESET_TIME = 0; 13475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 13575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // How long between activity launches that we consider safe to not warn 13675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // the user about an unexpected activity being launched on top. 13775f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final long START_WARN_TIME = 5 * 1000; 13875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 13975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Set to false to disable the preview that is shown while a new activity 14075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // is being started. 14175f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final boolean SHOW_APP_STARTING_PREVIEW = true; 14275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 14375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // How long to wait for all background Activities to redraw following a call to 14475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // convertToTranslucent(). 14575f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000; 14675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 14775f0d3110b04346b901771f96ce15cdbe907278fYang Ni enum ActivityState { 14875f0d3110b04346b901771f96ce15cdbe907278fYang Ni INITIALIZING, 14975f0d3110b04346b901771f96ce15cdbe907278fYang Ni RESUMED, 15075f0d3110b04346b901771f96ce15cdbe907278fYang Ni PAUSING, 15175f0d3110b04346b901771f96ce15cdbe907278fYang Ni PAUSED, 15275f0d3110b04346b901771f96ce15cdbe907278fYang Ni STOPPING, 15375f0d3110b04346b901771f96ce15cdbe907278fYang Ni STOPPED, 15475f0d3110b04346b901771f96ce15cdbe907278fYang Ni FINISHING, 15575f0d3110b04346b901771f96ce15cdbe907278fYang Ni DESTROYING, 15675f0d3110b04346b901771f96ce15cdbe907278fYang Ni DESTROYED 15775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 15875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 15975f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityManagerService mService; 16075f0d3110b04346b901771f96ce15cdbe907278fYang Ni final WindowManagerService mWindowManager; 16175f0d3110b04346b901771f96ce15cdbe907278fYang Ni private final RecentTasks mRecentTasks; 16275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 16375f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 16475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * The back history of all previous (and possibly still 16575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * running) activities. It contains #TaskRecord objects. 16675f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 16775f0d3110b04346b901771f96ce15cdbe907278fYang Ni private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>(); 16875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 16975f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 17075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Used for validating app tokens with window manager. 17175f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 17275f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<>(); 17375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 17475f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 17575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * List of running activities, sorted by recent usage. 17675f0d3110b04346b901771f96ce15cdbe907278fYang Ni * The first entry in the list is the least recently used. 17775f0d3110b04346b901771f96ce15cdbe907278fYang Ni * It contains HistoryRecord objects. 17875f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 17975f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>(); 18075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 18175f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 18275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Animations that for the current transition have requested not to 18375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * be considered for the transition animation. 18475f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 18575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>(); 18675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 18775f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 18875f0d3110b04346b901771f96ce15cdbe907278fYang Ni * When we are in the process of pausing an activity, before starting the 18975f0d3110b04346b901771f96ce15cdbe907278fYang Ni * next one, this variable holds the activity that is currently being paused. 19075f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 19175f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord mPausingActivity = null; 19275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 19375f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 19475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * This is the last activity that we put into the paused state. This is 19575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * used to determine if we need to do an activity transition while sleeping, 19675f0d3110b04346b901771f96ce15cdbe907278fYang Ni * when we normally hold the top activity paused. 19775f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 19875f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord mLastPausedActivity = null; 19975f0d3110b04346b901771f96ce15cdbe907278fYang Ni 20075f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 20175f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Activities that specify No History must be removed once the user navigates away from them. 20275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * If the device goes to sleep with such an activity in the paused state then we save it here 20375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * and finish it later if another activity replaces it on wakeup. 20475f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 20575f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord mLastNoHistoryActivity = null; 20675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 20775f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 20875f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Current activity that is resumed, or null if there is none. 20975f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 21075f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord mResumedActivity = null; 21175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 21275f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 21375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * This is the last activity that has been started. It is only used to 21475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * identify when multiple activities are started at once so that the user 21575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * can be warned they may not be in the activity they think they are. 21675f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 21775f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord mLastStartedActivity = null; 21875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 21975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // The topmost Activity passed to convertToTranslucent(). When non-null it means we are 22075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they 22175f0d3110b04346b901771f96ce15cdbe907278fYang Ni // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the 22275f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Activity in mTranslucentActivityWaiting is notified via 22375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last 22475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // background activity being drawn then the same call will be made with a true value. 22575f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord mTranslucentActivityWaiting = null; 22675f0d3110b04346b901771f96ce15cdbe907278fYang Ni private ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>(); 22775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 22875f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 22975f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Set when we know we are going to be calling updateConfiguration() 23075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * soon, so want to skip intermediate config checks. 23175f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 23275f0d3110b04346b901771f96ce15cdbe907278fYang Ni boolean mConfigWillChange; 23375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 23475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Whether or not this stack covers the entire screen; by default stacks are fullscreen 23575f0d3110b04346b901771f96ce15cdbe907278fYang Ni boolean mFullscreen = true; 23675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Current bounds of the stack or null if fullscreen. 23775f0d3110b04346b901771f96ce15cdbe907278fYang Ni Rect mBounds = null; 23875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 23975f0d3110b04346b901771f96ce15cdbe907278fYang Ni long mLaunchStartTime = 0; 24075f0d3110b04346b901771f96ce15cdbe907278fYang Ni long mFullyDrawnStartTime = 0; 24175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 24275f0d3110b04346b901771f96ce15cdbe907278fYang Ni int mCurrentUser; 24375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 24475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final int mStackId; 24575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityContainer mActivityContainer; 24675f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** The other stacks, in order, on the attached display. Updated at attach/detach time. */ 24775f0d3110b04346b901771f96ce15cdbe907278fYang Ni ArrayList<ActivityStack> mStacks; 24875f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** The attached Display's unique identifier, or -1 if detached */ 24975f0d3110b04346b901771f96ce15cdbe907278fYang Ni int mDisplayId; 25075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 25175f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** Run all ActivityStacks through this */ 25275f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityStackSupervisor mStackSupervisor; 25375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 25475f0d3110b04346b901771f96ce15cdbe907278fYang Ni private final LaunchingTaskPositioner mTaskPositioner; 25575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 25675f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1; 25775f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2; 25875f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3; 25975f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4; 26075f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5; 26175f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6; 26275f0d3110b04346b901771f96ce15cdbe907278fYang Ni static final int RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG = 26375f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7; 26475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 26575f0d3110b04346b901771f96ce15cdbe907278fYang Ni static class ScheduleDestroyArgs { 26675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ProcessRecord mOwner; 26775f0d3110b04346b901771f96ce15cdbe907278fYang Ni final String mReason; 26875f0d3110b04346b901771f96ce15cdbe907278fYang Ni ScheduleDestroyArgs(ProcessRecord owner, String reason) { 26975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mOwner = owner; 27075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mReason = reason; 27175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 27275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 27375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 27475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final Handler mHandler; 27575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 27675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final class ActivityStackHandler extends Handler { 27775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 27875f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityStackHandler(Looper looper) { 27975f0d3110b04346b901771f96ce15cdbe907278fYang Ni super(looper); 28075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 28175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 28275f0d3110b04346b901771f96ce15cdbe907278fYang Ni @Override 28375f0d3110b04346b901771f96ce15cdbe907278fYang Ni public void handleMessage(Message msg) { 28475f0d3110b04346b901771f96ce15cdbe907278fYang Ni switch (msg.what) { 28575f0d3110b04346b901771f96ce15cdbe907278fYang Ni case PAUSE_TIMEOUT_MSG: { 28675f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord r = (ActivityRecord)msg.obj; 28775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // We don't at this point know if the activity is fullscreen, 28875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // so we need to be conservative and assume it isn't. 28975f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.w(TAG, "Activity pause timeout for " + r); 29075f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (mService) { 29175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.app != null) { 29275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r); 29375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 29475f0d3110b04346b901771f96ce15cdbe907278fYang Ni activityPausedLocked(r.appToken, true); 29575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 29675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } break; 29775f0d3110b04346b901771f96ce15cdbe907278fYang Ni case LAUNCH_TICK_MSG: { 29875f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord r = (ActivityRecord)msg.obj; 29975f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (mService) { 30075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.continueLaunchTickingLocked()) { 30175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r); 30275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 30375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 30475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } break; 30575f0d3110b04346b901771f96ce15cdbe907278fYang Ni case DESTROY_TIMEOUT_MSG: { 30675f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord r = (ActivityRecord)msg.obj; 30775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // We don't at this point know if the activity is fullscreen, 30875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // so we need to be conservative and assume it isn't. 30975f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.w(TAG, "Activity destroy timeout for " + r); 31075f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (mService) { 31175f0d3110b04346b901771f96ce15cdbe907278fYang Ni activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout"); 31275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 31375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } break; 31475f0d3110b04346b901771f96ce15cdbe907278fYang Ni case STOP_TIMEOUT_MSG: { 31575f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord r = (ActivityRecord)msg.obj; 31675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // We don't at this point know if the activity is fullscreen, 31775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // so we need to be conservative and assume it isn't. 31875f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.w(TAG, "Activity stop timeout for " + r); 31975f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (mService) { 32075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.isInHistory()) { 32175f0d3110b04346b901771f96ce15cdbe907278fYang Ni activityStoppedLocked(r, null, null, null); 32275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 32375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 32475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } break; 32575f0d3110b04346b901771f96ce15cdbe907278fYang Ni case DESTROY_ACTIVITIES_MSG: { 32675f0d3110b04346b901771f96ce15cdbe907278fYang Ni ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj; 32775f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (mService) { 32875f0d3110b04346b901771f96ce15cdbe907278fYang Ni destroyActivitiesLocked(args.mOwner, args.mReason); 32975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 33075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } break; 33175f0d3110b04346b901771f96ce15cdbe907278fYang Ni case TRANSLUCENT_TIMEOUT_MSG: { 33275f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (mService) { 33375f0d3110b04346b901771f96ce15cdbe907278fYang Ni notifyActivityDrawnLocked(null); 33475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 33575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } break; 33675f0d3110b04346b901771f96ce15cdbe907278fYang Ni case RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG: { 33775f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (mService) { 33875f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = getVisibleBehindActivity(); 33975f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.e(TAG, "Timeout waiting for cancelVisibleBehind player=" + r); 34075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r != null) { 34175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService.killAppAtUsersRequest(r.app, null); 34275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 34375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 34475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } break; 34575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 34675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 34775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 34875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 34975f0d3110b04346b901771f96ce15cdbe907278fYang Ni int numActivities() { 35075f0d3110b04346b901771f96ce15cdbe907278fYang Ni int count = 0; 35175f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 35275f0d3110b04346b901771f96ce15cdbe907278fYang Ni count += mTaskHistory.get(taskNdx).mActivities.size(); 35375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 35475f0d3110b04346b901771f96ce15cdbe907278fYang Ni return count; 35575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 35675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 35775f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer, 35875f0d3110b04346b901771f96ce15cdbe907278fYang Ni RecentTasks recentTasks) { 35975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mActivityContainer = activityContainer; 36075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor = activityContainer.getOuter(); 36175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService = mStackSupervisor.mService; 36275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mHandler = new ActivityStackHandler(mService.mHandler.getLooper()); 36375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mWindowManager = mService.mWindowManager; 36475f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackId = activityContainer.mStackId; 36575f0d3110b04346b901771f96ce15cdbe907278fYang Ni mCurrentUser = mService.mUserController.getCurrentUserIdLocked(); 36675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mRecentTasks = recentTasks; 36775f0d3110b04346b901771f96ce15cdbe907278fYang Ni mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID 36875f0d3110b04346b901771f96ce15cdbe907278fYang Ni ? new LaunchingTaskPositioner() : null; 36975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 37075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 37175f0d3110b04346b901771f96ce15cdbe907278fYang Ni void attachDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) { 37275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mDisplayId = activityDisplay.mDisplayId; 37375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStacks = activityDisplay.mStacks; 37475f0d3110b04346b901771f96ce15cdbe907278fYang Ni mBounds = mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId, onTop); 37575f0d3110b04346b901771f96ce15cdbe907278fYang Ni mFullscreen = mBounds == null; 37675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mTaskPositioner != null) { 37775f0d3110b04346b901771f96ce15cdbe907278fYang Ni mTaskPositioner.setDisplay(activityDisplay.mDisplay); 37875f0d3110b04346b901771f96ce15cdbe907278fYang Ni mTaskPositioner.configure(mBounds); 37975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 38075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 38175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 38275f0d3110b04346b901771f96ce15cdbe907278fYang Ni void detachDisplay() { 38375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mDisplayId = Display.INVALID_DISPLAY; 38475f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStacks = null; 38575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mTaskPositioner != null) { 38675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mTaskPositioner.reset(); 38775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 38875f0d3110b04346b901771f96ce15cdbe907278fYang Ni mWindowManager.detachStack(mStackId); 38975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 39075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 39175f0d3110b04346b901771f96ce15cdbe907278fYang Ni void setBounds(Rect bounds) { 39275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mBounds = mFullscreen ? null : new Rect(bounds); 39375f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mTaskPositioner != null) { 39475f0d3110b04346b901771f96ce15cdbe907278fYang Ni mTaskPositioner.configure(bounds); 39575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 39675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 39775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 39875f0d3110b04346b901771f96ce15cdbe907278fYang Ni boolean okToShowLocked(ActivityRecord r) { 39975f0d3110b04346b901771f96ce15cdbe907278fYang Ni return mStackSupervisor.okToShowLocked(r); 40075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 40175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 40275f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord topRunningActivityLocked() { 40375f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 40475f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(); 40575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r != null) { 40675f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 40775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 40875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 40975f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 41075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 41175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 41275f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) { 41375f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 41475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final TaskRecord task = mTaskHistory.get(taskNdx); 41575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ArrayList<ActivityRecord> activities = task.mActivities; 41675f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 41775f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord r = activities.get(activityNdx); 41875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!r.finishing && !r.delayedResume && r != notTop && okToShowLocked(r)) { 41975f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 42075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 42175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 42275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 42375f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 42475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 42575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 42675f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 42775f0d3110b04346b901771f96ce15cdbe907278fYang Ni * This is a simplified version of topRunningActivityLocked that provides a number of 42875f0d3110b04346b901771f96ce15cdbe907278fYang Ni * optional skip-over modes. It is intended for use with the ActivityController hook only. 42975f0d3110b04346b901771f96ce15cdbe907278fYang Ni * 43075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param token If non-null, any history records matching this token will be skipped. 43175f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param taskId If non-zero, we'll attempt to skip over records with the same task ID. 43275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * 43375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @return Returns the HistoryRecord of the next activity on the stack. 43475f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 43575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) { 43675f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 43775f0d3110b04346b901771f96ce15cdbe907278fYang Ni TaskRecord task = mTaskHistory.get(taskNdx); 43875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task.taskId == taskId) { 43975f0d3110b04346b901771f96ce15cdbe907278fYang Ni continue; 44075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 44175f0d3110b04346b901771f96ce15cdbe907278fYang Ni ArrayList<ActivityRecord> activities = task.mActivities; 44275f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int i = activities.size() - 1; i >= 0; --i) { 44375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = activities.get(i); 44475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Note: the taskId check depends on real taskId fields being non-zero 44575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!r.finishing && (token != r.appToken) && okToShowLocked(r)) { 44675f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 44775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 44875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 44975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 45075f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 45175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 45275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 45375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord topActivity() { 45475f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 45575f0d3110b04346b901771f96ce15cdbe907278fYang Ni ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 45675f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 45775f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = activities.get(activityNdx); 45875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!r.finishing) { 45975f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 46075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 46175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 46275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 46375f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 46475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 46575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 46675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final TaskRecord topTask() { 46775f0d3110b04346b901771f96ce15cdbe907278fYang Ni final int size = mTaskHistory.size(); 46875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (size > 0) { 46975f0d3110b04346b901771f96ce15cdbe907278fYang Ni return mTaskHistory.get(size - 1); 47075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 47175f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 47275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 47375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 47475f0d3110b04346b901771f96ce15cdbe907278fYang Ni TaskRecord taskForIdLocked(int id) { 47575f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 47675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final TaskRecord task = mTaskHistory.get(taskNdx); 47775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task.taskId == id) { 47875f0d3110b04346b901771f96ce15cdbe907278fYang Ni return task; 47975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 48075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 48175f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 48275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 48375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 48475f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord isInStackLocked(IBinder token) { 48575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = ActivityRecord.forTokenLocked(token); 48675f0d3110b04346b901771f96ce15cdbe907278fYang Ni return isInStackLocked(r); 48775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 48875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 48975f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord isInStackLocked(ActivityRecord r) { 49075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r == null) { 49175f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 49275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 49375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final TaskRecord task = r.task; 49475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task != null && task.stack != null 49575f0d3110b04346b901771f96ce15cdbe907278fYang Ni && task.mActivities.contains(r) && mTaskHistory.contains(task)) { 49675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task.stack != this) Slog.w(TAG, 49775f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Illegal state! task does not point to stack it is in."); 49875f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 49975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 50075f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 50175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 50275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 50375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean updateLRUListLocked(ActivityRecord r) { 50475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean hadit = mLRUActivities.remove(r); 50575f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLRUActivities.add(r); 50675f0d3110b04346b901771f96ce15cdbe907278fYang Ni return hadit; 50775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 50875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 50975f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean isHomeStack() { 51075f0d3110b04346b901771f96ce15cdbe907278fYang Ni return mStackId == HOME_STACK_ID; 51175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 51275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 51375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean isOnHomeDisplay() { 51475f0d3110b04346b901771f96ce15cdbe907278fYang Ni return isAttached() && 51575f0d3110b04346b901771f96ce15cdbe907278fYang Ni mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY; 51675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 51775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 51875f0d3110b04346b901771f96ce15cdbe907278fYang Ni void moveToFront(String reason) { 51975f0d3110b04346b901771f96ce15cdbe907278fYang Ni moveToFront(reason, null); 52075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 52175f0d3110b04346b901771f96ce15cdbe907278fYang Ni 52275f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 52375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param reason The reason for moving the stack to the front. 52475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param task If non-null, the task will be moved to the top of the stack. 52575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * */ 52675f0d3110b04346b901771f96ce15cdbe907278fYang Ni void moveToFront(String reason, TaskRecord task) { 52775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!isAttached()) { 52875f0d3110b04346b901771f96ce15cdbe907278fYang Ni return; 52975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 53075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 53175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStacks.remove(this); 53275f0d3110b04346b901771f96ce15cdbe907278fYang Ni int addIndex = mStacks.size(); 53375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 53475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (addIndex > 0) { 53575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityStack topStack = mStacks.get(addIndex - 1); 53675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (topStack.mStackId == PINNED_STACK_ID && topStack != this) { 53775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // The pinned stack is always the top most stack (always-on-top). 53875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // So, stack is moved just below the pinned stack. 53975f0d3110b04346b901771f96ce15cdbe907278fYang Ni addIndex--; 54075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 54175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 54275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 54375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStacks.add(addIndex, this); 54475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 54575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // TODO(multi-display): Needs to also work if focus is moving to the non-home display. 54675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (isOnHomeDisplay()) { 54775f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.setFocusStack(reason, this); 54875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 54975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task != null) { 55075f0d3110b04346b901771f96ce15cdbe907278fYang Ni insertTaskAtTop(task, null); 55175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 55275f0d3110b04346b901771f96ce15cdbe907278fYang Ni task = topTask(); 55375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 55475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task != null) { 55575f0d3110b04346b901771f96ce15cdbe907278fYang Ni mWindowManager.moveTaskToTop(task.taskId); 55675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 55775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 55875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 55975f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean isAttached() { 56075f0d3110b04346b901771f96ce15cdbe907278fYang Ni return mStacks != null; 56175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 56275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 56375f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 56475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Returns the top activity in any existing task matching the given 56575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Intent. Returns null if no such task is found. 56675f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 56775f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord findTaskLocked(ActivityRecord target) { 56875f0d3110b04346b901771f96ce15cdbe907278fYang Ni Intent intent = target.intent; 56975f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityInfo info = target.info; 57075f0d3110b04346b901771f96ce15cdbe907278fYang Ni ComponentName cls = intent.getComponent(); 57175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (info.targetActivity != null) { 57275f0d3110b04346b901771f96ce15cdbe907278fYang Ni cls = new ComponentName(info.packageName, info.targetActivity); 57375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 57475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final int userId = UserHandle.getUserId(info.applicationInfo.uid); 57575f0d3110b04346b901771f96ce15cdbe907278fYang Ni boolean isDocument = intent != null & intent.isDocument(); 57675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // If documentData is non-null then it must match the existing task data. 57775f0d3110b04346b901771f96ce15cdbe907278fYang Ni Uri documentData = isDocument ? intent.getData() : null; 57875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 57975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this); 58075f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 58175f0d3110b04346b901771f96ce15cdbe907278fYang Ni final TaskRecord task = mTaskHistory.get(taskNdx); 58275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task.voiceSession != null) { 58375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // We never match voice sessions; those always run independently. 58475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session"); 58575f0d3110b04346b901771f96ce15cdbe907278fYang Ni continue; 58675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 58775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task.userId != userId) { 58875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Looking for a different task. 58975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user"); 59075f0d3110b04346b901771f96ce15cdbe907278fYang Ni continue; 59175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 59275f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = task.getTopActivity(); 59375f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r == null || r.finishing || r.userId != userId || 59475f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 59575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r); 59675f0d3110b04346b901771f96ce15cdbe907278fYang Ni continue; 59775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 59875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.mActivityType != target.mActivityType) { 59975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type"); 60075f0d3110b04346b901771f96ce15cdbe907278fYang Ni continue; 60175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 60275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 60375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final Intent taskIntent = task.intent; 60475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final Intent affinityIntent = task.affinityIntent; 60575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean taskIsDocument; 60675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final Uri taskDocumentData; 60775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (taskIntent != null && taskIntent.isDocument()) { 60875f0d3110b04346b901771f96ce15cdbe907278fYang Ni taskIsDocument = true; 60975f0d3110b04346b901771f96ce15cdbe907278fYang Ni taskDocumentData = taskIntent.getData(); 61075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (affinityIntent != null && affinityIntent.isDocument()) { 61175f0d3110b04346b901771f96ce15cdbe907278fYang Ni taskIsDocument = true; 61275f0d3110b04346b901771f96ce15cdbe907278fYang Ni taskDocumentData = affinityIntent.getData(); 61375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 61475f0d3110b04346b901771f96ce15cdbe907278fYang Ni taskIsDocument = false; 61575f0d3110b04346b901771f96ce15cdbe907278fYang Ni taskDocumentData = null; 61675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 61775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 61875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls=" 61975f0d3110b04346b901771f96ce15cdbe907278fYang Ni + taskIntent.getComponent().flattenToShortString() 62075f0d3110b04346b901771f96ce15cdbe907278fYang Ni + "/aff=" + r.task.rootAffinity + " to new cls=" 62175f0d3110b04346b901771f96ce15cdbe907278fYang Ni + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity); 62275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!isDocument && !taskIsDocument && task.rootAffinity != null) { 62375f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (task.rootAffinity.equals(target.taskAffinity)) { 62475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity!"); 62575f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 62675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 62775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (taskIntent != null && taskIntent.getComponent() != null && 62875f0d3110b04346b901771f96ce15cdbe907278fYang Ni taskIntent.getComponent().compareTo(cls) == 0 && 62975f0d3110b04346b901771f96ce15cdbe907278fYang Ni Objects.equals(documentData, taskDocumentData)) { 63075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!"); 63175f0d3110b04346b901771f96ce15cdbe907278fYang Ni //dump(); 63275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, 63375f0d3110b04346b901771f96ce15cdbe907278fYang Ni "For Intent " + intent + " bringing to top: " + r.intent); 63475f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 63575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (affinityIntent != null && affinityIntent.getComponent() != null && 63675f0d3110b04346b901771f96ce15cdbe907278fYang Ni affinityIntent.getComponent().compareTo(cls) == 0 && 63775f0d3110b04346b901771f96ce15cdbe907278fYang Ni Objects.equals(documentData, taskDocumentData)) { 63875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!"); 63975f0d3110b04346b901771f96ce15cdbe907278fYang Ni //dump(); 64075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, 64175f0d3110b04346b901771f96ce15cdbe907278fYang Ni "For Intent " + intent + " bringing to top: " + r.intent); 64275f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 64375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task); 64475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 64575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 64675f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 64775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 64875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 64975f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 65075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Returns the first activity (starting from the top of the stack) that 65175f0d3110b04346b901771f96ce15cdbe907278fYang Ni * is the same as the given activity. Returns null if no such activity 65275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * is found. 65375f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 65475f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) { 65575f0d3110b04346b901771f96ce15cdbe907278fYang Ni ComponentName cls = intent.getComponent(); 65675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (info.targetActivity != null) { 65775f0d3110b04346b901771f96ce15cdbe907278fYang Ni cls = new ComponentName(info.packageName, info.targetActivity); 65875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 65975f0d3110b04346b901771f96ce15cdbe907278fYang Ni final int userId = UserHandle.getUserId(info.applicationInfo.uid); 66075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 66175f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 66275f0d3110b04346b901771f96ce15cdbe907278fYang Ni final TaskRecord task = mTaskHistory.get(taskNdx); 66375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean notCurrentUserTask = 66475f0d3110b04346b901771f96ce15cdbe907278fYang Ni !mStackSupervisor.isCurrentProfileLocked(task.userId); 66575f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ArrayList<ActivityRecord> activities = task.mActivities; 66675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 66775f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 66875f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord r = activities.get(activityNdx); 66975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (notCurrentUserTask && (r.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) { 67075f0d3110b04346b901771f96ce15cdbe907278fYang Ni continue; 67175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 67275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) { 67375f0d3110b04346b901771f96ce15cdbe907278fYang Ni return r; 67475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 67575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 67675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 67775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 67875f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 67975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 68075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 68175f0d3110b04346b901771f96ce15cdbe907278fYang Ni /* 68275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Move the activities around in the stack to bring a user to the foreground. 68375f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 68475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final void switchUserLocked(int userId) { 68575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mCurrentUser == userId) { 68675f0d3110b04346b901771f96ce15cdbe907278fYang Ni return; 68775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 68875f0d3110b04346b901771f96ce15cdbe907278fYang Ni mCurrentUser = userId; 68975f0d3110b04346b901771f96ce15cdbe907278fYang Ni 69075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Move userId's tasks to the top. 69175f0d3110b04346b901771f96ce15cdbe907278fYang Ni int index = mTaskHistory.size(); 69275f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int i = 0; i < index; ) { 69375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final TaskRecord task = mTaskHistory.get(i); 69475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 69575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is 69675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // okay to show the activity when locked. 69775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mStackSupervisor.isCurrentProfileLocked(task.userId) 69875f0d3110b04346b901771f96ce15cdbe907278fYang Ni || task.topRunningActivityLocked() != null) { 69975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUserLocked: stack=" + getStackId() + 70075f0d3110b04346b901771f96ce15cdbe907278fYang Ni " moving " + task + " to top"); 70175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mTaskHistory.remove(i); 70275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mTaskHistory.add(task); 70375f0d3110b04346b901771f96ce15cdbe907278fYang Ni --index; 70475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Use same value for i. 70575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 70675f0d3110b04346b901771f96ce15cdbe907278fYang Ni ++i; 70775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 70875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 70975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (VALIDATE_TOKENS) { 71075f0d3110b04346b901771f96ce15cdbe907278fYang Ni validateAppTokensLocked(); 71175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 71275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 71375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 71475f0d3110b04346b901771f96ce15cdbe907278fYang Ni void minimalResumeActivityLocked(ActivityRecord r) { 71575f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.state = ActivityState.RESUMED; 71675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_STATES) Slog.v(TAG_STATES, 71775f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Moving to RESUMED: " + r + " (starting new instance)"); 71875f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.stopped = false; 71975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mResumedActivity = r; 72075f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.task.touchActiveTime(); 72175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mRecentTasks.addLocked(r.task); 72275f0d3110b04346b901771f96ce15cdbe907278fYang Ni completeResumeLocked(r); 72375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.checkReadyForSleepLocked(); 72475f0d3110b04346b901771f96ce15cdbe907278fYang Ni setLaunchTime(r); 72575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, 72675f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Launch completed; removing icicle of " + r.icicle); 72775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 72875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 72975f0d3110b04346b901771f96ce15cdbe907278fYang Ni private void addRecentActivityLocked(ActivityRecord r) { 73075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r != null) { 73175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mRecentTasks.addLocked(r.task); 73275f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.task.touchActiveTime(); 73375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 73475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 73575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 73675f0d3110b04346b901771f96ce15cdbe907278fYang Ni private void startLaunchTraces(String packageName) { 73775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mFullyDrawnStartTime != 0) { 73875f0d3110b04346b901771f96ce15cdbe907278fYang Ni Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0); 73975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 74075f0d3110b04346b901771f96ce15cdbe907278fYang Ni Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0); 74175f0d3110b04346b901771f96ce15cdbe907278fYang Ni Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0); 74275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 74375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 74475f0d3110b04346b901771f96ce15cdbe907278fYang Ni private void stopFullyDrawnTraceIfNeeded() { 74575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mFullyDrawnStartTime != 0 && mLaunchStartTime == 0) { 74675f0d3110b04346b901771f96ce15cdbe907278fYang Ni Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0); 74775f0d3110b04346b901771f96ce15cdbe907278fYang Ni mFullyDrawnStartTime = 0; 74875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 74975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 75075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 75175f0d3110b04346b901771f96ce15cdbe907278fYang Ni void setLaunchTime(ActivityRecord r) { 75275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.displayStartTime == 0) { 75375f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis(); 75475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mLaunchStartTime == 0) { 75575f0d3110b04346b901771f96ce15cdbe907278fYang Ni startLaunchTraces(r.packageName); 75675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime; 75775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 75875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (mLaunchStartTime == 0) { 75975f0d3110b04346b901771f96ce15cdbe907278fYang Ni startLaunchTraces(r.packageName); 76075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLaunchStartTime = mFullyDrawnStartTime = SystemClock.uptimeMillis(); 76175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 76275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 76375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 76475f0d3110b04346b901771f96ce15cdbe907278fYang Ni void clearLaunchTime(ActivityRecord r) { 76575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Make sure that there is no activity waiting for this to launch. 76675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) { 76775f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.displayStartTime = r.fullyDrawnStartTime = 0; 76875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 76975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.removeTimeoutsForActivityLocked(r); 77075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.scheduleIdleTimeoutLocked(r); 77175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 77275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 77375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 77475f0d3110b04346b901771f96ce15cdbe907278fYang Ni void awakeFromSleepingLocked() { 77575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Ensure activities are no longer sleeping. 77675f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 77775f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 77875f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 77975f0d3110b04346b901771f96ce15cdbe907278fYang Ni activities.get(activityNdx).setSleeping(false); 78075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 78175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 78275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mPausingActivity != null) { 78375f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause"); 78475f0d3110b04346b901771f96ce15cdbe907278fYang Ni activityPausedLocked(mPausingActivity.appToken, true); 78575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 78675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 78775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 78875f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 78975f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @return true if something must be done before going to sleep. 79075f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 79175f0d3110b04346b901771f96ce15cdbe907278fYang Ni boolean checkReadyForSleepLocked() { 79275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mResumedActivity != null) { 79375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Still have something resumed; can't sleep until it is paused. 79475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity); 79575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 79675f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Sleep => pause with userLeaving=false"); 79775f0d3110b04346b901771f96ce15cdbe907278fYang Ni startPausingLocked(false, true, false, false); 79875f0d3110b04346b901771f96ce15cdbe907278fYang Ni return true; 79975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 80075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mPausingActivity != null) { 80175f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Still waiting for something to pause; can't sleep yet. 80275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity); 80375f0d3110b04346b901771f96ce15cdbe907278fYang Ni return true; 80475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 80575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 80675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (hasVisibleBehindActivity()) { 80775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Stop visible behind activity before going to sleep. 80875f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = mActivityContainer.mActivityDisplay.mVisibleBehindActivity; 80975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.mStoppingActivities.add(r); 81075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_STATES) Slog.v(TAG_STATES, 81175f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Sleep still waiting to stop visible behind " + r); 81275f0d3110b04346b901771f96ce15cdbe907278fYang Ni return true; 81375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 81475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 81575f0d3110b04346b901771f96ce15cdbe907278fYang Ni return false; 81675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 81775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 81875f0d3110b04346b901771f96ce15cdbe907278fYang Ni void goToSleep() { 81975f0d3110b04346b901771f96ce15cdbe907278fYang Ni ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); 82075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 82175f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Make sure any stopped but visible activities are now sleeping. 82275f0d3110b04346b901771f96ce15cdbe907278fYang Ni // This ensures that the activity's onStop() is called. 82375f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 82475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 82575f0d3110b04346b901771f96ce15cdbe907278fYang Ni for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 82675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = activities.get(activityNdx); 82775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) { 82875f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.setSleeping(true); 82975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 83075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 83175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 83275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 83375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 83475f0d3110b04346b901771f96ce15cdbe907278fYang Ni public final Bitmap screenshotActivities(ActivityRecord who) { 83575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "screenshotActivities: " + who); 83675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (who.noDisplay) { 83775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tNo display"); 83875f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 83975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 84075f0d3110b04346b901771f96ce15cdbe907278fYang Ni 84175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (isHomeStack()) { 84275f0d3110b04346b901771f96ce15cdbe907278fYang Ni // This is an optimization -- since we never show Home or Recents within Recents itself, 84375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // we can just go ahead and skip taking the screenshot if this is the home stack. 84475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tHome stack"); 84575f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 84675f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 84775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 84875f0d3110b04346b901771f96ce15cdbe907278fYang Ni int w = mService.mThumbnailWidth; 84975f0d3110b04346b901771f96ce15cdbe907278fYang Ni int h = mService.mThumbnailHeight; 85075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (w > 0) { 85175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot"); 85275f0d3110b04346b901771f96ce15cdbe907278fYang Ni return mWindowManager.screenshotApplications(who.appToken, Display.DEFAULT_DISPLAY, 85375f0d3110b04346b901771f96ce15cdbe907278fYang Ni w, h); 85475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 85575f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.e(TAG, "Invalid thumbnail dimensions: " + w + "x" + h); 85675f0d3110b04346b901771f96ce15cdbe907278fYang Ni return null; 85775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 85875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 85975f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 86075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Start pausing the currently resumed activity. It is an error to call this if there 86175f0d3110b04346b901771f96ce15cdbe907278fYang Ni * is already an activity being paused or there is no resumed activity. 86275f0d3110b04346b901771f96ce15cdbe907278fYang Ni * 86375f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param userLeaving True if this should result in an onUserLeaving to the current activity. 86475f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param uiSleeping True if this is happening with the user interface going to sleep (the 86575f0d3110b04346b901771f96ce15cdbe907278fYang Ni * screen turning off). 86675f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param resuming True if this is being called as part of resuming the top activity, so 86775f0d3110b04346b901771f96ce15cdbe907278fYang Ni * we shouldn't try to instigate a resume here. 86875f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @param dontWait True if the caller does not want to wait for the pause to complete. If 86975f0d3110b04346b901771f96ce15cdbe907278fYang Ni * set to true, we will immediately complete the pause here before returning. 87075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * @return Returns true if an activity now is in the PAUSING state, and we are waiting for 87175f0d3110b04346b901771f96ce15cdbe907278fYang Ni * it to tell us when it is done. 87275f0d3110b04346b901771f96ce15cdbe907278fYang Ni */ 87375f0d3110b04346b901771f96ce15cdbe907278fYang Ni final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming, 87475f0d3110b04346b901771f96ce15cdbe907278fYang Ni boolean dontWait) { 87575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mPausingActivity != null) { 87675f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity 87775f0d3110b04346b901771f96ce15cdbe907278fYang Ni + " state=" + mPausingActivity.state); 87875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!mService.isSleeping()) { 87975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Avoid recursion among check for sleep and complete pause during sleeping. 88075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Because activity will be paused immediately after resume, just let pause 88175f0d3110b04346b901771f96ce15cdbe907278fYang Ni // be completed by the order of activity paused from clients. 88275f0d3110b04346b901771f96ce15cdbe907278fYang Ni completePauseLocked(false); 88375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 88475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 88575f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord prev = mResumedActivity; 88675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (prev == null) { 88775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!resuming) { 88875f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.wtf(TAG, "Trying to pause when nothing is resumed"); 88975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.resumeTopActivitiesLocked(); 89075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 89175f0d3110b04346b901771f96ce15cdbe907278fYang Ni return false; 89275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 89375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 89475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mActivityContainer.mParentActivity == null) { 89575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Top level stack, not a child. Look for child stacks. 89675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait); 89775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 89875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 89975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev); 90075f0d3110b04346b901771f96ce15cdbe907278fYang Ni else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev); 90175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mResumedActivity = null; 90275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mPausingActivity = prev; 90375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLastPausedActivity = prev; 90475f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 90575f0d3110b04346b901771f96ce15cdbe907278fYang Ni || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null; 90675f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.state = ActivityState.PAUSING; 90775f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.task.touchActiveTime(); 90875f0d3110b04346b901771f96ce15cdbe907278fYang Ni clearLaunchTime(prev); 90975f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord next = mStackSupervisor.topRunningActivityLocked(); 91075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mService.mHasRecents 91175f0d3110b04346b901771f96ce15cdbe907278fYang Ni && (next == null || next.noDisplay || next.task != prev.task || uiSleeping)) { 91275f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.updateThumbnailLocked(screenshotActivities(prev), null); 91375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 91475f0d3110b04346b901771f96ce15cdbe907278fYang Ni stopFullyDrawnTraceIfNeeded(); 91575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 91675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService.updateCpuStats(); 91775f0d3110b04346b901771f96ce15cdbe907278fYang Ni 91875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (prev.app != null && prev.app.thread != null) { 91975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev); 92075f0d3110b04346b901771f96ce15cdbe907278fYang Ni try { 92175f0d3110b04346b901771f96ce15cdbe907278fYang Ni EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY, 92275f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.userId, System.identityHashCode(prev), 92375f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.shortComponentName); 92475f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService.updateUsageStats(prev, false); 92575f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing, 92675f0d3110b04346b901771f96ce15cdbe907278fYang Ni userLeaving, prev.configChangeFlags, dontWait); 92775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } catch (Exception e) { 92875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Ignore exception, if process died other code will cleanup. 92975f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.w(TAG, "Exception thrown during pause", e); 93075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mPausingActivity = null; 93175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLastPausedActivity = null; 93275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLastNoHistoryActivity = null; 93375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 93475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 93575f0d3110b04346b901771f96ce15cdbe907278fYang Ni mPausingActivity = null; 93675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLastPausedActivity = null; 93775f0d3110b04346b901771f96ce15cdbe907278fYang Ni mLastNoHistoryActivity = null; 93875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 93975f0d3110b04346b901771f96ce15cdbe907278fYang Ni 94075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // If we are not going to sleep, we want to ensure the device is 94175f0d3110b04346b901771f96ce15cdbe907278fYang Ni // awake until the next activity is started. 94275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!uiSleeping && !mService.isSleepingOrShuttingDown()) { 94375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.acquireLaunchWakelock(); 94475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 94575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 94675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mPausingActivity != null) { 94775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Have the window manager pause its key dispatching until the new 94875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // activity has started. If we're pausing the activity just because 94975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // the screen is being turned off and the UI is sleeping, don't interrupt 95075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // key dispatch; the same activity will pick it up again on wakeup. 95175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!uiSleeping) { 95275f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.pauseKeyDispatchingLocked(); 95375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (DEBUG_PAUSE) { 95475f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off"); 95575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 95675f0d3110b04346b901771f96ce15cdbe907278fYang Ni 95775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (dontWait) { 95875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // If the caller said they don't want to wait for the pause, then complete 95975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // the pause now. 96075f0d3110b04346b901771f96ce15cdbe907278fYang Ni completePauseLocked(false); 96175f0d3110b04346b901771f96ce15cdbe907278fYang Ni return false; 96275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 96375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 96475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Schedule a pause timeout in case the app doesn't respond. 96575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // We don't give it much time because this directly impacts the 96675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // responsiveness seen by the user. 96775f0d3110b04346b901771f96ce15cdbe907278fYang Ni Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); 96875f0d3110b04346b901771f96ce15cdbe907278fYang Ni msg.obj = prev; 96975f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.pauseTime = SystemClock.uptimeMillis(); 97075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); 97175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete..."); 97275f0d3110b04346b901771f96ce15cdbe907278fYang Ni return true; 97375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 97475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 97575f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 97675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // This activity failed to schedule the 97775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // pause, so just treat it as being paused now. 97875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next."); 97975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!resuming) { 98075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null); 98175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 98275f0d3110b04346b901771f96ce15cdbe907278fYang Ni return false; 98375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 98475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 98575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 98675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final void activityPausedLocked(IBinder token, boolean timeout) { 98775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, 98875f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Activity paused: token=" + token + ", timeout=" + timeout); 98975f0d3110b04346b901771f96ce15cdbe907278fYang Ni 99075f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityRecord r = isInStackLocked(token); 99175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r != null) { 99275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 99375f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mPausingActivity == r) { 99475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r 99575f0d3110b04346b901771f96ce15cdbe907278fYang Ni + (timeout ? " (due to timeout)" : " (pause complete)")); 99675f0d3110b04346b901771f96ce15cdbe907278fYang Ni completePauseLocked(true); 99775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 99875f0d3110b04346b901771f96ce15cdbe907278fYang Ni EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE, 99975f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.userId, System.identityHashCode(r), r.shortComponentName, 100075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mPausingActivity != null 100175f0d3110b04346b901771f96ce15cdbe907278fYang Ni ? mPausingActivity.shortComponentName : "(none)"); 100275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.state == ActivityState.PAUSING) { 100375f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.state = ActivityState.PAUSED; 100475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.finishing) { 100575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG, 100675f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Executing finish of failed to pause activity: " + r); 100775f0d3110b04346b901771f96ce15cdbe907278fYang Ni finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false); 100875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 100975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 101075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 101175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 101275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 101375f0d3110b04346b901771f96ce15cdbe907278fYang Ni 101475f0d3110b04346b901771f96ce15cdbe907278fYang Ni final void activityStoppedLocked(ActivityRecord r, Bundle icicle, 101575f0d3110b04346b901771f96ce15cdbe907278fYang Ni PersistableBundle persistentState, CharSequence description) { 101675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.state != ActivityState.STOPPING) { 101775f0d3110b04346b901771f96ce15cdbe907278fYang Ni Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r); 101875f0d3110b04346b901771f96ce15cdbe907278fYang Ni mHandler.removeMessages(STOP_TIMEOUT_MSG, r); 101975f0d3110b04346b901771f96ce15cdbe907278fYang Ni return; 102075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 102175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (persistentState != null) { 102275f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.persistentState = persistentState; 102375f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService.notifyTaskPersisterLocked(r.task, false); 102475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 102575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + r + ": " + icicle); 102675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (icicle != null) { 102775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // If icicle is null, this is happening due to a timeout, so we 102875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // haven't really saved the state. 102975f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.icicle = icicle; 103075f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.haveState = true; 103175f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.launchCount = 0; 103275f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.updateThumbnailLocked(null, description); 103375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 103475f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!r.stopped) { 103575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + r + " (stop complete)"); 103675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mHandler.removeMessages(STOP_TIMEOUT_MSG, r); 103775f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.stopped = true; 103875f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.state = ActivityState.STOPPED; 103975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mActivityContainer.mActivityDisplay.mVisibleBehindActivity == r) { 104075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.requestVisibleBehindLocked(r, false); 104175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 104275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.finishing) { 104375f0d3110b04346b901771f96ce15cdbe907278fYang Ni r.clearOptionsLocked(); 104475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 104575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (r.configDestroy) { 104675f0d3110b04346b901771f96ce15cdbe907278fYang Ni destroyActivityLocked(r, true, "stop-config"); 104775f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.resumeTopActivitiesLocked(); 104875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 104975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.updatePreviousProcessLocked(r); 105075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 105175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 105275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 105375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 105475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 105575f0d3110b04346b901771f96ce15cdbe907278fYang Ni private void completePauseLocked(boolean resumeNext) { 105675f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord prev = mPausingActivity; 105775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev); 105875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 105975f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (prev != null) { 106075f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.state = ActivityState.PAUSED; 106175f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (prev.finishing) { 106275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev); 106375f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false); 106475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (prev.app != null) { 106575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending stop: " + prev); 106675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) { 106775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE, 106875f0d3110b04346b901771f96ce15cdbe907278fYang Ni "Complete pause, no longer waiting: " + prev); 106975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 107075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (prev.configDestroy) { 107175f0d3110b04346b901771f96ce15cdbe907278fYang Ni // The previous is being paused because the configuration 107275f0d3110b04346b901771f96ce15cdbe907278fYang Ni // is changing, which means it is actually stopping... 107375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // To juggle the fact that we are also starting a new 107475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // instance right now, we need to first completely stop 107575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // the current instance before starting the new one. 107675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Destroying after pause: " + prev); 107775f0d3110b04346b901771f96ce15cdbe907278fYang Ni destroyActivityLocked(prev, true, "pause-config"); 107875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else if (!hasVisibleBehindActivity() || mService.isSleepingOrShuttingDown()) { 107975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // If we were visible then resumeTopActivities will release resources before 108075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // stopping. 108175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.mStoppingActivities.add(prev); 108275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (mStackSupervisor.mStoppingActivities.size() > 3 || 108375f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.frontOfTask && mTaskHistory.size() <= 1) { 108475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // If we already have a few activities waiting to stop, 108575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // then give up on things going idle and start clearing 108675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // them out. Or if r is the last of activity of the last task the stack 108775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // will be empty and must be cleared immediately. 108875f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "To many pending stops, forcing idle"); 108975f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.scheduleIdleLocked(); 109075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 109175f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.checkReadyForSleepLocked(); 109275f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 109375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 109475f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 109575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev); 109675f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev = null; 109775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 109875f0d3110b04346b901771f96ce15cdbe907278fYang Ni // It is possible the activity was freezing the screen before it was paused. 109975f0d3110b04346b901771f96ce15cdbe907278fYang Ni // In that case go ahead and remove the freeze this activity has on the screen 110075f0d3110b04346b901771f96ce15cdbe907278fYang Ni // since it is no longer visible. 110175f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.stopFreezingScreenLocked(true /*force*/); 110275f0d3110b04346b901771f96ce15cdbe907278fYang Ni mPausingActivity = null; 110375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 110475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 110575f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (resumeNext) { 110675f0d3110b04346b901771f96ce15cdbe907278fYang Ni final ActivityStack topStack = mStackSupervisor.getFocusedStack(); 110775f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (!mService.isSleepingOrShuttingDown()) { 110875f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null); 110975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } else { 111075f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.checkReadyForSleepLocked(); 111175f0d3110b04346b901771f96ce15cdbe907278fYang Ni ActivityRecord top = topStack.topRunningActivityLocked(); 111275f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (top == null || (prev != null && top != prev)) { 111375f0d3110b04346b901771f96ce15cdbe907278fYang Ni // If there are no more activities available to run, 111475f0d3110b04346b901771f96ce15cdbe907278fYang Ni // do resume anyway to start something. Also if the top 111575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // activity on the stack is not the just paused activity, 111675f0d3110b04346b901771f96ce15cdbe907278fYang Ni // we need to go ahead and resume it to ensure we complete 111775f0d3110b04346b901771f96ce15cdbe907278fYang Ni // an in-flight app switch. 111875f0d3110b04346b901771f96ce15cdbe907278fYang Ni mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null); 111975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 112075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 112175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 112275f0d3110b04346b901771f96ce15cdbe907278fYang Ni 112375f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (prev != null) { 112475f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.resumeKeyDispatchingLocked(); 112575f0d3110b04346b901771f96ce15cdbe907278fYang Ni 112675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (prev.app != null && prev.cpuTimeAtResume > 0 112775f0d3110b04346b901771f96ce15cdbe907278fYang Ni && mService.mBatteryStatsService.isOnBattery()) { 112875f0d3110b04346b901771f96ce15cdbe907278fYang Ni long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid) 112975f0d3110b04346b901771f96ce15cdbe907278fYang Ni - prev.cpuTimeAtResume; 113075f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (diff > 0) { 113175f0d3110b04346b901771f96ce15cdbe907278fYang Ni BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics(); 113275f0d3110b04346b901771f96ce15cdbe907278fYang Ni synchronized (bsi) { 113375f0d3110b04346b901771f96ce15cdbe907278fYang Ni BatteryStatsImpl.Uid.Proc ps = 113475f0d3110b04346b901771f96ce15cdbe907278fYang Ni bsi.getProcessStatsLocked(prev.info.applicationInfo.uid, 113575f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.info.packageName); 113675f0d3110b04346b901771f96ce15cdbe907278fYang Ni if (ps != null) { 113775f0d3110b04346b901771f96ce15cdbe907278fYang Ni ps.addForegroundTimeLocked(diff); 113875f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 113975f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 114075f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 114175f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 114275f0d3110b04346b901771f96ce15cdbe907278fYang Ni prev.cpuTimeAtResume = 0; // reset it 114375f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 114475f0d3110b04346b901771f96ce15cdbe907278fYang Ni 114575f0d3110b04346b901771f96ce15cdbe907278fYang Ni // Notfiy when the task stack has changed 114675f0d3110b04346b901771f96ce15cdbe907278fYang Ni mService.notifyTaskStackChangedLocked(); 114775f0d3110b04346b901771f96ce15cdbe907278fYang Ni } 114875f0d3110b04346b901771f96ce15cdbe907278fYang Ni 114975f0d3110b04346b901771f96ce15cdbe907278fYang Ni /** 115075f0d3110b04346b901771f96ce15cdbe907278fYang Ni * Once we know that we have asked an application to put an activity in 1151 * the resumed state (either by launching it or explicitly telling it), 1152 * this function updates the rest of our state to match that fact. 1153 */ 1154 private void completeResumeLocked(ActivityRecord next) { 1155 next.idle = false; 1156 next.results = null; 1157 next.newIntents = null; 1158 1159 if (next.isHomeActivity()) { 1160 ProcessRecord app = next.task.mActivities.get(0).app; 1161 if (app != null && app != mService.mHomeProcess) { 1162 mService.mHomeProcess = app; 1163 } 1164 } 1165 1166 if (next.nowVisible) { 1167 // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now. 1168 mStackSupervisor.notifyActivityDrawnForKeyguard(); 1169 } 1170 1171 // schedule an idle timeout in case the app doesn't do it for us. 1172 mStackSupervisor.scheduleIdleTimeoutLocked(next); 1173 1174 mStackSupervisor.reportResumedActivityLocked(next); 1175 1176 next.resumeKeyDispatchingLocked(); 1177 mNoAnimActivities.clear(); 1178 1179 // Mark the point when the activity is resuming 1180 // TODO: To be more accurate, the mark should be before the onCreate, 1181 // not after the onResume. But for subsequent starts, onResume is fine. 1182 if (next.app != null) { 1183 next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid); 1184 } else { 1185 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process 1186 } 1187 1188 next.returningOptions = null; 1189 1190 if (mActivityContainer.mActivityDisplay.mVisibleBehindActivity == next) { 1191 // When resuming an activity, require it to call requestVisibleBehind() again. 1192 mActivityContainer.mActivityDisplay.setVisibleBehindActivity(null); 1193 } 1194 } 1195 1196 private void setVisible(ActivityRecord r, boolean visible) { 1197 r.visible = visible; 1198 mWindowManager.setAppVisibility(r.appToken, visible); 1199 final ArrayList<ActivityContainer> containers = r.mChildContainers; 1200 for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) { 1201 ActivityContainer container = containers.get(containerNdx); 1202 container.setVisible(visible); 1203 } 1204 } 1205 1206 // Find the first visible activity above the passed activity and if it is translucent return it 1207 // otherwise return null; 1208 ActivityRecord findNextTranslucentActivity(ActivityRecord r) { 1209 TaskRecord task = r.task; 1210 if (task == null) { 1211 return null; 1212 } 1213 1214 ActivityStack stack = task.stack; 1215 if (stack == null) { 1216 return null; 1217 } 1218 1219 int stackNdx = mStacks.indexOf(stack); 1220 1221 ArrayList<TaskRecord> tasks = stack.mTaskHistory; 1222 int taskNdx = tasks.indexOf(task); 1223 1224 ArrayList<ActivityRecord> activities = task.mActivities; 1225 int activityNdx = activities.indexOf(r) + 1; 1226 1227 final int numStacks = mStacks.size(); 1228 while (stackNdx < numStacks) { 1229 final ActivityStack historyStack = mStacks.get(stackNdx); 1230 tasks = historyStack.mTaskHistory; 1231 final int numTasks = tasks.size(); 1232 while (taskNdx < numTasks) { 1233 final TaskRecord currentTask = tasks.get(taskNdx); 1234 activities = currentTask.mActivities; 1235 final int numActivities = activities.size(); 1236 while (activityNdx < numActivities) { 1237 final ActivityRecord activity = activities.get(activityNdx); 1238 if (!activity.finishing) { 1239 return historyStack.mFullscreen 1240 && currentTask.mFullscreen && activity.fullscreen ? null : activity; 1241 } 1242 ++activityNdx; 1243 } 1244 activityNdx = 0; 1245 ++taskNdx; 1246 } 1247 taskNdx = 0; 1248 ++stackNdx; 1249 } 1250 1251 return null; 1252 } 1253 1254 private ActivityStack getNextVisibleStackLocked() { 1255 ArrayList<ActivityStack> stacks = mStacks; 1256 final ActivityRecord parent = mActivityContainer.mParentActivity; 1257 if (parent != null) { 1258 stacks = parent.task.stack.mStacks; 1259 } 1260 if (stacks != null) { 1261 for (int i = stacks.size() - 1; i >= 0; --i) { 1262 ActivityStack stack = stacks.get(i); 1263 if (stack != this && stack.isStackVisibleLocked()) { 1264 return stack; 1265 } 1266 } 1267 } 1268 return null; 1269 } 1270 1271 /** Returns true if the stack contains a fullscreen task. */ 1272 private boolean hasFullscreenTask() { 1273 for (int i = mTaskHistory.size() - 1; i >= 0; --i) { 1274 final TaskRecord task = mTaskHistory.get(i); 1275 if (task.mFullscreen) { 1276 return true; 1277 } 1278 } 1279 return false; 1280 } 1281 1282 private boolean hasTranslucentActivity(ActivityStack stack) { 1283 final ArrayList<TaskRecord> tasks = stack.getAllTasks(); 1284 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { 1285 final TaskRecord task = tasks.get(taskNdx); 1286 final ArrayList<ActivityRecord> activities = task.mActivities; 1287 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1288 final ActivityRecord r = activities.get(activityNdx); 1289 1290 // Conditions for an activity to obscure the stack we're 1291 // examining: 1292 // 1. Not Finishing AND Visible AND: 1293 // 2. Either: 1294 // - Full Screen Activity OR 1295 // - On top of Home and our stack is NOT home 1296 if (!r.finishing && r.visible && (r.fullscreen || 1297 (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) { 1298 return false; 1299 } 1300 } 1301 } 1302 return true; 1303 } 1304 1305 /** Returns true if the stack is considered visible. */ 1306 private boolean isStackVisibleLocked() { 1307 if (!isAttached()) { 1308 return false; 1309 } 1310 1311 if (mStackSupervisor.isFrontStack(this) || mStackSupervisor.isFocusedStack(this)) { 1312 return true; 1313 } 1314 1315 final int stackIndex = mStacks.indexOf(this); 1316 1317 if (stackIndex == mStacks.size() - 1) { 1318 Slog.wtf(TAG, 1319 "Stack=" + this + " isn't front stack but is at the top of the stack list"); 1320 return false; 1321 } 1322 1323 final ActivityStack focusedStack = mStackSupervisor.getFocusedStack(); 1324 final int focusedStackId = focusedStack.mStackId; 1325 1326 if (mStackId == DOCKED_STACK_ID) { 1327 // Docked stack is always visible, except in the case where the home activity 1328 // is the top running activity in the focused home stack. 1329 if (focusedStackId != HOME_STACK_ID) { 1330 return true; 1331 } 1332 ActivityRecord topHomeActivity = focusedStack.topRunningActivityLocked(); 1333 return topHomeActivity == null || !topHomeActivity.isHomeActivity(); 1334 } 1335 1336 final int belowFocusedIndex = mStacks.indexOf(focusedStack) - 1; 1337 if ((focusedStackId == DOCKED_STACK_ID || focusedStackId == PINNED_STACK_ID) 1338 && stackIndex == belowFocusedIndex) { 1339 // Stacks directly behind the docked or pinned stack are always visible. 1340 return true; 1341 } 1342 1343 if (focusedStackId == FULLSCREEN_WORKSPACE_STACK_ID 1344 && hasTranslucentActivity(focusedStack)) { 1345 // Stacks behind the fullscreen stack with a translucent activity are always 1346 // visible so they can act as a backdrop to the translucent activity. 1347 // For example, dialog activities 1348 if (stackIndex == belowFocusedIndex) { 1349 return true; 1350 } 1351 if (belowFocusedIndex >= 0) { 1352 final ActivityStack stack = mStacks.get(belowFocusedIndex); 1353 if ((stack.mStackId == DOCKED_STACK_ID || stack.mStackId == PINNED_STACK_ID) 1354 && stackIndex == (belowFocusedIndex - 1)) { 1355 // The stack behind the docked or pinned stack is also visible so we can have a 1356 // complete backdrop to the translucent activity when the docked stack is up. 1357 return true; 1358 } 1359 } 1360 } 1361 1362 if (StackId.isStaticStack(mStackId)) { 1363 // Visibility of any static stack should have been determined by the conditions above. 1364 return false; 1365 } 1366 1367 for (int i = stackIndex + 1; i < mStacks.size(); i++) { 1368 final ActivityStack stack = mStacks.get(i); 1369 1370 if (!stack.mFullscreen && !stack.hasFullscreenTask()) { 1371 continue; 1372 } 1373 1374 if (!StackId.isDynamicStacksVisibleBehindAllowed(stack.mStackId)) { 1375 // These stacks can't have any dynamic stacks visible behind them. 1376 return false; 1377 } 1378 1379 if (!hasTranslucentActivity(stack)) { 1380 return false; 1381 } 1382 } 1383 1384 return true; 1385 } 1386 1387 final int rankTaskLayers(int baseLayer) { 1388 int layer = 0; 1389 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1390 final TaskRecord task = mTaskHistory.get(taskNdx); 1391 ActivityRecord r = task.topRunningActivityLocked(); 1392 if (r == null || r.finishing || !r.visible) { 1393 task.mLayerRank = -1; 1394 } else { 1395 task.mLayerRank = baseLayer + layer++; 1396 } 1397 } 1398 return layer; 1399 } 1400 1401 /** 1402 * Make sure that all activities that need to be visible (that is, they 1403 * currently can be seen by the user) actually are. 1404 */ 1405 final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, 1406 boolean preserveWindows) { 1407 ActivityRecord top = topRunningActivityLocked(); 1408 if (top == null) { 1409 return; 1410 } 1411 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1412 "ensureActivitiesVisible behind " + top 1413 + " configChanges=0x" + Integer.toHexString(configChanges)); 1414 1415 if (mTranslucentActivityWaiting != top) { 1416 mUndrawnActivitiesBelowTopTranslucent.clear(); 1417 if (mTranslucentActivityWaiting != null) { 1418 // Call the callback with a timeout indication. 1419 notifyActivityDrawnLocked(null); 1420 mTranslucentActivityWaiting = null; 1421 } 1422 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 1423 } 1424 1425 // If the top activity is not fullscreen, then we need to 1426 // make sure any activities under it are now visible. 1427 boolean aboveTop = true; 1428 final boolean stackInvisible = !isStackVisibleLocked(); 1429 boolean behindFullscreenActivity = stackInvisible; 1430 boolean noStackActivityResumed = (isInStackLocked(starting) == null); 1431 1432 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1433 final TaskRecord task = mTaskHistory.get(taskNdx); 1434 final ArrayList<ActivityRecord> activities = task.mActivities; 1435 1436 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1437 final ActivityRecord r = activities.get(activityNdx); 1438 if (r.finishing) { 1439 continue; 1440 } 1441 if (aboveTop && r != top) { 1442 continue; 1443 } 1444 aboveTop = false; 1445 // mLaunchingBehind: Activities launching behind are at the back of the task stack 1446 // but must be drawn initially for the animation as though they were visible. 1447 if (!behindFullscreenActivity || r.mLaunchTaskBehind) { 1448 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1449 "Make visible? " + r + " finishing=" + r.finishing 1450 + " state=" + r.state); 1451 1452 // First: if this is not the current activity being started, make 1453 // sure it matches the current configuration. 1454 if (r != starting) { 1455 ensureActivityConfigurationLocked(r, 0, preserveWindows); 1456 } 1457 1458 if (r.app == null || r.app.thread == null) { 1459 // This activity needs to be visible, but isn't even running... 1460 // get it started and resume if no other stack in this stack is resumed. 1461 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1462 "Start and freeze screen for " + r); 1463 if (r != starting) { 1464 r.startFreezingScreenLocked(r.app, configChanges); 1465 } 1466 if (!r.visible || r.mLaunchTaskBehind) { 1467 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1468 "Starting and making visible: " + r); 1469 setVisible(r, true); 1470 } 1471 if (r != starting) { 1472 mStackSupervisor.startSpecificActivityLocked( 1473 r, noStackActivityResumed, false); 1474 if (activityNdx >= activities.size()) { 1475 // Record may be removed if its process needs to restart. 1476 activityNdx = activities.size() - 1; 1477 } else { 1478 noStackActivityResumed = false; 1479 } 1480 } 1481 1482 } else if (r.visible) { 1483 // If this activity is already visible, then there is nothing 1484 // else to do here. 1485 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1486 "Skipping: already visible at " + r); 1487 r.stopFreezingScreenLocked(false); 1488 try { 1489 if (r.returningOptions != null) { 1490 r.app.thread.scheduleOnNewActivityOptions(r.appToken, 1491 r.returningOptions); 1492 } 1493 } catch(RemoteException e) { 1494 } 1495 if (r.state == ActivityState.RESUMED) { 1496 noStackActivityResumed = false; 1497 } 1498 } else { 1499 // This activity is not currently visible, but is running. 1500 // Tell it to become visible. 1501 r.visible = true; 1502 if (r.state != ActivityState.RESUMED && r != starting) { 1503 // If this activity is paused, tell it 1504 // to now show its window. 1505 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1506 "Making visible and scheduling visibility: " + r); 1507 try { 1508 if (mTranslucentActivityWaiting != null) { 1509 r.updateOptionsLocked(r.returningOptions); 1510 mUndrawnActivitiesBelowTopTranslucent.add(r); 1511 } 1512 setVisible(r, true); 1513 r.sleeping = false; 1514 r.app.pendingUiClean = true; 1515 r.app.thread.scheduleWindowVisibility(r.appToken, true); 1516 r.stopFreezingScreenLocked(false); 1517 } catch (Exception e) { 1518 // Just skip on any failure; we'll make it 1519 // visible when it next restarts. 1520 Slog.w(TAG, "Exception thrown making visibile: " 1521 + r.intent.getComponent(), e); 1522 } 1523 } 1524 } 1525 1526 // Aggregate current change flags. 1527 configChanges |= r.configChangeFlags; 1528 1529 if (r.fullscreen) { 1530 // At this point, nothing else needs to be shown in this task. 1531 behindFullscreenActivity = true; 1532 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r 1533 + " stackInvisible=" + stackInvisible 1534 + " behindFullscreenActivity=" + behindFullscreenActivity); 1535 } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) { 1536 behindFullscreenActivity = true; 1537 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r 1538 + " stackInvisible=" + stackInvisible 1539 + " behindFullscreenActivity=" + behindFullscreenActivity); 1540 } 1541 } else { 1542 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1543 "Make invisible? " + r + " finishing=" + r.finishing 1544 + " state=" + r.state + " stackInvisible=" + stackInvisible 1545 + " behindFullscreenActivity=" + behindFullscreenActivity); 1546 // Now for any activities that aren't visible to the user, make 1547 // sure they no longer are keeping the screen frozen. 1548 if (r.visible) { 1549 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r); 1550 try { 1551 setVisible(r, false); 1552 switch (r.state) { 1553 case STOPPING: 1554 case STOPPED: 1555 if (r.app != null && r.app.thread != null) { 1556 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 1557 "Scheduling invisibility: " + r); 1558 r.app.thread.scheduleWindowVisibility(r.appToken, false); 1559 } 1560 break; 1561 1562 case INITIALIZING: 1563 case RESUMED: 1564 case PAUSING: 1565 case PAUSED: 1566 // This case created for transitioning activities from 1567 // translucent to opaque {@link Activity#convertToOpaque}. 1568 if (getVisibleBehindActivity() == r) { 1569 releaseBackgroundResources(r); 1570 } else { 1571 if (!mStackSupervisor.mStoppingActivities.contains(r)) { 1572 mStackSupervisor.mStoppingActivities.add(r); 1573 } 1574 mStackSupervisor.scheduleIdleLocked(); 1575 } 1576 break; 1577 1578 default: 1579 break; 1580 } 1581 } catch (Exception e) { 1582 // Just skip on any failure; we'll make it 1583 // visible when it next restarts. 1584 Slog.w(TAG, "Exception thrown making hidden: " 1585 + r.intent.getComponent(), e); 1586 } 1587 } else { 1588 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r); 1589 } 1590 } 1591 } 1592 if (mStackId == FREEFORM_WORKSPACE_STACK_ID) { 1593 // The visibility of tasks and the activities they contain in freeform stack are 1594 // determined individually unlike other stacks where the visibility or fullscreen 1595 // status of an activity in a previous task affects other. 1596 behindFullscreenActivity = stackInvisible; 1597 } 1598 } 1599 1600 if (mTranslucentActivityWaiting != null && 1601 mUndrawnActivitiesBelowTopTranslucent.isEmpty()) { 1602 // Nothing is getting drawn or everything was already visible, don't wait for timeout. 1603 notifyActivityDrawnLocked(null); 1604 } 1605 } 1606 1607 void convertActivityToTranslucent(ActivityRecord r) { 1608 mTranslucentActivityWaiting = r; 1609 mUndrawnActivitiesBelowTopTranslucent.clear(); 1610 mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT); 1611 } 1612 1613 void clearOtherAppTimeTrackers(AppTimeTracker except) { 1614 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1615 final TaskRecord task = mTaskHistory.get(taskNdx); 1616 final ArrayList<ActivityRecord> activities = task.mActivities; 1617 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1618 final ActivityRecord r = activities.get(activityNdx); 1619 if ( r.appTimeTracker != except) { 1620 r.appTimeTracker = null; 1621 } 1622 } 1623 } 1624 } 1625 1626 /** 1627 * Called as activities below the top translucent activity are redrawn. When the last one is 1628 * redrawn notify the top activity by calling 1629 * {@link Activity#onTranslucentConversionComplete}. 1630 * 1631 * @param r The most recent background activity to be drawn. Or, if r is null then a timeout 1632 * occurred and the activity will be notified immediately. 1633 */ 1634 void notifyActivityDrawnLocked(ActivityRecord r) { 1635 mActivityContainer.setDrawn(); 1636 if ((r == null) 1637 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) && 1638 mUndrawnActivitiesBelowTopTranslucent.isEmpty())) { 1639 // The last undrawn activity below the top has just been drawn. If there is an 1640 // opaque activity at the top, notify it that it can become translucent safely now. 1641 final ActivityRecord waitingActivity = mTranslucentActivityWaiting; 1642 mTranslucentActivityWaiting = null; 1643 mUndrawnActivitiesBelowTopTranslucent.clear(); 1644 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 1645 1646 if (waitingActivity != null) { 1647 mWindowManager.setWindowOpaque(waitingActivity.appToken, false); 1648 if (waitingActivity.app != null && waitingActivity.app.thread != null) { 1649 try { 1650 waitingActivity.app.thread.scheduleTranslucentConversionComplete( 1651 waitingActivity.appToken, r != null); 1652 } catch (RemoteException e) { 1653 } 1654 } 1655 } 1656 } 1657 } 1658 1659 /** If any activities below the top running one are in the INITIALIZING state and they have a 1660 * starting window displayed then remove that starting window. It is possible that the activity 1661 * in this state will never resumed in which case that starting window will be orphaned. */ 1662 void cancelInitializingActivities() { 1663 final ActivityRecord topActivity = topRunningActivityLocked(); 1664 boolean aboveTop = true; 1665 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1666 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 1667 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1668 final ActivityRecord r = activities.get(activityNdx); 1669 if (aboveTop) { 1670 if (r == topActivity) { 1671 aboveTop = false; 1672 } 1673 continue; 1674 } 1675 1676 if (r.state == ActivityState.INITIALIZING && r.mStartingWindowShown) { 1677 if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, 1678 "Found orphaned starting window " + r); 1679 r.mStartingWindowShown = false; 1680 mWindowManager.removeAppStartingWindow(r.appToken); 1681 } 1682 } 1683 } 1684 } 1685 1686 /** 1687 * Ensure that the top activity in the stack is resumed. 1688 * 1689 * @param prev The previously resumed activity, for when in the process 1690 * of pausing; can be null to call from elsewhere. 1691 * 1692 * @return Returns true if something is being resumed, or false if 1693 * nothing happened. 1694 */ 1695 final boolean resumeTopActivityLocked(ActivityRecord prev) { 1696 return resumeTopActivityLocked(prev, null); 1697 } 1698 1699 final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { 1700 if (mStackSupervisor.inResumeTopActivity) { 1701 // Don't even start recursing. 1702 return false; 1703 } 1704 1705 boolean result = false; 1706 try { 1707 // Protect against recursion. 1708 mStackSupervisor.inResumeTopActivity = true; 1709 if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) { 1710 mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN; 1711 mService.updateSleepIfNeededLocked(); 1712 } 1713 result = resumeTopActivityInnerLocked(prev, options); 1714 } finally { 1715 mStackSupervisor.inResumeTopActivity = false; 1716 } 1717 return result; 1718 } 1719 1720 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { 1721 if (DEBUG_LOCKSCREEN) mService.logLockScreen(""); 1722 1723 if (!mService.mBooting && !mService.mBooted) { 1724 // Not ready yet! 1725 return false; 1726 } 1727 1728 ActivityRecord parent = mActivityContainer.mParentActivity; 1729 if ((parent != null && parent.state != ActivityState.RESUMED) || 1730 !mActivityContainer.isAttachedLocked()) { 1731 // Do not resume this stack if its parent is not resumed. 1732 // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st. 1733 return false; 1734 } 1735 1736 cancelInitializingActivities(); 1737 1738 // Find the first activity that is not finishing. 1739 final ActivityRecord next = topRunningActivityLocked(); 1740 1741 // Remember how we'll process this pause/resume situation, and ensure 1742 // that the state is reset however we wind up proceeding. 1743 final boolean userLeaving = mStackSupervisor.mUserLeaving; 1744 mStackSupervisor.mUserLeaving = false; 1745 1746 final TaskRecord prevTask = prev != null ? prev.task : null; 1747 if (next == null) { 1748 // There are no more activities! 1749 final String reason = "noMoreActivities"; 1750 if (!mFullscreen) { 1751 // Try to move focus to the next visible stack with a running activity if this 1752 // stack is not covering the entire screen. 1753 final ActivityStack stack = getNextVisibleStackLocked(); 1754 if (adjustFocusToNextVisibleStackLocked(stack, reason)) { 1755 return mStackSupervisor.resumeTopActivitiesLocked(stack, prev, null); 1756 } 1757 } 1758 // Let's just start up the Launcher... 1759 ActivityOptions.abort(options); 1760 if (DEBUG_STATES) Slog.d(TAG_STATES, 1761 "resumeTopActivityLocked: No more activities go home"); 1762 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 1763 // Only resume home if on home display 1764 final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? 1765 HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); 1766 return isOnHomeDisplay() && 1767 mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason); 1768 } 1769 1770 next.delayedResume = false; 1771 1772 // If the top activity is the resumed one, nothing to do. 1773 if (mResumedActivity == next && next.state == ActivityState.RESUMED && 1774 mStackSupervisor.allResumedActivitiesComplete()) { 1775 // Make sure we have executed any pending transitions, since there 1776 // should be nothing left to do at this point. 1777 mWindowManager.executeAppTransition(); 1778 mNoAnimActivities.clear(); 1779 ActivityOptions.abort(options); 1780 if (DEBUG_STATES) Slog.d(TAG_STATES, 1781 "resumeTopActivityLocked: Top activity resumed " + next); 1782 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 1783 return false; 1784 } 1785 1786 final TaskRecord nextTask = next.task; 1787 if (prevTask != null && prevTask.stack == this && 1788 prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { 1789 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 1790 if (prevTask == nextTask) { 1791 prevTask.setFrontOfTask(); 1792 } else if (prevTask != topTask()) { 1793 // This task is going away but it was supposed to return to the home stack. 1794 // Now the task above it has to return to the home task instead. 1795 final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; 1796 mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); 1797 } else if (!isOnHomeDisplay()) { 1798 return false; 1799 } else if (!isHomeStack()){ 1800 if (DEBUG_STATES) Slog.d(TAG_STATES, 1801 "resumeTopActivityLocked: Launching home next"); 1802 final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? 1803 HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); 1804 return isOnHomeDisplay() && 1805 mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished"); 1806 } 1807 } 1808 1809 // If we are sleeping, and there is no resumed activity, and the top 1810 // activity is paused, well that is the state we want. 1811 if (mService.isSleepingOrShuttingDown() 1812 && mLastPausedActivity == next 1813 && mStackSupervisor.allPausedActivitiesComplete()) { 1814 // Make sure we have executed any pending transitions, since there 1815 // should be nothing left to do at this point. 1816 mWindowManager.executeAppTransition(); 1817 mNoAnimActivities.clear(); 1818 ActivityOptions.abort(options); 1819 if (DEBUG_STATES) Slog.d(TAG_STATES, 1820 "resumeTopActivityLocked: Going to sleep and all paused"); 1821 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 1822 return false; 1823 } 1824 1825 // Make sure that the user who owns this activity is started. If not, 1826 // we will just leave it as is because someone should be bringing 1827 // another user's activities to the top of the stack. 1828 if (!mService.mUserController.hasStartedUserState(next.userId)) { 1829 Slog.w(TAG, "Skipping resume of top activity " + next 1830 + ": user " + next.userId + " is stopped"); 1831 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 1832 return false; 1833 } 1834 1835 // The activity may be waiting for stop, but that is no longer 1836 // appropriate for it. 1837 mStackSupervisor.mStoppingActivities.remove(next); 1838 mStackSupervisor.mGoingToSleepActivities.remove(next); 1839 next.sleeping = false; 1840 mStackSupervisor.mWaitingVisibleActivities.remove(next); 1841 1842 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); 1843 1844 // If we are currently pausing an activity, then don't do anything 1845 // until that is done. 1846 if (!mStackSupervisor.allPausedActivitiesComplete()) { 1847 if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, 1848 "resumeTopActivityLocked: Skip resume: some activity pausing."); 1849 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 1850 return false; 1851 } 1852 1853 // Okay we are now going to start a switch, to 'next'. We may first 1854 // have to pause the current activity, but this is an important point 1855 // where we have decided to go to 'next' so keep track of that. 1856 // XXX "App Redirected" dialog is getting too many false positives 1857 // at this point, so turn off for now. 1858 if (false) { 1859 if (mLastStartedActivity != null && !mLastStartedActivity.finishing) { 1860 long now = SystemClock.uptimeMillis(); 1861 final boolean inTime = mLastStartedActivity.startTime != 0 1862 && (mLastStartedActivity.startTime + START_WARN_TIME) >= now; 1863 final int lastUid = mLastStartedActivity.info.applicationInfo.uid; 1864 final int nextUid = next.info.applicationInfo.uid; 1865 if (inTime && lastUid != nextUid 1866 && lastUid != next.launchedFromUid 1867 && mService.checkPermission( 1868 android.Manifest.permission.STOP_APP_SWITCHES, 1869 -1, next.launchedFromUid) 1870 != PackageManager.PERMISSION_GRANTED) { 1871 mService.showLaunchWarningLocked(mLastStartedActivity, next); 1872 } else { 1873 next.startTime = now; 1874 mLastStartedActivity = next; 1875 } 1876 } else { 1877 next.startTime = SystemClock.uptimeMillis(); 1878 mLastStartedActivity = next; 1879 } 1880 } 1881 1882 mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); 1883 1884 // We need to start pausing the current activity so the top one 1885 // can be resumed... 1886 boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0; 1887 boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause); 1888 if (mResumedActivity != null) { 1889 if (DEBUG_STATES) Slog.d(TAG_STATES, 1890 "resumeTopActivityLocked: Pausing " + mResumedActivity); 1891 pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); 1892 } 1893 if (pausing) { 1894 if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, 1895 "resumeTopActivityLocked: Skip resume: need to start pausing"); 1896 // At this point we want to put the upcoming activity's process 1897 // at the top of the LRU list, since we know we will be needing it 1898 // very soon and it would be a waste to let it get killed if it 1899 // happens to be sitting towards the end. 1900 if (next.app != null && next.app.thread != null) { 1901 mService.updateLruProcessLocked(next.app, true, null); 1902 } 1903 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 1904 return true; 1905 } 1906 1907 // If the most recent activity was noHistory but was only stopped rather 1908 // than stopped+finished because the device went to sleep, we need to make 1909 // sure to finish it as we're making a new activity topmost. 1910 if (mService.isSleeping() && mLastNoHistoryActivity != null && 1911 !mLastNoHistoryActivity.finishing) { 1912 if (DEBUG_STATES) Slog.d(TAG_STATES, 1913 "no-history finish of " + mLastNoHistoryActivity + " on new resume"); 1914 requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, 1915 null, "resume-no-history", false); 1916 mLastNoHistoryActivity = null; 1917 } 1918 1919 if (prev != null && prev != next) { 1920 if (!mStackSupervisor.mWaitingVisibleActivities.contains(prev) 1921 && next != null && !next.nowVisible) { 1922 mStackSupervisor.mWaitingVisibleActivities.add(prev); 1923 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 1924 "Resuming top, waiting visible to hide: " + prev); 1925 } else { 1926 // The next activity is already visible, so hide the previous 1927 // activity's windows right now so we can show the new one ASAP. 1928 // We only do this if the previous is finishing, which should mean 1929 // it is on top of the one being resumed so hiding it quickly 1930 // is good. Otherwise, we want to do the normal route of allowing 1931 // the resumed activity to be shown so we can decide if the 1932 // previous should actually be hidden depending on whether the 1933 // new one is found to be full-screen or not. 1934 if (prev.finishing) { 1935 mWindowManager.setAppVisibility(prev.appToken, false); 1936 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 1937 "Not waiting for visible to hide: " + prev + ", waitingVisible=" 1938 + mStackSupervisor.mWaitingVisibleActivities.contains(prev) 1939 + ", nowVisible=" + next.nowVisible); 1940 } else { 1941 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 1942 "Previous already visible but still waiting to hide: " + prev 1943 + ", waitingVisible=" 1944 + mStackSupervisor.mWaitingVisibleActivities.contains(prev) 1945 + ", nowVisible=" + next.nowVisible); 1946 } 1947 } 1948 } 1949 1950 // Launching this app's activity, make sure the app is no longer 1951 // considered stopped. 1952 try { 1953 AppGlobals.getPackageManager().setPackageStoppedState( 1954 next.packageName, false, next.userId); /* TODO: Verify if correct userid */ 1955 } catch (RemoteException e1) { 1956 } catch (IllegalArgumentException e) { 1957 Slog.w(TAG, "Failed trying to unstop package " 1958 + next.packageName + ": " + e); 1959 } 1960 1961 // We are starting up the next activity, so tell the window manager 1962 // that the previous one will be hidden soon. This way it can know 1963 // to ignore it when computing the desired screen orientation. 1964 boolean anim = true; 1965 if (prev != null) { 1966 if (prev.finishing) { 1967 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 1968 "Prepare close transition: prev=" + prev); 1969 if (mNoAnimActivities.contains(prev)) { 1970 anim = false; 1971 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); 1972 } else { 1973 mWindowManager.prepareAppTransition(prev.task == next.task 1974 ? AppTransition.TRANSIT_ACTIVITY_CLOSE 1975 : AppTransition.TRANSIT_TASK_CLOSE, false); 1976 } 1977 mWindowManager.setAppVisibility(prev.appToken, false); 1978 } else { 1979 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 1980 "Prepare open transition: prev=" + prev); 1981 if (mNoAnimActivities.contains(next)) { 1982 anim = false; 1983 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); 1984 } else { 1985 mWindowManager.prepareAppTransition(prev.task == next.task 1986 ? AppTransition.TRANSIT_ACTIVITY_OPEN 1987 : next.mLaunchTaskBehind 1988 ? AppTransition.TRANSIT_TASK_OPEN_BEHIND 1989 : AppTransition.TRANSIT_TASK_OPEN, false); 1990 } 1991 } 1992 } else { 1993 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous"); 1994 if (mNoAnimActivities.contains(next)) { 1995 anim = false; 1996 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); 1997 } else { 1998 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false); 1999 } 2000 } 2001 2002 Bundle resumeAnimOptions = null; 2003 if (anim) { 2004 ActivityOptions opts = next.getOptionsForTargetActivityLocked(); 2005 if (opts != null) { 2006 resumeAnimOptions = opts.toBundle(); 2007 } 2008 next.applyOptionsLocked(); 2009 } else { 2010 next.clearOptionsLocked(); 2011 } 2012 2013 ActivityStack lastStack = mStackSupervisor.getLastStack(); 2014 if (next.app != null && next.app.thread != null) { 2015 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next); 2016 2017 // This activity is now becoming visible. 2018 mWindowManager.setAppVisibility(next.appToken, true); 2019 2020 // schedule launch ticks to collect information about slow apps. 2021 next.startLaunchTickingLocked(); 2022 2023 ActivityRecord lastResumedActivity = 2024 lastStack == null ? null :lastStack.mResumedActivity; 2025 ActivityState lastState = next.state; 2026 2027 mService.updateCpuStats(); 2028 2029 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next + " (in existing)"); 2030 next.state = ActivityState.RESUMED; 2031 mResumedActivity = next; 2032 next.task.touchActiveTime(); 2033 mRecentTasks.addLocked(next.task); 2034 mService.updateLruProcessLocked(next.app, true, null); 2035 updateLRUListLocked(next); 2036 mService.updateOomAdjLocked(); 2037 2038 // Have the window manager re-evaluate the orientation of 2039 // the screen based on the new activity order. 2040 boolean notUpdated = true; 2041 if (mStackSupervisor.isFocusedStack(this)) { 2042 Configuration config = mWindowManager.updateOrientationFromAppTokens( 2043 mService.mConfiguration, 2044 next.mayFreezeScreenLocked(next.app) ? next.appToken : null); 2045 if (config != null) { 2046 next.frozenBeforeDestroy = true; 2047 } 2048 notUpdated = !mService.updateConfigurationLocked(config, next, false); 2049 } 2050 2051 if (notUpdated) { 2052 // The configuration update wasn't able to keep the existing 2053 // instance of the activity, and instead started a new one. 2054 // We should be all done, but let's just make sure our activity 2055 // is still at the top and schedule another run if something 2056 // weird happened. 2057 ActivityRecord nextNext = topRunningActivityLocked(); 2058 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES, 2059 "Activity config changed during resume: " + next 2060 + ", new next: " + nextNext); 2061 if (nextNext != next) { 2062 // Do over! 2063 mStackSupervisor.scheduleResumeTopActivities(); 2064 } 2065 if (mStackSupervisor.reportResumedActivityLocked(next)) { 2066 mNoAnimActivities.clear(); 2067 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 2068 return true; 2069 } 2070 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 2071 return false; 2072 } 2073 2074 try { 2075 // Deliver all pending results. 2076 ArrayList<ResultInfo> a = next.results; 2077 if (a != null) { 2078 final int N = a.size(); 2079 if (!next.finishing && N > 0) { 2080 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, 2081 "Delivering results to " + next + ": " + a); 2082 next.app.thread.scheduleSendResult(next.appToken, a); 2083 } 2084 } 2085 2086 if (next.newIntents != null) { 2087 next.app.thread.scheduleNewIntent(next.newIntents, next.appToken); 2088 } 2089 2090 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId, 2091 System.identityHashCode(next), next.task.taskId, next.shortComponentName); 2092 2093 next.sleeping = false; 2094 mService.showAskCompatModeDialogLocked(next); 2095 next.app.pendingUiClean = true; 2096 next.app.forceProcessStateUpTo(mService.mTopProcessState); 2097 next.clearOptionsLocked(); 2098 next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState, 2099 mService.isNextTransitionForward(), resumeAnimOptions); 2100 2101 mStackSupervisor.checkReadyForSleepLocked(); 2102 2103 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next); 2104 } catch (Exception e) { 2105 // Whoops, need to restart this activity! 2106 if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " 2107 + lastState + ": " + next); 2108 next.state = lastState; 2109 if (lastStack != null) { 2110 lastStack.mResumedActivity = lastResumedActivity; 2111 } 2112 Slog.i(TAG, "Restarting because process died: " + next); 2113 if (!next.hasBeenLaunched) { 2114 next.hasBeenLaunched = true; 2115 } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null && 2116 mStackSupervisor.isFrontStack(lastStack)) { 2117 mWindowManager.setAppStartingWindow( 2118 next.appToken, next.packageName, next.theme, 2119 mService.compatibilityInfoForPackageLocked(next.info.applicationInfo), 2120 next.nonLocalizedLabel, next.labelRes, next.icon, next.logo, 2121 next.windowFlags, null, true); 2122 } 2123 mStackSupervisor.startSpecificActivityLocked(next, true, false); 2124 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 2125 return true; 2126 } 2127 2128 // From this point on, if something goes wrong there is no way 2129 // to recover the activity. 2130 try { 2131 next.visible = true; 2132 completeResumeLocked(next); 2133 } catch (Exception e) { 2134 // If any exception gets thrown, toss away this 2135 // activity and try the next one. 2136 Slog.w(TAG, "Exception thrown during resume of " + next, e); 2137 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, 2138 "resume-exception", true); 2139 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 2140 return true; 2141 } 2142 next.stopped = false; 2143 2144 } else { 2145 // Whoops, need to restart this activity! 2146 if (!next.hasBeenLaunched) { 2147 next.hasBeenLaunched = true; 2148 } else { 2149 if (SHOW_APP_STARTING_PREVIEW) { 2150 mWindowManager.setAppStartingWindow( 2151 next.appToken, next.packageName, next.theme, 2152 mService.compatibilityInfoForPackageLocked( 2153 next.info.applicationInfo), 2154 next.nonLocalizedLabel, 2155 next.labelRes, next.icon, next.logo, next.windowFlags, 2156 null, true); 2157 } 2158 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next); 2159 } 2160 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next); 2161 mStackSupervisor.startSpecificActivityLocked(next, true, true); 2162 } 2163 2164 if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); 2165 return true; 2166 } 2167 2168 private TaskRecord getNextTask(TaskRecord targetTask) { 2169 final int index = mTaskHistory.indexOf(targetTask); 2170 if (index >= 0) { 2171 final int numTasks = mTaskHistory.size(); 2172 for (int i = index + 1; i < numTasks; ++i) { 2173 TaskRecord task = mTaskHistory.get(i); 2174 if (task.userId == targetTask.userId) { 2175 return task; 2176 } 2177 } 2178 } 2179 return null; 2180 } 2181 2182 private void insertTaskAtPosition(TaskRecord task, int position) { 2183 if (position >= mTaskHistory.size()) { 2184 insertTaskAtTop(task, null); 2185 return; 2186 } 2187 // Calculate maximum possible position for this task. 2188 int maxPosition = mTaskHistory.size(); 2189 if (!mStackSupervisor.isCurrentProfileLocked(task.userId) 2190 && task.topRunningActivityLocked() == null) { 2191 // Put non-current user tasks below current user tasks. 2192 while (maxPosition > 0) { 2193 final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1); 2194 if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId) 2195 || tmpTask.topRunningActivityLocked() == null) { 2196 break; 2197 } 2198 maxPosition--; 2199 } 2200 } 2201 position = Math.min(position, maxPosition); 2202 mTaskHistory.remove(task); 2203 mTaskHistory.add(position, task); 2204 updateTaskMovement(task, true); 2205 } 2206 2207 private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) { 2208 // If the moving task is over home stack, transfer its return type to next task 2209 if (task.isOverHomeStack()) { 2210 final TaskRecord nextTask = getNextTask(task); 2211 if (nextTask != null) { 2212 nextTask.setTaskToReturnTo(task.getTaskToReturnTo()); 2213 } 2214 } 2215 2216 // If this is being moved to the top by another activity or being launched from the home 2217 // activity, set mTaskToReturnTo accordingly. 2218 if (isOnHomeDisplay()) { 2219 ActivityStack lastStack = mStackSupervisor.getLastStack(); 2220 final boolean fromHome = lastStack.isHomeStack(); 2221 if (!isHomeStack() && (fromHome || topTask() != task)) { 2222 task.setTaskToReturnTo(fromHome 2223 ? lastStack.topTask() == null 2224 ? HOME_ACTIVITY_TYPE 2225 : lastStack.topTask().taskType 2226 : APPLICATION_ACTIVITY_TYPE); 2227 } 2228 } else { 2229 task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); 2230 } 2231 2232 mTaskHistory.remove(task); 2233 // Now put task at top. 2234 int taskNdx = mTaskHistory.size(); 2235 final boolean notShownWhenLocked = 2236 (newActivity != null && (newActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) == 0) 2237 || (newActivity == null && task.topRunningActivityLocked() == null); 2238 if (!mStackSupervisor.isCurrentProfileLocked(task.userId) && notShownWhenLocked) { 2239 // Put non-current user tasks below current user tasks. 2240 while (--taskNdx >= 0) { 2241 final TaskRecord tmpTask = mTaskHistory.get(taskNdx); 2242 if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId) 2243 || tmpTask.topRunningActivityLocked() == null) { 2244 break; 2245 } 2246 } 2247 ++taskNdx; 2248 } 2249 mTaskHistory.add(taskNdx, task); 2250 updateTaskMovement(task, true); 2251 } 2252 2253 final void startActivityLocked(ActivityRecord r, boolean newTask, 2254 boolean doResume, boolean keepCurTransition, Bundle options) { 2255 TaskRecord rTask = r.task; 2256 final int taskId = rTask.taskId; 2257 // mLaunchTaskBehind tasks get placed at the back of the task stack. 2258 if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) { 2259 // Last activity in task had been removed or ActivityManagerService is reusing task. 2260 // Insert or replace. 2261 // Might not even be in. 2262 insertTaskAtTop(rTask, r); 2263 mWindowManager.moveTaskToTop(taskId); 2264 } 2265 TaskRecord task = null; 2266 if (!newTask) { 2267 // If starting in an existing task, find where that is... 2268 boolean startIt = true; 2269 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2270 task = mTaskHistory.get(taskNdx); 2271 if (task.getTopActivity() == null) { 2272 // All activities in task are finishing. 2273 continue; 2274 } 2275 if (task == r.task) { 2276 // Here it is! Now, if this is not yet visible to the 2277 // user, then just add it without starting; it will 2278 // get started when the user navigates back to it. 2279 if (!startIt) { 2280 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task " 2281 + task, new RuntimeException("here").fillInStackTrace()); 2282 task.addActivityToTop(r); 2283 r.putInHistory(); 2284 addConfigOverride(r, task); 2285 if (VALIDATE_TOKENS) { 2286 validateAppTokensLocked(); 2287 } 2288 ActivityOptions.abort(options); 2289 return; 2290 } 2291 break; 2292 } else if (task.numFullscreen > 0) { 2293 startIt = false; 2294 } 2295 } 2296 } 2297 2298 // Place a new activity at top of stack, so it is next to interact 2299 // with the user. 2300 2301 // If we are not placing the new activity frontmost, we do not want 2302 // to deliver the onUserLeaving callback to the actual frontmost 2303 // activity 2304 if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) { 2305 mStackSupervisor.mUserLeaving = false; 2306 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 2307 "startActivity() behind front, mUserLeaving=false"); 2308 } 2309 2310 task = r.task; 2311 2312 // Slot the activity into the history stack and proceed 2313 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task, 2314 new RuntimeException("here").fillInStackTrace()); 2315 task.addActivityToTop(r); 2316 task.setFrontOfTask(); 2317 2318 r.putInHistory(); 2319 if (!isHomeStack() || numActivities() > 0) { 2320 // We want to show the starting preview window if we are 2321 // switching to a new task, or the next activity's process is 2322 // not currently running. 2323 boolean showStartingIcon = newTask; 2324 ProcessRecord proc = r.app; 2325 if (proc == null) { 2326 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid); 2327 } 2328 if (proc == null || proc.thread == null) { 2329 showStartingIcon = true; 2330 } 2331 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 2332 "Prepare open transition: starting " + r); 2333 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 2334 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition); 2335 mNoAnimActivities.add(r); 2336 } else { 2337 mWindowManager.prepareAppTransition(newTask 2338 ? r.mLaunchTaskBehind 2339 ? AppTransition.TRANSIT_TASK_OPEN_BEHIND 2340 : AppTransition.TRANSIT_TASK_OPEN 2341 : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition); 2342 mNoAnimActivities.remove(r); 2343 } 2344 addConfigOverride(r, task); 2345 boolean doShow = true; 2346 if (newTask) { 2347 // Even though this activity is starting fresh, we still need 2348 // to reset it to make sure we apply affinities to move any 2349 // existing activities from other tasks in to it. 2350 // If the caller has requested that the target task be 2351 // reset, then do so. 2352 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 2353 resetTaskIfNeededLocked(r, r); 2354 doShow = topRunningNonDelayedActivityLocked(null) == r; 2355 } 2356 } else if (options != null && new ActivityOptions(options).getAnimationType() 2357 == ActivityOptions.ANIM_SCENE_TRANSITION) { 2358 doShow = false; 2359 } 2360 if (r.mLaunchTaskBehind) { 2361 // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we 2362 // tell WindowManager that r is visible even though it is at the back of the stack. 2363 mWindowManager.setAppVisibility(r.appToken, true); 2364 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); 2365 } else if (SHOW_APP_STARTING_PREVIEW && doShow) { 2366 // Figure out if we are transitioning from another activity that is 2367 // "has the same starting icon" as the next one. This allows the 2368 // window manager to keep the previous window it had previously 2369 // created, if it still had one. 2370 ActivityRecord prev = mResumedActivity; 2371 if (prev != null) { 2372 // We don't want to reuse the previous starting preview if: 2373 // (1) The current activity is in a different task. 2374 if (prev.task != r.task) { 2375 prev = null; 2376 } 2377 // (2) The current activity is already displayed. 2378 else if (prev.nowVisible) { 2379 prev = null; 2380 } 2381 } 2382 mWindowManager.setAppStartingWindow( 2383 r.appToken, r.packageName, r.theme, 2384 mService.compatibilityInfoForPackageLocked( 2385 r.info.applicationInfo), r.nonLocalizedLabel, 2386 r.labelRes, r.icon, r.logo, r.windowFlags, 2387 prev != null ? prev.appToken : null, showStartingIcon); 2388 r.mStartingWindowShown = true; 2389 } 2390 } else { 2391 // If this is the first activity, don't do any fancy animations, 2392 // because there is nothing for it to animate on top of. 2393 addConfigOverride(r, task); 2394 ActivityOptions.abort(options); 2395 options = null; 2396 } 2397 if (VALIDATE_TOKENS) { 2398 validateAppTokensLocked(); 2399 } 2400 2401 if (doResume) { 2402 mStackSupervisor.resumeTopActivitiesLocked(this, r, options); 2403 } else { 2404 addRecentActivityLocked(r); 2405 } 2406 } 2407 2408 final void validateAppTokensLocked() { 2409 mValidateAppTokens.clear(); 2410 mValidateAppTokens.ensureCapacity(numActivities()); 2411 final int numTasks = mTaskHistory.size(); 2412 for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) { 2413 TaskRecord task = mTaskHistory.get(taskNdx); 2414 final ArrayList<ActivityRecord> activities = task.mActivities; 2415 if (activities.isEmpty()) { 2416 continue; 2417 } 2418 TaskGroup group = new TaskGroup(); 2419 group.taskId = task.taskId; 2420 mValidateAppTokens.add(group); 2421 final int numActivities = activities.size(); 2422 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { 2423 final ActivityRecord r = activities.get(activityNdx); 2424 group.tokens.add(r.appToken); 2425 } 2426 } 2427 mWindowManager.validateAppTokens(mStackId, mValidateAppTokens); 2428 } 2429 2430 /** 2431 * Perform a reset of the given task, if needed as part of launching it. 2432 * Returns the new HistoryRecord at the top of the task. 2433 */ 2434 /** 2435 * Helper method for #resetTaskIfNeededLocked. 2436 * We are inside of the task being reset... we'll either finish this activity, push it out 2437 * for another task, or leave it as-is. 2438 * @param task The task containing the Activity (taskTop) that might be reset. 2439 * @param forceReset 2440 * @return An ActivityOptions that needs to be processed. 2441 */ 2442 final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) { 2443 ActivityOptions topOptions = null; 2444 2445 int replyChainEnd = -1; 2446 boolean canMoveOptions = true; 2447 2448 // We only do this for activities that are not the root of the task (since if we finish 2449 // the root, we may no longer have the task!). 2450 final ArrayList<ActivityRecord> activities = task.mActivities; 2451 final int numActivities = activities.size(); 2452 final int rootActivityNdx = task.findEffectiveRootIndex(); 2453 for (int i = numActivities - 1; i > rootActivityNdx; --i ) { 2454 ActivityRecord target = activities.get(i); 2455 if (target.frontOfTask) 2456 break; 2457 2458 final int flags = target.info.flags; 2459 final boolean finishOnTaskLaunch = 2460 (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0; 2461 final boolean allowTaskReparenting = 2462 (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0; 2463 final boolean clearWhenTaskReset = 2464 (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0; 2465 2466 if (!finishOnTaskLaunch 2467 && !clearWhenTaskReset 2468 && target.resultTo != null) { 2469 // If this activity is sending a reply to a previous 2470 // activity, we can't do anything with it now until 2471 // we reach the start of the reply chain. 2472 // XXX note that we are assuming the result is always 2473 // to the previous activity, which is almost always 2474 // the case but we really shouldn't count on. 2475 if (replyChainEnd < 0) { 2476 replyChainEnd = i; 2477 } 2478 } else if (!finishOnTaskLaunch 2479 && !clearWhenTaskReset 2480 && allowTaskReparenting 2481 && target.taskAffinity != null 2482 && !target.taskAffinity.equals(task.affinity)) { 2483 // If this activity has an affinity for another 2484 // task, then we need to move it out of here. We will 2485 // move it as far out of the way as possible, to the 2486 // bottom of the activity stack. This also keeps it 2487 // correctly ordered with any activities we previously 2488 // moved. 2489 final TaskRecord targetTask; 2490 final ActivityRecord bottom = 2491 !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ? 2492 mTaskHistory.get(0).mActivities.get(0) : null; 2493 if (bottom != null && target.taskAffinity != null 2494 && target.taskAffinity.equals(bottom.task.affinity)) { 2495 // If the activity currently at the bottom has the 2496 // same task affinity as the one we are moving, 2497 // then merge it into the same task. 2498 targetTask = bottom.task; 2499 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target 2500 + " out to bottom task " + bottom.task); 2501 } else { 2502 targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info, 2503 null, null, null, false); 2504 targetTask.affinityIntent = target.intent; 2505 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target 2506 + " out to new task " + target.task); 2507 } 2508 2509 setAppTask(target, targetTask); 2510 2511 boolean noOptions = canMoveOptions; 2512 final int start = replyChainEnd < 0 ? i : replyChainEnd; 2513 for (int srcPos = start; srcPos >= i; --srcPos) { 2514 final ActivityRecord p = activities.get(srcPos); 2515 if (p.finishing) { 2516 continue; 2517 } 2518 2519 canMoveOptions = false; 2520 if (noOptions && topOptions == null) { 2521 topOptions = p.takeOptionsLocked(); 2522 if (topOptions != null) { 2523 noOptions = false; 2524 } 2525 } 2526 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 2527 "Removing activity " + p + " from task=" + task + " adding to task=" 2528 + targetTask + " Callers=" + Debug.getCallers(4)); 2529 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 2530 "Pushing next activity " + p + " out to target's task " + target.task); 2531 p.setTask(targetTask, null); 2532 targetTask.addActivityAtBottom(p); 2533 2534 setAppTask(p, targetTask); 2535 } 2536 2537 mWindowManager.moveTaskToBottom(targetTask.taskId); 2538 if (VALIDATE_TOKENS) { 2539 validateAppTokensLocked(); 2540 } 2541 2542 replyChainEnd = -1; 2543 } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) { 2544 // If the activity should just be removed -- either 2545 // because it asks for it, or the task should be 2546 // cleared -- then finish it and anything that is 2547 // part of its reply chain. 2548 int end; 2549 if (clearWhenTaskReset) { 2550 // In this case, we want to finish this activity 2551 // and everything above it, so be sneaky and pretend 2552 // like these are all in the reply chain. 2553 end = activities.size() - 1; 2554 } else if (replyChainEnd < 0) { 2555 end = i; 2556 } else { 2557 end = replyChainEnd; 2558 } 2559 boolean noOptions = canMoveOptions; 2560 for (int srcPos = i; srcPos <= end; srcPos++) { 2561 ActivityRecord p = activities.get(srcPos); 2562 if (p.finishing) { 2563 continue; 2564 } 2565 canMoveOptions = false; 2566 if (noOptions && topOptions == null) { 2567 topOptions = p.takeOptionsLocked(); 2568 if (topOptions != null) { 2569 noOptions = false; 2570 } 2571 } 2572 if (DEBUG_TASKS) Slog.w(TAG_TASKS, 2573 "resetTaskIntendedTask: calling finishActivity on " + p); 2574 if (finishActivityLocked( 2575 p, Activity.RESULT_CANCELED, null, "reset-task", false)) { 2576 end--; 2577 srcPos--; 2578 } 2579 } 2580 replyChainEnd = -1; 2581 } else { 2582 // If we were in the middle of a chain, well the 2583 // activity that started it all doesn't want anything 2584 // special, so leave it all as-is. 2585 replyChainEnd = -1; 2586 } 2587 } 2588 2589 return topOptions; 2590 } 2591 2592 /** 2593 * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given 2594 * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop. 2595 * @param affinityTask The task we are looking for an affinity to. 2596 * @param task Task that resetTaskIfNeededLocked.taskTop belongs to. 2597 * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked. 2598 * @param forceReset Flag passed in to resetTaskIfNeededLocked. 2599 */ 2600 private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, 2601 boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) { 2602 int replyChainEnd = -1; 2603 final int taskId = task.taskId; 2604 final String taskAffinity = task.affinity; 2605 2606 final ArrayList<ActivityRecord> activities = affinityTask.mActivities; 2607 final int numActivities = activities.size(); 2608 final int rootActivityNdx = affinityTask.findEffectiveRootIndex(); 2609 2610 // Do not operate on or below the effective root Activity. 2611 for (int i = numActivities - 1; i > rootActivityNdx; --i) { 2612 ActivityRecord target = activities.get(i); 2613 if (target.frontOfTask) 2614 break; 2615 2616 final int flags = target.info.flags; 2617 boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0; 2618 boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0; 2619 2620 if (target.resultTo != null) { 2621 // If this activity is sending a reply to a previous 2622 // activity, we can't do anything with it now until 2623 // we reach the start of the reply chain. 2624 // XXX note that we are assuming the result is always 2625 // to the previous activity, which is almost always 2626 // the case but we really shouldn't count on. 2627 if (replyChainEnd < 0) { 2628 replyChainEnd = i; 2629 } 2630 } else if (topTaskIsHigher 2631 && allowTaskReparenting 2632 && taskAffinity != null 2633 && taskAffinity.equals(target.taskAffinity)) { 2634 // This activity has an affinity for our task. Either remove it if we are 2635 // clearing or move it over to our task. Note that 2636 // we currently punt on the case where we are resetting a 2637 // task that is not at the top but who has activities above 2638 // with an affinity to it... this is really not a normal 2639 // case, and we will need to later pull that task to the front 2640 // and usually at that point we will do the reset and pick 2641 // up those remaining activities. (This only happens if 2642 // someone starts an activity in a new task from an activity 2643 // in a task that is not currently on top.) 2644 if (forceReset || finishOnTaskLaunch) { 2645 final int start = replyChainEnd >= 0 ? replyChainEnd : i; 2646 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 2647 "Finishing task at index " + start + " to " + i); 2648 for (int srcPos = start; srcPos >= i; --srcPos) { 2649 final ActivityRecord p = activities.get(srcPos); 2650 if (p.finishing) { 2651 continue; 2652 } 2653 finishActivityLocked( 2654 p, Activity.RESULT_CANCELED, null, "move-affinity", false); 2655 } 2656 } else { 2657 if (taskInsertionPoint < 0) { 2658 taskInsertionPoint = task.mActivities.size(); 2659 2660 } 2661 2662 final int start = replyChainEnd >= 0 ? replyChainEnd : i; 2663 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 2664 "Reparenting from task=" + affinityTask + ":" + start + "-" + i 2665 + " to task=" + task + ":" + taskInsertionPoint); 2666 for (int srcPos = start; srcPos >= i; --srcPos) { 2667 final ActivityRecord p = activities.get(srcPos); 2668 p.setTask(task, null); 2669 task.addActivityAtIndex(taskInsertionPoint, p); 2670 2671 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 2672 "Removing and adding activity " + p + " to stack at " + task 2673 + " callers=" + Debug.getCallers(3)); 2674 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p 2675 + " from " + srcPos + " in to resetting task " + task); 2676 setAppTask(p, task); 2677 } 2678 mWindowManager.moveTaskToTop(taskId); 2679 if (VALIDATE_TOKENS) { 2680 validateAppTokensLocked(); 2681 } 2682 2683 // Now we've moved it in to place... but what if this is 2684 // a singleTop activity and we have put it on top of another 2685 // instance of the same activity? Then we drop the instance 2686 // below so it remains singleTop. 2687 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) { 2688 ArrayList<ActivityRecord> taskActivities = task.mActivities; 2689 int targetNdx = taskActivities.indexOf(target); 2690 if (targetNdx > 0) { 2691 ActivityRecord p = taskActivities.get(targetNdx - 1); 2692 if (p.intent.getComponent().equals(target.intent.getComponent())) { 2693 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace", 2694 false); 2695 } 2696 } 2697 } 2698 } 2699 2700 replyChainEnd = -1; 2701 } 2702 } 2703 return taskInsertionPoint; 2704 } 2705 2706 final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop, 2707 ActivityRecord newActivity) { 2708 boolean forceReset = 2709 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0; 2710 if (ACTIVITY_INACTIVE_RESET_TIME > 0 2711 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) { 2712 if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) { 2713 forceReset = true; 2714 } 2715 } 2716 2717 final TaskRecord task = taskTop.task; 2718 2719 /** False until we evaluate the TaskRecord associated with taskTop. Switches to true 2720 * for remaining tasks. Used for later tasks to reparent to task. */ 2721 boolean taskFound = false; 2722 2723 /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */ 2724 ActivityOptions topOptions = null; 2725 2726 // Preserve the location for reparenting in the new task. 2727 int reparentInsertionPoint = -1; 2728 2729 for (int i = mTaskHistory.size() - 1; i >= 0; --i) { 2730 final TaskRecord targetTask = mTaskHistory.get(i); 2731 2732 if (targetTask == task) { 2733 topOptions = resetTargetTaskIfNeededLocked(task, forceReset); 2734 taskFound = true; 2735 } else { 2736 reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task, 2737 taskFound, forceReset, reparentInsertionPoint); 2738 } 2739 } 2740 2741 int taskNdx = mTaskHistory.indexOf(task); 2742 if (taskNdx >= 0) { 2743 do { 2744 taskTop = mTaskHistory.get(taskNdx--).getTopActivity(); 2745 } while (taskTop == null && taskNdx >= 0); 2746 } 2747 2748 if (topOptions != null) { 2749 // If we got some ActivityOptions from an activity on top that 2750 // was removed from the task, propagate them to the new real top. 2751 if (taskTop != null) { 2752 taskTop.updateOptionsLocked(topOptions); 2753 } else { 2754 topOptions.abort(); 2755 } 2756 } 2757 2758 return taskTop; 2759 } 2760 2761 void sendActivityResultLocked(int callingUid, ActivityRecord r, 2762 String resultWho, int requestCode, int resultCode, Intent data) { 2763 2764 if (callingUid > 0) { 2765 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, 2766 data, r.getUriPermissionsLocked(), r.userId); 2767 } 2768 2769 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r 2770 + " : who=" + resultWho + " req=" + requestCode 2771 + " res=" + resultCode + " data=" + data); 2772 if (mResumedActivity == r && r.app != null && r.app.thread != null) { 2773 try { 2774 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 2775 list.add(new ResultInfo(resultWho, requestCode, 2776 resultCode, data)); 2777 r.app.thread.scheduleSendResult(r.appToken, list); 2778 return; 2779 } catch (Exception e) { 2780 Slog.w(TAG, "Exception thrown sending result to " + r, e); 2781 } 2782 } 2783 2784 r.addResultLocked(null, resultWho, requestCode, resultCode, data); 2785 } 2786 2787 private void adjustFocusedActivityLocked(ActivityRecord r, String reason) { 2788 if (mStackSupervisor.isFocusedStack(this) && mService.mFocusedActivity == r) { 2789 ActivityRecord next = topRunningActivityLocked(); 2790 final String myReason = reason + " adjustFocus"; 2791 if (next != r) { 2792 if (next != null && StackId.keepFocusInStackIfPossible(mStackId)) { 2793 // For freeform, docked, and pinned stacks we always keep the focus within the 2794 // stack as long as there is a running activity in the stack that we can adjust 2795 // focus to. 2796 mService.setFocusedActivityLocked(next, myReason); 2797 return; 2798 } else { 2799 final TaskRecord task = r.task; 2800 if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) { 2801 // For non-fullscreen stack, we want to move the focus to the next visible 2802 // stack to prevent the home screen from moving to the top and obscuring 2803 // other visible stacks. 2804 if (!mFullscreen 2805 && adjustFocusToNextVisibleStackLocked(null, myReason)) { 2806 return; 2807 } 2808 // Move the home stack to the top if this stack is fullscreen or there is no 2809 // other visible stack. 2810 if (mStackSupervisor.moveHomeStackTaskToTop( 2811 task.getTaskToReturnTo(), myReason)) { 2812 // Activity focus was already adjusted. Nothing else to do... 2813 return; 2814 } 2815 } 2816 } 2817 } 2818 2819 final ActivityRecord top = mStackSupervisor.topRunningActivityLocked(); 2820 if (top != null) { 2821 mService.setFocusedActivityLocked(top, myReason); 2822 } 2823 } 2824 } 2825 2826 private boolean adjustFocusToNextVisibleStackLocked(ActivityStack inStack, String reason) { 2827 final ActivityStack stack = (inStack != null) ? inStack : getNextVisibleStackLocked(); 2828 final String myReason = reason + " adjustFocusToNextVisibleStack"; 2829 if (stack == null) { 2830 return false; 2831 } 2832 final ActivityRecord top = stack.topRunningActivityLocked(); 2833 if (top == null) { 2834 return false; 2835 } 2836 mService.setFocusedActivityLocked(top, myReason); 2837 return true; 2838 } 2839 2840 final void stopActivityLocked(ActivityRecord r) { 2841 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r); 2842 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 2843 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { 2844 if (!r.finishing) { 2845 if (!mService.isSleeping()) { 2846 if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); 2847 if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, 2848 "stop-no-history", false)) { 2849 // Activity was finished, no need to continue trying to schedule stop. 2850 adjustFocusedActivityLocked(r, "stopActivityFinished"); 2851 r.resumeKeyDispatchingLocked(); 2852 return; 2853 } 2854 } else { 2855 if (DEBUG_STATES) Slog.d(TAG_STATES, "Not finishing noHistory " + r 2856 + " on stop because we're just sleeping"); 2857 } 2858 } 2859 } 2860 2861 if (r.app != null && r.app.thread != null) { 2862 adjustFocusedActivityLocked(r, "stopActivity"); 2863 r.resumeKeyDispatchingLocked(); 2864 try { 2865 r.stopped = false; 2866 if (DEBUG_STATES) Slog.v(TAG_STATES, 2867 "Moving to STOPPING: " + r + " (stop requested)"); 2868 r.state = ActivityState.STOPPING; 2869 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 2870 "Stopping visible=" + r.visible + " for " + r); 2871 if (!r.visible) { 2872 mWindowManager.setAppVisibility(r.appToken, false); 2873 } 2874 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); 2875 if (mService.isSleepingOrShuttingDown()) { 2876 r.setSleeping(true); 2877 } 2878 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r); 2879 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); 2880 } catch (Exception e) { 2881 // Maybe just ignore exceptions here... if the process 2882 // has crashed, our death notification will clean things 2883 // up. 2884 Slog.w(TAG, "Exception thrown during pause", e); 2885 // Just in case, assume it to be stopped. 2886 r.stopped = true; 2887 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r); 2888 r.state = ActivityState.STOPPED; 2889 if (r.configDestroy) { 2890 destroyActivityLocked(r, true, "stop-except"); 2891 } 2892 } 2893 } 2894 } 2895 2896 /** 2897 * @return Returns true if the activity is being finished, false if for 2898 * some reason it is being left as-is. 2899 */ 2900 final boolean requestFinishActivityLocked(IBinder token, int resultCode, 2901 Intent resultData, String reason, boolean oomAdj) { 2902 ActivityRecord r = isInStackLocked(token); 2903 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES, 2904 "Finishing activity token=" + token + " r=" 2905 + ", result=" + resultCode + ", data=" + resultData 2906 + ", reason=" + reason); 2907 if (r == null) { 2908 return false; 2909 } 2910 2911 finishActivityLocked(r, resultCode, resultData, reason, oomAdj); 2912 return true; 2913 } 2914 2915 final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) { 2916 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2917 ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 2918 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 2919 ActivityRecord r = activities.get(activityNdx); 2920 if (r.resultTo == self && r.requestCode == requestCode) { 2921 if ((r.resultWho == null && resultWho == null) || 2922 (r.resultWho != null && r.resultWho.equals(resultWho))) { 2923 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub", 2924 false); 2925 } 2926 } 2927 } 2928 } 2929 mService.updateOomAdjLocked(); 2930 } 2931 2932 final void finishTopRunningActivityLocked(ProcessRecord app, String reason) { 2933 ActivityRecord r = topRunningActivityLocked(); 2934 if (r != null && r.app == app) { 2935 // If the top running activity is from this crashing 2936 // process, then terminate it to avoid getting in a loop. 2937 Slog.w(TAG, " Force finishing activity " 2938 + r.intent.getComponent().flattenToShortString()); 2939 int taskNdx = mTaskHistory.indexOf(r.task); 2940 int activityNdx = r.task.mActivities.indexOf(r); 2941 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); 2942 // Also terminate any activities below it that aren't yet 2943 // stopped, to avoid a situation where one will get 2944 // re-start our crashing activity once it gets resumed again. 2945 --activityNdx; 2946 if (activityNdx < 0) { 2947 do { 2948 --taskNdx; 2949 if (taskNdx < 0) { 2950 break; 2951 } 2952 activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1; 2953 } while (activityNdx < 0); 2954 } 2955 if (activityNdx >= 0) { 2956 r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx); 2957 if (r.state == ActivityState.RESUMED 2958 || r.state == ActivityState.PAUSING 2959 || r.state == ActivityState.PAUSED) { 2960 if (!r.isHomeActivity() || mService.mHomeProcess != r.app) { 2961 Slog.w(TAG, " Force finishing activity " 2962 + r.intent.getComponent().flattenToShortString()); 2963 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); 2964 } 2965 } 2966 } 2967 } 2968 } 2969 2970 final void finishVoiceTask(IVoiceInteractionSession session) { 2971 IBinder sessionBinder = session.asBinder(); 2972 boolean didOne = false; 2973 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2974 TaskRecord tr = mTaskHistory.get(taskNdx); 2975 if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) { 2976 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) { 2977 ActivityRecord r = tr.mActivities.get(activityNdx); 2978 if (!r.finishing) { 2979 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice", 2980 false); 2981 didOne = true; 2982 } 2983 } 2984 } 2985 } 2986 if (didOne) { 2987 mService.updateOomAdjLocked(); 2988 } 2989 } 2990 2991 final boolean finishActivityAffinityLocked(ActivityRecord r) { 2992 ArrayList<ActivityRecord> activities = r.task.mActivities; 2993 for (int index = activities.indexOf(r); index >= 0; --index) { 2994 ActivityRecord cur = activities.get(index); 2995 if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) { 2996 break; 2997 } 2998 finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true); 2999 } 3000 return true; 3001 } 3002 3003 final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) { 3004 // send the result 3005 ActivityRecord resultTo = r.resultTo; 3006 if (resultTo != null) { 3007 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo 3008 + " who=" + r.resultWho + " req=" + r.requestCode 3009 + " res=" + resultCode + " data=" + resultData); 3010 if (resultTo.userId != r.userId) { 3011 if (resultData != null) { 3012 resultData.prepareToLeaveUser(r.userId); 3013 } 3014 } 3015 if (r.info.applicationInfo.uid > 0) { 3016 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, 3017 resultTo.packageName, resultData, 3018 resultTo.getUriPermissionsLocked(), resultTo.userId); 3019 } 3020 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, 3021 resultData); 3022 r.resultTo = null; 3023 } 3024 else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r); 3025 3026 // Make sure this HistoryRecord is not holding on to other resources, 3027 // because clients have remote IPC references to this object so we 3028 // can't assume that will go away and want to avoid circular IPC refs. 3029 r.results = null; 3030 r.pendingResults = null; 3031 r.newIntents = null; 3032 r.icicle = null; 3033 } 3034 3035 /** 3036 * @return Returns true if this activity has been removed from the history 3037 * list, or false if it is still in the list and will be removed later. 3038 */ 3039 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, 3040 String reason, boolean oomAdj) { 3041 if (r.finishing) { 3042 Slog.w(TAG, "Duplicate finish request for " + r); 3043 return false; 3044 } 3045 3046 r.makeFinishingLocked(); 3047 final TaskRecord task = r.task; 3048 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 3049 r.userId, System.identityHashCode(r), 3050 task.taskId, r.shortComponentName, reason); 3051 final ArrayList<ActivityRecord> activities = task.mActivities; 3052 final int index = activities.indexOf(r); 3053 if (index < (activities.size() - 1)) { 3054 task.setFrontOfTask(); 3055 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { 3056 // If the caller asked that this activity (and all above it) 3057 // be cleared when the task is reset, don't lose that information, 3058 // but propagate it up to the next activity. 3059 ActivityRecord next = activities.get(index+1); 3060 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 3061 } 3062 } 3063 3064 r.pauseKeyDispatchingLocked(); 3065 3066 adjustFocusedActivityLocked(r, "finishActivity"); 3067 3068 finishActivityResultsLocked(r, resultCode, resultData); 3069 3070 if (mResumedActivity == r) { 3071 boolean endTask = index <= 0; 3072 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 3073 "Prepare close transition: finishing " + r); 3074 mWindowManager.prepareAppTransition(endTask 3075 ? AppTransition.TRANSIT_TASK_CLOSE 3076 : AppTransition.TRANSIT_ACTIVITY_CLOSE, false); 3077 3078 // Tell window manager to prepare for this one to be removed. 3079 mWindowManager.setAppVisibility(r.appToken, false); 3080 3081 if (mPausingActivity == null) { 3082 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r); 3083 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 3084 "finish() => pause with userLeaving=false"); 3085 startPausingLocked(false, false, false, false); 3086 } 3087 3088 if (endTask) { 3089 mStackSupervisor.removeLockedTaskLocked(task); 3090 } 3091 } else if (r.state != ActivityState.PAUSING) { 3092 // If the activity is PAUSING, we will complete the finish once 3093 // it is done pausing; else we can just directly finish it here. 3094 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r); 3095 return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null; 3096 } else { 3097 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r); 3098 } 3099 3100 return false; 3101 } 3102 3103 static final int FINISH_IMMEDIATELY = 0; 3104 static final int FINISH_AFTER_PAUSE = 1; 3105 static final int FINISH_AFTER_VISIBLE = 2; 3106 3107 final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) { 3108 // First things first: if this activity is currently visible, 3109 // and the resumed activity is not yet visible, then hold off on 3110 // finishing until the resumed one becomes visible. 3111 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) { 3112 if (!mStackSupervisor.mStoppingActivities.contains(r)) { 3113 mStackSupervisor.mStoppingActivities.add(r); 3114 if (mStackSupervisor.mStoppingActivities.size() > 3 3115 || r.frontOfTask && mTaskHistory.size() <= 1) { 3116 // If we already have a few activities waiting to stop, 3117 // then give up on things going idle and start clearing 3118 // them out. Or if r is the last of activity of the last task the stack 3119 // will be empty and must be cleared immediately. 3120 mStackSupervisor.scheduleIdleLocked(); 3121 } else { 3122 mStackSupervisor.checkReadyForSleepLocked(); 3123 } 3124 } 3125 if (DEBUG_STATES) Slog.v(TAG_STATES, 3126 "Moving to STOPPING: "+ r + " (finish requested)"); 3127 r.state = ActivityState.STOPPING; 3128 if (oomAdj) { 3129 mService.updateOomAdjLocked(); 3130 } 3131 return r; 3132 } 3133 3134 // make sure the record is cleaned out of other places. 3135 mStackSupervisor.mStoppingActivities.remove(r); 3136 mStackSupervisor.mGoingToSleepActivities.remove(r); 3137 mStackSupervisor.mWaitingVisibleActivities.remove(r); 3138 if (mResumedActivity == r) { 3139 mResumedActivity = null; 3140 } 3141 final ActivityState prevState = r.state; 3142 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r); 3143 r.state = ActivityState.FINISHING; 3144 3145 if (mode == FINISH_IMMEDIATELY 3146 || (mode == FINISH_AFTER_PAUSE && prevState == ActivityState.PAUSED) 3147 || prevState == ActivityState.STOPPED 3148 || prevState == ActivityState.INITIALIZING) { 3149 // If this activity is already stopped, we can just finish 3150 // it right now. 3151 r.makeFinishingLocked(); 3152 boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm"); 3153 if (activityRemoved) { 3154 mStackSupervisor.resumeTopActivitiesLocked(); 3155 } 3156 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, 3157 "destroyActivityLocked: finishCurrentActivityLocked r=" + r + 3158 " destroy returned removed=" + activityRemoved); 3159 return activityRemoved ? null : r; 3160 } 3161 3162 // Need to go through the full pause cycle to get this 3163 // activity into the stopped state and then finish it. 3164 if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r); 3165 mStackSupervisor.mFinishingActivities.add(r); 3166 r.resumeKeyDispatchingLocked(); 3167 mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null); 3168 return r; 3169 } 3170 3171 void finishAllActivitiesLocked(boolean immediately) { 3172 boolean noActivitiesInStack = true; 3173 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3174 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 3175 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 3176 final ActivityRecord r = activities.get(activityNdx); 3177 noActivitiesInStack = false; 3178 if (r.finishing && !immediately) { 3179 continue; 3180 } 3181 Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately"); 3182 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false); 3183 } 3184 } 3185 if (noActivitiesInStack) { 3186 mActivityContainer.onTaskListEmptyLocked(); 3187 } 3188 } 3189 3190 final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) { 3191 // Basic case: for simple app-centric recents, we need to recreate 3192 // the task if the affinity has changed. 3193 if (srec == null || srec.task.affinity == null || 3194 !srec.task.affinity.equals(destAffinity)) { 3195 return true; 3196 } 3197 // Document-centric case: an app may be split in to multiple documents; 3198 // they need to re-create their task if this current activity is the root 3199 // of a document, unless simply finishing it will return them to the the 3200 // correct app behind. 3201 if (srec.frontOfTask && srec.task != null && srec.task.getBaseIntent() != null 3202 && srec.task.getBaseIntent().isDocument()) { 3203 // Okay, this activity is at the root of its task. What to do, what to do... 3204 if (srec.task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) { 3205 // Finishing won't return to an application, so we need to recreate. 3206 return true; 3207 } 3208 // We now need to get the task below it to determine what to do. 3209 int taskIdx = mTaskHistory.indexOf(srec.task); 3210 if (taskIdx <= 0) { 3211 Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec); 3212 return false; 3213 } 3214 if (taskIdx == 0) { 3215 // At the bottom of the stack, nothing to go back to. 3216 return true; 3217 } 3218 TaskRecord prevTask = mTaskHistory.get(taskIdx); 3219 if (!srec.task.affinity.equals(prevTask.affinity)) { 3220 // These are different apps, so need to recreate. 3221 return true; 3222 } 3223 } 3224 return false; 3225 } 3226 3227 final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, 3228 Intent resultData) { 3229 final TaskRecord task = srec.task; 3230 final ArrayList<ActivityRecord> activities = task.mActivities; 3231 final int start = activities.indexOf(srec); 3232 if (!mTaskHistory.contains(task) || (start < 0)) { 3233 return false; 3234 } 3235 int finishTo = start - 1; 3236 ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo); 3237 boolean foundParentInTask = false; 3238 final ComponentName dest = destIntent.getComponent(); 3239 if (start > 0 && dest != null) { 3240 for (int i = finishTo; i >= 0; i--) { 3241 ActivityRecord r = activities.get(i); 3242 if (r.info.packageName.equals(dest.getPackageName()) && 3243 r.info.name.equals(dest.getClassName())) { 3244 finishTo = i; 3245 parent = r; 3246 foundParentInTask = true; 3247 break; 3248 } 3249 } 3250 } 3251 3252 IActivityController controller = mService.mController; 3253 if (controller != null) { 3254 ActivityRecord next = topRunningActivityLocked(srec.appToken, 0); 3255 if (next != null) { 3256 // ask watcher if this is allowed 3257 boolean resumeOK = true; 3258 try { 3259 resumeOK = controller.activityResuming(next.packageName); 3260 } catch (RemoteException e) { 3261 mService.mController = null; 3262 Watchdog.getInstance().setActivityController(null); 3263 } 3264 3265 if (!resumeOK) { 3266 return false; 3267 } 3268 } 3269 } 3270 final long origId = Binder.clearCallingIdentity(); 3271 for (int i = start; i > finishTo; i--) { 3272 ActivityRecord r = activities.get(i); 3273 requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true); 3274 // Only return the supplied result for the first activity finished 3275 resultCode = Activity.RESULT_CANCELED; 3276 resultData = null; 3277 } 3278 3279 if (parent != null && foundParentInTask) { 3280 final int parentLaunchMode = parent.info.launchMode; 3281 final int destIntentFlags = destIntent.getFlags(); 3282 if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || 3283 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || 3284 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || 3285 (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { 3286 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent, 3287 srec.packageName); 3288 } else { 3289 try { 3290 ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( 3291 destIntent.getComponent(), 0, srec.userId); 3292 int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent, 3293 null, aInfo, null, null, parent.appToken, null, 3294 0, -1, parent.launchedFromUid, parent.launchedFromPackage, 3295 -1, parent.launchedFromUid, 0, null, false, true, null, null, null); 3296 foundParentInTask = res == ActivityManager.START_SUCCESS; 3297 } catch (RemoteException e) { 3298 foundParentInTask = false; 3299 } 3300 requestFinishActivityLocked(parent.appToken, resultCode, 3301 resultData, "navigate-top", true); 3302 } 3303 } 3304 Binder.restoreCallingIdentity(origId); 3305 return foundParentInTask; 3306 } 3307 /** 3308 * Perform the common clean-up of an activity record. This is called both 3309 * as part of destroyActivityLocked() (when destroying the client-side 3310 * representation) and cleaning things up as a result of its hosting 3311 * processing going away, in which case there is no remaining client-side 3312 * state to destroy so only the cleanup here is needed. 3313 * 3314 * Note: Call before #removeActivityFromHistoryLocked. 3315 */ 3316 final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, 3317 boolean setState) { 3318 if (mResumedActivity == r) { 3319 mResumedActivity = null; 3320 } 3321 if (mPausingActivity == r) { 3322 mPausingActivity = null; 3323 } 3324 mService.clearFocusedActivity(r); 3325 3326 r.configDestroy = false; 3327 r.frozenBeforeDestroy = false; 3328 3329 if (setState) { 3330 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)"); 3331 r.state = ActivityState.DESTROYED; 3332 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r); 3333 r.app = null; 3334 } 3335 3336 // Make sure this record is no longer in the pending finishes list. 3337 // This could happen, for example, if we are trimming activities 3338 // down to the max limit while they are still waiting to finish. 3339 mStackSupervisor.mFinishingActivities.remove(r); 3340 mStackSupervisor.mWaitingVisibleActivities.remove(r); 3341 3342 // Remove any pending results. 3343 if (r.finishing && r.pendingResults != null) { 3344 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) { 3345 PendingIntentRecord rec = apr.get(); 3346 if (rec != null) { 3347 mService.cancelIntentSenderLocked(rec, false); 3348 } 3349 } 3350 r.pendingResults = null; 3351 } 3352 3353 if (cleanServices) { 3354 cleanUpActivityServicesLocked(r); 3355 } 3356 3357 // Get rid of any pending idle timeouts. 3358 removeTimeoutsForActivityLocked(r); 3359 if (getVisibleBehindActivity() == r) { 3360 mStackSupervisor.requestVisibleBehindLocked(r, false); 3361 } 3362 } 3363 3364 private void removeTimeoutsForActivityLocked(ActivityRecord r) { 3365 mStackSupervisor.removeTimeoutsForActivityLocked(r); 3366 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 3367 mHandler.removeMessages(STOP_TIMEOUT_MSG, r); 3368 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 3369 r.finishLaunchTickingLocked(); 3370 } 3371 3372 private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) { 3373 mStackSupervisor.removeChildActivityContainers(r); 3374 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null); 3375 r.makeFinishingLocked(); 3376 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 3377 "Removing activity " + r + " from stack callers=" + Debug.getCallers(5)); 3378 3379 r.takeFromHistory(); 3380 removeTimeoutsForActivityLocked(r); 3381 if (DEBUG_STATES) Slog.v(TAG_STATES, 3382 "Moving to DESTROYED: " + r + " (removed from history)"); 3383 r.state = ActivityState.DESTROYED; 3384 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r); 3385 r.app = null; 3386 mWindowManager.removeAppToken(r.appToken); 3387 if (VALIDATE_TOKENS) { 3388 validateAppTokensLocked(); 3389 } 3390 final TaskRecord task = r.task; 3391 if (task != null && task.removeActivity(r)) { 3392 if (DEBUG_STACK) Slog.i(TAG_STACK, 3393 "removeActivityFromHistoryLocked: last activity removed from " + this); 3394 if (mStackSupervisor.isFocusedStack(this) && task == topTask() && 3395 task.isOverHomeStack()) { 3396 mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason); 3397 } 3398 removeTask(task, reason); 3399 } 3400 cleanUpActivityServicesLocked(r); 3401 r.removeUriPermissionsLocked(); 3402 } 3403 3404 /** 3405 * Perform clean-up of service connections in an activity record. 3406 */ 3407 final void cleanUpActivityServicesLocked(ActivityRecord r) { 3408 // Throw away any services that have been bound by this activity. 3409 if (r.connections != null) { 3410 Iterator<ConnectionRecord> it = r.connections.iterator(); 3411 while (it.hasNext()) { 3412 ConnectionRecord c = it.next(); 3413 mService.mServices.removeConnectionLocked(c, null, r); 3414 } 3415 r.connections = null; 3416 } 3417 } 3418 3419 final void scheduleDestroyActivities(ProcessRecord owner, String reason) { 3420 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG); 3421 msg.obj = new ScheduleDestroyArgs(owner, reason); 3422 mHandler.sendMessage(msg); 3423 } 3424 3425 final void destroyActivitiesLocked(ProcessRecord owner, String reason) { 3426 boolean lastIsOpaque = false; 3427 boolean activityRemoved = false; 3428 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3429 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 3430 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 3431 final ActivityRecord r = activities.get(activityNdx); 3432 if (r.finishing) { 3433 continue; 3434 } 3435 if (r.fullscreen) { 3436 lastIsOpaque = true; 3437 } 3438 if (owner != null && r.app != owner) { 3439 continue; 3440 } 3441 if (!lastIsOpaque) { 3442 continue; 3443 } 3444 if (r.isDestroyable()) { 3445 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.state 3446 + " resumed=" + mResumedActivity 3447 + " pausing=" + mPausingActivity + " for reason " + reason); 3448 if (destroyActivityLocked(r, true, reason)) { 3449 activityRemoved = true; 3450 } 3451 } 3452 } 3453 } 3454 if (activityRemoved) { 3455 mStackSupervisor.resumeTopActivitiesLocked(); 3456 } 3457 } 3458 3459 final boolean safelyDestroyActivityLocked(ActivityRecord r, String reason) { 3460 if (r.isDestroyable()) { 3461 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 3462 "Destroying " + r + " in state " + r.state + " resumed=" + mResumedActivity 3463 + " pausing=" + mPausingActivity + " for reason " + reason); 3464 return destroyActivityLocked(r, true, reason); 3465 } 3466 return false; 3467 } 3468 3469 final int releaseSomeActivitiesLocked(ProcessRecord app, ArraySet<TaskRecord> tasks, 3470 String reason) { 3471 // Iterate over tasks starting at the back (oldest) first. 3472 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app); 3473 int maxTasks = tasks.size() / 4; 3474 if (maxTasks < 1) { 3475 maxTasks = 1; 3476 } 3477 int numReleased = 0; 3478 for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) { 3479 final TaskRecord task = mTaskHistory.get(taskNdx); 3480 if (!tasks.contains(task)) { 3481 continue; 3482 } 3483 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Looking for activities to release in " + task); 3484 int curNum = 0; 3485 final ArrayList<ActivityRecord> activities = task.mActivities; 3486 for (int actNdx = 0; actNdx < activities.size(); actNdx++) { 3487 final ActivityRecord activity = activities.get(actNdx); 3488 if (activity.app == app && activity.isDestroyable()) { 3489 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + activity 3490 + " in state " + activity.state + " resumed=" + mResumedActivity 3491 + " pausing=" + mPausingActivity + " for reason " + reason); 3492 destroyActivityLocked(activity, true, reason); 3493 if (activities.get(actNdx) != activity) { 3494 // Was removed from list, back up so we don't miss the next one. 3495 actNdx--; 3496 } 3497 curNum++; 3498 } 3499 } 3500 if (curNum > 0) { 3501 numReleased += curNum; 3502 maxTasks--; 3503 if (mTaskHistory.get(taskNdx) != task) { 3504 // The entire task got removed, back up so we don't miss the next one. 3505 taskNdx--; 3506 } 3507 } 3508 } 3509 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, 3510 "Done releasing: did " + numReleased + " activities"); 3511 return numReleased; 3512 } 3513 3514 /** 3515 * Destroy the current CLIENT SIDE instance of an activity. This may be 3516 * called both when actually finishing an activity, or when performing 3517 * a configuration switch where we destroy the current client-side object 3518 * but then create a new client-side object for this same HistoryRecord. 3519 */ 3520 final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) { 3521 if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH, 3522 "Removing activity from " + reason + ": token=" + r 3523 + ", app=" + (r.app != null ? r.app.processName : "(null)")); 3524 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, 3525 r.userId, System.identityHashCode(r), 3526 r.task.taskId, r.shortComponentName, reason); 3527 3528 boolean removedFromHistory = false; 3529 3530 cleanUpActivityLocked(r, false, false); 3531 3532 final boolean hadApp = r.app != null; 3533 3534 if (hadApp) { 3535 if (removeFromApp) { 3536 r.app.activities.remove(r); 3537 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) { 3538 mService.mHeavyWeightProcess = null; 3539 mService.mHandler.sendEmptyMessage( 3540 ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG); 3541 } 3542 if (r.app.activities.isEmpty()) { 3543 // Update any services we are bound to that might care about whether 3544 // their client may have activities. 3545 mService.mServices.updateServiceConnectionActivitiesLocked(r.app); 3546 // No longer have activities, so update LRU list and oom adj. 3547 mService.updateLruProcessLocked(r.app, false, null); 3548 mService.updateOomAdjLocked(); 3549 } 3550 } 3551 3552 boolean skipDestroy = false; 3553 3554 try { 3555 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r); 3556 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing, 3557 r.configChangeFlags); 3558 } catch (Exception e) { 3559 // We can just ignore exceptions here... if the process 3560 // has crashed, our death notification will clean things 3561 // up. 3562 //Slog.w(TAG, "Exception thrown during finish", e); 3563 if (r.finishing) { 3564 removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy"); 3565 removedFromHistory = true; 3566 skipDestroy = true; 3567 } 3568 } 3569 3570 r.nowVisible = false; 3571 3572 // If the activity is finishing, we need to wait on removing it 3573 // from the list to give it a chance to do its cleanup. During 3574 // that time it may make calls back with its token so we need to 3575 // be able to find it on the list and so we don't want to remove 3576 // it from the list yet. Otherwise, we can just immediately put 3577 // it in the destroyed state since we are not removing it from the 3578 // list. 3579 if (r.finishing && !skipDestroy) { 3580 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYING: " + r 3581 + " (destroy requested)"); 3582 r.state = ActivityState.DESTROYING; 3583 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r); 3584 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT); 3585 } else { 3586 if (DEBUG_STATES) Slog.v(TAG_STATES, 3587 "Moving to DESTROYED: " + r + " (destroy skipped)"); 3588 r.state = ActivityState.DESTROYED; 3589 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r); 3590 r.app = null; 3591 } 3592 } else { 3593 // remove this record from the history. 3594 if (r.finishing) { 3595 removeActivityFromHistoryLocked(r, reason + " hadNoApp"); 3596 removedFromHistory = true; 3597 } else { 3598 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (no app)"); 3599 r.state = ActivityState.DESTROYED; 3600 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r); 3601 r.app = null; 3602 } 3603 } 3604 3605 r.configChangeFlags = 0; 3606 3607 if (!mLRUActivities.remove(r) && hadApp) { 3608 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list"); 3609 } 3610 3611 return removedFromHistory; 3612 } 3613 3614 final void activityDestroyedLocked(IBinder token, String reason) { 3615 final long origId = Binder.clearCallingIdentity(); 3616 try { 3617 ActivityRecord r = ActivityRecord.forTokenLocked(token); 3618 if (r != null) { 3619 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 3620 } 3621 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + r); 3622 3623 if (isInStackLocked(r) != null) { 3624 if (r.state == ActivityState.DESTROYING) { 3625 cleanUpActivityLocked(r, true, false); 3626 removeActivityFromHistoryLocked(r, reason); 3627 } 3628 } 3629 mStackSupervisor.resumeTopActivitiesLocked(); 3630 } finally { 3631 Binder.restoreCallingIdentity(origId); 3632 } 3633 } 3634 3635 void releaseBackgroundResources(ActivityRecord r) { 3636 if (hasVisibleBehindActivity() && 3637 !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) { 3638 if (r == topRunningActivityLocked()) { 3639 // Don't release the top activity if it has requested to run behind the next 3640 // activity. 3641 return; 3642 } 3643 if (DEBUG_STATES) Slog.d(TAG_STATES, "releaseBackgroundResources activtyDisplay=" + 3644 mActivityContainer.mActivityDisplay + " visibleBehind=" + r + " app=" + r.app + 3645 " thread=" + r.app.thread); 3646 if (r != null && r.app != null && r.app.thread != null) { 3647 try { 3648 r.app.thread.scheduleCancelVisibleBehind(r.appToken); 3649 } catch (RemoteException e) { 3650 } 3651 mHandler.sendEmptyMessageDelayed(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG, 500); 3652 } else { 3653 Slog.e(TAG, "releaseBackgroundResources: activity " + r + " no longer running"); 3654 backgroundResourcesReleased(); 3655 } 3656 } 3657 } 3658 3659 final void backgroundResourcesReleased() { 3660 mHandler.removeMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG); 3661 final ActivityRecord r = getVisibleBehindActivity(); 3662 if (r != null) { 3663 mStackSupervisor.mStoppingActivities.add(r); 3664 setVisibleBehindActivity(null); 3665 mStackSupervisor.scheduleIdleTimeoutLocked(null); 3666 } 3667 mStackSupervisor.resumeTopActivitiesLocked(); 3668 } 3669 3670 boolean hasVisibleBehindActivity() { 3671 return isAttached() && mActivityContainer.mActivityDisplay.hasVisibleBehindActivity(); 3672 } 3673 3674 void setVisibleBehindActivity(ActivityRecord r) { 3675 if (isAttached()) { 3676 mActivityContainer.mActivityDisplay.setVisibleBehindActivity(r); 3677 } 3678 } 3679 3680 ActivityRecord getVisibleBehindActivity() { 3681 return isAttached() ? mActivityContainer.mActivityDisplay.mVisibleBehindActivity : null; 3682 } 3683 3684 private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, 3685 ProcessRecord app, String listName) { 3686 int i = list.size(); 3687 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 3688 "Removing app " + app + " from list " + listName + " with " + i + " entries"); 3689 while (i > 0) { 3690 i--; 3691 ActivityRecord r = list.get(i); 3692 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r); 3693 if (r.app == app) { 3694 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!"); 3695 list.remove(i); 3696 removeTimeoutsForActivityLocked(r); 3697 } 3698 } 3699 } 3700 3701 boolean removeHistoryRecordsForAppLocked(ProcessRecord app) { 3702 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities"); 3703 removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app, 3704 "mStoppingActivities"); 3705 removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app, 3706 "mGoingToSleepActivities"); 3707 removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app, 3708 "mWaitingVisibleActivities"); 3709 removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app, 3710 "mFinishingActivities"); 3711 3712 boolean hasVisibleActivities = false; 3713 3714 // Clean out the history list. 3715 int i = numActivities(); 3716 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 3717 "Removing app " + app + " from history with " + i + " entries"); 3718 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3719 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 3720 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 3721 final ActivityRecord r = activities.get(activityNdx); 3722 --i; 3723 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 3724 "Record #" + i + " " + r + ": app=" + r.app); 3725 if (r.app == app) { 3726 if (r.visible) { 3727 hasVisibleActivities = true; 3728 } 3729 final boolean remove; 3730 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) { 3731 // Don't currently have state for the activity, or 3732 // it is finishing -- always remove it. 3733 remove = true; 3734 } else if (r.launchCount > 2 && 3735 r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) { 3736 // We have launched this activity too many times since it was 3737 // able to run, so give up and remove it. 3738 remove = true; 3739 } else { 3740 // The process may be gone, but the activity lives on! 3741 remove = false; 3742 } 3743 if (remove) { 3744 if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE, 3745 "Removing activity " + r + " from stack at " + i 3746 + ": haveState=" + r.haveState 3747 + " stateNotNeeded=" + r.stateNotNeeded 3748 + " finishing=" + r.finishing 3749 + " state=" + r.state + " callers=" + Debug.getCallers(5)); 3750 if (!r.finishing) { 3751 Slog.w(TAG, "Force removing " + r + ": app died, no saved state"); 3752 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 3753 r.userId, System.identityHashCode(r), 3754 r.task.taskId, r.shortComponentName, 3755 "proc died without state saved"); 3756 if (r.state == ActivityState.RESUMED) { 3757 mService.updateUsageStats(r, false); 3758 } 3759 } 3760 } else { 3761 // We have the current state for this activity, so 3762 // it can be restarted later when needed. 3763 if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null"); 3764 if (DEBUG_APP) Slog.v(TAG_APP, 3765 "Clearing app during removeHistory for activity " + r); 3766 r.app = null; 3767 r.nowVisible = false; 3768 if (!r.haveState) { 3769 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, 3770 "App died, clearing saved state of " + r); 3771 r.icicle = null; 3772 } 3773 } 3774 cleanUpActivityLocked(r, true, true); 3775 if (remove) { 3776 removeActivityFromHistoryLocked(r, "appDied"); 3777 } 3778 } 3779 } 3780 } 3781 3782 return hasVisibleActivities; 3783 } 3784 3785 final void updateTransitLocked(int transit, Bundle options) { 3786 if (options != null) { 3787 ActivityRecord r = topRunningActivityLocked(); 3788 if (r != null && r.state != ActivityState.RESUMED) { 3789 r.updateOptionsLocked(options); 3790 } else { 3791 ActivityOptions.abort(options); 3792 } 3793 } 3794 mWindowManager.prepareAppTransition(transit, false); 3795 } 3796 3797 void updateTaskMovement(TaskRecord task, boolean toFront) { 3798 if (task.isPersistable) { 3799 task.mLastTimeMoved = System.currentTimeMillis(); 3800 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most 3801 // recently will be most negative, tasks sent to the bottom before that will be less 3802 // negative. Similarly for recent tasks moved to the top which will be most positive. 3803 if (!toFront) { 3804 task.mLastTimeMoved *= -1; 3805 } 3806 } 3807 mStackSupervisor.invalidateTaskLayers(); 3808 } 3809 3810 void moveHomeStackTaskToTop(int homeStackTaskType) { 3811 final int top = mTaskHistory.size() - 1; 3812 for (int taskNdx = top; taskNdx >= 0; --taskNdx) { 3813 final TaskRecord task = mTaskHistory.get(taskNdx); 3814 if (task.taskType == homeStackTaskType) { 3815 if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG_STACK, 3816 "moveHomeStackTaskToTop: moving " + task); 3817 mTaskHistory.remove(taskNdx); 3818 mTaskHistory.add(top, task); 3819 updateTaskMovement(task, true); 3820 return; 3821 } 3822 } 3823 } 3824 3825 final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, Bundle options, 3826 AppTimeTracker timeTracker, String reason) { 3827 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr); 3828 3829 final int numTasks = mTaskHistory.size(); 3830 final int index = mTaskHistory.indexOf(tr); 3831 if (numTasks == 0 || index < 0) { 3832 // nothing to do! 3833 if (noAnimation) { 3834 ActivityOptions.abort(options); 3835 } else { 3836 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options); 3837 } 3838 return; 3839 } 3840 3841 if (timeTracker != null) { 3842 // The caller wants a time tracker associated with this task. 3843 for (int i = tr.mActivities.size() - 1; i >= 0; i--) { 3844 tr.mActivities.get(i).appTimeTracker = timeTracker; 3845 } 3846 } 3847 3848 // Shift all activities with this task up to the top 3849 // of the stack, keeping them in the same internal order. 3850 insertTaskAtTop(tr, null); 3851 3852 // Don't refocus if invisible to current user 3853 ActivityRecord top = tr.getTopActivity(); 3854 if (!okToShowLocked(top)) { 3855 addRecentActivityLocked(top); 3856 ActivityOptions.abort(options); 3857 return; 3858 } 3859 3860 // Set focus to the top running activity of this stack. 3861 ActivityRecord r = topRunningActivityLocked(); 3862 mService.setFocusedActivityLocked(r, reason); 3863 3864 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr); 3865 if (noAnimation) { 3866 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); 3867 if (r != null) { 3868 mNoAnimActivities.add(r); 3869 } 3870 ActivityOptions.abort(options); 3871 } else { 3872 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options); 3873 } 3874 3875 mStackSupervisor.resumeTopActivitiesLocked(); 3876 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId); 3877 3878 if (VALIDATE_TOKENS) { 3879 validateAppTokensLocked(); 3880 } 3881 } 3882 3883 /** 3884 * Worker method for rearranging history stack. Implements the function of moving all 3885 * activities for a specific task (gathering them if disjoint) into a single group at the 3886 * bottom of the stack. 3887 * 3888 * If a watcher is installed, the action is preflighted and the watcher has an opportunity 3889 * to premeptively cancel the move. 3890 * 3891 * @param taskId The taskId to collect and move to the bottom. 3892 * @return Returns true if the move completed, false if not. 3893 */ 3894 final boolean moveTaskToBackLocked(int taskId) { 3895 final TaskRecord tr = taskForIdLocked(taskId); 3896 if (tr == null) { 3897 Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId); 3898 return false; 3899 } 3900 3901 Slog.i(TAG, "moveTaskToBack: " + tr); 3902 mStackSupervisor.removeLockedTaskLocked(tr); 3903 3904 // If we have a watcher, preflight the move before committing to it. First check 3905 // for *other* available tasks, but if none are available, then try again allowing the 3906 // current task to be selected. 3907 if (mStackSupervisor.isFrontStack(this) && mService.mController != null) { 3908 ActivityRecord next = topRunningActivityLocked(null, taskId); 3909 if (next == null) { 3910 next = topRunningActivityLocked(null, 0); 3911 } 3912 if (next != null) { 3913 // ask watcher if this is allowed 3914 boolean moveOK = true; 3915 try { 3916 moveOK = mService.mController.activityResuming(next.packageName); 3917 } catch (RemoteException e) { 3918 mService.mController = null; 3919 Watchdog.getInstance().setActivityController(null); 3920 } 3921 if (!moveOK) { 3922 return false; 3923 } 3924 } 3925 } 3926 3927 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId); 3928 3929 boolean prevIsHome = false; 3930 3931 // If true, we should resume the home activity next if the task we are moving to the 3932 // back is over the home stack. We force to false if the task we are moving to back 3933 // is the home task and we don't want it resumed after moving to the back. 3934 final boolean canGoHome = !tr.isHomeTask() && tr.isOverHomeStack(); 3935 if (canGoHome) { 3936 final TaskRecord nextTask = getNextTask(tr); 3937 if (nextTask != null) { 3938 nextTask.setTaskToReturnTo(tr.getTaskToReturnTo()); 3939 } else { 3940 prevIsHome = true; 3941 } 3942 } 3943 mTaskHistory.remove(tr); 3944 mTaskHistory.add(0, tr); 3945 updateTaskMovement(tr, false); 3946 3947 // There is an assumption that moving a task to the back moves it behind the home activity. 3948 // We make sure here that some activity in the stack will launch home. 3949 int numTasks = mTaskHistory.size(); 3950 for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) { 3951 final TaskRecord task = mTaskHistory.get(taskNdx); 3952 if (task.isOverHomeStack()) { 3953 break; 3954 } 3955 if (taskNdx == 1) { 3956 // Set the last task before tr to go to home. 3957 task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); 3958 } 3959 } 3960 3961 mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false); 3962 mWindowManager.moveTaskToBottom(taskId); 3963 3964 if (VALIDATE_TOKENS) { 3965 validateAppTokensLocked(); 3966 } 3967 3968 final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; 3969 if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) { 3970 if (!mService.mBooting && !mService.mBooted) { 3971 // Not ready yet! 3972 return false; 3973 } 3974 final int taskToReturnTo = tr.getTaskToReturnTo(); 3975 tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); 3976 return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null, "moveTaskToBack"); 3977 } 3978 3979 mStackSupervisor.resumeTopActivitiesLocked(); 3980 return true; 3981 } 3982 3983 static final void logStartActivity(int tag, ActivityRecord r, 3984 TaskRecord task) { 3985 final Uri data = r.intent.getData(); 3986 final String strData = data != null ? data.toSafeString() : null; 3987 3988 EventLog.writeEvent(tag, 3989 r.userId, System.identityHashCode(r), task.taskId, 3990 r.shortComponentName, r.intent.getAction(), 3991 r.intent.getType(), strData, r.intent.getFlags()); 3992 } 3993 3994 /** 3995 * Make sure the given activity matches the current configuration. Returns 3996 * false if the activity had to be destroyed. Returns true if the 3997 * configuration is the same, or the activity will remain running as-is 3998 * for whatever reason. Ensures the HistoryRecord is updated with the 3999 * correct configuration and all other bookkeeping is handled. 4000 */ 4001 final boolean ensureActivityConfigurationLocked(ActivityRecord r, int globalChanges, 4002 boolean preserveWindow) { 4003 if (mConfigWillChange) { 4004 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4005 "Skipping config check (will change): " + r); 4006 return true; 4007 } 4008 4009 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4010 "Ensuring correct configuration: " + r); 4011 4012 // Short circuit: if the two configurations are the exact same 4013 // object (the common case), then there is nothing to do. 4014 final Configuration newConfig = mService.mConfiguration; 4015 final Configuration taskConfig = r.task.mOverrideConfig; 4016 if (r.configuration == newConfig 4017 && r.taskConfigOverride == taskConfig 4018 && !r.forceNewConfig) { 4019 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4020 "Configuration unchanged in " + r); 4021 return true; 4022 } 4023 4024 // We don't worry about activities that are finishing. 4025 if (r.finishing) { 4026 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4027 "Configuration doesn't matter in finishing " + r); 4028 r.stopFreezingScreenLocked(false); 4029 return true; 4030 } 4031 4032 // Okay we now are going to make this activity have the new config. 4033 // But then we need to figure out how it needs to deal with that. 4034 final Configuration oldConfig = r.configuration; 4035 final Configuration oldTaskOverride = r.taskConfigOverride; 4036 r.configuration = newConfig; 4037 r.taskConfigOverride = taskConfig; 4038 4039 int taskChanges = getTaskConfigurationChanges(r, taskConfig, oldTaskOverride); 4040 final int changes = oldConfig.diff(newConfig) | taskChanges; 4041 if (changes == 0 && !r.forceNewConfig) { 4042 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4043 "Configuration no differences in " + r); 4044 return true; 4045 } 4046 4047 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4048 "Configuration changes for " + r + " ; taskChanges=" 4049 + Configuration.configurationDiffToString(taskChanges) + ", allChanges=" 4050 + Configuration.configurationDiffToString(changes)); 4051 4052 // If the activity isn't currently running, just leave the new 4053 // configuration and it will pick that up next time it starts. 4054 if (r.app == null || r.app.thread == null) { 4055 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4056 "Configuration doesn't matter not running " + r); 4057 r.stopFreezingScreenLocked(false); 4058 r.forceNewConfig = false; 4059 return true; 4060 } 4061 4062 // Figure out how to handle the changes between the configurations. 4063 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4064 "Checking to restart " + r.info.name + ": changed=0x" 4065 + Integer.toHexString(changes) + ", handles=0x" 4066 + Integer.toHexString(r.info.getRealConfigChanged()) + ", newConfig=" + newConfig); 4067 4068 if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) { 4069 // Aha, the activity isn't handling the change, so DIE DIE DIE. 4070 r.configChangeFlags |= changes; 4071 r.startFreezingScreenLocked(r.app, globalChanges); 4072 r.forceNewConfig = false; 4073 if (r.app == null || r.app.thread == null) { 4074 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4075 "Config is destroying non-running " + r); 4076 destroyActivityLocked(r, true, "config"); 4077 } else if (r.state == ActivityState.PAUSING) { 4078 // A little annoying: we are waiting for this activity to 4079 // finish pausing. Let's not do anything now, but just 4080 // flag that it needs to be restarted when done pausing. 4081 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4082 "Config is skipping already pausing " + r); 4083 r.configDestroy = true; 4084 return true; 4085 } else if (r.state == ActivityState.RESUMED) { 4086 // Try to optimize this case: the configuration is changing 4087 // and we need to restart the top, resumed activity. 4088 // Instead of doing the normal handshaking, just say 4089 // "restart!". 4090 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4091 "Config is relaunching resumed " + r); 4092 relaunchActivityLocked(r, r.configChangeFlags, true, 4093 preserveWindow && isResizeOnlyChange(changes)); 4094 r.configChangeFlags = 0; 4095 } else { 4096 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, 4097 "Config is relaunching non-resumed " + r); 4098 relaunchActivityLocked(r, r.configChangeFlags, false, 4099 preserveWindow && isResizeOnlyChange(changes)); 4100 r.configChangeFlags = 0; 4101 } 4102 4103 // All done... tell the caller we weren't able to keep this 4104 // activity around. 4105 return false; 4106 } 4107 4108 // Default case: the activity can handle this new configuration, so hand it over. 4109 // NOTE: We only forward the task override configuration as the system level configuration 4110 // changes is always sent to all processes when they happen so it can just use whatever 4111 // system level configuration it last got. 4112 if (r.app != null && r.app.thread != null) { 4113 try { 4114 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending new config to " + r); 4115 r.app.thread.scheduleActivityConfigurationChanged( 4116 r.appToken, new Configuration(taskConfig)); 4117 } catch (RemoteException e) { 4118 // If process died, whatever. 4119 } 4120 } 4121 r.stopFreezingScreenLocked(false); 4122 4123 return true; 4124 } 4125 4126 private int getTaskConfigurationChanges(ActivityRecord record, Configuration taskConfig, 4127 Configuration oldTaskOverride) { 4128 // Determine what has changed. May be nothing, if this is a config 4129 // that has come back from the app after going idle. In that case 4130 // we just want to leave the official config object now in the 4131 // activity and do nothing else. 4132 int taskChanges = oldTaskOverride.diff(taskConfig); 4133 // We don't want to use size changes if they don't cross boundaries that are important to 4134 // the app. 4135 if ((taskChanges & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) { 4136 final boolean crosses = record.crossesHorizontalSizeThreshold( 4137 oldTaskOverride.screenWidthDp, taskConfig.screenWidthDp) 4138 || record.crossesVerticalSizeThreshold( 4139 oldTaskOverride.screenHeightDp, taskConfig.screenHeightDp); 4140 if (!crosses) { 4141 taskChanges &= ~ActivityInfo.CONFIG_SCREEN_SIZE; 4142 } 4143 } 4144 if ((taskChanges & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) { 4145 final int oldSmallest = oldTaskOverride.smallestScreenWidthDp; 4146 final int newSmallest = taskConfig.smallestScreenWidthDp; 4147 if (!record.crossesSmallestSizeThreshold(oldSmallest, newSmallest)) { 4148 taskChanges &= ~ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 4149 } 4150 } 4151 return catchConfigChangesFromUnset(taskConfig, oldTaskOverride, taskChanges); 4152 } 4153 4154 private static int catchConfigChangesFromUnset(Configuration taskConfig, 4155 Configuration oldTaskOverride, int taskChanges) { 4156 if (taskChanges == 0) { 4157 // {@link Configuration#diff} doesn't catch changes from unset values. 4158 // Check for changes we care about. 4159 if (oldTaskOverride.orientation != taskConfig.orientation) { 4160 taskChanges |= ActivityInfo.CONFIG_ORIENTATION; 4161 } 4162 // We want to explicitly track situations where the size configuration goes from 4163 // undefined to defined. We don't care about crossing the threshold in that case, 4164 // because there is no threshold. 4165 final int oldHeight = oldTaskOverride.screenHeightDp; 4166 final int newHeight = taskConfig.screenHeightDp; 4167 final int undefinedHeight = Configuration.SCREEN_HEIGHT_DP_UNDEFINED; 4168 if ((oldHeight == undefinedHeight && newHeight != undefinedHeight) 4169 || (oldHeight != undefinedHeight && newHeight == undefinedHeight)) { 4170 taskChanges |= ActivityInfo.CONFIG_SCREEN_SIZE; 4171 } 4172 final int oldWidth = oldTaskOverride.screenWidthDp; 4173 final int newWidth = taskConfig.screenWidthDp; 4174 final int undefinedWidth = Configuration.SCREEN_WIDTH_DP_UNDEFINED; 4175 if ((oldWidth == undefinedWidth && newWidth != undefinedWidth) 4176 || (oldWidth != undefinedWidth && newWidth == undefinedWidth)) { 4177 taskChanges |= ActivityInfo.CONFIG_SCREEN_SIZE; 4178 } 4179 final int oldSmallest = oldTaskOverride.smallestScreenWidthDp; 4180 final int newSmallest = taskConfig.smallestScreenWidthDp; 4181 final int undefinedSmallest = Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED; 4182 if ((oldSmallest == undefinedSmallest && newSmallest != undefinedSmallest) 4183 || (oldSmallest != undefinedSmallest && newSmallest == undefinedSmallest)) { 4184 taskChanges |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; 4185 } 4186 } 4187 return taskChanges; 4188 } 4189 4190 private static boolean isResizeOnlyChange(int change) { 4191 return (change & ~(ActivityInfo.CONFIG_SCREEN_SIZE 4192 | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) == 0; 4193 } 4194 4195 private void relaunchActivityLocked( 4196 ActivityRecord r, int changes, boolean andResume, boolean preserveWindow) { 4197 if (mService.mSuppressResizeConfigChanges && preserveWindow) { 4198 return; 4199 } 4200 4201 List<ResultInfo> results = null; 4202 List<ReferrerIntent> newIntents = null; 4203 if (andResume) { 4204 results = r.results; 4205 newIntents = r.newIntents; 4206 } 4207 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 4208 "Relaunching: " + r + " with results=" + results + " newIntents=" + newIntents 4209 + " andResume=" + andResume + " preserveWindow=" + preserveWindow); 4210 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY 4211 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r), 4212 r.task.taskId, r.shortComponentName); 4213 4214 r.startFreezingScreenLocked(r.app, 0); 4215 4216 mStackSupervisor.removeChildActivityContainers(r); 4217 4218 try { 4219 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, 4220 "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + r); 4221 r.forceNewConfig = false; 4222 r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes, 4223 !andResume, new Configuration(mService.mConfiguration), 4224 new Configuration(r.task.mOverrideConfig), preserveWindow); 4225 // Note: don't need to call pauseIfSleepingLocked() here, because 4226 // the caller will only pass in 'andResume' if this activity is 4227 // currently resumed, which implies we aren't sleeping. 4228 } catch (RemoteException e) { 4229 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e); 4230 } 4231 4232 if (andResume) { 4233 r.results = null; 4234 r.newIntents = null; 4235 r.state = ActivityState.RESUMED; 4236 } else { 4237 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 4238 r.state = ActivityState.PAUSED; 4239 } 4240 } 4241 4242 boolean willActivityBeVisibleLocked(IBinder token) { 4243 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4244 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4245 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4246 final ActivityRecord r = activities.get(activityNdx); 4247 if (r.appToken == token) { 4248 return true; 4249 } 4250 if (r.fullscreen && !r.finishing) { 4251 return false; 4252 } 4253 } 4254 } 4255 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 4256 if (r == null) { 4257 return false; 4258 } 4259 if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false," 4260 + " would have returned true for r=" + r); 4261 return !r.finishing; 4262 } 4263 4264 void closeSystemDialogsLocked() { 4265 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4266 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4267 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4268 final ActivityRecord r = activities.get(activityNdx); 4269 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) { 4270 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true); 4271 } 4272 } 4273 } 4274 } 4275 4276 boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, 4277 boolean doit, boolean evenPersistent, int userId) { 4278 boolean didSomething = false; 4279 TaskRecord lastTask = null; 4280 ComponentName homeActivity = null; 4281 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4282 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4283 int numActivities = activities.size(); 4284 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { 4285 ActivityRecord r = activities.get(activityNdx); 4286 final boolean sameComponent = 4287 (r.packageName.equals(packageName) && (filterByClasses == null 4288 || filterByClasses.contains(r.realActivity.getClassName()))) 4289 || (packageName == null && r.userId == userId); 4290 if ((userId == UserHandle.USER_ALL || r.userId == userId) 4291 && (sameComponent || r.task == lastTask) 4292 && (r.app == null || evenPersistent || !r.app.persistent)) { 4293 if (!doit) { 4294 if (r.finishing) { 4295 // If this activity is just finishing, then it is not 4296 // interesting as far as something to stop. 4297 continue; 4298 } 4299 return true; 4300 } 4301 if (r.isHomeActivity()) { 4302 if (homeActivity != null && homeActivity.equals(r.realActivity)) { 4303 Slog.i(TAG, "Skip force-stop again " + r); 4304 continue; 4305 } else { 4306 homeActivity = r.realActivity; 4307 } 4308 } 4309 didSomething = true; 4310 Slog.i(TAG, " Force finishing activity " + r); 4311 if (sameComponent) { 4312 if (r.app != null) { 4313 r.app.removed = true; 4314 } 4315 r.app = null; 4316 } 4317 lastTask = r.task; 4318 if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop", 4319 true)) { 4320 // r has been deleted from mActivities, accommodate. 4321 --numActivities; 4322 --activityNdx; 4323 } 4324 } 4325 } 4326 } 4327 return didSomething; 4328 } 4329 4330 void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) { 4331 boolean focusedStack = mStackSupervisor.getFocusedStack() == this; 4332 boolean topTask = true; 4333 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4334 final TaskRecord task = mTaskHistory.get(taskNdx); 4335 if (task.getTopActivity() == null) { 4336 continue; 4337 } 4338 ActivityRecord r = null; 4339 ActivityRecord top = null; 4340 ActivityRecord tmp; 4341 int numActivities = 0; 4342 int numRunning = 0; 4343 final ArrayList<ActivityRecord> activities = task.mActivities; 4344 if (!allowed && !task.isHomeTask() && task.effectiveUid != callingUid) { 4345 continue; 4346 } 4347 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4348 tmp = activities.get(activityNdx); 4349 if (tmp.finishing) { 4350 continue; 4351 } 4352 r = tmp; 4353 4354 // Initialize state for next task if needed. 4355 if (top == null || (top.state == ActivityState.INITIALIZING)) { 4356 top = r; 4357 numActivities = numRunning = 0; 4358 } 4359 4360 // Add 'r' into the current task. 4361 numActivities++; 4362 if (r.app != null && r.app.thread != null) { 4363 numRunning++; 4364 } 4365 4366 if (DEBUG_ALL) Slog.v( 4367 TAG, r.intent.getComponent().flattenToShortString() 4368 + ": task=" + r.task); 4369 } 4370 4371 RunningTaskInfo ci = new RunningTaskInfo(); 4372 ci.id = task.taskId; 4373 ci.stackId = mStackId; 4374 ci.baseActivity = r.intent.getComponent(); 4375 ci.topActivity = top.intent.getComponent(); 4376 ci.lastActiveTime = task.lastActiveTime; 4377 if (focusedStack && topTask) { 4378 // Give the latest time to ensure foreground task can be sorted 4379 // at the first, because lastActiveTime of creating task is 0. 4380 ci.lastActiveTime = System.currentTimeMillis(); 4381 topTask = false; 4382 } 4383 4384 if (top.task != null) { 4385 ci.description = top.task.lastDescription; 4386 } 4387 ci.numActivities = numActivities; 4388 ci.numRunning = numRunning; 4389 list.add(ci); 4390 } 4391 } 4392 4393 public void unhandledBackLocked() { 4394 final int top = mTaskHistory.size() - 1; 4395 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top); 4396 if (top >= 0) { 4397 final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities; 4398 int activityTop = activities.size() - 1; 4399 if (activityTop > 0) { 4400 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null, 4401 "unhandled-back", true); 4402 } 4403 } 4404 } 4405 4406 /** 4407 * Reset local parameters because an app's activity died. 4408 * @param app The app of the activity that died. 4409 * @return result from removeHistoryRecordsForAppLocked. 4410 */ 4411 boolean handleAppDiedLocked(ProcessRecord app) { 4412 if (mPausingActivity != null && mPausingActivity.app == app) { 4413 if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE, 4414 "App died while pausing: " + mPausingActivity); 4415 mPausingActivity = null; 4416 } 4417 if (mLastPausedActivity != null && mLastPausedActivity.app == app) { 4418 mLastPausedActivity = null; 4419 mLastNoHistoryActivity = null; 4420 } 4421 4422 return removeHistoryRecordsForAppLocked(app); 4423 } 4424 4425 void handleAppCrashLocked(ProcessRecord app) { 4426 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4427 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4428 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4429 final ActivityRecord r = activities.get(activityNdx); 4430 if (r.app == app) { 4431 Slog.w(TAG, " Force finishing activity " 4432 + r.intent.getComponent().flattenToShortString()); 4433 // Force the destroy to skip right to removal. 4434 r.app = null; 4435 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false); 4436 } 4437 } 4438 } 4439 } 4440 4441 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, 4442 boolean dumpClient, String dumpPackage, boolean needSep, String header) { 4443 boolean printed = false; 4444 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4445 final TaskRecord task = mTaskHistory.get(taskNdx); 4446 printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw, 4447 mTaskHistory.get(taskNdx).mActivities, " ", "Hist", true, !dumpAll, 4448 dumpClient, dumpPackage, needSep, header, 4449 " Task id #" + task.taskId + "\n" + 4450 " mFullscreen=" + task.mFullscreen + "\n" + 4451 " mBounds=" + task.mBounds + "\n" + 4452 " mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds); 4453 if (printed) { 4454 header = null; 4455 } 4456 } 4457 return printed; 4458 } 4459 4460 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { 4461 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(); 4462 4463 if ("all".equals(name)) { 4464 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4465 activities.addAll(mTaskHistory.get(taskNdx).mActivities); 4466 } 4467 } else if ("top".equals(name)) { 4468 final int top = mTaskHistory.size() - 1; 4469 if (top >= 0) { 4470 final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities; 4471 int listTop = list.size() - 1; 4472 if (listTop >= 0) { 4473 activities.add(list.get(listTop)); 4474 } 4475 } 4476 } else { 4477 ItemMatcher matcher = new ItemMatcher(); 4478 matcher.build(name); 4479 4480 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4481 for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) { 4482 if (matcher.match(r1, r1.intent.getComponent())) { 4483 activities.add(r1); 4484 } 4485 } 4486 } 4487 } 4488 4489 return activities; 4490 } 4491 4492 ActivityRecord restartPackage(String packageName) { 4493 ActivityRecord starting = topRunningActivityLocked(); 4494 4495 // All activities that came from the package must be 4496 // restarted as if there was a config change. 4497 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4498 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4499 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4500 final ActivityRecord a = activities.get(activityNdx); 4501 if (a.info.packageName.equals(packageName)) { 4502 a.forceNewConfig = true; 4503 if (starting != null && a == starting && a.visible) { 4504 a.startFreezingScreenLocked(starting.app, 4505 ActivityInfo.CONFIG_SCREEN_LAYOUT); 4506 } 4507 } 4508 } 4509 } 4510 4511 return starting; 4512 } 4513 4514 void removeTask(TaskRecord task, String reason) { 4515 removeTask(task, reason, !MOVING); 4516 } 4517 4518 /** 4519 * Removes the input task from this stack. 4520 * @param task to remove. 4521 * @param reason for removal. 4522 * @param moving task to another stack. In the case we are moving we don't want to perform 4523 * some operations on the task like removing it from window manager or recents. 4524 */ 4525 void removeTask(TaskRecord task, String reason, boolean moving) { 4526 if (!moving) { 4527 mStackSupervisor.removeLockedTaskLocked(task); 4528 mWindowManager.removeTask(task.taskId); 4529 } 4530 4531 final ActivityRecord r = mResumedActivity; 4532 if (r != null && r.task == task) { 4533 mResumedActivity = null; 4534 } 4535 4536 final int taskNdx = mTaskHistory.indexOf(task); 4537 final int topTaskNdx = mTaskHistory.size() - 1; 4538 if (task.isOverHomeStack() && taskNdx < topTaskNdx) { 4539 final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1); 4540 if (!nextTask.isOverHomeStack()) { 4541 nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE); 4542 } 4543 } 4544 mTaskHistory.remove(task); 4545 updateTaskMovement(task, true); 4546 4547 if (!moving && task.mActivities.isEmpty()) { 4548 final boolean isVoiceSession = task.voiceSession != null; 4549 if (isVoiceSession) { 4550 try { 4551 task.voiceSession.taskFinished(task.intent, task.taskId); 4552 } catch (RemoteException e) { 4553 } 4554 } 4555 if (task.autoRemoveFromRecents() || isVoiceSession) { 4556 // Task creator asked to remove this when done, or this task was a voice 4557 // interaction, so it should not remain on the recent tasks list. 4558 mRecentTasks.remove(task); 4559 task.removedFromRecents(); 4560 } 4561 } 4562 4563 if (mTaskHistory.isEmpty()) { 4564 if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this); 4565 // We only need to adjust focused stack if this stack is in focus. 4566 if (isOnHomeDisplay() && mStackSupervisor.isFocusedStack(this)) { 4567 String myReason = reason + " leftTaskHistoryEmpty"; 4568 if (mFullscreen || !adjustFocusToNextVisibleStackLocked(null, myReason)) { 4569 mStackSupervisor.moveHomeStackToFront(myReason); 4570 } 4571 } 4572 if (mStacks != null) { 4573 mStacks.remove(this); 4574 mStacks.add(0, this); 4575 } 4576 if (!isHomeStack()) { 4577 mActivityContainer.onTaskListEmptyLocked(); 4578 } 4579 } 4580 4581 task.stack = null; 4582 } 4583 4584 TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, 4585 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 4586 boolean toTop) { 4587 TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession, 4588 voiceInteractor); 4589 // add the task to stack first, mTaskPositioner might need the stack association 4590 addTask(task, toTop, false); 4591 if (mTaskPositioner != null) { 4592 mTaskPositioner.updateDefaultBounds(task, mTaskHistory, info.layout); 4593 } else if (mBounds != null && task.mResizeable) { 4594 task.updateOverrideConfiguration(mBounds); 4595 } 4596 return task; 4597 } 4598 4599 ArrayList<TaskRecord> getAllTasks() { 4600 return new ArrayList<>(mTaskHistory); 4601 } 4602 4603 void addTask(final TaskRecord task, final boolean toTop, boolean moving) { 4604 task.stack = this; 4605 if (toTop) { 4606 insertTaskAtTop(task, null); 4607 } else { 4608 mTaskHistory.add(0, task); 4609 updateTaskMovement(task, false); 4610 } 4611 if (!moving && task.voiceSession != null) { 4612 try { 4613 task.voiceSession.taskStarted(task.intent, task.taskId); 4614 } catch (RemoteException e) { 4615 } 4616 } 4617 } 4618 4619 void positionTask(final TaskRecord task, int position, boolean moving) { 4620 task.stack = this; 4621 insertTaskAtPosition(task, position); 4622 if (!moving && task.voiceSession != null) { 4623 try { 4624 task.voiceSession.taskStarted(task.intent, task.taskId); 4625 } catch (RemoteException e) { 4626 } 4627 } 4628 } 4629 4630 void addConfigOverride(ActivityRecord r, TaskRecord task) { 4631 final Rect bounds = task.getLaunchBounds(); 4632 task.updateOverrideConfiguration(bounds); 4633 mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken, 4634 r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen, 4635 (r.info.flags & ActivityInfo.FLAG_SHOW_FOR_ALL_USERS) != 0, r.userId, 4636 r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind, 4637 bounds, task.mOverrideConfig, !r.isHomeActivity()); 4638 r.taskConfigOverride = task.mOverrideConfig; 4639 } 4640 4641 void setFocusAndResumeStateIfNeeded( 4642 ActivityRecord r, boolean setFocus, boolean setResume, String reason) { 4643 // If the activity had focus before move focus to this stack. 4644 if (setFocus) { 4645 // If the activity owns the last resumed activity, transfer that together, 4646 // so that we don't resume the same activity again in the new stack. 4647 // Apps may depend on onResume()/onPause() being called in pairs. 4648 if (setResume) { 4649 mResumedActivity = r; 4650 // Move the stack in which we are placing the activity to the front. We don't use 4651 // ActivityManagerService.setFocusedActivityLocked, because if the activity is 4652 // already focused, the call will short-circuit and do nothing. 4653 moveToFront(reason); 4654 } else { 4655 // We need to not only move the stack to the front, but also have the activity 4656 // focused. This will achieve both goals. 4657 mService.setFocusedActivityLocked(r, reason); 4658 } 4659 } 4660 } 4661 4662 /** 4663 * Moves the input activity from its current stack to this one. 4664 * NOTE: The current task of the activity isn't moved to this stack. Instead a new task is 4665 * created on this stack which the activity is added to. 4666 * */ 4667 void moveActivityToStack(ActivityRecord r) { 4668 final ActivityStack prevStack = r.task.stack; 4669 if (prevStack.mStackId == mStackId) { 4670 // You are already in the right stack silly... 4671 return; 4672 } 4673 4674 final boolean wasFocused = mStackSupervisor.isFocusedStack(prevStack) 4675 && (mStackSupervisor.topRunningActivityLocked() == r); 4676 final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r); 4677 4678 final TaskRecord task = createTaskRecord( 4679 mStackSupervisor.getNextTaskId(), r.info, r.intent, null, null, true); 4680 r.setTask(task, null); 4681 task.addActivityToTop(r); 4682 setAppTask(r, task); 4683 setFocusAndResumeStateIfNeeded(r, wasFocused, wasResumed, "moveActivityToStack"); 4684 } 4685 4686 private void setAppTask(ActivityRecord r, TaskRecord task) { 4687 final Rect bounds = task.getLaunchBounds(); 4688 task.updateOverrideConfiguration(bounds); 4689 mWindowManager.setAppTask( 4690 r.appToken, task.taskId, task.getLaunchBounds(), task.mOverrideConfig); 4691 r.taskConfigOverride = task.mOverrideConfig; 4692 } 4693 4694 public int getStackId() { 4695 return mStackId; 4696 } 4697 4698 @Override 4699 public String toString() { 4700 return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this)) 4701 + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}"; 4702 } 4703 4704 void onLockTaskPackagesUpdatedLocked() { 4705 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4706 mTaskHistory.get(taskNdx).setLockTaskAuth(); 4707 } 4708 } 4709} 4710