blob: fccd6859c64164102c4f164b549b1545d1917fa4 [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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 Intent intent; // The original intent that started the task.
207 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700208 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 ComponentName origActivity; // The non-alias activity component of the intent.
210 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000211 boolean realActivitySuspended; // True if the actual activity component that started the
212 // task is suspended.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700213 boolean inRecents; // Actually in the recents list?
Winson Chungfb44d212017-10-04 11:39:10 -0700214 long lastActiveTime; // Last time this task was active in the current device session,
215 // including sleep. This time is initialized to the elapsed time when
216 // restored from disk.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700217 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 boolean rootWasReset; // True if the intent at the root of the task had
219 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700220 boolean autoRemoveRecents; // If true, we should automatically remove the task from
221 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700222 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700223 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 -0800224
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700225 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700226 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800227 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
228 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800229
230 int numFullscreen; // Number of fullscreen activities.
231
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800232 int mResizeMode; // The resize mode of this task and its activities.
233 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800234 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
235 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
236 // of the root activity.
Craig Mautner15df08a2015-04-01 12:17:18 -0700237 /** Can't be put in lockTask mode. */
238 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100239 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700240 final static int LOCK_TASK_AUTH_PINNABLE = 1;
241 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
242 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100243 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700244 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100245 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
246 * lockTask task. */
247 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700248 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
249
250 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800251
Winson Chung03a9bae2014-05-02 09:56:12 -0700252 // This represents the last resolved activity values for this task
253 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700254 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700255
Craig Mautnerd2328952013-03-05 12:46:26 -0800256 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700257 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800258
Andrii Kulian02b7a832016-10-06 23:11:56 -0700259 /** Current stack. Setter must always be used to update the value. */
260 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800261
Dianne Hackborn68a06332017-11-15 17:54:18 -0800262 /** The process that had previously hosted the root activity of this task.
263 * Used to know that we should try harder to keep this process around, in case the
264 * user wants to return to it. */
265 private ProcessRecord mRootProcess;
266
Craig Mautner21d24a22014-04-23 11:45:37 -0700267 /** Takes on same value as first root activity */
268 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700269 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700270
271 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
272 * determining the order when restoring. Sign indicates whether last task movement was to front
273 * (positive) or back (negative). Absolute value indicates time. */
274 long mLastTimeMoved = System.currentTimeMillis();
275
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700276 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700277 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700278
Craig Mautner362449a2014-06-20 14:04:39 -0700279 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
280 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800281 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700282
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700283 CharSequence lastDescription; // Last description captured for this item.
284
Craig Mautnera228ae92014-07-09 05:44:55 -0700285 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700286 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700287 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800288 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700289 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800290 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700291
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700292 // For relaunching the task from recents as though it was launched by the original launcher.
293 int mCallingUid;
294 String mCallingPackage;
295
Craig Mautner21d24a22014-04-23 11:45:37 -0700296 final ActivityManagerService mService;
297
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800298 private final Rect mTmpStableBounds = new Rect();
299 private final Rect mTmpNonDecorBounds = new Rect();
Wale Ogunwale9a08f822016-02-17 19:03:58 -0800300 private final Rect mTmpRect = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800301
Wale Ogunwale706ed792015-08-02 10:29:44 -0700302 // Last non-fullscreen bounds the task was launched in or resized to.
303 // The information is persisted and used to determine the appropriate stack to launch the
304 // task into on restore.
305 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700306 // Minimal width and height of this task when it's resizeable. -1 means it should use the
307 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700308 int mMinWidth;
309 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700310
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700311 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
312 // This number will be assigned when we evaluate OOM scores for all visible tasks.
313 int mLayerRank = -1;
314
Andrii Kulian1779e612016-10-12 21:58:25 -0700315 /** Helper object used for updating override configuration. */
316 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700317
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800318 private TaskWindowContainerController mWindowContainerController;
319
Garfield Tan9b1efea2017-12-05 16:43:46 -0800320 /**
321 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
322 * Intent, TaskDescription)} instead.
323 */
Craig Mautner21d24a22014-04-23 11:45:37 -0700324 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700325 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700326 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800327 userId = UserHandle.getUserId(info.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700329 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautnera228ae92014-07-09 05:44:55 -0700330 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700331 voiceSession = _voiceSession;
332 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700333 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800334 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700335 mCallingUid = info.applicationInfo.uid;
336 mCallingPackage = info.packageName;
Martijn Coenend4a69702014-06-30 11:12:17 -0700337 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700338 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700339 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700340 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700341 }
342
Garfield Tan9b1efea2017-12-05 16:43:46 -0800343 /**
344 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
345 * Intent, IVoiceInteractionSession, IVoiceInteractor)} instead.
346 */
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700347 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200348 TaskDescription _taskDescription) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700349 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800350 userId = UserHandle.getUserId(info.applicationInfo.uid);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700351 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700352 lastActiveTime = SystemClock.elapsedRealtime();
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700353 mAffiliatedTaskId = _taskId;
354 voiceSession = null;
355 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700356 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800357 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700358 mCallingUid = info.applicationInfo.uid;
359 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700360 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700361 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700362
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700363 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700364 // Clamp to [1, max].
365 maxRecents = Math.min(Math.max(info.maxRecents, 1),
366 ActivityManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700367
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700368 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700369 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700370 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700371 }
372
Garfield Tan9b1efea2017-12-05 16:43:46 -0800373 /**
374 * Don't use constructor directly. This is only used by XML parser.
375 */
376 TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800377 Intent _affinityIntent, String _affinity, String _rootAffinity,
378 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700379 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800380 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
Winson Chungfb44d212017-10-04 11:39:10 -0700381 long lastTimeMoved, boolean neverRelinquishIdentity,
382 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
383 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Charles He2bf28322017-10-12 22:24:49 +0100384 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
385 boolean userSetupComplete, int minWidth, int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700386 mService = service;
387 taskId = _taskId;
388 intent = _intent;
389 affinityIntent = _affinityIntent;
390 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800391 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700392 voiceSession = null;
393 voiceInteractor = null;
394 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800395 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700396 origActivity = _origActivity;
397 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700398 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700399 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700400 askedCompatMode = _askedCompatMode;
Craig Mautner21d24a22014-04-23 11:45:37 -0700401 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800402 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700403 effectiveUid = _effectiveUid;
Winson Chungfb44d212017-10-04 11:39:10 -0700404 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautner21d24a22014-04-23 11:45:37 -0700405 lastDescription = _lastDescription;
406 mActivities = activities;
407 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700408 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700409 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700410 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700411 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700412 mPrevAffiliateTaskId = prevTaskId;
413 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700414 mCallingUid = callingUid;
415 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800416 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800417 mSupportsPictureInPicture = supportsPictureInPicture;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700418 mMinWidth = minWidth;
419 mMinHeight = minHeight;
Yorke Leebd54c2a2016-10-25 13:49:23 -0700420 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800423 TaskWindowContainerController getWindowContainerController() {
424 return mWindowContainerController;
425 }
426
427 void createWindowContainer(boolean onTop, boolean showForAllUsers) {
428 if (mWindowContainerController != null) {
429 throw new IllegalArgumentException("Window container=" + mWindowContainerController
430 + " already created for task=" + this);
431 }
432
433 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
Bryce Lee04ab3462017-04-10 15:06:33 -0700434 setWindowContainerController(new TaskWindowContainerController(taskId, this,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700435 getStack().getWindowContainerController(), userId, bounds,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700436 mResizeMode, mSupportsPictureInPicture, onTop,
437 showForAllUsers, lastTaskDescription));
Bryce Lee04ab3462017-04-10 15:06:33 -0700438 }
439
440 /**
441 * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
442 */
443 @VisibleForTesting
444 protected void setWindowContainerController(TaskWindowContainerController controller) {
445 if (mWindowContainerController != null) {
446 throw new IllegalArgumentException("Window container=" + mWindowContainerController
447 + " already created for task=" + this);
448 }
449
450 mWindowContainerController = controller;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800451 }
452
453 void removeWindowContainer() {
Charles Heff9b4dff2017-09-22 10:18:37 +0100454 mService.mLockTaskController.clearLockedTask(this);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800455 mWindowContainerController.removeContainer();
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700456 if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800457 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
458 // default configuration the next time it launches.
459 updateOverrideConfiguration(null);
460 }
461 mService.mTaskChangeNotificationController.notifyTaskRemoved(taskId);
462 mWindowContainerController = null;
463 }
464
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100465 @Override
466 public void onSnapshotChanged(TaskSnapshot snapshot) {
467 mService.mTaskChangeNotificationController.notifyTaskSnapshotChanged(taskId, snapshot);
468 }
469
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800470 void setResizeMode(int resizeMode) {
471 if (mResizeMode == resizeMode) {
472 return;
473 }
474 mResizeMode = resizeMode;
475 mWindowContainerController.setResizeable(resizeMode);
476 mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
477 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
478 }
479
480 void setTaskDockedResizing(boolean resizing) {
481 mWindowContainerController.setTaskDockedResizing(resizing);
482 }
483
Wale Ogunwale1666e312016-12-16 11:27:18 -0800484 // TODO: Consolidate this with the resize() method below.
485 @Override
486 public void requestResize(Rect bounds, int resizeMode) {
487 mService.resizeTask(taskId, bounds, resizeMode);
488 }
489
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800490 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800491 mService.mWindowManager.deferSurfaceLayout();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800492
Bryce Leef3c6a472017-11-14 14:53:06 -0800493 try {
494 if (!isResizeable()) {
495 Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
496 return true;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800497 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800498
Bryce Leef3c6a472017-11-14 14:53:06 -0800499 // If this is a forced resize, let it go through even if the bounds is not changing,
500 // as we might need a relayout due to surface size change (to/from fullscreen).
501 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
502 if (equivalentOverrideBounds(bounds) && !forced) {
503 // Nothing to do here...
504 return true;
505 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800506
Bryce Leef3c6a472017-11-14 14:53:06 -0800507 if (mWindowContainerController == null) {
508 // Task doesn't exist in window manager yet (e.g. was restored from recents).
509 // All we can do for now is update the bounds so it can be used when the task is
510 // added to window manager.
511 updateOverrideConfiguration(bounds);
512 if (!inFreeformWindowingMode()) {
513 // re-restore the task so it can have the proper stack association.
514 mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
515 }
516 return true;
517 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800518
Bryce Leef3c6a472017-11-14 14:53:06 -0800519 if (!canResizeToBounds(bounds)) {
520 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
521 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
522 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800523
Bryce Leef3c6a472017-11-14 14:53:06 -0800524 // Do not move the task to another stack here.
525 // This method assumes that the task is already placed in the right stack.
526 // we do not mess with that decision and we only do the resize!
527
528 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
529
530 final boolean updatedConfig = updateOverrideConfiguration(bounds);
531 // This variable holds information whether the configuration didn't change in a significant
532
533 // way and the activity was kept the way it was. If it's false, it means the activity
534 // had
535 // to be relaunched due to configuration change.
536 boolean kept = true;
537 if (updatedConfig) {
538 final ActivityRecord r = topRunningActivityLocked();
539 if (r != null && !deferResume) {
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800540 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800541 preserveWindow);
542 mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0,
543 !PRESERVE_WINDOWS);
544 if (!kept) {
545 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
546 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800547 }
548 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800549 mWindowContainerController.resize(kept, forced);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800550
Bryce Leef3c6a472017-11-14 14:53:06 -0800551 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
552 return kept;
553 } finally {
554 mService.mWindowManager.continueSurfaceLayout();
555 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800556 }
557
558 // TODO: Investigate combining with the resize() method above.
559 void resizeWindowContainer() {
Bryce Leef3c6a472017-11-14 14:53:06 -0800560 mWindowContainerController.resize(false /* relayout */, false /* forced */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800561 }
562
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800563 void getWindowContainerBounds(Rect bounds) {
564 mWindowContainerController.getBounds(bounds);
565 }
566
Winson Chung74666102017-02-22 17:49:24 -0800567 /**
568 * Convenience method to reparent a task to the top or bottom position of the stack.
569 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700570 boolean reparent(ActivityStack preferredStack, boolean toTop,
571 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
572 String reason) {
573 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
574 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung5af42fc2017-03-24 17:11:33 -0700575 }
576
577 /**
578 * Convenience method to reparent a task to the top or bottom position of the stack, with
579 * an option to skip scheduling the picture-in-picture mode change.
580 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700581 boolean reparent(ActivityStack preferredStack, boolean toTop,
582 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
583 boolean schedulePictureInPictureModeChange, String reason) {
584 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700585 deferResume, schedulePictureInPictureModeChange, reason);
586 }
587
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700588 /** Convenience method to reparent a task to a specific position of the stack. */
589 boolean reparent(ActivityStack preferredStack, int position,
590 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
591 String reason) {
592 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
Winson Chung5af42fc2017-03-24 17:11:33 -0700593 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800594 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800595
Winson Chung74666102017-02-22 17:49:24 -0800596 /**
597 * Reparents the task into a preferred stack, creating it if necessary.
598 *
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700599 * @param preferredStack the target stack to move this task
Winson Chung74666102017-02-22 17:49:24 -0800600 * @param position the position to place this task in the new stack
601 * @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 -0700602 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800603 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700604 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800605 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700606 * have changed as a result of this reparenting
607 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
608 * change. Callers may set this to false if they are explicitly scheduling PiP mode
609 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800610 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700611 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800612 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700613 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700614 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700615 boolean reparent(ActivityStack preferredStack, int position,
616 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
617 boolean schedulePictureInPictureModeChange, String reason) {
Winson Chung74666102017-02-22 17:49:24 -0800618 final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
619 final WindowManagerService windowManager = mService.mWindowManager;
620 final ActivityStack sourceStack = getStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700621 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
Winson Chung74666102017-02-22 17:49:24 -0800622 position == MAX_VALUE);
623 if (toStack == sourceStack) {
624 return false;
625 }
Andrii Kulianb850ea52017-12-12 23:49:10 -0800626 if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
627 return false;
628 }
Winson Chung74666102017-02-22 17:49:24 -0800629
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700630 final int toStackWindowingMode = toStack.getWindowingMode();
Winson Chung74666102017-02-22 17:49:24 -0800631 final ActivityRecord topActivity = getTopActivity();
632
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800633 final boolean mightReplaceWindow = topActivity != null
634 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
Winson Chung74666102017-02-22 17:49:24 -0800635 if (mightReplaceWindow) {
636 // We are about to relaunch the activity because its configuration changed due to
637 // being maximized, i.e. size change. The activity will first remove the old window
638 // and then add a new one. This call will tell window manager about this, so it can
639 // preserve the old window until the new one is drawn. This prevents having a gap
640 // between the removal and addition, in which no window is visible. We also want the
641 // entrance of the new window to be properly animated.
642 // Note here we always set the replacing window first, as the flags might be needed
643 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
644 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
645 }
646
647 windowManager.deferSurfaceLayout();
648 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800649 try {
Winson Chung74666102017-02-22 17:49:24 -0800650 final ActivityRecord r = topRunningActivityLocked();
Winson Chung95f8f0e2017-03-24 09:20:17 -0700651 final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800652 && (topRunningActivityLocked() == r);
Bryce Leec4ab62a2018-03-05 14:19:26 -0800653 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
Winson Chung95f8f0e2017-03-24 09:20:17 -0700654 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800655
656 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
657 // Whenever we are moving the top activity from the front stack we want to make sure to
658 // move the stack to the front.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700659 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Winson Chung74666102017-02-22 17:49:24 -0800660 && (sourceStack.topRunningActivityLocked() == r);
661
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800662 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800663 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800664
665 // Must reparent first in window manager to avoid a situation where AM can delete the
666 // we are coming from in WM before we reparent because it became empty.
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700667 mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
668 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800669
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700670 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
671 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800672 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700673 sourceStack.removeTask(this, reason, moveStackToFront
674 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700675 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800676
Winson Chung5af42fc2017-03-24 17:11:33 -0700677 if (schedulePictureInPictureModeChange) {
678 // Notify of picture-in-picture mode changes
679 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
680 }
Winson Chung74666102017-02-22 17:49:24 -0800681
682 // TODO: Ensure that this is actually necessary here
683 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800684 if (voiceSession != null) {
685 try {
686 voiceSession.taskStarted(intent, taskId);
687 } catch (RemoteException e) {
688 }
689 }
Winson Chung74666102017-02-22 17:49:24 -0800690
691 // If the task had focus before (or we're requested to move focus), move focus to the
692 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700693 if (r != null) {
694 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
695 wasPaused, reason);
696 }
Winson Chung74666102017-02-22 17:49:24 -0800697 if (!animate) {
Jorim Jaggifa9ed962018-01-25 00:16:49 +0100698 mService.mStackSupervisor.mNoAnimActivities.add(topActivity);
Winson Chung74666102017-02-22 17:49:24 -0800699 }
700
701 // We might trigger a configuration change. Save the current task bounds for freezing.
702 // TODO: Should this call be moved inside the resize method in WM?
703 toStack.prepareFreezingTaskBounds();
704
705 // Make sure the task has the appropriate bounds/size for the stack it is in.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700706 final boolean toStackSplitScreenPrimary =
707 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Bryce Leef3c6a472017-11-14 14:53:06 -0800708 final Rect configBounds = getOverrideBounds();
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700709 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
710 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
Bryce Leef3c6a472017-11-14 14:53:06 -0800711 && !Objects.equals(configBounds, toStack.getOverrideBounds())) {
712 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800713 deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700714 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Winson Chung74666102017-02-22 17:49:24 -0800715 Rect bounds = getLaunchBounds();
716 if (bounds == null) {
Bryce Leeec55eb02017-12-05 20:51:27 -0800717 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800718 bounds = configBounds;
Winson Chung74666102017-02-22 17:49:24 -0800719 }
720 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700721 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
722 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
Matthew Ng330757d2017-02-28 14:19:17 -0800723 // Move recents to front so it is not behind home stack when going into docked
724 // mode
725 mService.mStackSupervisor.moveRecentsStackToFront(reason);
726 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800727 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800728 deferResume);
729 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800730 } finally {
Winson Chung74666102017-02-22 17:49:24 -0800731 windowManager.continueSurfaceLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800732 }
Winson Chung74666102017-02-22 17:49:24 -0800733
734 if (mightReplaceWindow) {
735 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
736 // window), we need to clear the replace window settings. Otherwise, we schedule a
737 // timeout to remove the old window if the replacing window is not coming in time.
738 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
739 }
740
741 if (!deferResume) {
742 // The task might have already been running and its visibility needs to be synchronized
743 // with the visibility of the stack / windows.
744 supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
745 supervisor.resumeFocusedStackTopActivityLocked();
746 }
747
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700748 // TODO: Handle incorrect request to move before the actual move, not after.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700749 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700750 DEFAULT_DISPLAY, toStack);
Winson Chung74666102017-02-22 17:49:24 -0800751
Winson Chungdff7a732017-12-11 12:17:06 -0800752 return (preferredStack == toStack);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800753 }
754
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700755 /**
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800756 * @return True if the windows of tasks being moved to the target stack from the source stack
757 * should be replaced, meaning that window manager will keep the old window around until the new
758 * is ready.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700759 */
760 private static boolean replaceWindowsOnTaskMove(
761 int sourceWindowingMode, int targetWindowingMode) {
762 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
763 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
764 }
765
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800766 void cancelWindowTransition() {
767 mWindowContainerController.cancelWindowTransition();
768 }
769
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100770 /**
771 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
772 */
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100773 TaskSnapshot getSnapshot(boolean reducedResolution) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100774
775 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
776 // synchronized between AM and WM.
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100777 return mService.mWindowManager.getTaskSnapshot(taskId, userId, reducedResolution);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800778 }
779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 void touchActiveTime() {
Winson Chungfb44d212017-10-04 11:39:10 -0700781 lastActiveTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 long getInactiveDuration() {
Winson Chungfb44d212017-10-04 11:39:10 -0700785 return SystemClock.elapsedRealtime() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700787
Winson Chungfee26772014-08-05 12:21:52 -0700788 /** Sets the original intent, and the calling uid and package. */
789 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700790 mCallingUid = r.launchedFromUid;
791 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700792 setIntent(r.intent, r.info);
Charles He2bf28322017-10-12 22:24:49 +0100793 setLockTaskAuth(r);
Winson Chungfee26772014-08-05 12:21:52 -0700794 }
795
796 /** Sets the original intent, _without_ updating the calling uid or package. */
797 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700798 if (intent == null) {
799 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700800 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700801 } else if (mNeverRelinquishIdentity) {
802 return;
803 }
804
805 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700806 if (intent == null) {
807 // If this task already has an intent associated with it, don't set the root
808 // affinity -- we don't want it changing after initially set, but the initially
809 // set value may be null.
810 rootAffinity = affinity;
811 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700812 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700813 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800816 if (_intent != null) {
817 // If this Intent has a selector, we want to clear it for the
818 // recent task since it is not relevant if the user later wants
819 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700820 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800821 _intent = new Intent(_intent);
822 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700823 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800824 }
825 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700826 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 intent = _intent;
828 realActivity = _intent != null ? _intent.getComponent() : null;
829 origActivity = null;
830 } else {
831 ComponentName targetComponent = new ComponentName(
832 info.packageName, info.targetActivity);
833 if (_intent != null) {
834 Intent targetIntent = new Intent(_intent);
835 targetIntent.setComponent(targetComponent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800836 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700837 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700838 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700839 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 intent = targetIntent;
841 realActivity = targetComponent;
842 origActivity = _intent.getComponent();
843 } else {
844 intent = null;
845 realActivity = targetComponent;
846 origActivity = new ComponentName(info.packageName, info.name);
847 }
848 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700849
Craig Mautner47b20ba2014-09-17 17:23:44 -0700850 final int intentFlags = intent == null ? 0 : intent.getFlags();
851 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 // Once we are set to an Intent with this flag, we count this
853 // task as having a true root activity.
854 rootWasReset = true;
855 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700856 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000857 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
858 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700859 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700860 // If the activity itself has requested auto-remove, then just always do it.
861 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700862 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
863 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700864 // If the caller has not asked for the document to be retained, then we may
865 // want to turn on auto-remove, depending on whether the target has set its
866 // own document launch mode.
867 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
868 autoRemoveRecents = false;
869 } else {
870 autoRemoveRecents = true;
871 }
872 } else {
873 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700874 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800875 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800876 mSupportsPictureInPicture = info.supportsPictureInPicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800878
Andrii Kulian2e751b82016-03-16 16:59:32 -0700879 /** Sets the original minimal width and height. */
880 private void setMinDimensions(ActivityInfo info) {
881 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700882 mMinWidth = info.windowLayout.minWidth;
883 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700884 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700885 mMinWidth = INVALID_MIN_SIZE;
886 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700887 }
888 }
889
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800890 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700891 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800892 * record is based on (normally the root activity intent).
893 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700894 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800895 final Intent intent = new Intent(r.intent);
896 // Correct the activity intent for aliasing. The task record intent will always be based on
897 // the real activity that will be launched not the alias, so we need to use an intent with
898 // the component name pointing to the real activity not the alias in the activity record.
899 intent.setComponent(r.realActivity);
900 return this.intent.filterEquals(intent);
901 }
902
Wale Ogunwale66e16852017-10-19 13:35:52 -0700903 boolean returnsToHomeStack() {
904 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
905 return (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700906 }
907
Craig Mautnera228ae92014-07-09 05:44:55 -0700908 void setPrevAffiliate(TaskRecord prevAffiliate) {
909 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800910 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700911 }
912
913 void setNextAffiliate(TaskRecord nextAffiliate) {
914 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800915 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700916 }
917
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700918 <T extends ActivityStack> T getStack() {
919 return (T) mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700920 }
921
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800922 /**
923 * Must be used for setting parent stack because it performs configuration updates.
924 * Must be called after adding task as a child to the stack.
925 */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700926 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800927 if (stack != null && !stack.isInStackLocked(this)) {
928 throw new IllegalStateException("Task must be added as a Stack child first.");
929 }
Bryce Lee84730a02018-04-03 14:10:04 -0700930 final ActivityStack oldStack = mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700931 mStack = stack;
Bryce Lee84730a02018-04-03 14:10:04 -0700932
933 // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
934 // {@link ActivityRecord} from its current {@link ActivityStack}.
935
936 if (oldStack != mStack) {
937 for (int i = getChildCount() - 1; i >= 0; --i) {
938 final ActivityRecord activity = getChildAt(i);
939
940 if (oldStack != null) {
941 oldStack.onActivityRemovedFromStack(activity);
942 }
943
944 if (mStack != null) {
945 stack.onActivityAddedToStack(activity);
946 }
947 }
948 }
949
Andrii Kulian1779e612016-10-12 21:58:25 -0700950 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700951 }
952
953 /**
954 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
955 */
956 int getStackId() {
957 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
958 }
959
Andrii Kulian1779e612016-10-12 21:58:25 -0700960 @Override
961 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700962 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -0700963 }
964
965 @Override
chaviw82a0ba82018-03-15 14:26:29 -0700966 protected ActivityRecord getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700967 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -0700968 }
969
970 @Override
971 protected ConfigurationContainer getParent() {
972 return mStack;
973 }
974
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800975 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -0700976 protected void onParentChanged() {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800977 super.onParentChanged();
978 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
979 }
980
Craig Mautnera228ae92014-07-09 05:44:55 -0700981 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700982 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -0700983 if (mPrevAffiliate != null) {
984 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
985 }
986 if (mNextAffiliate != null) {
987 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
988 }
989 setPrevAffiliate(null);
990 setNextAffiliate(null);
991 }
992
Winson Chung740c3ac2014-11-12 16:14:38 -0800993 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -0700994 closeRecentsChain();
995 if (inRecents) {
996 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -0800997 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700998 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +0100999
Dianne Hackborn68a06332017-11-15 17:54:18 -08001000 clearRootProcess();
1001
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001002 // TODO: Use window container controller once tasks are better synced between AM and WM
1003 mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001004 }
1005
Craig Mautnera228ae92014-07-09 05:44:55 -07001006 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1007 closeRecentsChain();
1008 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -07001009 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -07001010 // Find the end
1011 while (taskToAffiliateWith.mNextAffiliate != null) {
1012 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
1013 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1014 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1015 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1016 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1017 nextRecents.setPrevAffiliate(null);
1018 }
1019 taskToAffiliateWith.setNextAffiliate(null);
1020 break;
1021 }
1022 taskToAffiliateWith = nextRecents;
1023 }
1024 taskToAffiliateWith.setNextAffiliate(this);
1025 setPrevAffiliate(taskToAffiliateWith);
1026 setNextAffiliate(null);
1027 }
1028
Winson Chung1147c402014-05-14 11:05:00 -07001029 /** Returns the intent for the root activity for this task */
1030 Intent getBaseIntent() {
1031 return intent != null ? intent : affinityIntent;
1032 }
1033
Winson Chung3b3f4642014-04-22 10:08:18 -07001034 /** Returns the first non-finishing activity from the root. */
1035 ActivityRecord getRootActivity() {
1036 for (int i = 0; i < mActivities.size(); i++) {
1037 final ActivityRecord r = mActivities.get(i);
1038 if (r.finishing) {
1039 continue;
1040 }
1041 return r;
1042 }
1043 return null;
1044 }
1045
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001046 ActivityRecord getTopActivity() {
Bryce Lee9f6affd2017-09-01 09:18:35 -07001047 return getTopActivity(true /* includeOverlays */);
1048 }
1049
1050 ActivityRecord getTopActivity(boolean includeOverlays) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001051 for (int i = mActivities.size() - 1; i >= 0; --i) {
1052 final ActivityRecord r = mActivities.get(i);
Bryce Lee9f6affd2017-09-01 09:18:35 -07001053 if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001054 continue;
1055 }
1056 return r;
1057 }
1058 return null;
1059 }
1060
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001061 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001062 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001063 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1064 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001065 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001066 return r;
1067 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001068 }
1069 }
1070 return null;
1071 }
1072
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001073 boolean isVisible() {
1074 for (int i = mActivities.size() - 1; i >= 0; --i) {
1075 final ActivityRecord r = mActivities.get(i);
1076 if (r.visible) {
1077 return true;
1078 }
1079 }
1080 return false;
1081 }
1082
Jorim Jaggiea039a82017-08-02 14:37:49 +02001083 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1084 if (mStack != null) {
1085 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1086 ActivityRecord r = mActivities.get(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001087 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001088 outActivities.add(r);
1089 }
1090 }
1091 }
1092 }
1093
Wale Ogunwale3b232392016-05-13 15:37:13 -07001094 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001095 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001096 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1097 ActivityRecord r = mActivities.get(activityNdx);
1098 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001099 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001100 continue;
1101 }
1102 return r;
1103 }
1104 }
1105 return null;
1106 }
1107
Winson Chung61c9e5a2017-10-11 10:39:32 -07001108 /**
1109 * Return the number of running activities, and the number of non-finishing/initializing
1110 * activities in the provided {@param reportOut} respectively.
1111 */
1112 void getNumRunningActivities(TaskActivitiesReport reportOut) {
1113 reportOut.reset();
1114 for (int i = mActivities.size() - 1; i >= 0; --i) {
1115 final ActivityRecord r = mActivities.get(i);
1116 if (r.finishing) {
1117 continue;
1118 }
1119
1120 reportOut.base = r;
1121
1122 // Increment the total number of non-finishing activities
1123 reportOut.numActivities++;
1124
Bryce Lee7ace3952018-02-16 14:34:32 -08001125 if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001126 reportOut.top = r;
1127 // Reset the number of running activities until we hit the first non-initializing
1128 // activity
1129 reportOut.numRunning = 0;
1130 }
1131 if (r.app != null && r.app.thread != null) {
1132 // Increment the number of actually running activities
1133 reportOut.numRunning++;
1134 }
1135 }
1136 }
1137
Chong Zhang87761972016-08-22 13:53:24 -07001138 boolean okToShowLocked() {
1139 // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
1140 // okay to show the activity when locked.
1141 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
1142 || topRunningActivityLocked() != null;
1143 }
1144
Craig Mautner3b475fe2013-12-16 15:58:31 -08001145 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Bryce Leed71317c2017-02-07 14:27:22 -08001146 final void setFrontOfTask() {
1147 boolean foundFront = false;
Craig Mautner3b475fe2013-12-16 15:58:31 -08001148 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -08001149 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -08001150 final ActivityRecord r = mActivities.get(activityNdx);
1151 if (foundFront || r.finishing) {
1152 r.frontOfTask = false;
1153 } else {
1154 r.frontOfTask = true;
1155 // Set frontOfTask false for every following activity.
1156 foundFront = true;
1157 }
1158 }
Craig Mautner9587ee02014-06-23 15:00:10 +00001159 if (!foundFront && numActivities > 0) {
1160 // All activities of this task are finishing. As we ought to have a frontOfTask
1161 // activity, make the bottom activity front.
1162 mActivities.get(0).frontOfTask = true;
1163 }
Craig Mautner3b475fe2013-12-16 15:58:31 -08001164 }
1165
Craig Mautnerde4ef022013-04-07 19:01:33 -07001166 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001167 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001168 */
1169 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001170 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1171 "Removing and adding activity " + newTop
1172 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001173
Craig Mautnerde4ef022013-04-07 19:01:33 -07001174 mActivities.remove(newTop);
1175 mActivities.add(newTop);
Bryce Leed58d7b32017-09-08 15:55:22 -07001176
1177 // Make sure window manager is aware of the position change.
1178 mWindowContainerController.positionChildAtTop(newTop.mWindowContainerController);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001179 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -08001180
Bryce Leed71317c2017-02-07 14:27:22 -08001181 setFrontOfTask();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001182 }
1183
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001184 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -08001185 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001186 }
1187
1188 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001189 addActivityAtIndex(mActivities.size(), r);
1190 }
1191
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001192 @Override
Wale Ogunwaleeea34ee92017-08-31 20:07:45 -07001193 /*@WindowConfiguration.ActivityType*/
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001194 public int getActivityType() {
1195 final int applicationType = super.getActivityType();
1196 if (applicationType != ACTIVITY_TYPE_UNDEFINED || mActivities.isEmpty()) {
1197 return applicationType;
1198 }
1199 return mActivities.get(0).getActivityType();
1200 }
1201
Winson Chung30480042017-01-26 10:55:34 -08001202 /**
1203 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1204 * be in the current task or unparented to any task.
1205 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001206 void addActivityAtIndex(int index, ActivityRecord r) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001207 TaskRecord task = r.getTask();
1208 if (task != null && task != this) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001209 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
Bryce Leeaf691c02017-03-20 14:20:22 -07001210 + " current parent=" + task);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001211 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001212
1213 r.setTask(this);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001214
Craig Mautner6170f732013-04-02 13:05:23 -07001215 // 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 -08001216 if (!mActivities.remove(r) && r.fullscreen) {
1217 // Was not previously in list.
1218 numFullscreen++;
1219 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001220 // Only set this based on the first activity
1221 if (mActivities.isEmpty()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001222 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1223 // Normally non-standard activity type for the activity record will be set when the
1224 // object is created, however we delay setting the standard application type until
1225 // this point so that the task can set the type for additional activities added in
1226 // the else condition below.
1227 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1228 }
1229 setActivityType(r.getActivityType());
Craig Mautner21d24a22014-04-23 11:45:37 -07001230 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001231 mCallingUid = r.launchedFromUid;
1232 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001233 // Clamp to [1, max].
1234 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1235 ActivityManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001236 } else {
1237 // Otherwise make all added activities match this one.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001238 r.setActivityType(getActivityType());
Craig Mautner78733002013-06-10 13:54:49 -07001239 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001240
1241 final int size = mActivities.size();
1242
1243 if (index == size && size > 0) {
1244 final ActivityRecord top = mActivities.get(size - 1);
1245 if (top.mTaskOverlay) {
1246 // Place below the task overlay activity since the overlay activity should always
1247 // be on top.
1248 index--;
1249 }
1250 }
1251
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001252 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001253 mActivities.add(index, r);
Bryce Lee84730a02018-04-03 14:10:04 -07001254
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001255 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001256 if (r.isPersistable()) {
1257 mService.notifyTaskPersisterLocked(this, false);
1258 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001259
1260 // Sync. with window manager
1261 updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001262 final AppWindowContainerController appController = r.getWindowContainerController();
1263 if (appController != null) {
1264 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1265 // created controller for the activity we are starting yet.
1266 mWindowContainerController.positionChildAt(appController, index);
1267 }
David Stevens82ea6cb2017-03-03 16:18:50 -08001268
1269 // Make sure the list of display UID whitelists is updated
1270 // now that this record is in a new task.
1271 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001272 }
1273
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001274 /**
Bryce Leeaf691c02017-03-20 14:20:22 -07001275 * Removes the specified activity from this task.
1276 * @param r The {@link ActivityRecord} to remove.
1277 * @return true if this was the last activity in the task.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001278 */
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001279 boolean removeActivity(ActivityRecord r) {
Bryce Lee84730a02018-04-03 14:10:04 -07001280 return removeActivity(r, false /* reparenting */);
Bryce Leeaf691c02017-03-20 14:20:22 -07001281 }
1282
1283 boolean removeActivity(ActivityRecord r, boolean reparenting) {
1284 if (r.getTask() != this) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001285 throw new IllegalArgumentException(
1286 "Activity=" + r + " does not belong to task=" + this);
1287 }
1288
Bryce Lee84730a02018-04-03 14:10:04 -07001289 r.setTask(null /* task */, reparenting /* reparenting */);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001290
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001291 if (mActivities.remove(r) && r.fullscreen) {
1292 // Was previously in list.
1293 numFullscreen--;
1294 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001295 if (r.isPersistable()) {
1296 mService.notifyTaskPersisterLocked(this, false);
1297 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001298
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001299 if (inPinnedWindowingMode()) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001300 // We normally notify listeners of task stack changes on pause, however pinned stack
1301 // activities are normally in the paused state so no notification will be sent there
1302 // before the activity is removed. We send it here so instead.
Yorke Leebd54c2a2016-10-25 13:49:23 -07001303 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001304 }
1305
Craig Mautner41326202014-06-20 14:38:21 -07001306 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001307 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001308 }
1309 updateEffectiveIntent();
1310 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001311 }
1312
Winson Chung6954fc92017-03-24 16:22:12 -07001313 /**
1314 * @return whether or not there are ONLY task overlay activities in the stack.
1315 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1316 * If there are no task overlay activities, this call returns false.
1317 */
1318 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1319 int count = 0;
1320 for (int i = mActivities.size() - 1; i >= 0; i--) {
1321 final ActivityRecord r = mActivities.get(i);
1322 if (excludeFinishing && r.finishing) {
1323 continue;
1324 }
1325 if (!r.mTaskOverlay) {
1326 return false;
1327 }
1328 count++;
1329 }
1330 return count > 0;
1331 }
1332
Craig Mautner41db4a72014-05-07 17:20:56 -07001333 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001334 // We will automatically remove the task either if it has explicitly asked for
1335 // this, or it is empty and has never contained an activity that got shown to
1336 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -07001337 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001338 }
1339
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001340 /**
1341 * Completely remove all activities associated with an existing
1342 * task starting at a specified index.
1343 */
Winson Chung0ec2a352017-10-26 11:38:30 -07001344 final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately,
1345 String reason) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001346 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001347 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001348 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001349 if (r.finishing) {
1350 continue;
1351 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001352 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001353 // Task was restored from persistent storage.
1354 r.takeFromHistory();
1355 mActivities.remove(activityNdx);
1356 --activityNdx;
1357 --numActivities;
Winson Chung6954fc92017-03-24 16:22:12 -07001358 } else if (mStack.finishActivityLocked(r, Activity.RESULT_CANCELED, null,
Winson Chung0ec2a352017-10-26 11:38:30 -07001359 reason, false, pauseImmediately)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001360 --activityNdx;
1361 --numActivities;
1362 }
1363 }
1364 }
1365
1366 /**
1367 * Completely remove all activities associated with an existing task.
1368 */
Benjamin Franza83859f2017-07-03 16:34:14 +01001369 void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001370 mReuseTask = true;
Winson Chung0ec2a352017-10-26 11:38:30 -07001371 performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY, "clear-task-all");
Craig Mautner362449a2014-06-20 14:04:39 -07001372 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001373 }
1374
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001375 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1376 mReuseTask = true;
1377 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1378 mReuseTask = false;
1379 return result;
1380 }
1381
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001382 /**
1383 * Perform clear operation as requested by
1384 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1385 * stack to the given task, then look for
1386 * an instance of that activity in the stack and, if found, finish all
1387 * activities on top of it and return the instance.
1388 *
1389 * @param newR Description of the new activity being started.
1390 * @return Returns the old activity that should be continued to be used,
1391 * or null if none was found.
1392 */
1393 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001394 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001395 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001396 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001397 if (r.finishing) {
1398 continue;
1399 }
1400 if (r.realActivity.equals(newR.realActivity)) {
1401 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001402 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001403
1404 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001405 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001406 if (r.finishing) {
1407 continue;
1408 }
1409 ActivityOptions opts = r.takeOptionsLocked();
1410 if (opts != null) {
1411 ret.updateOptionsLocked(opts);
1412 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001413 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001414 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001415 --activityNdx;
1416 --numActivities;
1417 }
1418 }
1419
1420 // Finally, if this is a normal launch mode (that is, not
1421 // expecting onNewIntent()), then we will finish the current
1422 // instance of the activity so a new fresh one can be started.
1423 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001424 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1425 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001426 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001427 if (mStack != null) {
1428 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -07001429 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1430 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001431 return null;
1432 }
1433 }
1434
1435 return ret;
1436 }
1437 }
1438
1439 return null;
1440 }
1441
Winson Chung0ec2a352017-10-26 11:38:30 -07001442 void removeTaskActivitiesLocked(boolean pauseImmediately, String reason) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001443 // Just remove the entire task.
Winson Chung0ec2a352017-10-26 11:38:30 -07001444 performClearTaskAtIndexLocked(0, pauseImmediately, reason);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001445 }
1446
Craig Mautner432f64e2015-05-20 14:59:57 -07001447 String lockTaskAuthToString() {
1448 switch (mLockTaskAuth) {
1449 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1450 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1451 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1452 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001453 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001454 default: return "unknown=" + mLockTaskAuth;
1455 }
1456 }
1457
Craig Mautner15df08a2015-04-01 12:17:18 -07001458 void setLockTaskAuth() {
Charles He2bf28322017-10-12 22:24:49 +01001459 setLockTaskAuth(getRootActivity());
1460 }
1461
1462 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1463 if (r == null) {
1464 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1465 return;
1466 }
1467
Charles He520b2832017-09-02 15:27:16 +01001468 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
Charles He2bf28322017-10-12 22:24:49 +01001469 switch (r.lockTaskLaunchMode) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001470 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
Charles He520b2832017-09-02 15:27:16 +01001471 mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
1472 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001473 break;
1474
1475 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001476 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001477 break;
1478
1479 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001480 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001481 break;
1482
1483 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
Charles He520b2832017-09-02 15:27:16 +01001484 mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
1485 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001486 break;
1487 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001488 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1489 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001490 }
1491
Winson Chungd3395382016-12-13 11:49:09 -08001492 private boolean isResizeable(boolean checkSupportsPip) {
1493 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001494 || (checkSupportsPip && mSupportsPictureInPicture));
Winson Chungd3395382016-12-13 11:49:09 -08001495 }
1496
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001497 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001498 return isResizeable(true /* checkSupportsPip */);
1499 }
1500
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001501 @Override
1502 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08001503 // A task can not be docked even if it is considered resizeable because it only supports
1504 // picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001505 return super.supportsSplitScreenWindowingMode()
1506 && mService.mSupportsSplitScreenMultiWindow
Bryce Leec857a5b2017-08-16 10:04:52 -07001507 && (mService.mForceResizableActivities
1508 || (isResizeable(false /* checkSupportsPip */)
1509 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001510 }
1511
skuhne@google.com322347b2016-12-02 12:54:03 -08001512 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001513 * Check whether this task can be launched on the specified display.
1514 * @param displayId Target display id.
1515 * @return {@code true} if either it is the default display or this activity is resizeable and
1516 * can be put a secondary screen.
1517 */
1518 boolean canBeLaunchedOnDisplay(int displayId) {
1519 return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Andrii Kulian02689a72017-07-06 14:28:59 -07001520 isResizeable(false /* checkSupportsPip */), -1 /* don't check PID */,
1521 -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001522 }
1523
1524 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001525 * Check that a given bounds matches the application requested orientation.
1526 *
1527 * @param bounds The bounds to be tested.
1528 * @return True if the requested bounds are okay for a resizing request.
1529 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001530 private boolean canResizeToBounds(Rect bounds) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001531 if (bounds == null || !inFreeformWindowingMode()) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001532 // Note: If not on the freeform workspace, we ignore the bounds.
1533 return true;
1534 }
1535 final boolean landscape = bounds.width() > bounds.height();
Bryce Leef3c6a472017-11-14 14:53:06 -08001536 final Rect configBounds = getOverrideBounds();
skuhne@google.com322347b2016-12-02 12:54:03 -08001537 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001538 return configBounds.isEmpty()
1539 || landscape == (configBounds.width() > configBounds.height());
skuhne@google.com322347b2016-12-02 12:54:03 -08001540 }
1541 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1542 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1543 }
1544
Craig Mautner525f3d92013-05-07 14:01:50 -07001545 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001546 * @return {@code true} if the task is being cleared for the purposes of being reused.
1547 */
1548 boolean isClearingToReuseTask() {
1549 return mReuseTask;
1550 }
1551
1552 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001553 * Find the activity in the history stack within the given task. Returns
1554 * the index within the history at which it's found, or < 0 if not found.
1555 */
1556 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
1557 final ComponentName realActivity = r.realActivity;
1558 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1559 ActivityRecord candidate = mActivities.get(activityNdx);
1560 if (candidate.finishing) {
1561 continue;
1562 }
1563 if (candidate.realActivity.equals(realActivity)) {
1564 return candidate;
1565 }
1566 }
1567 return null;
1568 }
1569
Winson Chunga449dc02014-05-16 11:15:04 -07001570 /** Updates the last task description values. */
1571 void updateTaskDescription() {
1572 // Traverse upwards looking for any break between main task activities and
1573 // utility activities.
1574 int activityNdx;
1575 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001576 final boolean relinquish = numActivities != 0 &&
1577 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001578 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001579 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001580 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001581 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001582 // This will be the top activity for determining taskDescription. Pre-inc to
1583 // overcome initial decrement below.
1584 ++activityNdx;
1585 break;
1586 }
Winson Chunga449dc02014-05-16 11:15:04 -07001587 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001588 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001589 break;
1590 }
1591 }
1592 if (activityNdx > 0) {
1593 // Traverse downwards starting below break looking for set label, icon.
1594 // Note that if there are activities in the task but none of them set the
1595 // recent activity values, then we do not fall back to the last set
1596 // values in the TaskRecord.
1597 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001598 String iconFilename = null;
Matthew Ng54bc9422017-10-02 17:16:28 -07001599 int iconResource = -1;
Winson Chunga449dc02014-05-16 11:15:04 -07001600 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001601 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001602 int statusBarColor = 0;
1603 int navigationBarColor = 0;
1604 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001605 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1606 final ActivityRecord r = mActivities.get(activityNdx);
1607 if (r.taskDescription != null) {
1608 if (label == null) {
1609 label = r.taskDescription.getLabel();
1610 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001611 if (iconResource == -1) {
1612 iconResource = r.taskDescription.getIconResource();
1613 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001614 if (iconFilename == null) {
1615 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001616 }
1617 if (colorPrimary == 0) {
1618 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001619 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001620 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001621 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001622 statusBarColor = r.taskDescription.getStatusBarColor();
1623 navigationBarColor = r.taskDescription.getNavigationBarColor();
Winson Chung1af8eda2016-02-05 17:55:56 +00001624 }
Winson Chunga449dc02014-05-16 11:15:04 -07001625 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001626 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001627 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001628 lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
1629 colorPrimary, colorBackground, statusBarColor, navigationBarColor);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001630 if (mWindowContainerController != null) {
1631 mWindowContainerController.setTaskDescription(lastTaskDescription);
1632 }
Winson Chungec396d62014-08-06 17:08:00 -07001633 // Update the task affiliation color if we are the parent of the group
1634 if (taskId == mAffiliatedTaskId) {
1635 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1636 }
Winson Chunga449dc02014-05-16 11:15:04 -07001637 }
1638 }
1639
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001640 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001641 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001642 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001643 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001644 final ActivityRecord r = mActivities.get(activityNdx);
1645 if (r.finishing) {
1646 continue;
1647 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001648 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001649 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001650 break;
1651 }
1652 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001653 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001654 }
1655
1656 void updateEffectiveIntent() {
1657 final int effectiveRootIndex = findEffectiveRootIndex();
1658 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001659 setIntent(r);
Winson Chung8d9009e2017-11-16 15:43:05 -08001660
1661 // Update the task description when the activities change
1662 updateTaskDescription();
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001663 }
1664
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001665 private void adjustForMinimalTaskDimensions(Rect bounds) {
1666 if (bounds == null) {
1667 return;
1668 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001669 int minWidth = mMinWidth;
1670 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001671 // If the task has no requested minimal size, we'd like to enforce a minimal size
1672 // so that the user can not render the task too small to manipulate. We don't need
1673 // to do this for the pinned stack as the bounds are controlled by the system.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001674 if (!inPinnedWindowingMode()) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001675 if (minWidth == INVALID_MIN_SIZE) {
1676 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001677 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001678 if (minHeight == INVALID_MIN_SIZE) {
1679 minHeight = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001680 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001681 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001682 final boolean adjustWidth = minWidth > bounds.width();
1683 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001684 if (!(adjustWidth || adjustHeight)) {
1685 return;
1686 }
1687
Bryce Leef3c6a472017-11-14 14:53:06 -08001688 final Rect configBounds = getOverrideBounds();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001689 if (adjustWidth) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001690 if (!configBounds.isEmpty() && bounds.right == configBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001691 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001692 } else {
1693 // Either left bounds match, or neither match, or the previous bounds were
1694 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001695 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001696 }
1697 }
1698 if (adjustHeight) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001699 if (!configBounds.isEmpty() && bounds.bottom == configBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001700 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001701 } else {
1702 // Either top bounds match, or neither match, or the previous bounds were
1703 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001704 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001705 }
1706 }
1707 }
1708
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001709 /**
Winson Chung5af42fc2017-03-24 17:11:33 -07001710 * @return a new Configuration for this Task, given the provided {@param bounds} and
1711 * {@param insetBounds}.
1712 */
1713 Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
1714 // Compute a new override configuration for the given bounds, if fullscreen bounds
1715 // (bounds == null), then leave the override config unset
1716 final Configuration newOverrideConfig = new Configuration();
1717 if (bounds != null) {
1718 newOverrideConfig.setTo(getOverrideConfiguration());
1719 mTmpRect.set(bounds);
1720 adjustForMinimalTaskDimensions(mTmpRect);
1721 computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds,
1722 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
1723 }
1724
1725 return newOverrideConfig;
1726 }
1727
1728 /**
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001729 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001730 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07001731 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001732 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001733 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001734 return updateOverrideConfiguration(bounds, null /* insetBounds */);
1735 }
1736
1737 /**
1738 * Update task's override configuration based on the bounds.
1739 * @param bounds The bounds of the task.
1740 * @param insetBounds The bounds used to calculate the system insets, which is used here to
1741 * subtract the navigation bar/status bar size from the screen size reported
1742 * to the application. See {@link IActivityManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07001743 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001744 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001745 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001746 if (equivalentOverrideBounds(bounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07001747 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001748 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001749 final Rect currentBounds = getOverrideBounds();
1750
Andrii Kulian1779e612016-10-12 21:58:25 -07001751 mTmpConfig.setTo(getOverrideConfiguration());
Andrii Kulian1779e612016-10-12 21:58:25 -07001752 final Configuration newConfig = getOverrideConfiguration();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001753
Bryce Leef3c6a472017-11-14 14:53:06 -08001754 final boolean matchParentBounds = bounds == null || bounds.isEmpty();
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001755 final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -08001756 if (matchParentBounds) {
1757 if (!currentBounds.isEmpty() && persistBounds) {
1758 mLastNonFullscreenBounds = currentBounds;
Wale Ogunwale706ed792015-08-02 10:29:44 -07001759 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001760 setBounds(null);
Andrii Kulian1779e612016-10-12 21:58:25 -07001761 newConfig.unset();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001762 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001763 mTmpRect.set(bounds);
1764 adjustForMinimalTaskDimensions(mTmpRect);
Bryce Leef3c6a472017-11-14 14:53:06 -08001765 setBounds(mTmpRect);
1766
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001767 if (mStack == null || persistBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001768 mLastNonFullscreenBounds = getOverrideBounds();
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -07001769 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001770 computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
Andrii Kuliandaea3572016-04-08 13:20:51 -07001771 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001772 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001773 onOverrideConfigurationChanged(newConfig);
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001774 return !mTmpConfig.equals(newConfig);
1775 }
Wale Ogunwale5f986092015-12-04 15:35:38 -08001776
Bryce Leec4ab62a2018-03-05 14:19:26 -08001777 /**
1778 * This should be called when an child activity changes state. This should only
1779 * be called from
1780 * {@link ActivityRecord#setState(ActivityState, String)} .
1781 * @param record The {@link ActivityRecord} whose state has changed.
1782 * @param state The new state.
1783 * @param reason The reason for the change.
1784 */
1785 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
1786 final ActivityStack parent = getStack();
1787
1788 if (parent != null) {
1789 parent.onActivityStateChanged(record, state, reason);
1790 }
1791 }
1792
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001793 @Override
1794 public void onConfigurationChanged(Configuration newParentConfig) {
1795 final boolean wasInMultiWindowMode = inMultiWindowMode();
1796 super.onConfigurationChanged(newParentConfig);
1797 if (wasInMultiWindowMode != inMultiWindowMode()) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001798 mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001799 }
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001800 // TODO: Should also take care of Pip mode changes here.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001801 }
1802
Andrii Kulian1779e612016-10-12 21:58:25 -07001803 /** Clears passed config and fills it with new override values. */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001804 // TODO(b/36505427): TaskRecord.computeOverrideConfiguration() is a utility method that doesn't
1805 // depend on task or stacks, but uses those object to get the display to base the calculation
1806 // on. Probably best to centralize calculations like this in ConfigurationContainer.
1807 void computeOverrideConfiguration(Configuration config, Rect bounds, Rect insetBounds,
Andrii Kuliana8a9bc52016-10-14 11:00:13 -07001808 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001809 mTmpNonDecorBounds.set(bounds);
1810 mTmpStableBounds.set(bounds);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001811
Andrii Kulian1779e612016-10-12 21:58:25 -07001812 config.unset();
Winson Chungbdc646f2017-02-13 12:12:22 -08001813 final Configuration parentConfig = getParent().getConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -07001814
Andrii Kulian1779e612016-10-12 21:58:25 -07001815 final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001816
Winson Chungbdc646f2017-02-13 12:12:22 -08001817 if (mStack != null) {
1818 final StackWindowController stackController = mStack.getWindowContainerController();
1819 stackController.adjustConfigurationForBounds(bounds, insetBounds,
1820 mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
1821 config, parentConfig);
1822 } else {
Bryce Lee7566d762017-03-30 09:34:15 -07001823 throw new IllegalArgumentException("Expected stack when calculating override config");
Winson Chungbdc646f2017-02-13 12:12:22 -08001824 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001825
Winson Chung60c1aba2017-03-14 17:47:42 -07001826 config.orientation = (config.screenWidthDp <= config.screenHeightDp)
1827 ? Configuration.ORIENTATION_PORTRAIT
1828 : Configuration.ORIENTATION_LANDSCAPE;
1829
Jorim Jaggi85639432016-05-06 17:27:55 -07001830 // For calculating screen layout, we need to use the non-decor inset screen area for the
1831 // calculation for compatibility reasons, i.e. screen area without system bars that could
1832 // never go away in Honeycomb.
Winson Chungbdc646f2017-02-13 12:12:22 -08001833 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
1834 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Andrii Kulian1779e612016-10-12 21:58:25 -07001835 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
1836 // calculation with partial default.
1837 final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001838 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
Andrii Kulian1779e612016-10-12 21:58:25 -07001839 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
Jorim Jaggi85639432016-05-06 17:27:55 -07001840 config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001841 }
1842
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001843 Rect updateOverrideConfigurationFromLaunchBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08001844 final Rect bounds = getLaunchBounds();
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001845 updateOverrideConfiguration(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -08001846 if (bounds != null && !bounds.isEmpty()) {
1847 // TODO: Review if we actually want to do this - we are setting the launch bounds
1848 // directly here.
1849 bounds.set(getOverrideBounds());
Andrii Kulian73336d812016-03-24 12:56:08 -07001850 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001851 return bounds;
1852 }
1853
Wale Ogunwale935e5022015-11-10 12:36:10 -08001854 /** Updates the task's bounds and override configuration to match what is expected for the
1855 * input stack. */
1856 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001857 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001858 return;
1859 }
1860
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001861 if (inStack.inFreeformWindowingMode()) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001862 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001863 throw new IllegalArgumentException("Can not position non-resizeable task="
1864 + this + " in stack=" + inStack);
1865 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001866 if (!matchParentBounds()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001867 return;
1868 }
1869 if (mLastNonFullscreenBounds != null) {
1870 updateOverrideConfiguration(mLastNonFullscreenBounds);
1871 } else {
Bryce Leeec55eb02017-12-05 20:51:27 -08001872 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Wale Ogunwale935e5022015-11-10 12:36:10 -08001873 }
1874 } else {
Bryce Leef3c6a472017-11-14 14:53:06 -08001875 updateOverrideConfiguration(inStack.getOverrideBounds());
Wale Ogunwale935e5022015-11-10 12:36:10 -08001876 }
1877 }
1878
Wale Ogunwale706ed792015-08-02 10:29:44 -07001879 /** Returns the bounds that should be used to launch this task. */
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001880 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001881 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08001882 return null;
1883 }
1884
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001885 final int windowingMode = getWindowingMode();
1886 if (!isActivityTypeStandardOrUndefined()
1887 || windowingMode == WINDOWING_MODE_FULLSCREEN
1888 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001889 return isResizeable() ? mStack.getOverrideBounds() : null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001890 } else if (!getWindowConfiguration().persistTaskBounds()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001891 return mStack.getOverrideBounds();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001892 }
1893 return mLastNonFullscreenBounds;
1894 }
1895
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01001896 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
1897 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1898 final ActivityRecord r = mActivities.get(activityNdx);
1899 if (r.visible) {
1900 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
1901 }
1902 }
1903 }
1904
Dianne Hackborn68a06332017-11-15 17:54:18 -08001905 void setRootProcess(ProcessRecord proc) {
1906 clearRootProcess();
1907 if (intent != null &&
1908 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
1909 mRootProcess = proc;
1910 proc.recentTasks.add(this);
1911 }
1912 }
1913
1914 void clearRootProcess() {
1915 if (mRootProcess != null) {
1916 mRootProcess.recentTasks.remove(this);
1917 mRootProcess = null;
1918 }
1919 }
1920
chaviw82a0ba82018-03-15 14:26:29 -07001921 void clearAllPendingOptions() {
1922 for (int i = getChildCount() - 1; i >= 0; i--) {
1923 getChildAt(i).clearOptionsLocked(false /* withAbort */);
1924 }
1925 }
1926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001927 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001928 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001929 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
1930 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08001931 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001932 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07001933 if (affinity != null || rootAffinity != null) {
1934 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
1935 if (affinity == null || !affinity.equals(rootAffinity)) {
1936 pw.print(" root="); pw.println(rootAffinity);
1937 } else {
1938 pw.println();
1939 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001940 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07001941 if (voiceSession != null || voiceInteractor != null) {
1942 pw.print(prefix); pw.print("VOICE: session=0x");
1943 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
1944 pw.print(" interactor=0x");
1945 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
1946 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001947 if (intent != null) {
1948 StringBuilder sb = new StringBuilder(128);
1949 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001950 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001951 sb.append('}');
1952 pw.println(sb.toString());
1953 }
1954 if (affinityIntent != null) {
1955 StringBuilder sb = new StringBuilder(128);
1956 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001957 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001958 sb.append('}');
1959 pw.println(sb.toString());
1960 }
1961 if (origActivity != null) {
1962 pw.print(prefix); pw.print("origActivity=");
1963 pw.println(origActivity.flattenToShortString());
1964 }
1965 if (realActivity != null) {
1966 pw.print(prefix); pw.print("realActivity=");
1967 pw.println(realActivity.flattenToShortString());
1968 }
Wale Ogunwale66e16852017-10-19 13:35:52 -07001969 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001970 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001971 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001972 pw.print(" numFullscreen="); pw.print(numFullscreen);
Wale Ogunwale66e16852017-10-19 13:35:52 -07001973 pw.print(" activityType="); pw.println(getActivityType());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001974 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001975 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
1976 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001977 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
1978 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07001979 pw.print(" mReuseTask="); pw.print(mReuseTask);
1980 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001981 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08001982 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
1983 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
1984 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001985 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
1986 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
1987 pw.print(" (");
1988 if (mPrevAffiliate == null) {
1989 pw.print("null");
1990 } else {
1991 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
1992 }
1993 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
1994 pw.print(" (");
1995 if (mNextAffiliate == null) {
1996 pw.print("null");
1997 } else {
1998 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
1999 }
2000 pw.println(")");
2001 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002002 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002003 if (!askedCompatMode || !inRecents || !isAvailable) {
2004 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2005 pw.print(" inRecents="); pw.print(inRecents);
2006 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002007 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002008 if (lastDescription != null) {
2009 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2010 }
Dianne Hackborn68a06332017-11-15 17:54:18 -08002011 if (mRootProcess != null) {
2012 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
2013 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002014 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002015 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2016 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002017 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002018 pw.print(" isResizeable=" + isResizeable());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002019 pw.print(" lastActiveTime=" + lastActiveTime);
2020 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 }
2022
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002023 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002025 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002026 if (stringName != null) {
2027 sb.append(stringName);
2028 sb.append(" U=");
2029 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002030 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002031 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002032 sb.append(" sz=");
2033 sb.append(mActivities.size());
2034 sb.append('}');
2035 return sb.toString();
2036 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002037 sb.append("TaskRecord{");
2038 sb.append(Integer.toHexString(System.identityHashCode(this)));
2039 sb.append(" #");
2040 sb.append(taskId);
2041 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002042 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002043 sb.append(affinity);
2044 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002045 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002046 sb.append(intent.getComponent().flattenToShortString());
Bryce Leefbd263b42018-03-07 10:33:55 -08002047 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002048 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002049 sb.append(affinityIntent.getComponent().flattenToShortString());
2050 } else {
2051 sb.append(" ??");
2052 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002053 stringName = sb.toString();
2054 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 }
Steven Timotius4346f0a2017-09-12 11:07:21 -07002056
2057 public void writeToProto(ProtoOutputStream proto, long fieldId) {
2058 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +02002059 super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002060 proto.write(ID, taskId);
2061 for (int i = mActivities.size() - 1; i >= 0; i--) {
2062 ActivityRecord activity = mActivities.get(i);
2063 activity.writeToProto(proto, ACTIVITIES);
2064 }
2065 proto.write(STACK_ID, mStack.mStackId);
2066 if (mLastNonFullscreenBounds != null) {
2067 mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
2068 }
2069 if (realActivity != null) {
2070 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
2071 }
2072 if (origActivity != null) {
2073 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
2074 }
2075 proto.write(ACTIVITY_TYPE, getActivityType());
Steven Timotius4346f0a2017-09-12 11:07:21 -07002076 proto.write(RESIZE_MODE, mResizeMode);
Bryce Leef3c6a472017-11-14 14:53:06 -08002077 // TODO: Remove, no longer needed with windowingMode.
2078 proto.write(FULLSCREEN, matchParentBounds());
2079
2080 if (!matchParentBounds()) {
2081 final Rect bounds = getOverrideBounds();
2082 bounds.writeToProto(proto, BOUNDS);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002083 }
2084 proto.write(MIN_WIDTH, mMinWidth);
2085 proto.write(MIN_HEIGHT, mMinHeight);
2086 proto.end(token);
2087 }
Winson Chung61c9e5a2017-10-11 10:39:32 -07002088
2089 /**
2090 * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
2091 */
2092 static class TaskActivitiesReport {
2093 int numRunning;
2094 int numActivities;
2095 ActivityRecord top;
2096 ActivityRecord base;
2097
2098 void reset() {
2099 numRunning = numActivities = 0;
2100 top = base = null;
2101 }
2102 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002103
2104 /**
2105 * Saves this {@link TaskRecord} to XML using given serializer.
2106 */
2107 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2108 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
2109
2110 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
2111 if (realActivity != null) {
2112 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
2113 }
2114 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
2115 if (origActivity != null) {
2116 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
2117 }
2118 // Write affinity, and root affinity if it is different from affinity.
2119 // We use the special string "@" for a null root affinity, so we can identify
2120 // later whether we were given a root affinity or should just make it the
2121 // same as the affinity.
2122 if (affinity != null) {
2123 out.attribute(null, ATTR_AFFINITY, affinity);
2124 if (!affinity.equals(rootAffinity)) {
2125 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2126 }
2127 } else if (rootAffinity != null) {
2128 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2129 }
2130 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
2131 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
2132 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
2133 out.attribute(null, ATTR_USERID, String.valueOf(userId));
2134 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
2135 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
2136 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
2137 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
2138 if (lastDescription != null) {
2139 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
2140 }
2141 if (lastTaskDescription != null) {
2142 lastTaskDescription.saveToXml(out);
2143 }
2144 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
2145 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
2146 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
2147 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
2148 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
2149 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
2150 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
2151 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
2152 String.valueOf(mSupportsPictureInPicture));
2153 if (mLastNonFullscreenBounds != null) {
2154 out.attribute(
2155 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
2156 }
2157 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
2158 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
2159 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
2160
2161 if (affinityIntent != null) {
2162 out.startTag(null, TAG_AFFINITYINTENT);
2163 affinityIntent.saveToXml(out);
2164 out.endTag(null, TAG_AFFINITYINTENT);
2165 }
2166
2167 out.startTag(null, TAG_INTENT);
2168 intent.saveToXml(out);
2169 out.endTag(null, TAG_INTENT);
2170
2171 final ArrayList<ActivityRecord> activities = mActivities;
2172 final int numActivities = activities.size();
2173 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
2174 final ActivityRecord r = activities.get(activityNdx);
2175 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
2176 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
2177 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
2178 activityNdx > 0) {
2179 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
2180 break;
2181 }
2182 out.startTag(null, TAG_ACTIVITY);
2183 r.saveToXml(out);
2184 out.endTag(null, TAG_ACTIVITY);
2185 }
2186 }
2187
2188 @VisibleForTesting
2189 static TaskRecordFactory getTaskRecordFactory() {
2190 if (sTaskRecordFactory == null) {
2191 setTaskRecordFactory(new TaskRecordFactory());
2192 }
2193 return sTaskRecordFactory;
2194 }
2195
2196 static void setTaskRecordFactory(TaskRecordFactory factory) {
2197 sTaskRecordFactory = factory;
2198 }
2199
2200 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2201 Intent intent, IVoiceInteractionSession voiceSession,
2202 IVoiceInteractor voiceInteractor) {
2203 return getTaskRecordFactory().create(
2204 service, taskId, info, intent, voiceSession, voiceInteractor);
2205 }
2206
2207 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2208 Intent intent, TaskDescription taskDescription) {
2209 return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
2210 }
2211
2212 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2213 throws IOException, XmlPullParserException {
2214 return getTaskRecordFactory().restoreFromXml(in, stackSupervisor);
2215 }
2216
2217 /**
2218 * A factory class used to create {@link TaskRecord} or its subclass if any. This can be
2219 * specified when system boots by setting it with
2220 * {@link #setTaskRecordFactory(TaskRecordFactory)}.
2221 */
2222 static class TaskRecordFactory {
2223
2224 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2225 Intent intent, IVoiceInteractionSession voiceSession,
2226 IVoiceInteractor voiceInteractor) {
2227 return new TaskRecord(
2228 service, taskId, info, intent, voiceSession, voiceInteractor);
2229 }
2230
2231 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2232 Intent intent, TaskDescription taskDescription) {
2233 return new TaskRecord(service, taskId, info, intent, taskDescription);
2234 }
2235
2236 /**
2237 * Should only be used when we're restoring {@link TaskRecord} from storage.
2238 */
2239 TaskRecord create(ActivityManagerService service, int taskId, Intent intent,
2240 Intent affinityIntent, String affinity, String rootAffinity,
2241 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
2242 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
2243 int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
2244 long lastTimeMoved, boolean neverRelinquishIdentity,
2245 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
2246 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
2247 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
2248 boolean userSetupComplete, int minWidth, int minHeight) {
2249 return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
2250 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
2251 askedCompatMode, userId, effectiveUid, lastDescription, activities,
2252 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
2253 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
2254 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
2255 minWidth, minHeight);
2256 }
2257
2258 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2259 throws IOException, XmlPullParserException {
2260 Intent intent = null;
2261 Intent affinityIntent = null;
2262 ArrayList<ActivityRecord> activities = new ArrayList<>();
2263 ComponentName realActivity = null;
2264 boolean realActivitySuspended = false;
2265 ComponentName origActivity = null;
2266 String affinity = null;
2267 String rootAffinity = null;
2268 boolean hasRootAffinity = false;
2269 boolean rootHasReset = false;
2270 boolean autoRemoveRecents = false;
2271 boolean askedCompatMode = false;
2272 int taskType = 0;
2273 int userId = 0;
2274 boolean userSetupComplete = true;
2275 int effectiveUid = -1;
2276 String lastDescription = null;
2277 long lastTimeOnTop = 0;
2278 boolean neverRelinquishIdentity = true;
2279 int taskId = INVALID_TASK_ID;
2280 final int outerDepth = in.getDepth();
2281 TaskDescription taskDescription = new TaskDescription();
2282 int taskAffiliation = INVALID_TASK_ID;
2283 int taskAffiliationColor = 0;
2284 int prevTaskId = INVALID_TASK_ID;
2285 int nextTaskId = INVALID_TASK_ID;
2286 int callingUid = -1;
2287 String callingPackage = "";
2288 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
2289 boolean supportsPictureInPicture = false;
Garfield Tan367b35a2017-12-13 12:16:21 -08002290 Rect lastNonFullscreenBounds = null;
Garfield Tan9b1efea2017-12-05 16:43:46 -08002291 int minWidth = INVALID_MIN_SIZE;
2292 int minHeight = INVALID_MIN_SIZE;
2293 int persistTaskVersion = 0;
2294
2295 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2296 final String attrName = in.getAttributeName(attrNdx);
2297 final String attrValue = in.getAttributeValue(attrNdx);
2298 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
2299 attrName + " value=" + attrValue);
2300 switch (attrName) {
2301 case ATTR_TASKID:
2302 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
2303 break;
2304 case ATTR_REALACTIVITY:
2305 realActivity = ComponentName.unflattenFromString(attrValue);
2306 break;
2307 case ATTR_REALACTIVITY_SUSPENDED:
2308 realActivitySuspended = Boolean.valueOf(attrValue);
2309 break;
2310 case ATTR_ORIGACTIVITY:
2311 origActivity = ComponentName.unflattenFromString(attrValue);
2312 break;
2313 case ATTR_AFFINITY:
2314 affinity = attrValue;
2315 break;
2316 case ATTR_ROOT_AFFINITY:
2317 rootAffinity = attrValue;
2318 hasRootAffinity = true;
2319 break;
2320 case ATTR_ROOTHASRESET:
2321 rootHasReset = Boolean.parseBoolean(attrValue);
2322 break;
2323 case ATTR_AUTOREMOVERECENTS:
2324 autoRemoveRecents = Boolean.parseBoolean(attrValue);
2325 break;
2326 case ATTR_ASKEDCOMPATMODE:
2327 askedCompatMode = Boolean.parseBoolean(attrValue);
2328 break;
2329 case ATTR_USERID:
2330 userId = Integer.parseInt(attrValue);
2331 break;
2332 case ATTR_USER_SETUP_COMPLETE:
2333 userSetupComplete = Boolean.parseBoolean(attrValue);
2334 break;
2335 case ATTR_EFFECTIVE_UID:
2336 effectiveUid = Integer.parseInt(attrValue);
2337 break;
2338 case ATTR_TASKTYPE:
2339 taskType = Integer.parseInt(attrValue);
2340 break;
2341 case ATTR_LASTDESCRIPTION:
2342 lastDescription = attrValue;
2343 break;
2344 case ATTR_LASTTIMEMOVED:
2345 lastTimeOnTop = Long.parseLong(attrValue);
2346 break;
2347 case ATTR_NEVERRELINQUISH:
2348 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
2349 break;
2350 case ATTR_TASK_AFFILIATION:
2351 taskAffiliation = Integer.parseInt(attrValue);
2352 break;
2353 case ATTR_PREV_AFFILIATION:
2354 prevTaskId = Integer.parseInt(attrValue);
2355 break;
2356 case ATTR_NEXT_AFFILIATION:
2357 nextTaskId = Integer.parseInt(attrValue);
2358 break;
2359 case ATTR_TASK_AFFILIATION_COLOR:
2360 taskAffiliationColor = Integer.parseInt(attrValue);
2361 break;
2362 case ATTR_CALLING_UID:
2363 callingUid = Integer.parseInt(attrValue);
2364 break;
2365 case ATTR_CALLING_PACKAGE:
2366 callingPackage = attrValue;
2367 break;
2368 case ATTR_RESIZE_MODE:
2369 resizeMode = Integer.parseInt(attrValue);
2370 break;
2371 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
2372 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
2373 break;
2374 case ATTR_NON_FULLSCREEN_BOUNDS:
Garfield Tan367b35a2017-12-13 12:16:21 -08002375 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002376 break;
2377 case ATTR_MIN_WIDTH:
2378 minWidth = Integer.parseInt(attrValue);
2379 break;
2380 case ATTR_MIN_HEIGHT:
2381 minHeight = Integer.parseInt(attrValue);
2382 break;
2383 case ATTR_PERSIST_TASK_VERSION:
2384 persistTaskVersion = Integer.parseInt(attrValue);
2385 break;
2386 default:
2387 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
2388 taskDescription.restoreFromXml(attrName, attrValue);
2389 } else {
2390 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
2391 }
2392 }
2393 }
2394
2395 int event;
2396 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
2397 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
2398 if (event == XmlPullParser.START_TAG) {
2399 final String name = in.getName();
2400 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
2401 "TaskRecord: START_TAG name=" + name);
2402 if (TAG_AFFINITYINTENT.equals(name)) {
2403 affinityIntent = Intent.restoreFromXml(in);
2404 } else if (TAG_INTENT.equals(name)) {
2405 intent = Intent.restoreFromXml(in);
2406 } else if (TAG_ACTIVITY.equals(name)) {
2407 ActivityRecord activity =
2408 ActivityRecord.restoreFromXml(in, stackSupervisor);
2409 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
2410 activity);
2411 if (activity != null) {
2412 activities.add(activity);
2413 }
2414 } else {
Garfield Tan1e740192017-12-12 14:37:42 -08002415 handleUnknownTag(name, in);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002416 }
2417 }
2418 }
2419 if (!hasRootAffinity) {
2420 rootAffinity = affinity;
2421 } else if ("@".equals(rootAffinity)) {
2422 rootAffinity = null;
2423 }
2424 if (effectiveUid <= 0) {
2425 Intent checkIntent = intent != null ? intent : affinityIntent;
2426 effectiveUid = 0;
2427 if (checkIntent != null) {
2428 IPackageManager pm = AppGlobals.getPackageManager();
2429 try {
2430 ApplicationInfo ai = pm.getApplicationInfo(
2431 checkIntent.getComponent().getPackageName(),
2432 PackageManager.MATCH_UNINSTALLED_PACKAGES
2433 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
2434 if (ai != null) {
2435 effectiveUid = ai.uid;
2436 }
2437 } catch (RemoteException e) {
2438 }
2439 }
2440 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
2441 + ": effectiveUid=" + effectiveUid);
2442 }
2443
2444 if (persistTaskVersion < 1) {
2445 // We need to convert the resize mode of home activities saved before version one if
2446 // they are marked as RESIZE_MODE_RESIZEABLE to
2447 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
2448 // before version 1 and the system didn't resize home activities before then.
2449 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
2450 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2451 }
2452 } else {
2453 // This activity has previously marked itself explicitly as both resizeable and
2454 // supporting picture-in-picture. Since there is no longer a requirement for
2455 // picture-in-picture activities to be resizeable, we can mark this simply as
2456 // resizeable and supporting picture-in-picture separately.
2457 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2458 resizeMode = RESIZE_MODE_RESIZEABLE;
2459 supportsPictureInPicture = true;
2460 }
2461 }
2462
2463 final TaskRecord task = create(stackSupervisor.mService, taskId, intent, affinityIntent,
2464 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
2465 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
2466 activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
2467 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
2468 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
2469 userSetupComplete, minWidth, minHeight);
Garfield Tan367b35a2017-12-13 12:16:21 -08002470 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
2471 task.setBounds(lastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002472
2473 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
2474 activities.get(activityNdx).setTask(task);
2475 }
2476
2477 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
2478 return task;
2479 }
Garfield Tan1e740192017-12-12 14:37:42 -08002480
2481 void handleUnknownTag(String name, XmlPullParser in)
2482 throws IOException, XmlPullParserException {
2483 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
2484 XmlUtils.skipCurrentTag(in);
2485 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002486 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487}