blob: d3ac7cb1582449f0307f4bebc1a02f009394959d [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080019import static android.app.ActivityManager.RESIZE_MODE_FORCED;
Winson Chung74666102017-02-22 17:49:24 -080020import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
Jorim Jaggi0a932142016-02-01 17:42:25 -080021import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070022import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070024import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
25import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
26import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
27import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale44f036f2017-09-29 05:09:09 -070028import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080029import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Wale Ogunwale66e16852017-10-19 13:35:52 -070030import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Jorim Jaggi0a932142016-02-01 17:42:25 -080031import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
Wale Ogunwale66e16852017-10-19 13:35:52 -070032import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale3eadad72016-10-13 09:16:59 -070033import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080034import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
35import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
36import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
37import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080038import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
39import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
40import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Wale Ogunwaled829d362016-02-10 19:24:49 -080041import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070042import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -080043import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070044import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080045import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
Suprabh Shukla7745c142016-03-07 18:21:10 -080046import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Andrii Kulian036e3ad2017-04-19 10:55:10 -070047import static android.view.Display.DEFAULT_DISPLAY;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070048
Jorim Jaggi0a932142016-02-01 17:42:25 -080049import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
50import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
51import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
52import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
53import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
54import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
55import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
56import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
57import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
58import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale3b232392016-05-13 15:37:13 -070059import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -080060import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
Wale Ogunwale56d8d162017-05-30 11:12:20 -070061import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
Wale Ogunwaleab5de372017-10-18 06:46:31 -070062import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Winson Chung6954fc92017-03-24 16:22:12 -070063import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080064import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070065import static com.android.server.am.TaskRecordProto.ACTIVITIES;
66import static com.android.server.am.TaskRecordProto.BOUNDS;
67import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
68import static com.android.server.am.TaskRecordProto.FULLSCREEN;
69import static com.android.server.am.TaskRecordProto.ID;
70import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
71import static com.android.server.am.TaskRecordProto.MIN_HEIGHT;
72import static com.android.server.am.TaskRecordProto.MIN_WIDTH;
73import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
74import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
75import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
76import static com.android.server.am.TaskRecordProto.STACK_ID;
77import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070078
Winson Chung74666102017-02-22 17:49:24 -080079import static java.lang.Integer.MAX_VALUE;
80
Jorim Jaggie7d2b852017-08-28 17:55:15 +020081import android.annotation.IntDef;
82import android.annotation.Nullable;
83import android.app.Activity;
84import android.app.ActivityManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020085import android.app.ActivityManager.TaskDescription;
86import android.app.ActivityManager.TaskSnapshot;
87import android.app.ActivityOptions;
88import android.app.AppGlobals;
89import android.app.IActivityManager;
90import android.content.ComponentName;
91import android.content.Intent;
92import android.content.pm.ActivityInfo;
93import android.content.pm.ApplicationInfo;
94import android.content.pm.IPackageManager;
95import android.content.pm.PackageManager;
96import android.content.res.Configuration;
97import android.graphics.Rect;
98import android.os.Debug;
99import android.os.RemoteException;
Winson Chungfb44d212017-10-04 11:39:10 -0700100import android.os.SystemClock;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200101import android.os.Trace;
102import android.os.UserHandle;
103import android.provider.Settings;
104import android.service.voice.IVoiceInteractionSession;
105import android.util.DisplayMetrics;
106import android.util.Slog;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700107import android.util.proto.ProtoOutputStream;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200108
109import com.android.internal.annotations.VisibleForTesting;
110import com.android.internal.app.IVoiceInteractor;
111import com.android.internal.util.XmlUtils;
Winson Chung61c9e5a2017-10-11 10:39:32 -0700112import com.android.server.am.ActivityStack.ActivityState;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200113import com.android.server.wm.AppWindowContainerController;
114import com.android.server.wm.ConfigurationContainer;
115import com.android.server.wm.StackWindowController;
116import com.android.server.wm.TaskWindowContainerController;
117import com.android.server.wm.TaskWindowContainerListener;
118import com.android.server.wm.WindowManagerService;
119
120import org.xmlpull.v1.XmlPullParser;
121import org.xmlpull.v1.XmlPullParserException;
122import org.xmlpull.v1.XmlSerializer;
123
124import java.io.IOException;
125import java.io.PrintWriter;
126import java.lang.annotation.Retention;
127import java.lang.annotation.RetentionPolicy;
128import java.util.ArrayList;
129import java.util.Objects;
130
Benjamin Franza83859f2017-07-03 16:34:14 +0100131class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800132 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700133 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700134 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700135 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700136 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800137
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700138 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700139 private static final String TAG_INTENT = "intent";
140 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700141 private static final String ATTR_REALACTIVITY = "real_activity";
142 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700143 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700144 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700145 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700146 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700147 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700148 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700149 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
150 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800151 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700152 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700153 @Deprecated
Craig Mautner21d24a22014-04-23 11:45:37 -0700154 private static final String ATTR_TASKTYPE = "task_type";
Craig Mautner21d24a22014-04-23 11:45:37 -0700155 private static final String ATTR_LASTDESCRIPTION = "last_description";
156 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700157 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700158 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700159 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
160 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700161 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700162 private static final String ATTR_CALLING_UID = "calling_uid";
163 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800164 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800165 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700166 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700167 private static final String ATTR_MIN_WIDTH = "min_width";
168 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700169 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700170
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700171 // Current version of the task record we persist. Used to check if we need to run any upgrade
172 // code.
173 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700174
Wale Ogunwale18795a22014-12-03 11:38:33 -0800175 static final int INVALID_TASK_ID = -1;
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700176 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800177
Winson Chung74666102017-02-22 17:49:24 -0800178 /**
179 * The modes to control how the stack is moved to the front when calling
180 * {@link TaskRecord#reparent}.
181 */
182 @Retention(RetentionPolicy.SOURCE)
183 @IntDef({
184 REPARENT_MOVE_STACK_TO_FRONT,
185 REPARENT_KEEP_STACK_AT_FRONT,
186 REPARENT_LEAVE_STACK_IN_PLACE
187 })
Wale Ogunwale66e16852017-10-19 13:35:52 -0700188 @interface ReparentMoveStackMode {}
Winson Chung74666102017-02-22 17:49:24 -0800189 // Moves the stack to the front if it was not at the front
Wale Ogunwale66e16852017-10-19 13:35:52 -0700190 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
Winson Chung74666102017-02-22 17:49:24 -0800191 // Only moves the stack to the front if it was focused or front most already
Wale Ogunwale66e16852017-10-19 13:35:52 -0700192 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
Winson Chung74666102017-02-22 17:49:24 -0800193 // Do not move the stack as a part of reparenting
Wale Ogunwale66e16852017-10-19 13:35:52 -0700194 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
Winson Chung74666102017-02-22 17:49:24 -0800195
Garfield Tan9b1efea2017-12-05 16:43:46 -0800196 /**
197 * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
198 */
199 private static TaskRecordFactory sTaskRecordFactory;
200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 final int taskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700202 String affinity; // The affinity name for this task, or null; may change identity.
203 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700204 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
205 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Bryce Lee1a990e52018-04-23 10:54:11 -0700206 Intent intent; // The original intent that started the task. Note that this value can
207 // be null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700209 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 ComponentName origActivity; // The non-alias activity component of the intent.
211 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000212 boolean realActivitySuspended; // True if the actual activity component that started the
213 // task is suspended.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700214 boolean inRecents; // Actually in the recents list?
Winson Chungfb44d212017-10-04 11:39:10 -0700215 long lastActiveTime; // Last time this task was active in the current device session,
216 // including sleep. This time is initialized to the elapsed time when
217 // restored from disk.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700218 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 boolean rootWasReset; // True if the intent at the root of the task had
220 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700221 boolean autoRemoveRecents; // If true, we should automatically remove the task from
222 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700223 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700224 boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700226 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700227 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800228 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
229 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800230
231 int numFullscreen; // Number of fullscreen activities.
232
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800233 int mResizeMode; // The resize mode of this task and its activities.
234 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800235 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
236 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
237 // of the root activity.
Craig Mautner15df08a2015-04-01 12:17:18 -0700238 /** Can't be put in lockTask mode. */
239 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100240 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700241 final static int LOCK_TASK_AUTH_PINNABLE = 1;
242 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
243 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100244 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700245 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100246 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
247 * lockTask task. */
248 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700249 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
250
251 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800252
Winson Chung03a9bae2014-05-02 09:56:12 -0700253 // This represents the last resolved activity values for this task
254 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700255 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700256
Craig Mautnerd2328952013-03-05 12:46:26 -0800257 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700258 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800259
Andrii Kulian02b7a832016-10-06 23:11:56 -0700260 /** Current stack. Setter must always be used to update the value. */
261 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800262
Dianne Hackborn68a06332017-11-15 17:54:18 -0800263 /** The process that had previously hosted the root activity of this task.
264 * Used to know that we should try harder to keep this process around, in case the
265 * user wants to return to it. */
266 private ProcessRecord mRootProcess;
267
Craig Mautner21d24a22014-04-23 11:45:37 -0700268 /** Takes on same value as first root activity */
269 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700270 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700271
272 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
273 * determining the order when restoring. Sign indicates whether last task movement was to front
274 * (positive) or back (negative). Absolute value indicates time. */
275 long mLastTimeMoved = System.currentTimeMillis();
276
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700277 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700278 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700279
Craig Mautner362449a2014-06-20 14:04:39 -0700280 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
281 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800282 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700283
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700284 CharSequence lastDescription; // Last description captured for this item.
285
Craig Mautnera228ae92014-07-09 05:44:55 -0700286 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700287 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700288 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800289 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700290 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800291 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700292
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700293 // For relaunching the task from recents as though it was launched by the original launcher.
294 int mCallingUid;
295 String mCallingPackage;
296
Craig Mautner21d24a22014-04-23 11:45:37 -0700297 final ActivityManagerService mService;
298
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800299 private final Rect mTmpStableBounds = new Rect();
300 private final Rect mTmpNonDecorBounds = new Rect();
Wale Ogunwale9a08f822016-02-17 19:03:58 -0800301 private final Rect mTmpRect = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800302
Wale Ogunwale706ed792015-08-02 10:29:44 -0700303 // Last non-fullscreen bounds the task was launched in or resized to.
304 // The information is persisted and used to determine the appropriate stack to launch the
305 // task into on restore.
306 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700307 // Minimal width and height of this task when it's resizeable. -1 means it should use the
308 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700309 int mMinWidth;
310 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700311
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700312 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
313 // This number will be assigned when we evaluate OOM scores for all visible tasks.
314 int mLayerRank = -1;
315
Andrii Kulian1779e612016-10-12 21:58:25 -0700316 /** Helper object used for updating override configuration. */
317 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700318
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800319 private TaskWindowContainerController mWindowContainerController;
320
Garfield Tan9b1efea2017-12-05 16:43:46 -0800321 /**
322 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
323 * Intent, TaskDescription)} instead.
324 */
Craig Mautner21d24a22014-04-23 11:45:37 -0700325 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700326 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700327 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800328 userId = UserHandle.getUserId(info.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700330 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautnera228ae92014-07-09 05:44:55 -0700331 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700332 voiceSession = _voiceSession;
333 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700334 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800335 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700336 mCallingUid = info.applicationInfo.uid;
337 mCallingPackage = info.packageName;
Martijn Coenend4a69702014-06-30 11:12:17 -0700338 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700339 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700340 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700341 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700342 }
343
Garfield Tan9b1efea2017-12-05 16:43:46 -0800344 /**
345 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
346 * Intent, IVoiceInteractionSession, IVoiceInteractor)} instead.
347 */
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700348 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200349 TaskDescription _taskDescription) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700350 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800351 userId = UserHandle.getUserId(info.applicationInfo.uid);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700352 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700353 lastActiveTime = SystemClock.elapsedRealtime();
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700354 mAffiliatedTaskId = _taskId;
355 voiceSession = null;
356 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700357 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800358 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700359 mCallingUid = info.applicationInfo.uid;
360 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700361 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700362 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700363
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700364 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700365 // Clamp to [1, max].
366 maxRecents = Math.min(Math.max(info.maxRecents, 1),
367 ActivityManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700368
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700369 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700370 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700371 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700372 }
373
Garfield Tan9b1efea2017-12-05 16:43:46 -0800374 /**
375 * Don't use constructor directly. This is only used by XML parser.
376 */
377 TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800378 Intent _affinityIntent, String _affinity, String _rootAffinity,
379 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700380 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800381 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
Winson Chungfb44d212017-10-04 11:39:10 -0700382 long lastTimeMoved, boolean neverRelinquishIdentity,
383 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
384 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Charles He2bf28322017-10-12 22:24:49 +0100385 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
386 boolean userSetupComplete, int minWidth, int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700387 mService = service;
388 taskId = _taskId;
389 intent = _intent;
390 affinityIntent = _affinityIntent;
391 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800392 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700393 voiceSession = null;
394 voiceInteractor = null;
395 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800396 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700397 origActivity = _origActivity;
398 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700399 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700400 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700401 askedCompatMode = _askedCompatMode;
Craig Mautner21d24a22014-04-23 11:45:37 -0700402 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800403 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700404 effectiveUid = _effectiveUid;
Winson Chungfb44d212017-10-04 11:39:10 -0700405 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautner21d24a22014-04-23 11:45:37 -0700406 lastDescription = _lastDescription;
407 mActivities = activities;
408 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700409 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700410 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700411 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700412 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700413 mPrevAffiliateTaskId = prevTaskId;
414 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700415 mCallingUid = callingUid;
416 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800417 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800418 mSupportsPictureInPicture = supportsPictureInPicture;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700419 mMinWidth = minWidth;
420 mMinHeight = minHeight;
Yorke Leebd54c2a2016-10-25 13:49:23 -0700421 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 }
423
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800424 TaskWindowContainerController getWindowContainerController() {
425 return mWindowContainerController;
426 }
427
428 void createWindowContainer(boolean onTop, boolean showForAllUsers) {
429 if (mWindowContainerController != null) {
430 throw new IllegalArgumentException("Window container=" + mWindowContainerController
431 + " already created for task=" + this);
432 }
433
434 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
Bryce Lee04ab3462017-04-10 15:06:33 -0700435 setWindowContainerController(new TaskWindowContainerController(taskId, this,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700436 getStack().getWindowContainerController(), userId, bounds,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700437 mResizeMode, mSupportsPictureInPicture, onTop,
438 showForAllUsers, lastTaskDescription));
Bryce Lee04ab3462017-04-10 15:06:33 -0700439 }
440
441 /**
442 * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
443 */
444 @VisibleForTesting
445 protected void setWindowContainerController(TaskWindowContainerController controller) {
446 if (mWindowContainerController != null) {
447 throw new IllegalArgumentException("Window container=" + mWindowContainerController
448 + " already created for task=" + this);
449 }
450
451 mWindowContainerController = controller;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800452 }
453
454 void removeWindowContainer() {
Bryce Lee2b8e0372018-04-05 17:01:37 -0700455 mService.getLockTaskController().clearLockedTask(this);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800456 mWindowContainerController.removeContainer();
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700457 if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800458 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
459 // default configuration the next time it launches.
460 updateOverrideConfiguration(null);
461 }
462 mService.mTaskChangeNotificationController.notifyTaskRemoved(taskId);
463 mWindowContainerController = null;
464 }
465
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100466 @Override
467 public void onSnapshotChanged(TaskSnapshot snapshot) {
468 mService.mTaskChangeNotificationController.notifyTaskSnapshotChanged(taskId, snapshot);
469 }
470
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800471 void setResizeMode(int resizeMode) {
472 if (mResizeMode == resizeMode) {
473 return;
474 }
475 mResizeMode = resizeMode;
476 mWindowContainerController.setResizeable(resizeMode);
477 mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
478 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
479 }
480
481 void setTaskDockedResizing(boolean resizing) {
482 mWindowContainerController.setTaskDockedResizing(resizing);
483 }
484
Wale Ogunwale1666e312016-12-16 11:27:18 -0800485 // TODO: Consolidate this with the resize() method below.
486 @Override
487 public void requestResize(Rect bounds, int resizeMode) {
488 mService.resizeTask(taskId, bounds, resizeMode);
489 }
490
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800491 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800492 mService.mWindowManager.deferSurfaceLayout();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800493
Bryce Leef3c6a472017-11-14 14:53:06 -0800494 try {
495 if (!isResizeable()) {
496 Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
497 return true;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800498 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800499
Bryce Leef3c6a472017-11-14 14:53:06 -0800500 // If this is a forced resize, let it go through even if the bounds is not changing,
501 // as we might need a relayout due to surface size change (to/from fullscreen).
502 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
503 if (equivalentOverrideBounds(bounds) && !forced) {
504 // Nothing to do here...
505 return true;
506 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800507
Bryce Leef3c6a472017-11-14 14:53:06 -0800508 if (mWindowContainerController == null) {
509 // Task doesn't exist in window manager yet (e.g. was restored from recents).
510 // All we can do for now is update the bounds so it can be used when the task is
511 // added to window manager.
512 updateOverrideConfiguration(bounds);
513 if (!inFreeformWindowingMode()) {
514 // re-restore the task so it can have the proper stack association.
515 mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
516 }
517 return true;
518 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800519
Bryce Leef3c6a472017-11-14 14:53:06 -0800520 if (!canResizeToBounds(bounds)) {
521 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
522 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
523 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800524
Bryce Leef3c6a472017-11-14 14:53:06 -0800525 // Do not move the task to another stack here.
526 // This method assumes that the task is already placed in the right stack.
527 // we do not mess with that decision and we only do the resize!
528
529 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
530
531 final boolean updatedConfig = updateOverrideConfiguration(bounds);
532 // This variable holds information whether the configuration didn't change in a significant
533
534 // way and the activity was kept the way it was. If it's false, it means the activity
535 // had
536 // to be relaunched due to configuration change.
537 boolean kept = true;
538 if (updatedConfig) {
539 final ActivityRecord r = topRunningActivityLocked();
540 if (r != null && !deferResume) {
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800541 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800542 preserveWindow);
543 mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0,
544 !PRESERVE_WINDOWS);
545 if (!kept) {
546 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
547 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800548 }
549 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800550 mWindowContainerController.resize(kept, forced);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800551
Bryce Leef3c6a472017-11-14 14:53:06 -0800552 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
553 return kept;
554 } finally {
555 mService.mWindowManager.continueSurfaceLayout();
556 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800557 }
558
559 // TODO: Investigate combining with the resize() method above.
560 void resizeWindowContainer() {
Bryce Leef3c6a472017-11-14 14:53:06 -0800561 mWindowContainerController.resize(false /* relayout */, false /* forced */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800562 }
563
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800564 void getWindowContainerBounds(Rect bounds) {
565 mWindowContainerController.getBounds(bounds);
566 }
567
Winson Chung74666102017-02-22 17:49:24 -0800568 /**
569 * Convenience method to reparent a task to the top or bottom position of the stack.
570 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700571 boolean reparent(ActivityStack preferredStack, boolean toTop,
572 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
573 String reason) {
574 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
575 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung5af42fc2017-03-24 17:11:33 -0700576 }
577
578 /**
579 * Convenience method to reparent a task to the top or bottom position of the stack, with
580 * an option to skip scheduling the picture-in-picture mode change.
581 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700582 boolean reparent(ActivityStack preferredStack, boolean toTop,
583 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
584 boolean schedulePictureInPictureModeChange, String reason) {
585 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700586 deferResume, schedulePictureInPictureModeChange, reason);
587 }
588
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700589 /** Convenience method to reparent a task to a specific position of the stack. */
590 boolean reparent(ActivityStack preferredStack, int position,
591 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
592 String reason) {
593 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
Winson Chung5af42fc2017-03-24 17:11:33 -0700594 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800595 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800596
Winson Chung74666102017-02-22 17:49:24 -0800597 /**
598 * Reparents the task into a preferred stack, creating it if necessary.
599 *
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700600 * @param preferredStack the target stack to move this task
Winson Chung74666102017-02-22 17:49:24 -0800601 * @param position the position to place this task in the new stack
602 * @param animate whether or not we should wait for the new window created as a part of the
Winson Chung5af42fc2017-03-24 17:11:33 -0700603 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800604 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700605 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800606 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700607 * have changed as a result of this reparenting
608 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
609 * change. Callers may set this to false if they are explicitly scheduling PiP mode
610 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800611 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700612 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800613 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700614 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700615 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700616 boolean reparent(ActivityStack preferredStack, int position,
617 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
618 boolean schedulePictureInPictureModeChange, String reason) {
Winson Chung74666102017-02-22 17:49:24 -0800619 final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
620 final WindowManagerService windowManager = mService.mWindowManager;
621 final ActivityStack sourceStack = getStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700622 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
Winson Chung74666102017-02-22 17:49:24 -0800623 position == MAX_VALUE);
624 if (toStack == sourceStack) {
625 return false;
626 }
Andrii Kulianb850ea52017-12-12 23:49:10 -0800627 if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
628 return false;
629 }
Winson Chung74666102017-02-22 17:49:24 -0800630
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700631 final int toStackWindowingMode = toStack.getWindowingMode();
Winson Chung74666102017-02-22 17:49:24 -0800632 final ActivityRecord topActivity = getTopActivity();
633
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800634 final boolean mightReplaceWindow = topActivity != null
635 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
Winson Chung74666102017-02-22 17:49:24 -0800636 if (mightReplaceWindow) {
637 // We are about to relaunch the activity because its configuration changed due to
638 // being maximized, i.e. size change. The activity will first remove the old window
639 // and then add a new one. This call will tell window manager about this, so it can
640 // preserve the old window until the new one is drawn. This prevents having a gap
641 // between the removal and addition, in which no window is visible. We also want the
642 // entrance of the new window to be properly animated.
643 // Note here we always set the replacing window first, as the flags might be needed
644 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
645 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
646 }
647
648 windowManager.deferSurfaceLayout();
649 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800650 try {
Winson Chung74666102017-02-22 17:49:24 -0800651 final ActivityRecord r = topRunningActivityLocked();
Winson Chung95f8f0e2017-03-24 09:20:17 -0700652 final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800653 && (topRunningActivityLocked() == r);
Bryce Leec4ab62a2018-03-05 14:19:26 -0800654 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
Winson Chung95f8f0e2017-03-24 09:20:17 -0700655 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800656
657 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
658 // Whenever we are moving the top activity from the front stack we want to make sure to
659 // move the stack to the front.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700660 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Winson Chung74666102017-02-22 17:49:24 -0800661 && (sourceStack.topRunningActivityLocked() == r);
662
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800663 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800664 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800665
666 // Must reparent first in window manager to avoid a situation where AM can delete the
667 // we are coming from in WM before we reparent because it became empty.
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700668 mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
669 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800670
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700671 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
672 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800673 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700674 sourceStack.removeTask(this, reason, moveStackToFront
675 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700676 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800677
Winson Chung5af42fc2017-03-24 17:11:33 -0700678 if (schedulePictureInPictureModeChange) {
679 // Notify of picture-in-picture mode changes
680 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
681 }
Winson Chung74666102017-02-22 17:49:24 -0800682
683 // TODO: Ensure that this is actually necessary here
684 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800685 if (voiceSession != null) {
686 try {
687 voiceSession.taskStarted(intent, taskId);
688 } catch (RemoteException e) {
689 }
690 }
Winson Chung74666102017-02-22 17:49:24 -0800691
692 // If the task had focus before (or we're requested to move focus), move focus to the
693 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700694 if (r != null) {
695 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
696 wasPaused, reason);
697 }
Winson Chung74666102017-02-22 17:49:24 -0800698 if (!animate) {
Jorim Jaggifa9ed962018-01-25 00:16:49 +0100699 mService.mStackSupervisor.mNoAnimActivities.add(topActivity);
Winson Chung74666102017-02-22 17:49:24 -0800700 }
701
702 // We might trigger a configuration change. Save the current task bounds for freezing.
703 // TODO: Should this call be moved inside the resize method in WM?
704 toStack.prepareFreezingTaskBounds();
705
706 // Make sure the task has the appropriate bounds/size for the stack it is in.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700707 final boolean toStackSplitScreenPrimary =
708 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Bryce Leef3c6a472017-11-14 14:53:06 -0800709 final Rect configBounds = getOverrideBounds();
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700710 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
711 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
Bryce Leef3c6a472017-11-14 14:53:06 -0800712 && !Objects.equals(configBounds, toStack.getOverrideBounds())) {
713 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800714 deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700715 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Winson Chung74666102017-02-22 17:49:24 -0800716 Rect bounds = getLaunchBounds();
717 if (bounds == null) {
Bryce Leeec55eb02017-12-05 20:51:27 -0800718 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800719 bounds = configBounds;
Winson Chung74666102017-02-22 17:49:24 -0800720 }
721 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700722 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
723 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
Matthew Ng330757d2017-02-28 14:19:17 -0800724 // Move recents to front so it is not behind home stack when going into docked
725 // mode
726 mService.mStackSupervisor.moveRecentsStackToFront(reason);
727 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800728 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800729 deferResume);
730 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800731 } finally {
Winson Chung74666102017-02-22 17:49:24 -0800732 windowManager.continueSurfaceLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800733 }
Winson Chung74666102017-02-22 17:49:24 -0800734
735 if (mightReplaceWindow) {
736 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
737 // window), we need to clear the replace window settings. Otherwise, we schedule a
738 // timeout to remove the old window if the replacing window is not coming in time.
739 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
740 }
741
742 if (!deferResume) {
743 // The task might have already been running and its visibility needs to be synchronized
744 // with the visibility of the stack / windows.
745 supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
746 supervisor.resumeFocusedStackTopActivityLocked();
747 }
748
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700749 // TODO: Handle incorrect request to move before the actual move, not after.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700750 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700751 DEFAULT_DISPLAY, toStack);
Winson Chung74666102017-02-22 17:49:24 -0800752
Winson Chungdff7a732017-12-11 12:17:06 -0800753 return (preferredStack == toStack);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800754 }
755
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700756 /**
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800757 * @return True if the windows of tasks being moved to the target stack from the source stack
758 * should be replaced, meaning that window manager will keep the old window around until the new
759 * is ready.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700760 */
761 private static boolean replaceWindowsOnTaskMove(
762 int sourceWindowingMode, int targetWindowingMode) {
763 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
764 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
765 }
766
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800767 void cancelWindowTransition() {
768 mWindowContainerController.cancelWindowTransition();
769 }
770
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100771 /**
772 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
773 */
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100774 TaskSnapshot getSnapshot(boolean reducedResolution) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100775
776 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
777 // synchronized between AM and WM.
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100778 return mService.mWindowManager.getTaskSnapshot(taskId, userId, reducedResolution);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800779 }
780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 void touchActiveTime() {
Winson Chungfb44d212017-10-04 11:39:10 -0700782 lastActiveTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 long getInactiveDuration() {
Winson Chungfb44d212017-10-04 11:39:10 -0700786 return SystemClock.elapsedRealtime() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700788
Winson Chungfee26772014-08-05 12:21:52 -0700789 /** Sets the original intent, and the calling uid and package. */
790 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700791 mCallingUid = r.launchedFromUid;
792 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700793 setIntent(r.intent, r.info);
Charles He2bf28322017-10-12 22:24:49 +0100794 setLockTaskAuth(r);
Winson Chungfee26772014-08-05 12:21:52 -0700795 }
796
797 /** Sets the original intent, _without_ updating the calling uid or package. */
798 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700799 if (intent == null) {
800 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700801 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700802 } else if (mNeverRelinquishIdentity) {
803 return;
804 }
805
806 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700807 if (intent == null) {
808 // If this task already has an intent associated with it, don't set the root
809 // affinity -- we don't want it changing after initially set, but the initially
810 // set value may be null.
811 rootAffinity = affinity;
812 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700813 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700814 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800817 if (_intent != null) {
818 // If this Intent has a selector, we want to clear it for the
819 // recent task since it is not relevant if the user later wants
820 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700821 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800822 _intent = new Intent(_intent);
823 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700824 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800825 }
826 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700827 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 intent = _intent;
829 realActivity = _intent != null ? _intent.getComponent() : null;
830 origActivity = null;
831 } else {
832 ComponentName targetComponent = new ComponentName(
833 info.packageName, info.targetActivity);
834 if (_intent != null) {
835 Intent targetIntent = new Intent(_intent);
836 targetIntent.setComponent(targetComponent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800837 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700838 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700839 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700840 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 intent = targetIntent;
842 realActivity = targetComponent;
843 origActivity = _intent.getComponent();
844 } else {
845 intent = null;
846 realActivity = targetComponent;
847 origActivity = new ComponentName(info.packageName, info.name);
848 }
849 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700850
Craig Mautner47b20ba2014-09-17 17:23:44 -0700851 final int intentFlags = intent == null ? 0 : intent.getFlags();
852 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 // Once we are set to an Intent with this flag, we count this
854 // task as having a true root activity.
855 rootWasReset = true;
856 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700857 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000858 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
859 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700860 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700861 // If the activity itself has requested auto-remove, then just always do it.
862 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700863 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
864 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700865 // If the caller has not asked for the document to be retained, then we may
866 // want to turn on auto-remove, depending on whether the target has set its
867 // own document launch mode.
868 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
869 autoRemoveRecents = false;
870 } else {
871 autoRemoveRecents = true;
872 }
873 } else {
874 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700875 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800876 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800877 mSupportsPictureInPicture = info.supportsPictureInPicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800879
Andrii Kulian2e751b82016-03-16 16:59:32 -0700880 /** Sets the original minimal width and height. */
881 private void setMinDimensions(ActivityInfo info) {
882 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700883 mMinWidth = info.windowLayout.minWidth;
884 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700885 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700886 mMinWidth = INVALID_MIN_SIZE;
887 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700888 }
889 }
890
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800891 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700892 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800893 * record is based on (normally the root activity intent).
894 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700895 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800896 final Intent intent = new Intent(r.intent);
897 // Correct the activity intent for aliasing. The task record intent will always be based on
898 // the real activity that will be launched not the alias, so we need to use an intent with
899 // the component name pointing to the real activity not the alias in the activity record.
900 intent.setComponent(r.realActivity);
Bryce Lee1a990e52018-04-23 10:54:11 -0700901 return intent.filterEquals(this.intent);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800902 }
903
Wale Ogunwale66e16852017-10-19 13:35:52 -0700904 boolean returnsToHomeStack() {
905 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
Bryce Lee1a990e52018-04-23 10:54:11 -0700906 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700907 }
908
Craig Mautnera228ae92014-07-09 05:44:55 -0700909 void setPrevAffiliate(TaskRecord prevAffiliate) {
910 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800911 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700912 }
913
914 void setNextAffiliate(TaskRecord nextAffiliate) {
915 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800916 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700917 }
918
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700919 <T extends ActivityStack> T getStack() {
920 return (T) mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700921 }
922
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800923 /**
924 * Must be used for setting parent stack because it performs configuration updates.
925 * Must be called after adding task as a child to the stack.
926 */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700927 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800928 if (stack != null && !stack.isInStackLocked(this)) {
929 throw new IllegalStateException("Task must be added as a Stack child first.");
930 }
Bryce Lee84730a02018-04-03 14:10:04 -0700931 final ActivityStack oldStack = mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700932 mStack = stack;
Bryce Lee84730a02018-04-03 14:10:04 -0700933
934 // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
935 // {@link ActivityRecord} from its current {@link ActivityStack}.
936
937 if (oldStack != mStack) {
938 for (int i = getChildCount() - 1; i >= 0; --i) {
939 final ActivityRecord activity = getChildAt(i);
940
941 if (oldStack != null) {
942 oldStack.onActivityRemovedFromStack(activity);
943 }
944
945 if (mStack != null) {
946 stack.onActivityAddedToStack(activity);
947 }
948 }
949 }
950
Andrii Kulian1779e612016-10-12 21:58:25 -0700951 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700952 }
953
954 /**
955 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
956 */
957 int getStackId() {
958 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
959 }
960
Andrii Kulian1779e612016-10-12 21:58:25 -0700961 @Override
962 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700963 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -0700964 }
965
966 @Override
chaviw82a0ba82018-03-15 14:26:29 -0700967 protected ActivityRecord getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700968 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -0700969 }
970
971 @Override
972 protected ConfigurationContainer getParent() {
973 return mStack;
974 }
975
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800976 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -0700977 protected void onParentChanged() {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800978 super.onParentChanged();
979 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
980 }
981
Craig Mautnera228ae92014-07-09 05:44:55 -0700982 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700983 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -0700984 if (mPrevAffiliate != null) {
985 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
986 }
987 if (mNextAffiliate != null) {
988 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
989 }
990 setPrevAffiliate(null);
991 setNextAffiliate(null);
992 }
993
Winson Chung740c3ac2014-11-12 16:14:38 -0800994 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -0700995 closeRecentsChain();
996 if (inRecents) {
997 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -0800998 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700999 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001000
Dianne Hackborn68a06332017-11-15 17:54:18 -08001001 clearRootProcess();
1002
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001003 // TODO: Use window container controller once tasks are better synced between AM and WM
1004 mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001005 }
1006
Craig Mautnera228ae92014-07-09 05:44:55 -07001007 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1008 closeRecentsChain();
1009 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -07001010 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -07001011 // Find the end
1012 while (taskToAffiliateWith.mNextAffiliate != null) {
1013 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
1014 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1015 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1016 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1017 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1018 nextRecents.setPrevAffiliate(null);
1019 }
1020 taskToAffiliateWith.setNextAffiliate(null);
1021 break;
1022 }
1023 taskToAffiliateWith = nextRecents;
1024 }
1025 taskToAffiliateWith.setNextAffiliate(this);
1026 setPrevAffiliate(taskToAffiliateWith);
1027 setNextAffiliate(null);
1028 }
1029
Winson Chung1147c402014-05-14 11:05:00 -07001030 /** Returns the intent for the root activity for this task */
1031 Intent getBaseIntent() {
1032 return intent != null ? intent : affinityIntent;
1033 }
1034
Winson Chung3b3f4642014-04-22 10:08:18 -07001035 /** Returns the first non-finishing activity from the root. */
1036 ActivityRecord getRootActivity() {
1037 for (int i = 0; i < mActivities.size(); i++) {
1038 final ActivityRecord r = mActivities.get(i);
1039 if (r.finishing) {
1040 continue;
1041 }
1042 return r;
1043 }
1044 return null;
1045 }
1046
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001047 ActivityRecord getTopActivity() {
Bryce Lee9f6affd2017-09-01 09:18:35 -07001048 return getTopActivity(true /* includeOverlays */);
1049 }
1050
1051 ActivityRecord getTopActivity(boolean includeOverlays) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001052 for (int i = mActivities.size() - 1; i >= 0; --i) {
1053 final ActivityRecord r = mActivities.get(i);
Bryce Lee9f6affd2017-09-01 09:18:35 -07001054 if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001055 continue;
1056 }
1057 return r;
1058 }
1059 return null;
1060 }
1061
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001062 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001063 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001064 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1065 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001066 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001067 return r;
1068 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001069 }
1070 }
1071 return null;
1072 }
1073
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001074 boolean isVisible() {
1075 for (int i = mActivities.size() - 1; i >= 0; --i) {
1076 final ActivityRecord r = mActivities.get(i);
1077 if (r.visible) {
1078 return true;
1079 }
1080 }
1081 return false;
1082 }
1083
Jorim Jaggiea039a82017-08-02 14:37:49 +02001084 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1085 if (mStack != null) {
1086 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1087 ActivityRecord r = mActivities.get(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001088 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001089 outActivities.add(r);
1090 }
1091 }
1092 }
1093 }
1094
Wale Ogunwale3b232392016-05-13 15:37:13 -07001095 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001096 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001097 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1098 ActivityRecord r = mActivities.get(activityNdx);
1099 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001100 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001101 continue;
1102 }
1103 return r;
1104 }
1105 }
1106 return null;
1107 }
1108
Winson Chung61c9e5a2017-10-11 10:39:32 -07001109 /**
1110 * Return the number of running activities, and the number of non-finishing/initializing
1111 * activities in the provided {@param reportOut} respectively.
1112 */
1113 void getNumRunningActivities(TaskActivitiesReport reportOut) {
1114 reportOut.reset();
1115 for (int i = mActivities.size() - 1; i >= 0; --i) {
1116 final ActivityRecord r = mActivities.get(i);
1117 if (r.finishing) {
1118 continue;
1119 }
1120
1121 reportOut.base = r;
1122
1123 // Increment the total number of non-finishing activities
1124 reportOut.numActivities++;
1125
Bryce Lee7ace3952018-02-16 14:34:32 -08001126 if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001127 reportOut.top = r;
1128 // Reset the number of running activities until we hit the first non-initializing
1129 // activity
1130 reportOut.numRunning = 0;
1131 }
1132 if (r.app != null && r.app.thread != null) {
1133 // Increment the number of actually running activities
1134 reportOut.numRunning++;
1135 }
1136 }
1137 }
1138
Chong Zhang87761972016-08-22 13:53:24 -07001139 boolean okToShowLocked() {
1140 // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
1141 // okay to show the activity when locked.
1142 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
1143 || topRunningActivityLocked() != null;
1144 }
1145
Craig Mautner3b475fe2013-12-16 15:58:31 -08001146 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Bryce Leed71317c2017-02-07 14:27:22 -08001147 final void setFrontOfTask() {
1148 boolean foundFront = false;
Craig Mautner3b475fe2013-12-16 15:58:31 -08001149 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -08001150 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -08001151 final ActivityRecord r = mActivities.get(activityNdx);
1152 if (foundFront || r.finishing) {
1153 r.frontOfTask = false;
1154 } else {
1155 r.frontOfTask = true;
1156 // Set frontOfTask false for every following activity.
1157 foundFront = true;
1158 }
1159 }
Craig Mautner9587ee02014-06-23 15:00:10 +00001160 if (!foundFront && numActivities > 0) {
1161 // All activities of this task are finishing. As we ought to have a frontOfTask
1162 // activity, make the bottom activity front.
1163 mActivities.get(0).frontOfTask = true;
1164 }
Craig Mautner3b475fe2013-12-16 15:58:31 -08001165 }
1166
Craig Mautnerde4ef022013-04-07 19:01:33 -07001167 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001168 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001169 */
1170 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001171 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1172 "Removing and adding activity " + newTop
1173 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001174
Craig Mautnerde4ef022013-04-07 19:01:33 -07001175 mActivities.remove(newTop);
1176 mActivities.add(newTop);
Bryce Leed58d7b32017-09-08 15:55:22 -07001177
1178 // Make sure window manager is aware of the position change.
1179 mWindowContainerController.positionChildAtTop(newTop.mWindowContainerController);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001180 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -08001181
Bryce Leed71317c2017-02-07 14:27:22 -08001182 setFrontOfTask();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001183 }
1184
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001185 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -08001186 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001187 }
1188
1189 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001190 addActivityAtIndex(mActivities.size(), r);
1191 }
1192
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001193 @Override
Wale Ogunwaleeea34ee92017-08-31 20:07:45 -07001194 /*@WindowConfiguration.ActivityType*/
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001195 public int getActivityType() {
1196 final int applicationType = super.getActivityType();
1197 if (applicationType != ACTIVITY_TYPE_UNDEFINED || mActivities.isEmpty()) {
1198 return applicationType;
1199 }
1200 return mActivities.get(0).getActivityType();
1201 }
1202
Winson Chung30480042017-01-26 10:55:34 -08001203 /**
1204 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1205 * be in the current task or unparented to any task.
1206 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001207 void addActivityAtIndex(int index, ActivityRecord r) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001208 TaskRecord task = r.getTask();
1209 if (task != null && task != this) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001210 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
Bryce Leeaf691c02017-03-20 14:20:22 -07001211 + " current parent=" + task);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001212 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001213
1214 r.setTask(this);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001215
Craig Mautner6170f732013-04-02 13:05:23 -07001216 // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001217 if (!mActivities.remove(r) && r.fullscreen) {
1218 // Was not previously in list.
1219 numFullscreen++;
1220 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001221 // Only set this based on the first activity
1222 if (mActivities.isEmpty()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001223 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1224 // Normally non-standard activity type for the activity record will be set when the
1225 // object is created, however we delay setting the standard application type until
1226 // this point so that the task can set the type for additional activities added in
1227 // the else condition below.
1228 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1229 }
1230 setActivityType(r.getActivityType());
Craig Mautner21d24a22014-04-23 11:45:37 -07001231 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001232 mCallingUid = r.launchedFromUid;
1233 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001234 // Clamp to [1, max].
1235 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1236 ActivityManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001237 } else {
1238 // Otherwise make all added activities match this one.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001239 r.setActivityType(getActivityType());
Craig Mautner78733002013-06-10 13:54:49 -07001240 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001241
1242 final int size = mActivities.size();
1243
1244 if (index == size && size > 0) {
1245 final ActivityRecord top = mActivities.get(size - 1);
1246 if (top.mTaskOverlay) {
1247 // Place below the task overlay activity since the overlay activity should always
1248 // be on top.
1249 index--;
1250 }
1251 }
1252
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001253 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001254 mActivities.add(index, r);
Bryce Lee84730a02018-04-03 14:10:04 -07001255
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001256 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001257 if (r.isPersistable()) {
1258 mService.notifyTaskPersisterLocked(this, false);
1259 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001260
1261 // Sync. with window manager
1262 updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001263 final AppWindowContainerController appController = r.getWindowContainerController();
1264 if (appController != null) {
1265 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1266 // created controller for the activity we are starting yet.
1267 mWindowContainerController.positionChildAt(appController, index);
1268 }
David Stevens82ea6cb2017-03-03 16:18:50 -08001269
1270 // Make sure the list of display UID whitelists is updated
1271 // now that this record is in a new task.
1272 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001273 }
1274
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001275 /**
Bryce Leeaf691c02017-03-20 14:20:22 -07001276 * Removes the specified activity from this task.
1277 * @param r The {@link ActivityRecord} to remove.
1278 * @return true if this was the last activity in the task.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001279 */
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001280 boolean removeActivity(ActivityRecord r) {
Bryce Lee84730a02018-04-03 14:10:04 -07001281 return removeActivity(r, false /* reparenting */);
Bryce Leeaf691c02017-03-20 14:20:22 -07001282 }
1283
1284 boolean removeActivity(ActivityRecord r, boolean reparenting) {
1285 if (r.getTask() != this) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001286 throw new IllegalArgumentException(
1287 "Activity=" + r + " does not belong to task=" + this);
1288 }
1289
Bryce Lee84730a02018-04-03 14:10:04 -07001290 r.setTask(null /* task */, reparenting /* reparenting */);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001291
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001292 if (mActivities.remove(r) && r.fullscreen) {
1293 // Was previously in list.
1294 numFullscreen--;
1295 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001296 if (r.isPersistable()) {
1297 mService.notifyTaskPersisterLocked(this, false);
1298 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001299
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001300 if (inPinnedWindowingMode()) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001301 // We normally notify listeners of task stack changes on pause, however pinned stack
1302 // activities are normally in the paused state so no notification will be sent there
1303 // before the activity is removed. We send it here so instead.
Yorke Leebd54c2a2016-10-25 13:49:23 -07001304 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001305 }
1306
Craig Mautner41326202014-06-20 14:38:21 -07001307 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001308 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001309 }
1310 updateEffectiveIntent();
1311 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001312 }
1313
Winson Chung6954fc92017-03-24 16:22:12 -07001314 /**
1315 * @return whether or not there are ONLY task overlay activities in the stack.
1316 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1317 * If there are no task overlay activities, this call returns false.
1318 */
1319 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1320 int count = 0;
1321 for (int i = mActivities.size() - 1; i >= 0; i--) {
1322 final ActivityRecord r = mActivities.get(i);
1323 if (excludeFinishing && r.finishing) {
1324 continue;
1325 }
1326 if (!r.mTaskOverlay) {
1327 return false;
1328 }
1329 count++;
1330 }
1331 return count > 0;
1332 }
1333
Craig Mautner41db4a72014-05-07 17:20:56 -07001334 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001335 // We will automatically remove the task either if it has explicitly asked for
1336 // this, or it is empty and has never contained an activity that got shown to
1337 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -07001338 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001339 }
1340
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001341 /**
1342 * Completely remove all activities associated with an existing
1343 * task starting at a specified index.
1344 */
Winson Chung0ec2a352017-10-26 11:38:30 -07001345 final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately,
1346 String reason) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001347 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001348 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001349 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001350 if (r.finishing) {
1351 continue;
1352 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001353 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001354 // Task was restored from persistent storage.
1355 r.takeFromHistory();
1356 mActivities.remove(activityNdx);
1357 --activityNdx;
1358 --numActivities;
Winson Chung6954fc92017-03-24 16:22:12 -07001359 } else if (mStack.finishActivityLocked(r, Activity.RESULT_CANCELED, null,
Winson Chung0ec2a352017-10-26 11:38:30 -07001360 reason, false, pauseImmediately)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001361 --activityNdx;
1362 --numActivities;
1363 }
1364 }
1365 }
1366
1367 /**
1368 * Completely remove all activities associated with an existing task.
1369 */
Benjamin Franza83859f2017-07-03 16:34:14 +01001370 void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001371 mReuseTask = true;
Winson Chung0ec2a352017-10-26 11:38:30 -07001372 performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY, "clear-task-all");
Craig Mautner362449a2014-06-20 14:04:39 -07001373 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001374 }
1375
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001376 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1377 mReuseTask = true;
1378 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1379 mReuseTask = false;
1380 return result;
1381 }
1382
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001383 /**
1384 * Perform clear operation as requested by
1385 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1386 * stack to the given task, then look for
1387 * an instance of that activity in the stack and, if found, finish all
1388 * activities on top of it and return the instance.
1389 *
1390 * @param newR Description of the new activity being started.
1391 * @return Returns the old activity that should be continued to be used,
1392 * or null if none was found.
1393 */
1394 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001395 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001396 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001397 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001398 if (r.finishing) {
1399 continue;
1400 }
1401 if (r.realActivity.equals(newR.realActivity)) {
1402 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001403 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001404
1405 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001406 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001407 if (r.finishing) {
1408 continue;
1409 }
1410 ActivityOptions opts = r.takeOptionsLocked();
1411 if (opts != null) {
1412 ret.updateOptionsLocked(opts);
1413 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001414 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001415 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001416 --activityNdx;
1417 --numActivities;
1418 }
1419 }
1420
1421 // Finally, if this is a normal launch mode (that is, not
1422 // expecting onNewIntent()), then we will finish the current
1423 // instance of the activity so a new fresh one can be started.
1424 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001425 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1426 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001427 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001428 if (mStack != null) {
1429 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -07001430 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1431 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001432 return null;
1433 }
1434 }
1435
1436 return ret;
1437 }
1438 }
1439
1440 return null;
1441 }
1442
Winson Chung0ec2a352017-10-26 11:38:30 -07001443 void removeTaskActivitiesLocked(boolean pauseImmediately, String reason) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001444 // Just remove the entire task.
Winson Chung0ec2a352017-10-26 11:38:30 -07001445 performClearTaskAtIndexLocked(0, pauseImmediately, reason);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001446 }
1447
Craig Mautner432f64e2015-05-20 14:59:57 -07001448 String lockTaskAuthToString() {
1449 switch (mLockTaskAuth) {
1450 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1451 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1452 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1453 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001454 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001455 default: return "unknown=" + mLockTaskAuth;
1456 }
1457 }
1458
Craig Mautner15df08a2015-04-01 12:17:18 -07001459 void setLockTaskAuth() {
Charles He2bf28322017-10-12 22:24:49 +01001460 setLockTaskAuth(getRootActivity());
1461 }
1462
1463 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1464 if (r == null) {
1465 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1466 return;
1467 }
1468
Charles He520b2832017-09-02 15:27:16 +01001469 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
Bryce Lee2b8e0372018-04-05 17:01:37 -07001470 final LockTaskController lockTaskController = mService.getLockTaskController();
Charles He2bf28322017-10-12 22:24:49 +01001471 switch (r.lockTaskLaunchMode) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001472 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
Bryce Lee2b8e0372018-04-05 17:01:37 -07001473 mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001474 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001475 break;
1476
1477 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001478 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001479 break;
1480
1481 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001482 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001483 break;
1484
1485 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
Bryce Lee2b8e0372018-04-05 17:01:37 -07001486 mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001487 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001488 break;
1489 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001490 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1491 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001492 }
1493
Winson Chungd3395382016-12-13 11:49:09 -08001494 private boolean isResizeable(boolean checkSupportsPip) {
1495 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001496 || (checkSupportsPip && mSupportsPictureInPicture));
Winson Chungd3395382016-12-13 11:49:09 -08001497 }
1498
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001499 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001500 return isResizeable(true /* checkSupportsPip */);
1501 }
1502
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001503 @Override
1504 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08001505 // A task can not be docked even if it is considered resizeable because it only supports
1506 // picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001507 return super.supportsSplitScreenWindowingMode()
1508 && mService.mSupportsSplitScreenMultiWindow
Bryce Leec857a5b2017-08-16 10:04:52 -07001509 && (mService.mForceResizableActivities
1510 || (isResizeable(false /* checkSupportsPip */)
1511 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001512 }
1513
skuhne@google.com322347b2016-12-02 12:54:03 -08001514 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001515 * Check whether this task can be launched on the specified display.
1516 * @param displayId Target display id.
1517 * @return {@code true} if either it is the default display or this activity is resizeable and
1518 * can be put a secondary screen.
1519 */
1520 boolean canBeLaunchedOnDisplay(int displayId) {
1521 return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Andrii Kulian02689a72017-07-06 14:28:59 -07001522 isResizeable(false /* checkSupportsPip */), -1 /* don't check PID */,
1523 -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001524 }
1525
1526 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001527 * Check that a given bounds matches the application requested orientation.
1528 *
1529 * @param bounds The bounds to be tested.
1530 * @return True if the requested bounds are okay for a resizing request.
1531 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001532 private boolean canResizeToBounds(Rect bounds) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001533 if (bounds == null || !inFreeformWindowingMode()) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001534 // Note: If not on the freeform workspace, we ignore the bounds.
1535 return true;
1536 }
1537 final boolean landscape = bounds.width() > bounds.height();
Bryce Leef3c6a472017-11-14 14:53:06 -08001538 final Rect configBounds = getOverrideBounds();
skuhne@google.com322347b2016-12-02 12:54:03 -08001539 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001540 return configBounds.isEmpty()
1541 || landscape == (configBounds.width() > configBounds.height());
skuhne@google.com322347b2016-12-02 12:54:03 -08001542 }
1543 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1544 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1545 }
1546
Craig Mautner525f3d92013-05-07 14:01:50 -07001547 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001548 * @return {@code true} if the task is being cleared for the purposes of being reused.
1549 */
1550 boolean isClearingToReuseTask() {
1551 return mReuseTask;
1552 }
1553
1554 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001555 * Find the activity in the history stack within the given task. Returns
1556 * the index within the history at which it's found, or < 0 if not found.
1557 */
1558 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
1559 final ComponentName realActivity = r.realActivity;
1560 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1561 ActivityRecord candidate = mActivities.get(activityNdx);
1562 if (candidate.finishing) {
1563 continue;
1564 }
1565 if (candidate.realActivity.equals(realActivity)) {
1566 return candidate;
1567 }
1568 }
1569 return null;
1570 }
1571
Winson Chunga449dc02014-05-16 11:15:04 -07001572 /** Updates the last task description values. */
1573 void updateTaskDescription() {
1574 // Traverse upwards looking for any break between main task activities and
1575 // utility activities.
1576 int activityNdx;
1577 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001578 final boolean relinquish = numActivities != 0 &&
1579 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001580 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001581 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001582 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001583 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001584 // This will be the top activity for determining taskDescription. Pre-inc to
1585 // overcome initial decrement below.
1586 ++activityNdx;
1587 break;
1588 }
Winson Chunga449dc02014-05-16 11:15:04 -07001589 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001590 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001591 break;
1592 }
1593 }
1594 if (activityNdx > 0) {
1595 // Traverse downwards starting below break looking for set label, icon.
1596 // Note that if there are activities in the task but none of them set the
1597 // recent activity values, then we do not fall back to the last set
1598 // values in the TaskRecord.
1599 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001600 String iconFilename = null;
Matthew Ng54bc9422017-10-02 17:16:28 -07001601 int iconResource = -1;
Winson Chunga449dc02014-05-16 11:15:04 -07001602 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001603 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001604 int statusBarColor = 0;
1605 int navigationBarColor = 0;
1606 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001607 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1608 final ActivityRecord r = mActivities.get(activityNdx);
Winson Chung80f80db2018-05-30 21:13:25 -07001609 if (r.mTaskOverlay) {
1610 continue;
1611 }
Winson Chunga449dc02014-05-16 11:15:04 -07001612 if (r.taskDescription != null) {
1613 if (label == null) {
1614 label = r.taskDescription.getLabel();
1615 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001616 if (iconResource == -1) {
1617 iconResource = r.taskDescription.getIconResource();
1618 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001619 if (iconFilename == null) {
1620 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001621 }
1622 if (colorPrimary == 0) {
1623 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001624 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001625 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001626 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001627 statusBarColor = r.taskDescription.getStatusBarColor();
1628 navigationBarColor = r.taskDescription.getNavigationBarColor();
Winson Chung1af8eda2016-02-05 17:55:56 +00001629 }
Winson Chunga449dc02014-05-16 11:15:04 -07001630 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001631 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001632 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001633 lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
1634 colorPrimary, colorBackground, statusBarColor, navigationBarColor);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001635 if (mWindowContainerController != null) {
1636 mWindowContainerController.setTaskDescription(lastTaskDescription);
1637 }
Winson Chungec396d62014-08-06 17:08:00 -07001638 // Update the task affiliation color if we are the parent of the group
1639 if (taskId == mAffiliatedTaskId) {
1640 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1641 }
Winson Chunga449dc02014-05-16 11:15:04 -07001642 }
1643 }
1644
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001645 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001646 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001647 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001648 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001649 final ActivityRecord r = mActivities.get(activityNdx);
1650 if (r.finishing) {
1651 continue;
1652 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001653 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001654 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001655 break;
1656 }
1657 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001658 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001659 }
1660
1661 void updateEffectiveIntent() {
1662 final int effectiveRootIndex = findEffectiveRootIndex();
1663 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001664 setIntent(r);
Winson Chung8d9009e2017-11-16 15:43:05 -08001665
1666 // Update the task description when the activities change
1667 updateTaskDescription();
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001668 }
1669
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001670 private void adjustForMinimalTaskDimensions(Rect bounds) {
1671 if (bounds == null) {
1672 return;
1673 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001674 int minWidth = mMinWidth;
1675 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001676 // If the task has no requested minimal size, we'd like to enforce a minimal size
1677 // so that the user can not render the task too small to manipulate. We don't need
1678 // to do this for the pinned stack as the bounds are controlled by the system.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001679 if (!inPinnedWindowingMode()) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001680 if (minWidth == INVALID_MIN_SIZE) {
1681 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001682 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001683 if (minHeight == INVALID_MIN_SIZE) {
1684 minHeight = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001685 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001686 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001687 final boolean adjustWidth = minWidth > bounds.width();
1688 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001689 if (!(adjustWidth || adjustHeight)) {
1690 return;
1691 }
1692
Bryce Leef3c6a472017-11-14 14:53:06 -08001693 final Rect configBounds = getOverrideBounds();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001694 if (adjustWidth) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001695 if (!configBounds.isEmpty() && bounds.right == configBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001696 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001697 } else {
1698 // Either left bounds match, or neither match, or the previous bounds were
1699 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001700 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001701 }
1702 }
1703 if (adjustHeight) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001704 if (!configBounds.isEmpty() && bounds.bottom == configBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001705 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001706 } else {
1707 // Either top bounds match, or neither match, or the previous bounds were
1708 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001709 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001710 }
1711 }
1712 }
1713
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001714 /**
Winson Chung5af42fc2017-03-24 17:11:33 -07001715 * @return a new Configuration for this Task, given the provided {@param bounds} and
1716 * {@param insetBounds}.
1717 */
1718 Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
1719 // Compute a new override configuration for the given bounds, if fullscreen bounds
1720 // (bounds == null), then leave the override config unset
1721 final Configuration newOverrideConfig = new Configuration();
1722 if (bounds != null) {
1723 newOverrideConfig.setTo(getOverrideConfiguration());
1724 mTmpRect.set(bounds);
1725 adjustForMinimalTaskDimensions(mTmpRect);
1726 computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds,
1727 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
1728 }
1729
1730 return newOverrideConfig;
1731 }
1732
1733 /**
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001734 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001735 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07001736 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001737 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001738 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001739 return updateOverrideConfiguration(bounds, null /* insetBounds */);
1740 }
1741
1742 /**
1743 * Update task's override configuration based on the bounds.
1744 * @param bounds The bounds of the task.
1745 * @param insetBounds The bounds used to calculate the system insets, which is used here to
1746 * subtract the navigation bar/status bar size from the screen size reported
1747 * to the application. See {@link IActivityManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07001748 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001749 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001750 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001751 if (equivalentOverrideBounds(bounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07001752 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001753 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001754 final Rect currentBounds = getOverrideBounds();
1755
Andrii Kulian1779e612016-10-12 21:58:25 -07001756 mTmpConfig.setTo(getOverrideConfiguration());
Andrii Kulian1779e612016-10-12 21:58:25 -07001757 final Configuration newConfig = getOverrideConfiguration();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001758
Bryce Leef3c6a472017-11-14 14:53:06 -08001759 final boolean matchParentBounds = bounds == null || bounds.isEmpty();
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001760 final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -08001761 if (matchParentBounds) {
1762 if (!currentBounds.isEmpty() && persistBounds) {
1763 mLastNonFullscreenBounds = currentBounds;
Wale Ogunwale706ed792015-08-02 10:29:44 -07001764 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001765 setBounds(null);
Andrii Kulian1779e612016-10-12 21:58:25 -07001766 newConfig.unset();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001767 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001768 mTmpRect.set(bounds);
1769 adjustForMinimalTaskDimensions(mTmpRect);
Bryce Leef3c6a472017-11-14 14:53:06 -08001770 setBounds(mTmpRect);
1771
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001772 if (mStack == null || persistBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001773 mLastNonFullscreenBounds = getOverrideBounds();
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -07001774 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001775 computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
Andrii Kuliandaea3572016-04-08 13:20:51 -07001776 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001777 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001778 onOverrideConfigurationChanged(newConfig);
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001779 return !mTmpConfig.equals(newConfig);
1780 }
Wale Ogunwale5f986092015-12-04 15:35:38 -08001781
Bryce Leec4ab62a2018-03-05 14:19:26 -08001782 /**
1783 * This should be called when an child activity changes state. This should only
1784 * be called from
1785 * {@link ActivityRecord#setState(ActivityState, String)} .
1786 * @param record The {@link ActivityRecord} whose state has changed.
1787 * @param state The new state.
1788 * @param reason The reason for the change.
1789 */
1790 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
1791 final ActivityStack parent = getStack();
1792
1793 if (parent != null) {
1794 parent.onActivityStateChanged(record, state, reason);
1795 }
1796 }
1797
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001798 @Override
1799 public void onConfigurationChanged(Configuration newParentConfig) {
1800 final boolean wasInMultiWindowMode = inMultiWindowMode();
1801 super.onConfigurationChanged(newParentConfig);
1802 if (wasInMultiWindowMode != inMultiWindowMode()) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001803 mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001804 }
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001805 // TODO: Should also take care of Pip mode changes here.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001806 }
1807
Andrii Kulian1779e612016-10-12 21:58:25 -07001808 /** Clears passed config and fills it with new override values. */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001809 // TODO(b/36505427): TaskRecord.computeOverrideConfiguration() is a utility method that doesn't
1810 // depend on task or stacks, but uses those object to get the display to base the calculation
1811 // on. Probably best to centralize calculations like this in ConfigurationContainer.
1812 void computeOverrideConfiguration(Configuration config, Rect bounds, Rect insetBounds,
Andrii Kuliana8a9bc52016-10-14 11:00:13 -07001813 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001814 mTmpNonDecorBounds.set(bounds);
1815 mTmpStableBounds.set(bounds);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001816
Andrii Kulian1779e612016-10-12 21:58:25 -07001817 config.unset();
Winson Chungbdc646f2017-02-13 12:12:22 -08001818 final Configuration parentConfig = getParent().getConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -07001819
Andrii Kulian1779e612016-10-12 21:58:25 -07001820 final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001821
Winson Chungbdc646f2017-02-13 12:12:22 -08001822 if (mStack != null) {
1823 final StackWindowController stackController = mStack.getWindowContainerController();
1824 stackController.adjustConfigurationForBounds(bounds, insetBounds,
1825 mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
Evan Roskyb0e38882018-04-25 12:48:54 -07001826 config, parentConfig, getWindowingMode());
Winson Chungbdc646f2017-02-13 12:12:22 -08001827 } else {
Bryce Lee7566d762017-03-30 09:34:15 -07001828 throw new IllegalArgumentException("Expected stack when calculating override config");
Winson Chungbdc646f2017-02-13 12:12:22 -08001829 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001830
Winson Chung60c1aba2017-03-14 17:47:42 -07001831 config.orientation = (config.screenWidthDp <= config.screenHeightDp)
1832 ? Configuration.ORIENTATION_PORTRAIT
1833 : Configuration.ORIENTATION_LANDSCAPE;
1834
Jorim Jaggi85639432016-05-06 17:27:55 -07001835 // For calculating screen layout, we need to use the non-decor inset screen area for the
1836 // calculation for compatibility reasons, i.e. screen area without system bars that could
1837 // never go away in Honeycomb.
Winson Chungbdc646f2017-02-13 12:12:22 -08001838 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
1839 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Andrii Kulian1779e612016-10-12 21:58:25 -07001840 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
1841 // calculation with partial default.
1842 final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001843 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
Andrii Kulian1779e612016-10-12 21:58:25 -07001844 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
Jorim Jaggi85639432016-05-06 17:27:55 -07001845 config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001846 }
1847
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001848 Rect updateOverrideConfigurationFromLaunchBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08001849 final Rect bounds = getLaunchBounds();
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001850 updateOverrideConfiguration(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -08001851 if (bounds != null && !bounds.isEmpty()) {
1852 // TODO: Review if we actually want to do this - we are setting the launch bounds
1853 // directly here.
1854 bounds.set(getOverrideBounds());
Andrii Kulian73336d812016-03-24 12:56:08 -07001855 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001856 return bounds;
1857 }
1858
Wale Ogunwale935e5022015-11-10 12:36:10 -08001859 /** Updates the task's bounds and override configuration to match what is expected for the
1860 * input stack. */
1861 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001862 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001863 return;
1864 }
1865
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001866 if (inStack.inFreeformWindowingMode()) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001867 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001868 throw new IllegalArgumentException("Can not position non-resizeable task="
1869 + this + " in stack=" + inStack);
1870 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001871 if (!matchParentBounds()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001872 return;
1873 }
1874 if (mLastNonFullscreenBounds != null) {
1875 updateOverrideConfiguration(mLastNonFullscreenBounds);
1876 } else {
Bryce Leeec55eb02017-12-05 20:51:27 -08001877 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Wale Ogunwale935e5022015-11-10 12:36:10 -08001878 }
1879 } else {
Bryce Leef3c6a472017-11-14 14:53:06 -08001880 updateOverrideConfiguration(inStack.getOverrideBounds());
Wale Ogunwale935e5022015-11-10 12:36:10 -08001881 }
1882 }
1883
Wale Ogunwale706ed792015-08-02 10:29:44 -07001884 /** Returns the bounds that should be used to launch this task. */
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001885 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001886 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08001887 return null;
1888 }
1889
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001890 final int windowingMode = getWindowingMode();
1891 if (!isActivityTypeStandardOrUndefined()
1892 || windowingMode == WINDOWING_MODE_FULLSCREEN
1893 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001894 return isResizeable() ? mStack.getOverrideBounds() : null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001895 } else if (!getWindowConfiguration().persistTaskBounds()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001896 return mStack.getOverrideBounds();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001897 }
1898 return mLastNonFullscreenBounds;
1899 }
1900
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01001901 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
1902 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1903 final ActivityRecord r = mActivities.get(activityNdx);
1904 if (r.visible) {
1905 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
1906 }
1907 }
1908 }
1909
Dianne Hackborn68a06332017-11-15 17:54:18 -08001910 void setRootProcess(ProcessRecord proc) {
1911 clearRootProcess();
1912 if (intent != null &&
1913 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
1914 mRootProcess = proc;
1915 proc.recentTasks.add(this);
1916 }
1917 }
1918
1919 void clearRootProcess() {
1920 if (mRootProcess != null) {
1921 mRootProcess.recentTasks.remove(this);
1922 mRootProcess = null;
1923 }
1924 }
1925
chaviw82a0ba82018-03-15 14:26:29 -07001926 void clearAllPendingOptions() {
1927 for (int i = getChildCount() - 1; i >= 0; i--) {
1928 getChildAt(i).clearOptionsLocked(false /* withAbort */);
1929 }
1930 }
1931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001933 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001934 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
1935 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08001936 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001937 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07001938 if (affinity != null || rootAffinity != null) {
1939 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
1940 if (affinity == null || !affinity.equals(rootAffinity)) {
1941 pw.print(" root="); pw.println(rootAffinity);
1942 } else {
1943 pw.println();
1944 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001945 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07001946 if (voiceSession != null || voiceInteractor != null) {
1947 pw.print(prefix); pw.print("VOICE: session=0x");
1948 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
1949 pw.print(" interactor=0x");
1950 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
1951 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001952 if (intent != null) {
1953 StringBuilder sb = new StringBuilder(128);
1954 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001955 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001956 sb.append('}');
1957 pw.println(sb.toString());
1958 }
1959 if (affinityIntent != null) {
1960 StringBuilder sb = new StringBuilder(128);
1961 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001962 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001963 sb.append('}');
1964 pw.println(sb.toString());
1965 }
1966 if (origActivity != null) {
1967 pw.print(prefix); pw.print("origActivity=");
1968 pw.println(origActivity.flattenToShortString());
1969 }
1970 if (realActivity != null) {
1971 pw.print(prefix); pw.print("realActivity=");
1972 pw.println(realActivity.flattenToShortString());
1973 }
Wale Ogunwale66e16852017-10-19 13:35:52 -07001974 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001975 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001976 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001977 pw.print(" numFullscreen="); pw.print(numFullscreen);
Wale Ogunwale66e16852017-10-19 13:35:52 -07001978 pw.print(" activityType="); pw.println(getActivityType());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001979 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001980 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
1981 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001982 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
1983 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07001984 pw.print(" mReuseTask="); pw.print(mReuseTask);
1985 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001986 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08001987 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
1988 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
1989 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001990 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
1991 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
1992 pw.print(" (");
1993 if (mPrevAffiliate == null) {
1994 pw.print("null");
1995 } else {
1996 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
1997 }
1998 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
1999 pw.print(" (");
2000 if (mNextAffiliate == null) {
2001 pw.print("null");
2002 } else {
2003 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
2004 }
2005 pw.println(")");
2006 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002007 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002008 if (!askedCompatMode || !inRecents || !isAvailable) {
2009 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2010 pw.print(" inRecents="); pw.print(inRecents);
2011 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002012 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002013 if (lastDescription != null) {
2014 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2015 }
Dianne Hackborn68a06332017-11-15 17:54:18 -08002016 if (mRootProcess != null) {
2017 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
2018 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002019 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002020 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2021 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002022 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002023 pw.print(" isResizeable=" + isResizeable());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002024 pw.print(" lastActiveTime=" + lastActiveTime);
2025 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 }
2027
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002028 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002030 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002031 if (stringName != null) {
2032 sb.append(stringName);
2033 sb.append(" U=");
2034 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002035 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002036 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002037 sb.append(" sz=");
2038 sb.append(mActivities.size());
2039 sb.append('}');
2040 return sb.toString();
2041 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002042 sb.append("TaskRecord{");
2043 sb.append(Integer.toHexString(System.identityHashCode(this)));
2044 sb.append(" #");
2045 sb.append(taskId);
2046 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002047 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002048 sb.append(affinity);
2049 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002050 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002051 sb.append(intent.getComponent().flattenToShortString());
Bryce Leefbd263b42018-03-07 10:33:55 -08002052 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002053 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002054 sb.append(affinityIntent.getComponent().flattenToShortString());
2055 } else {
2056 sb.append(" ??");
2057 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002058 stringName = sb.toString();
2059 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 }
Steven Timotius4346f0a2017-09-12 11:07:21 -07002061
2062 public void writeToProto(ProtoOutputStream proto, long fieldId) {
2063 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +02002064 super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002065 proto.write(ID, taskId);
2066 for (int i = mActivities.size() - 1; i >= 0; i--) {
2067 ActivityRecord activity = mActivities.get(i);
2068 activity.writeToProto(proto, ACTIVITIES);
2069 }
2070 proto.write(STACK_ID, mStack.mStackId);
2071 if (mLastNonFullscreenBounds != null) {
2072 mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
2073 }
2074 if (realActivity != null) {
2075 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
2076 }
2077 if (origActivity != null) {
2078 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
2079 }
2080 proto.write(ACTIVITY_TYPE, getActivityType());
Steven Timotius4346f0a2017-09-12 11:07:21 -07002081 proto.write(RESIZE_MODE, mResizeMode);
Bryce Leef3c6a472017-11-14 14:53:06 -08002082 // TODO: Remove, no longer needed with windowingMode.
2083 proto.write(FULLSCREEN, matchParentBounds());
2084
2085 if (!matchParentBounds()) {
2086 final Rect bounds = getOverrideBounds();
2087 bounds.writeToProto(proto, BOUNDS);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002088 }
2089 proto.write(MIN_WIDTH, mMinWidth);
2090 proto.write(MIN_HEIGHT, mMinHeight);
2091 proto.end(token);
2092 }
Winson Chung61c9e5a2017-10-11 10:39:32 -07002093
2094 /**
2095 * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
2096 */
2097 static class TaskActivitiesReport {
2098 int numRunning;
2099 int numActivities;
2100 ActivityRecord top;
2101 ActivityRecord base;
2102
2103 void reset() {
2104 numRunning = numActivities = 0;
2105 top = base = null;
2106 }
2107 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002108
2109 /**
2110 * Saves this {@link TaskRecord} to XML using given serializer.
2111 */
2112 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2113 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
2114
2115 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
2116 if (realActivity != null) {
2117 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
2118 }
2119 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
2120 if (origActivity != null) {
2121 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
2122 }
2123 // Write affinity, and root affinity if it is different from affinity.
2124 // We use the special string "@" for a null root affinity, so we can identify
2125 // later whether we were given a root affinity or should just make it the
2126 // same as the affinity.
2127 if (affinity != null) {
2128 out.attribute(null, ATTR_AFFINITY, affinity);
2129 if (!affinity.equals(rootAffinity)) {
2130 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2131 }
2132 } else if (rootAffinity != null) {
2133 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2134 }
2135 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
2136 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
2137 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
2138 out.attribute(null, ATTR_USERID, String.valueOf(userId));
2139 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
2140 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
2141 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
2142 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
2143 if (lastDescription != null) {
2144 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
2145 }
2146 if (lastTaskDescription != null) {
2147 lastTaskDescription.saveToXml(out);
2148 }
2149 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
2150 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
2151 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
2152 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
2153 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
2154 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
2155 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
2156 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
2157 String.valueOf(mSupportsPictureInPicture));
2158 if (mLastNonFullscreenBounds != null) {
2159 out.attribute(
2160 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
2161 }
2162 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
2163 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
2164 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
2165
2166 if (affinityIntent != null) {
2167 out.startTag(null, TAG_AFFINITYINTENT);
2168 affinityIntent.saveToXml(out);
2169 out.endTag(null, TAG_AFFINITYINTENT);
2170 }
2171
Bryce Lee1a990e52018-04-23 10:54:11 -07002172 if (intent != null) {
2173 out.startTag(null, TAG_INTENT);
2174 intent.saveToXml(out);
2175 out.endTag(null, TAG_INTENT);
2176 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002177
2178 final ArrayList<ActivityRecord> activities = mActivities;
2179 final int numActivities = activities.size();
2180 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
2181 final ActivityRecord r = activities.get(activityNdx);
2182 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
2183 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
2184 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
2185 activityNdx > 0) {
2186 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
2187 break;
2188 }
2189 out.startTag(null, TAG_ACTIVITY);
2190 r.saveToXml(out);
2191 out.endTag(null, TAG_ACTIVITY);
2192 }
2193 }
2194
2195 @VisibleForTesting
2196 static TaskRecordFactory getTaskRecordFactory() {
2197 if (sTaskRecordFactory == null) {
2198 setTaskRecordFactory(new TaskRecordFactory());
2199 }
2200 return sTaskRecordFactory;
2201 }
2202
2203 static void setTaskRecordFactory(TaskRecordFactory factory) {
2204 sTaskRecordFactory = factory;
2205 }
2206
2207 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2208 Intent intent, IVoiceInteractionSession voiceSession,
2209 IVoiceInteractor voiceInteractor) {
2210 return getTaskRecordFactory().create(
2211 service, taskId, info, intent, voiceSession, voiceInteractor);
2212 }
2213
2214 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2215 Intent intent, TaskDescription taskDescription) {
2216 return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
2217 }
2218
2219 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2220 throws IOException, XmlPullParserException {
2221 return getTaskRecordFactory().restoreFromXml(in, stackSupervisor);
2222 }
2223
2224 /**
2225 * A factory class used to create {@link TaskRecord} or its subclass if any. This can be
2226 * specified when system boots by setting it with
2227 * {@link #setTaskRecordFactory(TaskRecordFactory)}.
2228 */
2229 static class TaskRecordFactory {
2230
2231 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2232 Intent intent, IVoiceInteractionSession voiceSession,
2233 IVoiceInteractor voiceInteractor) {
2234 return new TaskRecord(
2235 service, taskId, info, intent, voiceSession, voiceInteractor);
2236 }
2237
2238 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2239 Intent intent, TaskDescription taskDescription) {
2240 return new TaskRecord(service, taskId, info, intent, taskDescription);
2241 }
2242
2243 /**
2244 * Should only be used when we're restoring {@link TaskRecord} from storage.
2245 */
2246 TaskRecord create(ActivityManagerService service, int taskId, Intent intent,
2247 Intent affinityIntent, String affinity, String rootAffinity,
2248 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
2249 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
2250 int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
2251 long lastTimeMoved, boolean neverRelinquishIdentity,
2252 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
2253 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
2254 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
2255 boolean userSetupComplete, int minWidth, int minHeight) {
2256 return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
2257 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
2258 askedCompatMode, userId, effectiveUid, lastDescription, activities,
2259 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
2260 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
2261 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
2262 minWidth, minHeight);
2263 }
2264
2265 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2266 throws IOException, XmlPullParserException {
2267 Intent intent = null;
2268 Intent affinityIntent = null;
2269 ArrayList<ActivityRecord> activities = new ArrayList<>();
2270 ComponentName realActivity = null;
2271 boolean realActivitySuspended = false;
2272 ComponentName origActivity = null;
2273 String affinity = null;
2274 String rootAffinity = null;
2275 boolean hasRootAffinity = false;
2276 boolean rootHasReset = false;
2277 boolean autoRemoveRecents = false;
2278 boolean askedCompatMode = false;
2279 int taskType = 0;
2280 int userId = 0;
2281 boolean userSetupComplete = true;
2282 int effectiveUid = -1;
2283 String lastDescription = null;
2284 long lastTimeOnTop = 0;
2285 boolean neverRelinquishIdentity = true;
2286 int taskId = INVALID_TASK_ID;
2287 final int outerDepth = in.getDepth();
2288 TaskDescription taskDescription = new TaskDescription();
2289 int taskAffiliation = INVALID_TASK_ID;
2290 int taskAffiliationColor = 0;
2291 int prevTaskId = INVALID_TASK_ID;
2292 int nextTaskId = INVALID_TASK_ID;
2293 int callingUid = -1;
2294 String callingPackage = "";
2295 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
2296 boolean supportsPictureInPicture = false;
Garfield Tan367b35a2017-12-13 12:16:21 -08002297 Rect lastNonFullscreenBounds = null;
Garfield Tan9b1efea2017-12-05 16:43:46 -08002298 int minWidth = INVALID_MIN_SIZE;
2299 int minHeight = INVALID_MIN_SIZE;
2300 int persistTaskVersion = 0;
2301
2302 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2303 final String attrName = in.getAttributeName(attrNdx);
2304 final String attrValue = in.getAttributeValue(attrNdx);
2305 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
2306 attrName + " value=" + attrValue);
2307 switch (attrName) {
2308 case ATTR_TASKID:
2309 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
2310 break;
2311 case ATTR_REALACTIVITY:
2312 realActivity = ComponentName.unflattenFromString(attrValue);
2313 break;
2314 case ATTR_REALACTIVITY_SUSPENDED:
2315 realActivitySuspended = Boolean.valueOf(attrValue);
2316 break;
2317 case ATTR_ORIGACTIVITY:
2318 origActivity = ComponentName.unflattenFromString(attrValue);
2319 break;
2320 case ATTR_AFFINITY:
2321 affinity = attrValue;
2322 break;
2323 case ATTR_ROOT_AFFINITY:
2324 rootAffinity = attrValue;
2325 hasRootAffinity = true;
2326 break;
2327 case ATTR_ROOTHASRESET:
2328 rootHasReset = Boolean.parseBoolean(attrValue);
2329 break;
2330 case ATTR_AUTOREMOVERECENTS:
2331 autoRemoveRecents = Boolean.parseBoolean(attrValue);
2332 break;
2333 case ATTR_ASKEDCOMPATMODE:
2334 askedCompatMode = Boolean.parseBoolean(attrValue);
2335 break;
2336 case ATTR_USERID:
2337 userId = Integer.parseInt(attrValue);
2338 break;
2339 case ATTR_USER_SETUP_COMPLETE:
2340 userSetupComplete = Boolean.parseBoolean(attrValue);
2341 break;
2342 case ATTR_EFFECTIVE_UID:
2343 effectiveUid = Integer.parseInt(attrValue);
2344 break;
2345 case ATTR_TASKTYPE:
2346 taskType = Integer.parseInt(attrValue);
2347 break;
2348 case ATTR_LASTDESCRIPTION:
2349 lastDescription = attrValue;
2350 break;
2351 case ATTR_LASTTIMEMOVED:
2352 lastTimeOnTop = Long.parseLong(attrValue);
2353 break;
2354 case ATTR_NEVERRELINQUISH:
2355 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
2356 break;
2357 case ATTR_TASK_AFFILIATION:
2358 taskAffiliation = Integer.parseInt(attrValue);
2359 break;
2360 case ATTR_PREV_AFFILIATION:
2361 prevTaskId = Integer.parseInt(attrValue);
2362 break;
2363 case ATTR_NEXT_AFFILIATION:
2364 nextTaskId = Integer.parseInt(attrValue);
2365 break;
2366 case ATTR_TASK_AFFILIATION_COLOR:
2367 taskAffiliationColor = Integer.parseInt(attrValue);
2368 break;
2369 case ATTR_CALLING_UID:
2370 callingUid = Integer.parseInt(attrValue);
2371 break;
2372 case ATTR_CALLING_PACKAGE:
2373 callingPackage = attrValue;
2374 break;
2375 case ATTR_RESIZE_MODE:
2376 resizeMode = Integer.parseInt(attrValue);
2377 break;
2378 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
2379 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
2380 break;
2381 case ATTR_NON_FULLSCREEN_BOUNDS:
Garfield Tan367b35a2017-12-13 12:16:21 -08002382 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002383 break;
2384 case ATTR_MIN_WIDTH:
2385 minWidth = Integer.parseInt(attrValue);
2386 break;
2387 case ATTR_MIN_HEIGHT:
2388 minHeight = Integer.parseInt(attrValue);
2389 break;
2390 case ATTR_PERSIST_TASK_VERSION:
2391 persistTaskVersion = Integer.parseInt(attrValue);
2392 break;
2393 default:
2394 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
2395 taskDescription.restoreFromXml(attrName, attrValue);
2396 } else {
2397 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
2398 }
2399 }
2400 }
2401
2402 int event;
2403 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
2404 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
2405 if (event == XmlPullParser.START_TAG) {
2406 final String name = in.getName();
2407 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
2408 "TaskRecord: START_TAG name=" + name);
2409 if (TAG_AFFINITYINTENT.equals(name)) {
2410 affinityIntent = Intent.restoreFromXml(in);
2411 } else if (TAG_INTENT.equals(name)) {
2412 intent = Intent.restoreFromXml(in);
2413 } else if (TAG_ACTIVITY.equals(name)) {
2414 ActivityRecord activity =
2415 ActivityRecord.restoreFromXml(in, stackSupervisor);
2416 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
2417 activity);
2418 if (activity != null) {
2419 activities.add(activity);
2420 }
2421 } else {
Garfield Tan1e740192017-12-12 14:37:42 -08002422 handleUnknownTag(name, in);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002423 }
2424 }
2425 }
2426 if (!hasRootAffinity) {
2427 rootAffinity = affinity;
2428 } else if ("@".equals(rootAffinity)) {
2429 rootAffinity = null;
2430 }
2431 if (effectiveUid <= 0) {
2432 Intent checkIntent = intent != null ? intent : affinityIntent;
2433 effectiveUid = 0;
2434 if (checkIntent != null) {
2435 IPackageManager pm = AppGlobals.getPackageManager();
2436 try {
2437 ApplicationInfo ai = pm.getApplicationInfo(
2438 checkIntent.getComponent().getPackageName(),
2439 PackageManager.MATCH_UNINSTALLED_PACKAGES
2440 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
2441 if (ai != null) {
2442 effectiveUid = ai.uid;
2443 }
2444 } catch (RemoteException e) {
2445 }
2446 }
2447 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
2448 + ": effectiveUid=" + effectiveUid);
2449 }
2450
2451 if (persistTaskVersion < 1) {
2452 // We need to convert the resize mode of home activities saved before version one if
2453 // they are marked as RESIZE_MODE_RESIZEABLE to
2454 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
2455 // before version 1 and the system didn't resize home activities before then.
2456 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
2457 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2458 }
2459 } else {
2460 // This activity has previously marked itself explicitly as both resizeable and
2461 // supporting picture-in-picture. Since there is no longer a requirement for
2462 // picture-in-picture activities to be resizeable, we can mark this simply as
2463 // resizeable and supporting picture-in-picture separately.
2464 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2465 resizeMode = RESIZE_MODE_RESIZEABLE;
2466 supportsPictureInPicture = true;
2467 }
2468 }
2469
2470 final TaskRecord task = create(stackSupervisor.mService, taskId, intent, affinityIntent,
2471 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
2472 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
2473 activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
2474 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
2475 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
2476 userSetupComplete, minWidth, minHeight);
Garfield Tan367b35a2017-12-13 12:16:21 -08002477 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
2478 task.setBounds(lastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002479
2480 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
2481 activities.get(activityNdx).setTask(task);
2482 }
2483
2484 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
2485 return task;
2486 }
Garfield Tan1e740192017-12-12 14:37:42 -08002487
2488 void handleUnknownTag(String name, XmlPullParser in)
2489 throws IOException, XmlPullParserException {
2490 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
2491 XmlUtils.skipCurrentTag(in);
2492 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494}