blob: 49918568a24c19f8e0b50f2caf980fbe6bb4b625 [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
Winson Chung74666102017-02-22 17:49:24 -080019import android.annotation.IntDef;
Jorim Jaggi0a932142016-02-01 17:42:25 -080020import android.annotation.Nullable;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -070021import android.app.Activity;
Craig Mautner9db9a0b2013-04-29 17:05:56 -070022import android.app.ActivityManager;
Wale Ogunwale3797c222015-10-27 14:21:58 -070023import android.app.ActivityManager.StackId;
Craig Mautner648f69b2014-09-18 14:16:26 -070024import android.app.ActivityManager.TaskDescription;
Jorim Jaggie2c77f92016-12-29 14:57:22 +010025import android.app.ActivityManager.TaskSnapshot;
Wale Ogunwaleff3c66c2015-11-18 19:22:49 -080026import android.app.ActivityManager.TaskThumbnail;
Winsonc809cbb2015-11-02 12:06:15 -080027import android.app.ActivityManager.TaskThumbnailInfo;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -070028import android.app.ActivityOptions;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070029import android.app.AppGlobals;
Jorim Jaggi0a932142016-02-01 17:42:25 -080030import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.content.ComponentName;
32import android.content.Intent;
33import android.content.pm.ActivityInfo;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070034import android.content.pm.ApplicationInfo;
35import android.content.pm.IPackageManager;
36import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070037import android.content.res.Configuration;
Craig Mautner9db9a0b2013-04-29 17:05:56 -070038import android.graphics.Bitmap;
Winsonc809cbb2015-11-02 12:06:15 -080039import android.graphics.Point;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070040import android.graphics.Rect;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -070041import android.os.Debug;
Craig Mautnerc0ffce52014-07-01 12:38:52 -070042import android.os.ParcelFileDescriptor;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070043import android.os.RemoteException;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080044import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070045import android.os.UserHandle;
Suprabh Shukla7745c142016-03-07 18:21:10 -080046import android.provider.Settings;
Dianne Hackborn91097de2014-04-04 18:02:06 -070047import android.service.voice.IVoiceInteractionSession;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070048import android.util.DisplayMetrics;
Dianne Hackborn7f96b792012-05-29 18:46:45 -070049import android.util.Slog;
Suprabh Shukla23593142015-11-03 17:31:15 -080050
Dianne Hackborn91097de2014-04-04 18:02:06 -070051import com.android.internal.app.IVoiceInteractor;
Craig Mautner21d24a22014-04-23 11:45:37 -070052import com.android.internal.util.XmlUtils;
Suprabh Shukla23593142015-11-03 17:31:15 -080053
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -080054import com.android.server.wm.AppWindowContainerController;
Winson Chungbdc646f2017-02-13 12:12:22 -080055import com.android.server.wm.StackWindowController;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080056import com.android.server.wm.TaskWindowContainerController;
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010057import com.android.server.wm.TaskWindowContainerListener;
Winson Chung74666102017-02-22 17:49:24 -080058import com.android.server.wm.WindowManagerService;
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010059
Craig Mautner21d24a22014-04-23 11:45:37 -070060import org.xmlpull.v1.XmlPullParser;
61import org.xmlpull.v1.XmlPullParserException;
62import org.xmlpull.v1.XmlSerializer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063
Craig Mautnerc0ffce52014-07-01 12:38:52 -070064import java.io.File;
Craig Mautner21d24a22014-04-23 11:45:37 -070065import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import java.io.PrintWriter;
Winson Chung74666102017-02-22 17:49:24 -080067import java.lang.annotation.Retention;
68import java.lang.annotation.RetentionPolicy;
Craig Mautner5d9c7be2013-02-15 14:02:56 -080069import java.util.ArrayList;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070070import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080072import static android.app.ActivityManager.RESIZE_MODE_FORCED;
Winson Chung74666102017-02-22 17:49:24 -080073import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
Winson Chung83471632016-12-13 11:02:12 -080074import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Jorim Jaggi0a932142016-02-01 17:42:25 -080075import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
76import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
77import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
78import static android.app.ActivityManager.StackId.HOME_STACK_ID;
79import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
80import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080081import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Jorim Jaggi0a932142016-02-01 17:42:25 -080082import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
83import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
Wale Ogunwale3eadad72016-10-13 09:16:59 -070084import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080085import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
86import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
87import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
88import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080089import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
90import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
91import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Wale Ogunwaled829d362016-02-10 19:24:49 -080092import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070093import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -080094import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070095import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Jorim Jaggi0a932142016-02-01 17:42:25 -080096import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080097import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
Suprabh Shukla7745c142016-03-07 18:21:10 -080098import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Jorim Jaggi0a932142016-02-01 17:42:25 -080099import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
100import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
101import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
102import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
103import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
104import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
105import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
106import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
107import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
108import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Jorim Jaggi0a932142016-02-01 17:42:25 -0800109import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Winson Chung83471632016-12-13 11:02:12 -0800110import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
Jorim Jaggi0a932142016-02-01 17:42:25 -0800111import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
112import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
Wale Ogunwale3b232392016-05-13 15:37:13 -0700113import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800114import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800115import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Jorim Jaggi0a932142016-02-01 17:42:25 -0800116
Winson Chung74666102017-02-22 17:49:24 -0800117import static java.lang.Integer.MAX_VALUE;
118
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100119final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800120 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700121 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700122 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700123 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700124 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800125
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700126 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700127 private static final String TAG_INTENT = "intent";
128 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700129 private static final String ATTR_REALACTIVITY = "real_activity";
130 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700131 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700132 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700133 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700134 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700135 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700136 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700137 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
138 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800139 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700140 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Craig Mautner21d24a22014-04-23 11:45:37 -0700141 private static final String ATTR_TASKTYPE = "task_type";
Winson Chungffa2ec62014-07-03 15:54:42 -0700142 private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
Winson Chungf1fbd772014-06-24 18:06:58 -0700143 private static final String ATTR_LASTACTIVETIME = "last_active_time";
Craig Mautner21d24a22014-04-23 11:45:37 -0700144 private static final String ATTR_LASTDESCRIPTION = "last_description";
145 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700146 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700147 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700148 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
149 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700150 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700151 private static final String ATTR_CALLING_UID = "calling_uid";
152 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800153 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800154 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700155 private static final String ATTR_PRIVILEGED = "privileged";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700156 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700157 private static final String ATTR_MIN_WIDTH = "min_width";
158 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700159 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700160
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700161 // Current version of the task record we persist. Used to check if we need to run any upgrade
162 // code.
163 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700164 private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
165
Wale Ogunwale18795a22014-12-03 11:38:33 -0800166 static final int INVALID_TASK_ID = -1;
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700167 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800168
Winson Chung74666102017-02-22 17:49:24 -0800169 /**
170 * The modes to control how the stack is moved to the front when calling
171 * {@link TaskRecord#reparent}.
172 */
173 @Retention(RetentionPolicy.SOURCE)
174 @IntDef({
175 REPARENT_MOVE_STACK_TO_FRONT,
176 REPARENT_KEEP_STACK_AT_FRONT,
177 REPARENT_LEAVE_STACK_IN_PLACE
178 })
179 public @interface ReparentMoveStackMode {}
180 // Moves the stack to the front if it was not at the front
181 public static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
182 // Only moves the stack to the front if it was focused or front most already
183 public static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
184 // Do not move the stack as a part of reparenting
185 public static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 final int taskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700188 String affinity; // The affinity name for this task, or null; may change identity.
189 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700190 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
191 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 Intent intent; // The original intent that started the task.
193 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700194 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 ComponentName origActivity; // The non-alias activity component of the intent.
196 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000197 boolean realActivitySuspended; // True if the actual activity component that started the
198 // task is suspended.
Winson Chung36f3f032016-09-08 23:29:43 +0000199 long firstActiveTime; // First time this task was active.
200 long lastActiveTime; // Last time this task was active, including sleep.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700201 boolean inRecents; // Actually in the recents list?
202 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 boolean rootWasReset; // True if the intent at the root of the task had
204 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700205 boolean autoRemoveRecents; // If true, we should automatically remove the task from
206 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700207 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700208 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 -0800209
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700210 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700211 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800212 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
213 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800214
215 int numFullscreen; // Number of fullscreen activities.
216
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800217 int mResizeMode; // The resize mode of this task and its activities.
218 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800219 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
220 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
221 // of the root activity.
Jorim Jaggi8202b2a2016-02-03 19:24:31 -0800222 boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
223 // changes on a temporary basis.
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700224 private int mLockTaskMode; // Which tasklock mode to launch this task in. One of
225 // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700226 private boolean mPrivileged; // The root activity application of this task holds
227 // privileged permissions.
228
Craig Mautner15df08a2015-04-01 12:17:18 -0700229 /** Can't be put in lockTask mode. */
230 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100231 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700232 final static int LOCK_TASK_AUTH_PINNABLE = 1;
233 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
234 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100235 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700236 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100237 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
238 * lockTask task. */
239 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700240 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
241
242 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800243
Winson Chung03a9bae2014-05-02 09:56:12 -0700244 // This represents the last resolved activity values for this task
245 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700246 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700247
Craig Mautnerd2328952013-03-05 12:46:26 -0800248 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700249 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800250
Andrii Kulian02b7a832016-10-06 23:11:56 -0700251 /** Current stack. Setter must always be used to update the value. */
252 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800253
Craig Mautner2c1faed2013-07-23 12:56:02 -0700254 /** Takes on same set of values as ActivityRecord.mActivityType */
Craig Mautner21d24a22014-04-23 11:45:37 -0700255 int taskType;
Craig Mautner1602ec22013-05-12 10:24:27 -0700256
Craig Mautner21d24a22014-04-23 11:45:37 -0700257 /** Takes on same value as first root activity */
258 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700259 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700260
261 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
262 * determining the order when restoring. Sign indicates whether last task movement was to front
263 * (positive) or back (negative). Absolute value indicates time. */
264 long mLastTimeMoved = System.currentTimeMillis();
265
Craig Mautner84984fa2014-06-19 11:19:20 -0700266 /** Indication of what to run next when task exits. Use ActivityRecord types.
267 * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the
268 * task stack. */
269 private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE;
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700270
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700271 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700272 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700273
Craig Mautner362449a2014-06-20 14:04:39 -0700274 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
275 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800276 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700277
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700278 private Bitmap mLastThumbnail; // Last thumbnail captured for this item.
Wale Ogunwalebe23ff42014-10-21 16:29:51 -0700279 private final File mLastThumbnailFile; // File containing last thumbnail.
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700280 private final String mFilename;
Winsonc809cbb2015-11-02 12:06:15 -0800281 private TaskThumbnailInfo mLastThumbnailInfo;
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700282 CharSequence lastDescription; // Last description captured for this item.
283
Craig Mautnera228ae92014-07-09 05:44:55 -0700284 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700285 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700286 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800287 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700288 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800289 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700290
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700291 // For relaunching the task from recents as though it was launched by the original launcher.
292 int mCallingUid;
293 String mCallingPackage;
294
Craig Mautner21d24a22014-04-23 11:45:37 -0700295 final ActivityManagerService mService;
296
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700297 // Whether or not this task covers the entire screen; by default tasks are fullscreen.
298 boolean mFullscreen = true;
299
300 // Bounds of the Task. null for fullscreen tasks.
301 Rect mBounds = null;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800302 private final Rect mTmpStableBounds = new Rect();
303 private final Rect mTmpNonDecorBounds = new Rect();
Wale Ogunwale9a08f822016-02-17 19:03:58 -0800304 private final Rect mTmpRect = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800305
Wale Ogunwale706ed792015-08-02 10:29:44 -0700306 // Last non-fullscreen bounds the task was launched in or resized to.
307 // The information is persisted and used to determine the appropriate stack to launch the
308 // task into on restore.
309 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700310 // Minimal width and height of this task when it's resizeable. -1 means it should use the
311 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700312 int mMinWidth;
313 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700314
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700315 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
316 // This number will be assigned when we evaluate OOM scores for all visible tasks.
317 int mLayerRank = -1;
318
Andrii Kulian1779e612016-10-12 21:58:25 -0700319 /** Helper object used for updating override configuration. */
320 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700321
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800322 private TaskWindowContainerController mWindowContainerController;
323
Craig Mautner21d24a22014-04-23 11:45:37 -0700324 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale72919d22016-12-08 18:58:50 -0800325 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700326 mService = service;
Craig Mautnera228ae92014-07-09 05:44:55 -0700327 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
328 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800329 userId = UserHandle.getUserId(info.applicationInfo.uid);
330 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800331 mLastThumbnailInfo = new TaskThumbnailInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 taskId = _taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700333 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700334 voiceSession = _voiceSession;
335 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700336 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800337 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700338 mCallingUid = info.applicationInfo.uid;
339 mCallingPackage = info.packageName;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800340 taskType = type;
Martijn Coenend4a69702014-06-30 11:12:17 -0700341 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700342 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700343 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700344 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700345 }
346
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700347 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Winsonc809cbb2015-11-02 12:06:15 -0800348 TaskDescription _taskDescription, TaskThumbnailInfo thumbnailInfo) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700349 mService = service;
350 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
351 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800352 userId = UserHandle.getUserId(info.applicationInfo.uid);
353 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800354 mLastThumbnailInfo = thumbnailInfo;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700355 taskId = _taskId;
356 mAffiliatedTaskId = _taskId;
357 voiceSession = null;
358 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700359 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800360 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700361 mCallingUid = info.applicationInfo.uid;
362 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700363 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700364 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700365
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700366 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700367 // Clamp to [1, max].
368 maxRecents = Math.min(Math.max(info.maxRecents, 1),
369 ActivityManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700370
371 taskType = APPLICATION_ACTIVITY_TYPE;
372 mTaskToReturnTo = HOME_ACTIVITY_TYPE;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700373 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700374 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700375 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700376 }
377
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800378 private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
379 Intent _affinityIntent, String _affinity, String _rootAffinity,
380 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
381 boolean _autoRemoveRecents, boolean _askedCompatMode, int _taskType, int _userId,
382 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
383 long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
384 boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
Winsonc809cbb2015-11-02 12:06:15 -0800385 TaskThumbnailInfo lastThumbnailInfo, int taskAffiliation, int prevTaskId,
386 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Winson Chungd3395382016-12-13 11:49:09 -0800387 int resizeMode, boolean supportsPictureInPicture, boolean privileged,
388 boolean _realActivitySuspended, boolean userSetupComplete, int minWidth,
389 int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700390 mService = service;
Craig Mautnera228ae92014-07-09 05:44:55 -0700391 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
392 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800393 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(_userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800394 mLastThumbnailInfo = lastThumbnailInfo;
Craig Mautner21d24a22014-04-23 11:45:37 -0700395 taskId = _taskId;
396 intent = _intent;
397 affinityIntent = _affinityIntent;
398 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800399 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700400 voiceSession = null;
401 voiceInteractor = null;
402 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800403 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700404 origActivity = _origActivity;
405 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700406 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700407 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700408 askedCompatMode = _askedCompatMode;
409 taskType = _taskType;
Craig Mautner84984fa2014-06-19 11:19:20 -0700410 mTaskToReturnTo = HOME_ACTIVITY_TYPE;
Craig Mautner21d24a22014-04-23 11:45:37 -0700411 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800412 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700413 effectiveUid = _effectiveUid;
Winson Chungffa2ec62014-07-03 15:54:42 -0700414 firstActiveTime = _firstActiveTime;
Winson Chungf1fbd772014-06-24 18:06:58 -0700415 lastActiveTime = _lastActiveTime;
Craig Mautner21d24a22014-04-23 11:45:37 -0700416 lastDescription = _lastDescription;
417 mActivities = activities;
418 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700419 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700420 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700421 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700422 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700423 mPrevAffiliateTaskId = prevTaskId;
424 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700425 mCallingUid = callingUid;
426 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800427 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800428 mSupportsPictureInPicture = supportsPictureInPicture;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700429 mPrivileged = privileged;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700430 mMinWidth = minWidth;
431 mMinHeight = minHeight;
Yorke Leebd54c2a2016-10-25 13:49:23 -0700432 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 }
434
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800435 TaskWindowContainerController getWindowContainerController() {
436 return mWindowContainerController;
437 }
438
439 void createWindowContainer(boolean onTop, boolean showForAllUsers) {
440 if (mWindowContainerController != null) {
441 throw new IllegalArgumentException("Window container=" + mWindowContainerController
442 + " already created for task=" + this);
443 }
444
445 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
446 final Configuration overrideConfig = getOverrideConfiguration();
Wale Ogunwale1666e312016-12-16 11:27:18 -0800447 mWindowContainerController = new TaskWindowContainerController(taskId, this,
448 getStack().getWindowContainerController(), userId, bounds, overrideConfig,
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800449 mResizeMode, mSupportsPictureInPicture, isHomeTask(), onTop, showForAllUsers,
450 lastTaskDescription);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800451 }
452
453 void removeWindowContainer() {
454 mService.mStackSupervisor.removeLockedTaskLocked(this);
455 mWindowContainerController.removeContainer();
456 if (!StackId.persistTaskBounds(getStackId())) {
457 // 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) {
491 if (!isResizeable()) {
492 Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
493 return true;
494 }
495
496 // If this is a forced resize, let it go through even if the bounds is not changing,
497 // as we might need a relayout due to surface size change (to/from fullscreen).
498 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
499 if (Objects.equals(mBounds, bounds) && !forced) {
500 // Nothing to do here...
501 return true;
502 }
503 bounds = validateBounds(bounds);
504
505 if (mWindowContainerController == null) {
506 // Task doesn't exist in window manager yet (e.g. was restored from recents).
507 // All we can do for now is update the bounds so it can be used when the task is
508 // added to window manager.
509 updateOverrideConfiguration(bounds);
510 if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
511 // re-restore the task so it can have the proper stack association.
512 mService.mStackSupervisor.restoreRecentTaskLocked(this,
513 FREEFORM_WORKSPACE_STACK_ID);
514 }
515 return true;
516 }
517
518 if (!canResizeToBounds(bounds)) {
519 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
520 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
521 }
522
523 // Do not move the task to another stack here.
524 // This method assumes that the task is already placed in the right stack.
525 // we do not mess with that decision and we only do the resize!
526
527 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
528
529 final boolean updatedConfig = updateOverrideConfiguration(bounds);
530 // This variable holds information whether the configuration didn't change in a significant
531 // way and the activity was kept the way it was. If it's false, it means the activity had
532 // to be relaunched due to configuration change.
533 boolean kept = true;
534 if (updatedConfig) {
535 final ActivityRecord r = topRunningActivityLocked();
536 if (r != null) {
537 kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow);
538
539 if (!deferResume) {
540 // All other activities must be made visible with their correct configuration.
541 mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
542 if (!kept) {
543 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
544 }
545 }
546 }
547 }
548 mWindowContainerController.resize(mBounds, getOverrideConfiguration(), kept, forced);
549
550 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
551 return kept;
552 }
553
554 // TODO: Investigate combining with the resize() method above.
555 void resizeWindowContainer() {
556 mWindowContainerController.resize(mBounds, getOverrideConfiguration(), false /* relayout */,
557 false /* forced */);
558 }
559
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800560 void getWindowContainerBounds(Rect bounds) {
561 mWindowContainerController.getBounds(bounds);
562 }
563
Winson Chung74666102017-02-22 17:49:24 -0800564 /**
565 * Convenience method to reparent a task to the top or bottom position of the stack.
566 */
567 boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
568 boolean animate, boolean deferResume, String reason) {
569 return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
570 deferResume, reason);
571 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800572
Winson Chung74666102017-02-22 17:49:24 -0800573 /**
574 * Reparents the task into a preferred stack, creating it if necessary.
575 *
576 * @param preferredStackId the stack id of the target stack to move this task
577 * @param position the position to place this task in the new stack
578 * @param animate whether or not we should wait for the new window created as a part of the
579 * reparenting to be drawn and animated in
580 * @param moveStackMode whether or not to move the stack to the front always, only if it was
581 * previously focused & in front, or never
582 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
583 * have changed as a result of this reparenting
584 * @param reason the caller of this reparenting
585 * @return
586 */
587 boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
588 boolean animate, boolean deferResume, String reason) {
589 final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
590 final WindowManagerService windowManager = mService.mWindowManager;
591 final ActivityStack sourceStack = getStack();
592 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStackId,
593 position == MAX_VALUE);
594 if (toStack == sourceStack) {
595 return false;
596 }
597
598 final int sourceStackId = getStackId();
599 final int stackId = toStack.getStackId();
600 final ActivityRecord topActivity = getTopActivity();
601
602 final boolean mightReplaceWindow = StackId.replaceWindowsOnTaskMove(sourceStackId, stackId)
603 && topActivity != null;
604 if (mightReplaceWindow) {
605 // We are about to relaunch the activity because its configuration changed due to
606 // being maximized, i.e. size change. The activity will first remove the old window
607 // and then add a new one. This call will tell window manager about this, so it can
608 // preserve the old window until the new one is drawn. This prevents having a gap
609 // between the removal and addition, in which no window is visible. We also want the
610 // entrance of the new window to be properly animated.
611 // Note here we always set the replacing window first, as the flags might be needed
612 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
613 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
614 }
615
616 windowManager.deferSurfaceLayout();
617 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800618 try {
Winson Chung74666102017-02-22 17:49:24 -0800619 final ActivityRecord r = topRunningActivityLocked();
620 final boolean wasFocused = supervisor.isFocusedStack(sourceStack)
621 && (topRunningActivityLocked() == r);
622 final boolean wasResumed = sourceStack.mResumedActivity == r;
623 final boolean wasPaused = sourceStack.mPausingActivity == r;
624
625 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
626 // Whenever we are moving the top activity from the front stack we want to make sure to
627 // move the stack to the front.
628 final boolean wasFront = supervisor.isFrontStackOnDisplay(sourceStack)
629 && (sourceStack.topRunningActivityLocked() == r);
630
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800631 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800632 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800633
634 // Must reparent first in window manager to avoid a situation where AM can delete the
635 // we are coming from in WM before we reparent because it became empty.
Winson Chung74666102017-02-22 17:49:24 -0800636 mWindowContainerController.reparent(toStack.getWindowContainerController(), position);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800637
Winson Chung74666102017-02-22 17:49:24 -0800638 // Reset the resumed activity on the previous stack
639 if (wasResumed) {
640 sourceStack.mResumedActivity = null;
641 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800642
Winson Chung74666102017-02-22 17:49:24 -0800643 // Reset the paused activity on the previous stack
644 if (wasPaused) {
645 sourceStack.mPausingActivity = null;
646 sourceStack.removeTimeoutsForActivityLocked(r);
647 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800648
Winson Chung74666102017-02-22 17:49:24 -0800649 // Move the task
650 sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
651 toStack.addTask(this, position, reason);
652
653 // TODO: Ensure that this is actually necessary here
654 // Notify of picture-in-picture mode changes
655 supervisor.scheduleReportPictureInPictureModeChangedIfNeeded(this, sourceStack);
656
657 // TODO: Ensure that this is actually necessary here
658 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800659 if (voiceSession != null) {
660 try {
661 voiceSession.taskStarted(intent, taskId);
662 } catch (RemoteException e) {
663 }
664 }
Winson Chung74666102017-02-22 17:49:24 -0800665
666 // If the task had focus before (or we're requested to move focus), move focus to the
667 // new stack by moving the stack to the front.
668 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
669 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
670 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed, wasPaused,
671 reason);
672 if (!animate) {
673 toStack.mNoAnimActivities.add(topActivity);
674 }
675
676 // We might trigger a configuration change. Save the current task bounds for freezing.
677 // TODO: Should this call be moved inside the resize method in WM?
678 toStack.prepareFreezingTaskBounds();
679
680 // Make sure the task has the appropriate bounds/size for the stack it is in.
681 if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
682 && !Objects.equals(mBounds, toStack.mBounds)) {
683 kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
684 deferResume);
685 } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
686 Rect bounds = getLaunchBounds();
687 if (bounds == null) {
688 toStack.layoutTaskInStack(this, null);
689 bounds = mBounds;
690 }
691 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
692 } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
693 kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
694 deferResume);
695 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800696 } finally {
Winson Chung74666102017-02-22 17:49:24 -0800697 windowManager.continueSurfaceLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800698 }
Winson Chung74666102017-02-22 17:49:24 -0800699
700 if (mightReplaceWindow) {
701 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
702 // window), we need to clear the replace window settings. Otherwise, we schedule a
703 // timeout to remove the old window if the replacing window is not coming in time.
704 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
705 }
706
707 if (!deferResume) {
708 // The task might have already been running and its visibility needs to be synchronized
709 // with the visibility of the stack / windows.
710 supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
711 supervisor.resumeFocusedStackTopActivityLocked();
712 }
713
714 supervisor.handleNonResizableTaskIfNeeded(this, preferredStackId, stackId);
715
716 return (preferredStackId == stackId);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800717 }
718
719 void cancelWindowTransition() {
720 mWindowContainerController.cancelWindowTransition();
721 }
722
723 void cancelThumbnailTransition() {
724 mWindowContainerController.cancelThumbnailTransition();
725 }
726
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100727 /**
728 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
729 */
730 TaskSnapshot getSnapshot() {
731
732 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
733 // synchronized between AM and WM.
734 return mService.mWindowManager.getTaskSnapshot(taskId, userId);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800735 }
736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 void touchActiveTime() {
Winson Chung36f3f032016-09-08 23:29:43 +0000738 lastActiveTime = System.currentTimeMillis();
Winson Chungffa2ec62014-07-03 15:54:42 -0700739 if (firstActiveTime == 0) {
740 firstActiveTime = lastActiveTime;
741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 long getInactiveDuration() {
Winson Chung36f3f032016-09-08 23:29:43 +0000745 return System.currentTimeMillis() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700747
Winson Chungfee26772014-08-05 12:21:52 -0700748 /** Sets the original intent, and the calling uid and package. */
749 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700750 mCallingUid = r.launchedFromUid;
751 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700752 setIntent(r.intent, r.info);
Winson Chungfee26772014-08-05 12:21:52 -0700753 }
754
755 /** Sets the original intent, _without_ updating the calling uid or package. */
756 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700757 if (intent == null) {
758 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700759 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700760 } else if (mNeverRelinquishIdentity) {
761 return;
762 }
763
764 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700765 if (intent == null) {
766 // If this task already has an intent associated with it, don't set the root
767 // affinity -- we don't want it changing after initially set, but the initially
768 // set value may be null.
769 rootAffinity = affinity;
770 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700771 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700772 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800775 if (_intent != null) {
776 // If this Intent has a selector, we want to clear it for the
777 // recent task since it is not relevant if the user later wants
778 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700779 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800780 _intent = new Intent(_intent);
781 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700782 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800783 }
784 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700785 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 intent = _intent;
787 realActivity = _intent != null ? _intent.getComponent() : null;
788 origActivity = null;
789 } else {
790 ComponentName targetComponent = new ComponentName(
791 info.packageName, info.targetActivity);
792 if (_intent != null) {
793 Intent targetIntent = new Intent(_intent);
794 targetIntent.setComponent(targetComponent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800795 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700796 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700797 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700798 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 intent = targetIntent;
800 realActivity = targetComponent;
801 origActivity = _intent.getComponent();
802 } else {
803 intent = null;
804 realActivity = targetComponent;
805 origActivity = new ComponentName(info.packageName, info.name);
806 }
807 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700808
Craig Mautner47b20ba2014-09-17 17:23:44 -0700809 final int intentFlags = intent == null ? 0 : intent.getFlags();
810 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 // Once we are set to an Intent with this flag, we count this
812 // task as having a true root activity.
813 rootWasReset = true;
814 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700815 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000816 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
817 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700818 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700819 // If the activity itself has requested auto-remove, then just always do it.
820 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700821 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
822 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700823 // If the caller has not asked for the document to be retained, then we may
824 // want to turn on auto-remove, depending on whether the target has set its
825 // own document launch mode.
826 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
827 autoRemoveRecents = false;
828 } else {
829 autoRemoveRecents = true;
830 }
831 } else {
832 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700833 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800834 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800835 mSupportsPictureInPicture = info.supportsPictureInPicture();
Craig Mautner15df08a2015-04-01 12:17:18 -0700836 mLockTaskMode = info.lockTaskLaunchMode;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700837 mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
Craig Mautner15df08a2015-04-01 12:17:18 -0700838 setLockTaskAuth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800840
Andrii Kulian2e751b82016-03-16 16:59:32 -0700841 /** Sets the original minimal width and height. */
842 private void setMinDimensions(ActivityInfo info) {
843 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700844 mMinWidth = info.windowLayout.minWidth;
845 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700846 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700847 mMinWidth = INVALID_MIN_SIZE;
848 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700849 }
850 }
851
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800852 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700853 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800854 * record is based on (normally the root activity intent).
855 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700856 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800857 final Intent intent = new Intent(r.intent);
858 // Correct the activity intent for aliasing. The task record intent will always be based on
859 // the real activity that will be launched not the alias, so we need to use an intent with
860 // the component name pointing to the real activity not the alias in the activity record.
861 intent.setComponent(r.realActivity);
862 return this.intent.filterEquals(intent);
863 }
864
Craig Mautner84984fa2014-06-19 11:19:20 -0700865 void setTaskToReturnTo(int taskToReturnTo) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -0800866 mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
867 ? HOME_ACTIVITY_TYPE : taskToReturnTo;
Craig Mautner84984fa2014-06-19 11:19:20 -0700868 }
869
Winson Chung83471632016-12-13 11:02:12 -0800870 void setTaskToReturnTo(ActivityRecord source) {
871 if (source.isRecentsActivity()) {
872 setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
873 } else if (source.isAssistantActivity()) {
874 setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
875 }
876 }
877
Craig Mautner84984fa2014-06-19 11:19:20 -0700878 int getTaskToReturnTo() {
879 return mTaskToReturnTo;
880 }
881
Craig Mautnera228ae92014-07-09 05:44:55 -0700882 void setPrevAffiliate(TaskRecord prevAffiliate) {
883 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800884 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700885 }
886
887 void setNextAffiliate(TaskRecord nextAffiliate) {
888 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800889 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700890 }
891
Andrii Kulian02b7a832016-10-06 23:11:56 -0700892 ActivityStack getStack() {
893 return mStack;
894 }
895
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800896 /**
897 * Must be used for setting parent stack because it performs configuration updates.
898 * Must be called after adding task as a child to the stack.
899 */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700900 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800901 if (stack != null && !stack.isInStackLocked(this)) {
902 throw new IllegalStateException("Task must be added as a Stack child first.");
903 }
Andrii Kulian02b7a832016-10-06 23:11:56 -0700904 mStack = stack;
Andrii Kulian1779e612016-10-12 21:58:25 -0700905 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700906 }
907
908 /**
909 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
910 */
911 int getStackId() {
912 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
913 }
914
Andrii Kulian1779e612016-10-12 21:58:25 -0700915 @Override
916 protected int getChildCount() {
917 return 0;
918 }
919
920 @Override
921 protected ConfigurationContainer getChildAt(int index) {
922 return null;
923 }
924
925 @Override
926 protected ConfigurationContainer getParent() {
927 return mStack;
928 }
929
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800930 @Override
931 void onParentChanged() {
932 super.onParentChanged();
933 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
934 }
935
Craig Mautnera228ae92014-07-09 05:44:55 -0700936 // Close up recents linked list.
937 void closeRecentsChain() {
938 if (mPrevAffiliate != null) {
939 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
940 }
941 if (mNextAffiliate != null) {
942 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
943 }
944 setPrevAffiliate(null);
945 setNextAffiliate(null);
946 }
947
Winson Chung740c3ac2014-11-12 16:14:38 -0800948 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -0700949 disposeThumbnail();
950 closeRecentsChain();
951 if (inRecents) {
952 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -0800953 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700954 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +0100955
956 // TODO: Use window container controller once tasks are better synced between AM and WM
957 mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700958 }
959
Craig Mautnera228ae92014-07-09 05:44:55 -0700960 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
961 closeRecentsChain();
962 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -0700963 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700964 // Find the end
965 while (taskToAffiliateWith.mNextAffiliate != null) {
966 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
967 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
968 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
969 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
970 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
971 nextRecents.setPrevAffiliate(null);
972 }
973 taskToAffiliateWith.setNextAffiliate(null);
974 break;
975 }
976 taskToAffiliateWith = nextRecents;
977 }
978 taskToAffiliateWith.setNextAffiliate(this);
979 setPrevAffiliate(taskToAffiliateWith);
980 setNextAffiliate(null);
981 }
982
Winson Chung096f36b2014-08-20 15:39:01 -0700983 /**
Winsonc809cbb2015-11-02 12:06:15 -0800984 * Sets the last thumbnail with the current task bounds and the system orientation.
Winson Chung096f36b2014-08-20 15:39:01 -0700985 * @return whether the thumbnail was set
986 */
Winsonc809cbb2015-11-02 12:06:15 -0800987 boolean setLastThumbnailLocked(Bitmap thumbnail) {
Winsonc809cbb2015-11-02 12:06:15 -0800988 int taskWidth = 0;
989 int taskHeight = 0;
990 if (mBounds != null) {
991 // Non-fullscreen tasks
992 taskWidth = mBounds.width();
993 taskHeight = mBounds.height();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700994 } else if (mStack != null) {
Winsonc809cbb2015-11-02 12:06:15 -0800995 // Fullscreen tasks
996 final Point displaySize = new Point();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700997 mStack.getDisplaySize(displaySize);
Winsonc809cbb2015-11-02 12:06:15 -0800998 taskWidth = displaySize.x;
999 taskHeight = displaySize.y;
1000 } else {
1001 Slog.e(TAG, "setLastThumbnailLocked() called on Task without stack");
1002 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001003 // We need to provide the current orientation of the display on which this task resides,
1004 // not the orientation of the task.
1005 final int orientation =
1006 getStack().mActivityContainer.mActivityDisplay.getConfiguration().orientation;
1007 return setLastThumbnailLocked(thumbnail, taskWidth, taskHeight, orientation);
Winsonc809cbb2015-11-02 12:06:15 -08001008 }
1009
1010 /**
1011 * Sets the last thumbnail with the current task bounds.
1012 * @return whether the thumbnail was set
1013 */
1014 private boolean setLastThumbnailLocked(Bitmap thumbnail, int taskWidth, int taskHeight,
1015 int screenOrientation) {
Winson Chung096f36b2014-08-20 15:39:01 -07001016 if (mLastThumbnail != thumbnail) {
1017 mLastThumbnail = thumbnail;
Winsonc809cbb2015-11-02 12:06:15 -08001018 mLastThumbnailInfo.taskWidth = taskWidth;
1019 mLastThumbnailInfo.taskHeight = taskHeight;
1020 mLastThumbnailInfo.screenOrientation = screenOrientation;
Winson Chung096f36b2014-08-20 15:39:01 -07001021 if (thumbnail == null) {
1022 if (mLastThumbnailFile != null) {
1023 mLastThumbnailFile.delete();
1024 }
1025 } else {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001026 mService.mRecentTasks.saveImage(thumbnail, mLastThumbnailFile.getAbsolutePath());
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001027 }
Winson Chung096f36b2014-08-20 15:39:01 -07001028 return true;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001029 }
Winson Chung096f36b2014-08-20 15:39:01 -07001030 return false;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001031 }
1032
1033 void getLastThumbnail(TaskThumbnail thumbs) {
1034 thumbs.mainThumbnail = mLastThumbnail;
Winsonc809cbb2015-11-02 12:06:15 -08001035 thumbs.thumbnailInfo = mLastThumbnailInfo;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001036 thumbs.thumbnailFileDescriptor = null;
Craig Mautnerf4f8bb72014-07-29 10:41:40 -07001037 if (mLastThumbnail == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001038 thumbs.mainThumbnail = mService.mRecentTasks.getImageFromWriteQueue(
Suprabh Shukla23593142015-11-03 17:31:15 -08001039 mLastThumbnailFile.getAbsolutePath());
Craig Mautnerf4f8bb72014-07-29 10:41:40 -07001040 }
Winson Chung096f36b2014-08-20 15:39:01 -07001041 // Only load the thumbnail file if we don't have a thumbnail
1042 if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001043 try {
1044 thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,
1045 ParcelFileDescriptor.MODE_READ_ONLY);
1046 } catch (IOException e) {
Dianne Hackborn9844d292013-10-04 16:44:22 -07001047 }
1048 }
1049 }
1050
Winsonc809cbb2015-11-02 12:06:15 -08001051 /**
1052 * Removes in-memory thumbnail data when the max number of in-memory task thumbnails is reached.
1053 */
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001054 void freeLastThumbnail() {
1055 mLastThumbnail = null;
1056 }
1057
Winsonc809cbb2015-11-02 12:06:15 -08001058 /**
1059 * Removes all associated thumbnail data when a task is removed or pruned from recents.
1060 */
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001061 void disposeThumbnail() {
Winsonc6a2da02015-11-11 18:11:59 -08001062 mLastThumbnailInfo.reset();
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001063 mLastThumbnail = null;
1064 lastDescription = null;
1065 }
1066
Winson Chung1147c402014-05-14 11:05:00 -07001067 /** Returns the intent for the root activity for this task */
1068 Intent getBaseIntent() {
1069 return intent != null ? intent : affinityIntent;
1070 }
1071
Winson Chung3b3f4642014-04-22 10:08:18 -07001072 /** Returns the first non-finishing activity from the root. */
1073 ActivityRecord getRootActivity() {
1074 for (int i = 0; i < mActivities.size(); i++) {
1075 final ActivityRecord r = mActivities.get(i);
1076 if (r.finishing) {
1077 continue;
1078 }
1079 return r;
1080 }
1081 return null;
1082 }
1083
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001084 ActivityRecord getTopActivity() {
1085 for (int i = mActivities.size() - 1; i >= 0; --i) {
1086 final ActivityRecord r = mActivities.get(i);
1087 if (r.finishing) {
1088 continue;
1089 }
1090 return r;
1091 }
1092 return null;
1093 }
1094
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001095 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001096 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001097 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1098 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001099 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001100 return r;
1101 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001102 }
1103 }
1104 return null;
1105 }
1106
Wale Ogunwale3b232392016-05-13 15:37:13 -07001107 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001108 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001109 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1110 ActivityRecord r = mActivities.get(activityNdx);
1111 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001112 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001113 continue;
1114 }
1115 return r;
1116 }
1117 }
1118 return null;
1119 }
1120
Chong Zhang87761972016-08-22 13:53:24 -07001121 boolean okToShowLocked() {
1122 // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
1123 // okay to show the activity when locked.
1124 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
1125 || topRunningActivityLocked() != null;
1126 }
1127
Craig Mautner3b475fe2013-12-16 15:58:31 -08001128 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Bryce Leed71317c2017-02-07 14:27:22 -08001129 final void setFrontOfTask() {
1130 boolean foundFront = false;
Craig Mautner3b475fe2013-12-16 15:58:31 -08001131 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -08001132 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -08001133 final ActivityRecord r = mActivities.get(activityNdx);
1134 if (foundFront || r.finishing) {
1135 r.frontOfTask = false;
1136 } else {
1137 r.frontOfTask = true;
1138 // Set frontOfTask false for every following activity.
1139 foundFront = true;
1140 }
1141 }
Craig Mautner9587ee02014-06-23 15:00:10 +00001142 if (!foundFront && numActivities > 0) {
1143 // All activities of this task are finishing. As we ought to have a frontOfTask
1144 // activity, make the bottom activity front.
1145 mActivities.get(0).frontOfTask = true;
1146 }
Craig Mautner3b475fe2013-12-16 15:58:31 -08001147 }
1148
Craig Mautnerde4ef022013-04-07 19:01:33 -07001149 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001150 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001151 */
1152 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001153 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1154 "Removing and adding activity " + newTop
1155 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001156
Craig Mautnerde4ef022013-04-07 19:01:33 -07001157 mActivities.remove(newTop);
1158 mActivities.add(newTop);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001159 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -08001160
Bryce Leed71317c2017-02-07 14:27:22 -08001161 setFrontOfTask();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001162 }
1163
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001164 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -08001165 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001166 }
1167
1168 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001169 addActivityAtIndex(mActivities.size(), r);
1170 }
1171
Winson Chung30480042017-01-26 10:55:34 -08001172 /**
1173 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1174 * be in the current task or unparented to any task.
1175 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001176 void addActivityAtIndex(int index, ActivityRecord r) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001177 if (r.task != null && r.task != this) {
1178 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
1179 + " current parent=" + r.task);
1180 }
1181 r.task = this;
1182
Craig Mautner6170f732013-04-02 13:05:23 -07001183 // 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 -08001184 if (!mActivities.remove(r) && r.fullscreen) {
1185 // Was not previously in list.
1186 numFullscreen++;
1187 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001188 // Only set this based on the first activity
1189 if (mActivities.isEmpty()) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001190 taskType = r.mActivityType;
1191 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001192 mCallingUid = r.launchedFromUid;
1193 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001194 // Clamp to [1, max].
1195 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1196 ActivityManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001197 } else {
1198 // Otherwise make all added activities match this one.
Craig Mautner21d24a22014-04-23 11:45:37 -07001199 r.mActivityType = taskType;
Craig Mautner78733002013-06-10 13:54:49 -07001200 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001201
1202 final int size = mActivities.size();
1203
1204 if (index == size && size > 0) {
1205 final ActivityRecord top = mActivities.get(size - 1);
1206 if (top.mTaskOverlay) {
1207 // Place below the task overlay activity since the overlay activity should always
1208 // be on top.
1209 index--;
1210 }
1211 }
1212
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001213 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001214 mActivities.add(index, r);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001215 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001216 if (r.isPersistable()) {
1217 mService.notifyTaskPersisterLocked(this, false);
1218 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001219
1220 // Sync. with window manager
1221 updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001222 final AppWindowContainerController appController = r.getWindowContainerController();
1223 if (appController != null) {
1224 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1225 // created controller for the activity we are starting yet.
1226 mWindowContainerController.positionChildAt(appController, index);
1227 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001228 r.onOverrideConfigurationSent();
Craig Mautner77878772013-03-04 19:46:24 -08001229 }
1230
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001231 /** @return true if this was the last activity in the task */
1232 boolean removeActivity(ActivityRecord r) {
1233 if (mActivities.remove(r) && r.fullscreen) {
1234 // Was previously in list.
1235 numFullscreen--;
1236 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001237 if (r.isPersistable()) {
1238 mService.notifyTaskPersisterLocked(this, false);
1239 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001240
Andrii Kulian02b7a832016-10-06 23:11:56 -07001241 if (getStackId() == PINNED_STACK_ID) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001242 // We normally notify listeners of task stack changes on pause, however pinned stack
1243 // activities are normally in the paused state so no notification will be sent there
1244 // before the activity is removed. We send it here so instead.
Yorke Leebd54c2a2016-10-25 13:49:23 -07001245 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001246 }
1247
Craig Mautner41326202014-06-20 14:38:21 -07001248 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001249 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001250 }
1251 updateEffectiveIntent();
1252 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001253 }
1254
Craig Mautner41db4a72014-05-07 17:20:56 -07001255 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001256 // We will automatically remove the task either if it has explicitly asked for
1257 // this, or it is empty and has never contained an activity that got shown to
1258 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -07001259 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001260 }
1261
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001262 /**
1263 * Completely remove all activities associated with an existing
1264 * task starting at a specified index.
1265 */
1266 final void performClearTaskAtIndexLocked(int activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001267 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001268 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001269 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001270 if (r.finishing) {
1271 continue;
1272 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001273 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001274 // Task was restored from persistent storage.
1275 r.takeFromHistory();
1276 mActivities.remove(activityNdx);
1277 --activityNdx;
1278 --numActivities;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001279 } else if (mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001280 r, Activity.RESULT_CANCELED, null, "clear-task-index", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001281 --activityNdx;
1282 --numActivities;
1283 }
1284 }
1285 }
1286
1287 /**
1288 * Completely remove all activities associated with an existing task.
1289 */
1290 final void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001291 mReuseTask = true;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001292 performClearTaskAtIndexLocked(0);
Craig Mautner362449a2014-06-20 14:04:39 -07001293 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001294 }
1295
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001296 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1297 mReuseTask = true;
1298 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1299 mReuseTask = false;
1300 return result;
1301 }
1302
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001303 /**
1304 * Perform clear operation as requested by
1305 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1306 * stack to the given task, then look for
1307 * an instance of that activity in the stack and, if found, finish all
1308 * activities on top of it and return the instance.
1309 *
1310 * @param newR Description of the new activity being started.
1311 * @return Returns the old activity that should be continued to be used,
1312 * or null if none was found.
1313 */
1314 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001315 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001316 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001317 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001318 if (r.finishing) {
1319 continue;
1320 }
1321 if (r.realActivity.equals(newR.realActivity)) {
1322 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001323 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001324
1325 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001326 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001327 if (r.finishing) {
1328 continue;
1329 }
1330 ActivityOptions opts = r.takeOptionsLocked();
1331 if (opts != null) {
1332 ret.updateOptionsLocked(opts);
1333 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001334 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001335 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001336 --activityNdx;
1337 --numActivities;
1338 }
1339 }
1340
1341 // Finally, if this is a normal launch mode (that is, not
1342 // expecting onNewIntent()), then we will finish the current
1343 // instance of the activity so a new fresh one can be started.
1344 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001345 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1346 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001347 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001348 if (mStack != null) {
1349 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -07001350 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1351 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001352 return null;
1353 }
1354 }
1355
1356 return ret;
1357 }
1358 }
1359
1360 return null;
1361 }
1362
Andrii Kulian21713ac2016-10-12 22:05:05 -07001363 TaskThumbnail getTaskThumbnailLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001364 if (mStack != null) {
1365 final ActivityRecord resumedActivity = mStack.mResumedActivity;
Craig Mautner21d24a22014-04-23 11:45:37 -07001366 if (resumedActivity != null && resumedActivity.task == this) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07001367 final Bitmap thumbnail = resumedActivity.screenshotActivityLocked();
Winsonc809cbb2015-11-02 12:06:15 -08001368 setLastThumbnailLocked(thumbnail);
Craig Mautner21d24a22014-04-23 11:45:37 -07001369 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001370 }
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001371 final TaskThumbnail taskThumbnail = new TaskThumbnail();
1372 getLastThumbnail(taskThumbnail);
1373 return taskThumbnail;
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001374 }
1375
Andrii Kulian21713ac2016-10-12 22:05:05 -07001376 void removeTaskActivitiesLocked() {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001377 // Just remove the entire task.
1378 performClearTaskAtIndexLocked(0);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001379 }
1380
Craig Mautner432f64e2015-05-20 14:59:57 -07001381 String lockTaskAuthToString() {
1382 switch (mLockTaskAuth) {
1383 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1384 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1385 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1386 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001387 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001388 default: return "unknown=" + mLockTaskAuth;
1389 }
1390 }
1391
Craig Mautner15df08a2015-04-01 12:17:18 -07001392 void setLockTaskAuth() {
Benjamin Franz469dd582015-06-09 14:24:36 +01001393 if (!mPrivileged &&
1394 (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS ||
1395 mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1396 // Non-priv apps are not allowed to use always or never, fall back to default
1397 mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1398 }
Craig Mautner15df08a2015-04-01 12:17:18 -07001399 switch (mLockTaskMode) {
1400 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1401 mLockTaskAuth = isLockTaskWhitelistedLocked() ?
1402 LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1403 break;
1404
1405 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001406 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001407 break;
1408
1409 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001410 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001411 break;
1412
1413 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1414 mLockTaskAuth = isLockTaskWhitelistedLocked() ?
1415 LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1416 break;
1417 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001418 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1419 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001420 }
1421
1422 boolean isLockTaskWhitelistedLocked() {
Benjamin Franz6fd84cc2015-08-06 18:09:03 +01001423 String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1424 if (pkg == null) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001425 return false;
1426 }
1427 String[] packages = mService.mLockTaskPackages.get(userId);
1428 if (packages == null) {
1429 return false;
1430 }
1431 for (int i = packages.length - 1; i >= 0; --i) {
Benjamin Franz6fd84cc2015-08-06 18:09:03 +01001432 if (pkg.equals(packages[i])) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001433 return true;
1434 }
1435 }
1436 return false;
1437 }
Wale Ogunwale74e26592016-02-05 11:48:37 -08001438
Craig Mautnera82aa092013-09-13 15:34:08 -07001439 boolean isHomeTask() {
Craig Mautner84984fa2014-06-19 11:19:20 -07001440 return taskType == HOME_ACTIVITY_TYPE;
Craig Mautnera82aa092013-09-13 15:34:08 -07001441 }
1442
Wale Ogunwale74e26592016-02-05 11:48:37 -08001443 boolean isRecentsTask() {
1444 return taskType == RECENTS_ACTIVITY_TYPE;
1445 }
1446
Winson Chung83471632016-12-13 11:02:12 -08001447 boolean isAssistantTask() {
1448 return taskType == ASSISTANT_ACTIVITY_TYPE;
1449 }
1450
Craig Mautner86d67a42013-05-14 10:34:38 -07001451 boolean isApplicationTask() {
Craig Mautner84984fa2014-06-19 11:19:20 -07001452 return taskType == APPLICATION_ACTIVITY_TYPE;
1453 }
1454
1455 boolean isOverHomeStack() {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001456 return mTaskToReturnTo == HOME_ACTIVITY_TYPE;
Craig Mautner1602ec22013-05-12 10:24:27 -07001457 }
1458
Winson Chung83471632016-12-13 11:02:12 -08001459 boolean isOverAssistantStack() {
1460 return mTaskToReturnTo == ASSISTANT_ACTIVITY_TYPE;
1461 }
1462
Winson Chungd3395382016-12-13 11:49:09 -08001463 private boolean isResizeable(boolean checkSupportsPip) {
1464 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
1465 || (checkSupportsPip && mSupportsPictureInPicture)) && !mTemporarilyUnresizable;
1466 }
1467
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001468 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001469 return isResizeable(true /* checkSupportsPip */);
1470 }
1471
1472 boolean supportsSplitScreen() {
1473 // A task can not be docked even if it is considered resizeable because it only supports
1474 // picture-in-picture mode but has a non-resizeable resizeMode
1475 return mService.mSupportsSplitScreenMultiWindow
1476 && isResizeable(false /* checkSupportsPip */)
1477 && !ActivityInfo.isPreserveOrientationMode(mResizeMode);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001478 }
1479
skuhne@google.com322347b2016-12-02 12:54:03 -08001480 /**
1481 * Check that a given bounds matches the application requested orientation.
1482 *
1483 * @param bounds The bounds to be tested.
1484 * @return True if the requested bounds are okay for a resizing request.
1485 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001486 private boolean canResizeToBounds(Rect bounds) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001487 if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
1488 // Note: If not on the freeform workspace, we ignore the bounds.
1489 return true;
1490 }
1491 final boolean landscape = bounds.width() > bounds.height();
1492 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1493 return mBounds == null || landscape == (mBounds.width() > mBounds.height());
1494 }
1495 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1496 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1497 }
1498
Craig Mautner525f3d92013-05-07 14:01:50 -07001499 /**
1500 * Find the activity in the history stack within the given task. Returns
1501 * the index within the history at which it's found, or < 0 if not found.
1502 */
1503 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
1504 final ComponentName realActivity = r.realActivity;
1505 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1506 ActivityRecord candidate = mActivities.get(activityNdx);
1507 if (candidate.finishing) {
1508 continue;
1509 }
1510 if (candidate.realActivity.equals(realActivity)) {
1511 return candidate;
1512 }
1513 }
1514 return null;
1515 }
1516
Winson Chunga449dc02014-05-16 11:15:04 -07001517 /** Updates the last task description values. */
1518 void updateTaskDescription() {
1519 // Traverse upwards looking for any break between main task activities and
1520 // utility activities.
1521 int activityNdx;
1522 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001523 final boolean relinquish = numActivities != 0 &&
1524 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001525 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001526 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001527 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001528 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001529 // This will be the top activity for determining taskDescription. Pre-inc to
1530 // overcome initial decrement below.
1531 ++activityNdx;
1532 break;
1533 }
Winson Chunga449dc02014-05-16 11:15:04 -07001534 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001535 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001536 break;
1537 }
1538 }
1539 if (activityNdx > 0) {
1540 // Traverse downwards starting below break looking for set label, icon.
1541 // Note that if there are activities in the task but none of them set the
1542 // recent activity values, then we do not fall back to the last set
1543 // values in the TaskRecord.
1544 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001545 String iconFilename = null;
Winson Chunga449dc02014-05-16 11:15:04 -07001546 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001547 int colorBackground = 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001548 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1549 final ActivityRecord r = mActivities.get(activityNdx);
1550 if (r.taskDescription != null) {
1551 if (label == null) {
1552 label = r.taskDescription.getLabel();
1553 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001554 if (iconFilename == null) {
1555 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001556 }
1557 if (colorPrimary == 0) {
1558 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001559 }
Winson Chung1af8eda2016-02-05 17:55:56 +00001560 if (colorBackground == 0) {
1561 colorBackground = r.taskDescription.getBackgroundColor();
1562 }
Winson Chunga449dc02014-05-16 11:15:04 -07001563 }
1564 }
Winson Chung1af8eda2016-02-05 17:55:56 +00001565 lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
1566 colorBackground);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001567 if (mWindowContainerController != null) {
1568 mWindowContainerController.setTaskDescription(lastTaskDescription);
1569 }
Winson Chungec396d62014-08-06 17:08:00 -07001570 // Update the task affiliation color if we are the parent of the group
1571 if (taskId == mAffiliatedTaskId) {
1572 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1573 }
Winson Chunga449dc02014-05-16 11:15:04 -07001574 }
1575 }
1576
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001577 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001578 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001579 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001580 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001581 final ActivityRecord r = mActivities.get(activityNdx);
1582 if (r.finishing) {
1583 continue;
1584 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001585 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001586 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001587 break;
1588 }
1589 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001590 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001591 }
1592
1593 void updateEffectiveIntent() {
1594 final int effectiveRootIndex = findEffectiveRootIndex();
1595 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001596 setIntent(r);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001597 }
1598
Craig Mautner21d24a22014-04-23 11:45:37 -07001599 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
Wale Ogunwaleee006da2015-03-30 14:49:25 -07001600 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
Craig Mautner21d24a22014-04-23 11:45:37 -07001601
1602 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
1603 if (realActivity != null) {
1604 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
1605 }
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001606 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
Craig Mautner21d24a22014-04-23 11:45:37 -07001607 if (origActivity != null) {
1608 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
1609 }
Dianne Hackborn79228822014-09-16 11:11:23 -07001610 // Write affinity, and root affinity if it is different from affinity.
1611 // We use the special string "@" for a null root affinity, so we can identify
1612 // later whether we were given a root affinity or should just make it the
1613 // same as the affinity.
Craig Mautner21d24a22014-04-23 11:45:37 -07001614 if (affinity != null) {
1615 out.attribute(null, ATTR_AFFINITY, affinity);
Dianne Hackborn79228822014-09-16 11:11:23 -07001616 if (!affinity.equals(rootAffinity)) {
1617 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
1618 }
1619 } else if (rootAffinity != null) {
1620 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
Craig Mautner21d24a22014-04-23 11:45:37 -07001621 }
1622 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
Dianne Hackborn13420f22014-07-18 15:43:56 -07001623 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
Craig Mautner21d24a22014-04-23 11:45:37 -07001624 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
1625 out.attribute(null, ATTR_USERID, String.valueOf(userId));
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001626 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001627 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
Craig Mautner21d24a22014-04-23 11:45:37 -07001628 out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
Winson Chungffa2ec62014-07-03 15:54:42 -07001629 out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
Winson Chungf1fbd772014-06-24 18:06:58 -07001630 out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
Craig Mautner21d24a22014-04-23 11:45:37 -07001631 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001632 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
Craig Mautner21d24a22014-04-23 11:45:37 -07001633 if (lastDescription != null) {
1634 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
1635 }
Winson Chung2cb86c72014-06-25 12:03:30 -07001636 if (lastTaskDescription != null) {
Craig Mautner648f69b2014-09-18 14:16:26 -07001637 lastTaskDescription.saveToXml(out);
Winson Chung2cb86c72014-06-25 12:03:30 -07001638 }
Winson Chung36f3f032016-09-08 23:29:43 +00001639 mLastThumbnailInfo.saveToXml(out);
Winson Chungec396d62014-08-06 17:08:00 -07001640 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
Craig Mautnera228ae92014-07-09 05:44:55 -07001641 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
1642 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
1643 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001644 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
1645 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001646 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08001647 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
1648 String.valueOf(mSupportsPictureInPicture));
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001649 out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
Wale Ogunwale706ed792015-08-02 10:29:44 -07001650 if (mLastNonFullscreenBounds != null) {
1651 out.attribute(
1652 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001653 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001654 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
1655 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001656 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
Winson Chung2cb86c72014-06-25 12:03:30 -07001657
Craig Mautner21d24a22014-04-23 11:45:37 -07001658 if (affinityIntent != null) {
1659 out.startTag(null, TAG_AFFINITYINTENT);
1660 affinityIntent.saveToXml(out);
1661 out.endTag(null, TAG_AFFINITYINTENT);
1662 }
1663
Winson Chung36f3f032016-09-08 23:29:43 +00001664 out.startTag(null, TAG_INTENT);
1665 intent.saveToXml(out);
1666 out.endTag(null, TAG_INTENT);
Craig Mautner21d24a22014-04-23 11:45:37 -07001667
1668 final ArrayList<ActivityRecord> activities = mActivities;
1669 final int numActivities = activities.size();
1670 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
1671 final ActivityRecord r = activities.get(activityNdx);
Craig Mautner43e52ed2014-06-16 17:18:52 -07001672 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
Wale Ogunwale843bfb92015-03-27 11:06:48 -07001673 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
1674 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
Craig Mautner43e52ed2014-06-16 17:18:52 -07001675 activityNdx > 0) {
Craig Mautnerf357c0c2014-06-09 09:23:27 -07001676 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
Craig Mautner21d24a22014-04-23 11:45:37 -07001677 break;
1678 }
1679 out.startTag(null, TAG_ACTIVITY);
1680 r.saveToXml(out);
1681 out.endTag(null, TAG_ACTIVITY);
1682 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001683 }
1684
Winson Chung36f3f032016-09-08 23:29:43 +00001685 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
1686 throws IOException, XmlPullParserException {
Craig Mautner21d24a22014-04-23 11:45:37 -07001687 Intent intent = null;
1688 Intent affinityIntent = null;
Winsonc809cbb2015-11-02 12:06:15 -08001689 ArrayList<ActivityRecord> activities = new ArrayList<>();
Craig Mautner21d24a22014-04-23 11:45:37 -07001690 ComponentName realActivity = null;
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001691 boolean realActivitySuspended = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001692 ComponentName origActivity = null;
1693 String affinity = null;
Dianne Hackborn79228822014-09-16 11:11:23 -07001694 String rootAffinity = null;
1695 boolean hasRootAffinity = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001696 boolean rootHasReset = false;
Dianne Hackborn13420f22014-07-18 15:43:56 -07001697 boolean autoRemoveRecents = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001698 boolean askedCompatMode = false;
1699 int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Craig Mautner21d24a22014-04-23 11:45:37 -07001700 int userId = 0;
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001701 boolean userSetupComplete = true;
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001702 int effectiveUid = -1;
Craig Mautner21d24a22014-04-23 11:45:37 -07001703 String lastDescription = null;
Winson Chungffa2ec62014-07-03 15:54:42 -07001704 long firstActiveTime = -1;
Winson Chung2cb86c72014-06-25 12:03:30 -07001705 long lastActiveTime = -1;
Craig Mautner21d24a22014-04-23 11:45:37 -07001706 long lastTimeOnTop = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001707 boolean neverRelinquishIdentity = true;
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001708 int taskId = INVALID_TASK_ID;
Craig Mautner21d24a22014-04-23 11:45:37 -07001709 final int outerDepth = in.getDepth();
Craig Mautner648f69b2014-09-18 14:16:26 -07001710 TaskDescription taskDescription = new TaskDescription();
Winsonc809cbb2015-11-02 12:06:15 -08001711 TaskThumbnailInfo thumbnailInfo = new TaskThumbnailInfo();
Wale Ogunwale18795a22014-12-03 11:38:33 -08001712 int taskAffiliation = INVALID_TASK_ID;
Winson Chungec396d62014-08-06 17:08:00 -07001713 int taskAffiliationColor = 0;
Wale Ogunwale18795a22014-12-03 11:38:33 -08001714 int prevTaskId = INVALID_TASK_ID;
1715 int nextTaskId = INVALID_TASK_ID;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001716 int callingUid = -1;
1717 String callingPackage = "";
Wale Ogunwaled829d362016-02-10 19:24:49 -08001718 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08001719 boolean supportsPictureInPicture = false;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001720 boolean privileged = false;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001721 Rect bounds = null;
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001722 int minWidth = INVALID_MIN_SIZE;
1723 int minHeight = INVALID_MIN_SIZE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001724 int persistTaskVersion = 0;
Craig Mautner21d24a22014-04-23 11:45:37 -07001725
1726 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
1727 final String attrName = in.getAttributeName(attrNdx);
1728 final String attrValue = in.getAttributeValue(attrNdx);
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001729 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
1730 attrName + " value=" + attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001731 if (ATTR_TASKID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001732 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001733 } else if (ATTR_REALACTIVITY.equals(attrName)) {
1734 realActivity = ComponentName.unflattenFromString(attrValue);
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001735 } else if (ATTR_REALACTIVITY_SUSPENDED.equals(attrName)) {
1736 realActivitySuspended = Boolean.valueOf(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001737 } else if (ATTR_ORIGACTIVITY.equals(attrName)) {
1738 origActivity = ComponentName.unflattenFromString(attrValue);
1739 } else if (ATTR_AFFINITY.equals(attrName)) {
1740 affinity = attrValue;
Dianne Hackborn79228822014-09-16 11:11:23 -07001741 } else if (ATTR_ROOT_AFFINITY.equals(attrName)) {
1742 rootAffinity = attrValue;
1743 hasRootAffinity = true;
Craig Mautner21d24a22014-04-23 11:45:37 -07001744 } else if (ATTR_ROOTHASRESET.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001745 rootHasReset = Boolean.parseBoolean(attrValue);
Dianne Hackborn13420f22014-07-18 15:43:56 -07001746 } else if (ATTR_AUTOREMOVERECENTS.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001747 autoRemoveRecents = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001748 } else if (ATTR_ASKEDCOMPATMODE.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001749 askedCompatMode = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001750 } else if (ATTR_USERID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001751 userId = Integer.parseInt(attrValue);
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001752 } else if (ATTR_USER_SETUP_COMPLETE.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001753 userSetupComplete = Boolean.parseBoolean(attrValue);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001754 } else if (ATTR_EFFECTIVE_UID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001755 effectiveUid = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001756 } else if (ATTR_TASKTYPE.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001757 taskType = Integer.parseInt(attrValue);
Winson Chungffa2ec62014-07-03 15:54:42 -07001758 } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001759 firstActiveTime = Long.parseLong(attrValue);
Winson Chungf1fbd772014-06-24 18:06:58 -07001760 } else if (ATTR_LASTACTIVETIME.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001761 lastActiveTime = Long.parseLong(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001762 } else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
1763 lastDescription = attrValue;
1764 } else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001765 lastTimeOnTop = Long.parseLong(attrValue);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001766 } else if (ATTR_NEVERRELINQUISH.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001767 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
Winsonc809cbb2015-11-02 12:06:15 -08001768 } else if (attrName.startsWith(TaskThumbnailInfo.ATTR_TASK_THUMBNAILINFO_PREFIX)) {
1769 thumbnailInfo.restoreFromXml(attrName, attrValue);
Craig Mautner648f69b2014-09-18 14:16:26 -07001770 } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
1771 taskDescription.restoreFromXml(attrName, attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001772 } else if (ATTR_TASK_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001773 taskAffiliation = Integer.parseInt(attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001774 } else if (ATTR_PREV_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001775 prevTaskId = Integer.parseInt(attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001776 } else if (ATTR_NEXT_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001777 nextTaskId = Integer.parseInt(attrValue);
Winson Chungec396d62014-08-06 17:08:00 -07001778 } else if (ATTR_TASK_AFFILIATION_COLOR.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001779 taskAffiliationColor = Integer.parseInt(attrValue);
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001780 } else if (ATTR_CALLING_UID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001781 callingUid = Integer.parseInt(attrValue);
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001782 } else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
1783 callingPackage = attrValue;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001784 } else if (ATTR_RESIZE_MODE.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001785 resizeMode = Integer.parseInt(attrValue);
Winson Chungd3395382016-12-13 11:49:09 -08001786 } else if (ATTR_SUPPORTS_PICTURE_IN_PICTURE.equals(attrName)) {
1787 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001788 } else if (ATTR_PRIVILEGED.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001789 privileged = Boolean.parseBoolean(attrValue);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001790 } else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001791 bounds = Rect.unflattenFromString(attrValue);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001792 } else if (ATTR_MIN_WIDTH.equals(attrName)) {
1793 minWidth = Integer.parseInt(attrValue);
1794 } else if (ATTR_MIN_HEIGHT.equals(attrName)) {
1795 minHeight = Integer.parseInt(attrValue);
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001796 } else if (ATTR_PERSIST_TASK_VERSION.equals(attrName)) {
1797 persistTaskVersion = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001798 } else {
1799 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
1800 }
1801 }
1802
1803 int event;
1804 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
Ben Kwa8814cf42015-07-08 10:54:56 -07001805 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001806 if (event == XmlPullParser.START_TAG) {
1807 final String name = in.getName();
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001808 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" +
1809 name);
Craig Mautner21d24a22014-04-23 11:45:37 -07001810 if (TAG_AFFINITYINTENT.equals(name)) {
1811 affinityIntent = Intent.restoreFromXml(in);
1812 } else if (TAG_INTENT.equals(name)) {
1813 intent = Intent.restoreFromXml(in);
1814 } else if (TAG_ACTIVITY.equals(name)) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08001815 ActivityRecord activity = ActivityRecord.restoreFromXml(in, stackSupervisor);
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001816 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
1817 activity);
Craig Mautner21d24a22014-04-23 11:45:37 -07001818 if (activity != null) {
1819 activities.add(activity);
1820 }
1821 } else {
1822 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
1823 XmlUtils.skipCurrentTag(in);
1824 }
1825 }
1826 }
Dianne Hackborn79228822014-09-16 11:11:23 -07001827 if (!hasRootAffinity) {
1828 rootAffinity = affinity;
1829 } else if ("@".equals(rootAffinity)) {
1830 rootAffinity = null;
1831 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001832 if (effectiveUid <= 0) {
1833 Intent checkIntent = intent != null ? intent : affinityIntent;
1834 effectiveUid = 0;
1835 if (checkIntent != null) {
1836 IPackageManager pm = AppGlobals.getPackageManager();
1837 try {
1838 ApplicationInfo ai = pm.getApplicationInfo(
1839 checkIntent.getComponent().getPackageName(),
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07001840 PackageManager.MATCH_UNINSTALLED_PACKAGES
1841 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001842 if (ai != null) {
1843 effectiveUid = ai.uid;
1844 }
1845 } catch (RemoteException e) {
1846 }
1847 }
1848 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
1849 + ": effectiveUid=" + effectiveUid);
1850 }
1851
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001852 if (persistTaskVersion < 1) {
1853 // We need to convert the resize mode of home activities saved before version one if
1854 // they are marked as RESIZE_MODE_RESIZEABLE to RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
1855 // since we didn't have that differentiation before version 1 and the system didn't
1856 // resize home activities before then.
1857 if (taskType == HOME_ACTIVITY_TYPE && resizeMode == RESIZE_MODE_RESIZEABLE) {
1858 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
1859 }
Winson Chungd3395382016-12-13 11:49:09 -08001860 } else {
1861 // This activity has previously marked itself explicitly as both resizeable and
1862 // supporting picture-in-picture. Since there is no longer a requirement for
1863 // picture-in-picture activities to be resizeable, we can mark this simply as
1864 // resizeable and supporting picture-in-picture separately.
1865 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
1866 resizeMode = RESIZE_MODE_RESIZEABLE;
1867 supportsPictureInPicture = true;
1868 }
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001869 }
1870
Winson Chung36f3f032016-09-08 23:29:43 +00001871 final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
Dianne Hackborn79228822014-09-16 11:11:23 -07001872 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001873 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
1874 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
Winsonc809cbb2015-11-02 12:06:15 -08001875 taskDescription, thumbnailInfo, taskAffiliation, prevTaskId, nextTaskId,
Winson Chungd3395382016-12-13 11:49:09 -08001876 taskAffiliationColor, callingUid, callingPackage, resizeMode,
1877 supportsPictureInPicture, privileged, realActivitySuspended, userSetupComplete,
1878 minWidth, minHeight);
Filip Gruszczynskiaff7f132015-09-02 17:21:21 -07001879 task.updateOverrideConfiguration(bounds);
Craig Mautner21d24a22014-04-23 11:45:37 -07001880
1881 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001882 activities.get(activityNdx).task = task;
Craig Mautner21d24a22014-04-23 11:45:37 -07001883 }
1884
Wale Ogunwaleee006da2015-03-30 14:49:25 -07001885 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
Craig Mautner21d24a22014-04-23 11:45:37 -07001886 return task;
1887 }
1888
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001889 private void adjustForMinimalTaskDimensions(Rect bounds) {
1890 if (bounds == null) {
1891 return;
1892 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001893 int minWidth = mMinWidth;
1894 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001895 // If the task has no requested minimal size, we'd like to enforce a minimal size
1896 // so that the user can not render the task too small to manipulate. We don't need
1897 // to do this for the pinned stack as the bounds are controlled by the system.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001898 if (getStackId() != PINNED_STACK_ID) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001899 if (minWidth == INVALID_MIN_SIZE) {
1900 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001901 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001902 if (minHeight == INVALID_MIN_SIZE) {
1903 minHeight = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001904 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001905 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001906 final boolean adjustWidth = minWidth > bounds.width();
1907 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001908 if (!(adjustWidth || adjustHeight)) {
1909 return;
1910 }
1911
1912 if (adjustWidth) {
1913 if (mBounds != null && bounds.right == mBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001914 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001915 } else {
1916 // Either left bounds match, or neither match, or the previous bounds were
1917 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001918 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001919 }
1920 }
1921 if (adjustHeight) {
1922 if (mBounds != null && bounds.bottom == mBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001923 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001924 } else {
1925 // Either top bounds match, or neither match, or the previous bounds were
1926 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001927 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001928 }
1929 }
1930 }
1931
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001932 /**
1933 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001934 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07001935 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001936 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001937 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001938 return updateOverrideConfiguration(bounds, null /* insetBounds */);
1939 }
1940
1941 /**
1942 * Update task's override configuration based on the bounds.
1943 * @param bounds The bounds of the task.
1944 * @param insetBounds The bounds used to calculate the system insets, which is used here to
1945 * subtract the navigation bar/status bar size from the screen size reported
1946 * to the application. See {@link IActivityManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07001947 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001948 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001949 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001950 if (Objects.equals(mBounds, bounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07001951 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001952 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001953 mTmpConfig.setTo(getOverrideConfiguration());
Wale Ogunwale5f986092015-12-04 15:35:38 -08001954 final boolean oldFullscreen = mFullscreen;
Andrii Kulian1779e612016-10-12 21:58:25 -07001955 final Configuration newConfig = getOverrideConfiguration();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001956
1957 mFullscreen = bounds == null;
Wale Ogunwale706ed792015-08-02 10:29:44 -07001958 if (mFullscreen) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001959 if (mBounds != null && StackId.persistTaskBounds(mStack.mStackId)) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07001960 mLastNonFullscreenBounds = mBounds;
1961 }
1962 mBounds = null;
Andrii Kulian1779e612016-10-12 21:58:25 -07001963 newConfig.unset();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001964 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001965 mTmpRect.set(bounds);
1966 adjustForMinimalTaskDimensions(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08001967 if (mBounds == null) {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001968 mBounds = new Rect(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08001969 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001970 mBounds.set(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08001971 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001972 if (mStack == null || StackId.persistTaskBounds(mStack.mStackId)) {
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -07001973 mLastNonFullscreenBounds = mBounds;
1974 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001975 calculateOverrideConfig(newConfig, mTmpRect, insetBounds,
Andrii Kuliandaea3572016-04-08 13:20:51 -07001976 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001977 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001978 onOverrideConfigurationChanged(newConfig);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001979
1980 if (mFullscreen != oldFullscreen) {
Andrii Kulian933076d2016-03-29 17:04:42 -07001981 mService.mStackSupervisor.scheduleReportMultiWindowModeChanged(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001982 }
1983
Andrii Kulian1779e612016-10-12 21:58:25 -07001984 return !mTmpConfig.equals(newConfig);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001985 }
1986
Andrii Kulian1779e612016-10-12 21:58:25 -07001987 /** Clears passed config and fills it with new override values. */
Andrii Kuliana8a9bc52016-10-14 11:00:13 -07001988 private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
1989 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001990 mTmpNonDecorBounds.set(bounds);
1991 mTmpStableBounds.set(bounds);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001992
Andrii Kulian1779e612016-10-12 21:58:25 -07001993 config.unset();
Winson Chungbdc646f2017-02-13 12:12:22 -08001994 final Configuration parentConfig = getParent().getConfiguration();
Andrii Kulian1779e612016-10-12 21:58:25 -07001995 final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001996
1997 // TODO: Orientation?
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001998 config.orientation = (config.screenWidthDp <= config.screenHeightDp)
1999 ? Configuration.ORIENTATION_PORTRAIT
2000 : Configuration.ORIENTATION_LANDSCAPE;
Winson Chungbdc646f2017-02-13 12:12:22 -08002001 if (mStack != null) {
2002 final StackWindowController stackController = mStack.getWindowContainerController();
2003 stackController.adjustConfigurationForBounds(bounds, insetBounds,
2004 mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
2005 config, parentConfig);
2006 } else {
2007 // No stack, give some default values
2008 config.smallestScreenWidthDp =
2009 mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
2010 config.screenWidthDp = config.screenHeightDp = config.smallestScreenWidthDp;
2011 Slog.wtf(TAG, "Expected stack when caclulating override config");
2012 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002013
Jorim Jaggi85639432016-05-06 17:27:55 -07002014 // For calculating screen layout, we need to use the non-decor inset screen area for the
2015 // calculation for compatibility reasons, i.e. screen area without system bars that could
2016 // never go away in Honeycomb.
Winson Chungbdc646f2017-02-13 12:12:22 -08002017 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2018 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Andrii Kulian1779e612016-10-12 21:58:25 -07002019 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
2020 // calculation with partial default.
2021 final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002022 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
Andrii Kulian1779e612016-10-12 21:58:25 -07002023 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
Jorim Jaggi85639432016-05-06 17:27:55 -07002024 config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
2025
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08002026 }
2027
2028 /**
2029 * Using the existing configuration {@param config}, creates a new task override config such
2030 * that all the fields that are usually set in an override config are set to the ones in
2031 * {@param config}.
2032 */
2033 Configuration extractOverrideConfig(Configuration config) {
Andrii Kulian1779e612016-10-12 21:58:25 -07002034 final Configuration extracted = new Configuration();
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08002035 extracted.screenWidthDp = config.screenWidthDp;
2036 extracted.screenHeightDp = config.screenHeightDp;
2037 extracted.smallestScreenWidthDp = config.smallestScreenWidthDp;
2038 extracted.orientation = config.orientation;
Andrii Kulian1779e612016-10-12 21:58:25 -07002039 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout.
2040 extracted.screenLayout = config.screenLayout & (Configuration.SCREENLAYOUT_LONG_MASK
2041 | Configuration.SCREENLAYOUT_SIZE_MASK | Configuration.SCREENLAYOUT_COMPAT_NEEDED);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08002042 return extracted;
2043 }
2044
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002045 Rect updateOverrideConfigurationFromLaunchBounds() {
2046 final Rect bounds = validateBounds(getLaunchBounds());
2047 updateOverrideConfiguration(bounds);
Andrii Kulian73336d812016-03-24 12:56:08 -07002048 if (bounds != null) {
2049 bounds.set(mBounds);
2050 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002051 return bounds;
2052 }
2053
2054 static Rect validateBounds(Rect bounds) {
2055 if (bounds != null && bounds.isEmpty()) {
2056 Slog.wtf(TAG, "Received strange task bounds: " + bounds, new Throwable());
2057 return null;
2058 }
2059 return bounds;
2060 }
2061
Wale Ogunwale935e5022015-11-10 12:36:10 -08002062 /** Updates the task's bounds and override configuration to match what is expected for the
2063 * input stack. */
2064 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002065 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002066 return;
2067 }
2068
2069 if (inStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002070 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002071 throw new IllegalArgumentException("Can not position non-resizeable task="
2072 + this + " in stack=" + inStack);
2073 }
2074 if (mBounds != null) {
2075 return;
2076 }
2077 if (mLastNonFullscreenBounds != null) {
2078 updateOverrideConfiguration(mLastNonFullscreenBounds);
2079 } else {
2080 inStack.layoutTaskInStack(this, null);
2081 }
2082 } else {
2083 updateOverrideConfiguration(inStack.mBounds);
2084 }
2085 }
2086
Chong Zhang0fa656b2015-08-31 15:17:21 -07002087 /**
2088 * Returns the correct stack to use based on task type and currently set bounds,
2089 * regardless of the focused stack and current stack association of the task.
2090 * The task will be moved (and stack focus changed) later if necessary.
2091 */
2092 int getLaunchStackId() {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08002093 if (isRecentsTask()) {
2094 return RECENTS_STACK_ID;
2095 }
2096 if (isHomeTask()) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07002097 return HOME_STACK_ID;
2098 }
Winson Chung83471632016-12-13 11:02:12 -08002099 if (isAssistantTask()) {
2100 return ASSISTANT_STACK_ID;
2101 }
Chong Zhang0fa656b2015-08-31 15:17:21 -07002102 if (mBounds != null) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07002103 return FREEFORM_WORKSPACE_STACK_ID;
2104 }
2105 return FULLSCREEN_WORKSPACE_STACK_ID;
2106 }
2107
2108 /** Returns the bounds that should be used to launch this task. */
2109 Rect getLaunchBounds() {
Chong Zhang75b37202015-12-04 14:16:36 -08002110 // If we're over lockscreen, forget about stack bounds and use fullscreen.
Jorim Jaggife762342016-10-13 14:33:27 +02002111 if (mService.mStackSupervisor.mKeyguardController.isKeyguardShowing()) {
Chong Zhang75b37202015-12-04 14:16:36 -08002112 return null;
2113 }
2114
Andrii Kulian02b7a832016-10-06 23:11:56 -07002115 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08002116 return null;
2117 }
2118
Andrii Kulian02b7a832016-10-06 23:11:56 -07002119 final int stackId = mStack.mStackId;
Chong Zhang7d5f5102016-01-13 10:29:24 -08002120 if (stackId == HOME_STACK_ID
Matthew Ngae1ff4f2016-11-10 15:49:14 -08002121 || stackId == RECENTS_STACK_ID
Winson Chung83471632016-12-13 11:02:12 -08002122 || stackId == ASSISTANT_STACK_ID
Chong Zhang7d5f5102016-01-13 10:29:24 -08002123 || stackId == FULLSCREEN_WORKSPACE_STACK_ID
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002124 || (stackId == DOCKED_STACK_ID && !isResizeable())) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002125 return isResizeable() ? mStack.mBounds : null;
Wale Ogunwale3797c222015-10-27 14:21:58 -07002126 } else if (!StackId.persistTaskBounds(stackId)) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002127 return mStack.mBounds;
Wale Ogunwale706ed792015-08-02 10:29:44 -07002128 }
2129 return mLastNonFullscreenBounds;
2130 }
2131
Wale Ogunwale39381972015-12-17 17:15:29 -08002132 boolean canMatchRootAffinity() {
2133 // We don't allow root affinity matching on the pinned stack as no other task should
2134 // be launching in it based on affinity.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002135 return rootAffinity != null && getStackId() != PINNED_STACK_ID;
Wale Ogunwale39381972015-12-17 17:15:29 -08002136 }
2137
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01002138 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
2139 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
2140 final ActivityRecord r = mActivities.get(activityNdx);
2141 if (r.visible) {
2142 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
2143 }
2144 }
2145 }
2146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002148 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07002149 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
2150 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08002151 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002152 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07002153 if (affinity != null || rootAffinity != null) {
2154 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
2155 if (affinity == null || !affinity.equals(rootAffinity)) {
2156 pw.print(" root="); pw.println(rootAffinity);
2157 } else {
2158 pw.println();
2159 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002160 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07002161 if (voiceSession != null || voiceInteractor != null) {
2162 pw.print(prefix); pw.print("VOICE: session=0x");
2163 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
2164 pw.print(" interactor=0x");
2165 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
2166 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002167 if (intent != null) {
2168 StringBuilder sb = new StringBuilder(128);
2169 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08002170 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002171 sb.append('}');
2172 pw.println(sb.toString());
2173 }
2174 if (affinityIntent != null) {
2175 StringBuilder sb = new StringBuilder(128);
2176 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08002177 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002178 sb.append('}');
2179 pw.println(sb.toString());
2180 }
2181 if (origActivity != null) {
2182 pw.print(prefix); pw.print("origActivity=");
2183 pw.println(origActivity.flattenToShortString());
2184 }
2185 if (realActivity != null) {
2186 pw.print(prefix); pw.print("realActivity=");
2187 pw.println(realActivity.flattenToShortString());
2188 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002189 if (autoRemoveRecents || isPersistable || taskType != 0 || mTaskToReturnTo != 0
2190 || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002191 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002192 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002193 pw.print(" numFullscreen="); pw.print(numFullscreen);
2194 pw.print(" taskType="); pw.print(taskType);
2195 pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo);
2196 }
Craig Mautner432f64e2015-05-20 14:59:57 -07002197 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
2198 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002199 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
2200 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07002201 pw.print(" mReuseTask="); pw.print(mReuseTask);
2202 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002203 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08002204 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
2205 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
2206 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07002207 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
2208 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
2209 pw.print(" (");
2210 if (mPrevAffiliate == null) {
2211 pw.print("null");
2212 } else {
2213 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
2214 }
2215 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
2216 pw.print(" (");
2217 if (mNextAffiliate == null) {
2218 pw.print("null");
2219 } else {
2220 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
2221 }
2222 pw.println(")");
2223 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002224 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002225 if (!askedCompatMode || !inRecents || !isAvailable) {
2226 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2227 pw.print(" inRecents="); pw.print(inRecents);
2228 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002229 }
Craig Mautnerc0ffce52014-07-01 12:38:52 -07002230 pw.print(prefix); pw.print("lastThumbnail="); pw.print(mLastThumbnail);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002231 pw.print(" lastThumbnailFile="); pw.println(mLastThumbnailFile);
2232 if (lastDescription != null) {
2233 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2234 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002235 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002236 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2237 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002238 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002239 pw.print(" isResizeable=" + isResizeable());
Winson Chung36f3f032016-09-08 23:29:43 +00002240 pw.print(" firstActiveTime=" + lastActiveTime);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002241 pw.print(" lastActiveTime=" + lastActiveTime);
2242 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 }
2244
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002245 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002246 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002247 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002248 if (stringName != null) {
2249 sb.append(stringName);
2250 sb.append(" U=");
2251 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002252 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002253 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002254 sb.append(" sz=");
2255 sb.append(mActivities.size());
2256 sb.append('}');
2257 return sb.toString();
2258 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002259 sb.append("TaskRecord{");
2260 sb.append(Integer.toHexString(System.identityHashCode(this)));
2261 sb.append(" #");
2262 sb.append(taskId);
2263 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002264 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002265 sb.append(affinity);
2266 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002267 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002268 sb.append(intent.getComponent().flattenToShortString());
2269 } else if (affinityIntent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002270 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002271 sb.append(affinityIntent.getComponent().flattenToShortString());
2272 } else {
2273 sb.append(" ??");
2274 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002275 stringName = sb.toString();
2276 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002277 }
2278}