blob: a17cf3b79cab21e0db1902960bacb9e1d8ca7a0a [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
Jorim Jaggi0a932142016-02-01 17:42:25 -080019import android.annotation.Nullable;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -070020import android.app.Activity;
Craig Mautner9db9a0b2013-04-29 17:05:56 -070021import android.app.ActivityManager;
Wale Ogunwale3797c222015-10-27 14:21:58 -070022import android.app.ActivityManager.StackId;
Craig Mautner648f69b2014-09-18 14:16:26 -070023import android.app.ActivityManager.TaskDescription;
Wale Ogunwaleff3c66c2015-11-18 19:22:49 -080024import android.app.ActivityManager.TaskThumbnail;
Winsonc809cbb2015-11-02 12:06:15 -080025import android.app.ActivityManager.TaskThumbnailInfo;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -070026import android.app.ActivityOptions;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070027import android.app.AppGlobals;
Jorim Jaggi0a932142016-02-01 17:42:25 -080028import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.content.ComponentName;
30import android.content.Intent;
31import android.content.pm.ActivityInfo;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070032import android.content.pm.ApplicationInfo;
33import android.content.pm.IPackageManager;
34import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070035import android.content.res.Configuration;
Craig Mautner9db9a0b2013-04-29 17:05:56 -070036import android.graphics.Bitmap;
Winsonc809cbb2015-11-02 12:06:15 -080037import android.graphics.Point;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070038import android.graphics.Rect;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -070039import android.os.Debug;
Craig Mautnerc0ffce52014-07-01 12:38:52 -070040import android.os.ParcelFileDescriptor;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070041import android.os.RemoteException;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070042import android.os.UserHandle;
Suprabh Shukla7745c142016-03-07 18:21:10 -080043import android.provider.Settings;
Dianne Hackborn91097de2014-04-04 18:02:06 -070044import android.service.voice.IVoiceInteractionSession;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070045import android.util.DisplayMetrics;
Dianne Hackborn7f96b792012-05-29 18:46:45 -070046import android.util.Slog;
Suprabh Shukla23593142015-11-03 17:31:15 -080047
Dianne Hackborn91097de2014-04-04 18:02:06 -070048import com.android.internal.app.IVoiceInteractor;
Craig Mautner21d24a22014-04-23 11:45:37 -070049import com.android.internal.util.XmlUtils;
Suprabh Shukla23593142015-11-03 17:31:15 -080050
Craig Mautner21d24a22014-04-23 11:45:37 -070051import org.xmlpull.v1.XmlPullParser;
52import org.xmlpull.v1.XmlPullParserException;
53import org.xmlpull.v1.XmlSerializer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
Craig Mautnerc0ffce52014-07-01 12:38:52 -070055import java.io.File;
Craig Mautner21d24a22014-04-23 11:45:37 -070056import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import java.io.PrintWriter;
Craig Mautner5d9c7be2013-02-15 14:02:56 -080058import java.util.ArrayList;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070059import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060
Jorim Jaggi0a932142016-02-01 17:42:25 -080061import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
62import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
63import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
64import static android.app.ActivityManager.StackId.HOME_STACK_ID;
65import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
66import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080067import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Jorim Jaggi0a932142016-02-01 17:42:25 -080068import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
69import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
Jiaquan Hedd1e66f2016-06-15 15:15:12 -070070import static android.content.pm.ActivityInfo.FLAG_ON_TOP_LAUNCHER;
Wale Ogunwale3eadad72016-10-13 09:16:59 -070071import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080072import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
73import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
74import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
75import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080076import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
77import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
78import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Wale Ogunwaled829d362016-02-10 19:24:49 -080079import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070080import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
81import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Jorim Jaggi0a932142016-02-01 17:42:25 -080082import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
Suprabh Shukla7745c142016-03-07 18:21:10 -080083import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Jorim Jaggi0a932142016-02-01 17:42:25 -080084import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
85import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
86import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
87import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
88import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
89import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
90import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
91import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
92import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
93import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Jorim Jaggi0a932142016-02-01 17:42:25 -080094import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
95import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
96import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
Wale Ogunwale3b232392016-05-13 15:37:13 -070097import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
Jorim Jaggi0a932142016-02-01 17:42:25 -080098
Andrii Kulian1779e612016-10-12 21:58:25 -070099final class TaskRecord extends ConfigurationContainer {
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800100 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700101 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700102 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700103 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700104 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800105
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700106 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700107 private static final String TAG_INTENT = "intent";
108 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700109 private static final String ATTR_REALACTIVITY = "real_activity";
110 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700111 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700112 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700113 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700114 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700115 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700116 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700117 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
118 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800119 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700120 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Craig Mautner21d24a22014-04-23 11:45:37 -0700121 private static final String ATTR_TASKTYPE = "task_type";
Winson Chungffa2ec62014-07-03 15:54:42 -0700122 private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
Winson Chungf1fbd772014-06-24 18:06:58 -0700123 private static final String ATTR_LASTACTIVETIME = "last_active_time";
Craig Mautner21d24a22014-04-23 11:45:37 -0700124 private static final String ATTR_LASTDESCRIPTION = "last_description";
125 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700126 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700127 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700128 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
129 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700130 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700131 private static final String ATTR_CALLING_UID = "calling_uid";
132 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800133 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700134 private static final String ATTR_PRIVILEGED = "privileged";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700135 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700136 private static final String ATTR_MIN_WIDTH = "min_width";
137 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700138 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700139
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700140 // Current version of the task record we persist. Used to check if we need to run any upgrade
141 // code.
142 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700143 private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
144
Wale Ogunwale18795a22014-12-03 11:38:33 -0800145 static final int INVALID_TASK_ID = -1;
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700146 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 final int taskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700149 String affinity; // The affinity name for this task, or null; may change identity.
150 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700151 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
152 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 Intent intent; // The original intent that started the task.
154 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700155 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 ComponentName origActivity; // The non-alias activity component of the intent.
157 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000158 boolean realActivitySuspended; // True if the actual activity component that started the
159 // task is suspended.
Winson Chung36f3f032016-09-08 23:29:43 +0000160 long firstActiveTime; // First time this task was active.
161 long lastActiveTime; // Last time this task was active, including sleep.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700162 boolean inRecents; // Actually in the recents list?
163 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 boolean rootWasReset; // True if the intent at the root of the task had
165 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700166 boolean autoRemoveRecents; // If true, we should automatically remove the task from
167 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700168 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700169 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 -0800170
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700171 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700172 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800173 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
174 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800175
176 int numFullscreen; // Number of fullscreen activities.
177
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800178 int mResizeMode; // The resize mode of this task and its activities.
179 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Jorim Jaggi8202b2a2016-02-03 19:24:31 -0800180 boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
181 // changes on a temporary basis.
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700182 private int mLockTaskMode; // Which tasklock mode to launch this task in. One of
183 // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700184 private boolean mPrivileged; // The root activity application of this task holds
185 // privileged permissions.
Jiaquan Hedd1e66f2016-06-15 15:15:12 -0700186 private boolean mIsOnTopLauncher; // Whether this task is an on-top launcher. See
187 // android.R.attr#onTopLauncher.
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700188
Craig Mautner15df08a2015-04-01 12:17:18 -0700189 /** Can't be put in lockTask mode. */
190 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100191 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700192 final static int LOCK_TASK_AUTH_PINNABLE = 1;
193 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
194 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100195 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700196 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100197 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
198 * lockTask task. */
199 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700200 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
201
202 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800203
Winson Chung03a9bae2014-05-02 09:56:12 -0700204 // This represents the last resolved activity values for this task
205 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700206 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700207
Craig Mautnerd2328952013-03-05 12:46:26 -0800208 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700209 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800210
Andrii Kulian02b7a832016-10-06 23:11:56 -0700211 /** Current stack. Setter must always be used to update the value. */
212 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800213
Craig Mautner2c1faed2013-07-23 12:56:02 -0700214 /** Takes on same set of values as ActivityRecord.mActivityType */
Craig Mautner21d24a22014-04-23 11:45:37 -0700215 int taskType;
Craig Mautner1602ec22013-05-12 10:24:27 -0700216
Craig Mautner21d24a22014-04-23 11:45:37 -0700217 /** Takes on same value as first root activity */
218 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700219 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700220
221 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
222 * determining the order when restoring. Sign indicates whether last task movement was to front
223 * (positive) or back (negative). Absolute value indicates time. */
224 long mLastTimeMoved = System.currentTimeMillis();
225
Craig Mautner84984fa2014-06-19 11:19:20 -0700226 /** Indication of what to run next when task exits. Use ActivityRecord types.
227 * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the
228 * task stack. */
229 private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE;
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700230
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700231 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700232 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700233
Craig Mautner362449a2014-06-20 14:04:39 -0700234 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
235 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800236 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700237
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700238 private Bitmap mLastThumbnail; // Last thumbnail captured for this item.
Wale Ogunwalebe23ff42014-10-21 16:29:51 -0700239 private final File mLastThumbnailFile; // File containing last thumbnail.
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700240 private final String mFilename;
Winsonc809cbb2015-11-02 12:06:15 -0800241 private TaskThumbnailInfo mLastThumbnailInfo;
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700242 CharSequence lastDescription; // Last description captured for this item.
243
Craig Mautnera228ae92014-07-09 05:44:55 -0700244 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700245 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700246 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800247 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700248 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800249 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700250
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700251 // For relaunching the task from recents as though it was launched by the original launcher.
252 int mCallingUid;
253 String mCallingPackage;
254
Craig Mautner21d24a22014-04-23 11:45:37 -0700255 final ActivityManagerService mService;
256
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700257 // Whether or not this task covers the entire screen; by default tasks are fullscreen.
258 boolean mFullscreen = true;
259
260 // Bounds of the Task. null for fullscreen tasks.
261 Rect mBounds = null;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800262 private final Rect mTmpStableBounds = new Rect();
263 private final Rect mTmpNonDecorBounds = new Rect();
Wale Ogunwale9a08f822016-02-17 19:03:58 -0800264 private final Rect mTmpRect = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800265 private final Rect mTmpRect2 = new Rect();
266
Wale Ogunwale706ed792015-08-02 10:29:44 -0700267 // Last non-fullscreen bounds the task was launched in or resized to.
268 // The information is persisted and used to determine the appropriate stack to launch the
269 // task into on restore.
270 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700271 // Minimal width and height of this task when it's resizeable. -1 means it should use the
272 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700273 int mMinWidth;
274 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700275
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700276 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
277 // This number will be assigned when we evaluate OOM scores for all visible tasks.
278 int mLayerRank = -1;
279
Andrii Kulian1779e612016-10-12 21:58:25 -0700280 /** Helper object used for updating override configuration. */
281 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700282
Craig Mautner21d24a22014-04-23 11:45:37 -0700283 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale72919d22016-12-08 18:58:50 -0800284 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700285 mService = service;
Craig Mautnera228ae92014-07-09 05:44:55 -0700286 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
287 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800288 userId = UserHandle.getUserId(info.applicationInfo.uid);
289 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800290 mLastThumbnailInfo = new TaskThumbnailInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 taskId = _taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700292 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700293 voiceSession = _voiceSession;
294 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700295 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800296 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700297 mCallingUid = info.applicationInfo.uid;
298 mCallingPackage = info.packageName;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800299 taskType = type;
Martijn Coenend4a69702014-06-30 11:12:17 -0700300 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700301 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700302 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700303 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700304 }
305
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700306 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Winsonc809cbb2015-11-02 12:06:15 -0800307 TaskDescription _taskDescription, TaskThumbnailInfo thumbnailInfo) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700308 mService = service;
309 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
310 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800311 userId = UserHandle.getUserId(info.applicationInfo.uid);
312 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800313 mLastThumbnailInfo = thumbnailInfo;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700314 taskId = _taskId;
315 mAffiliatedTaskId = _taskId;
316 voiceSession = null;
317 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700318 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800319 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700320 mCallingUid = info.applicationInfo.uid;
321 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700322 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700323 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700324
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700325 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700326 // Clamp to [1, max].
327 maxRecents = Math.min(Math.max(info.maxRecents, 1),
328 ActivityManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700329
330 taskType = APPLICATION_ACTIVITY_TYPE;
331 mTaskToReturnTo = HOME_ACTIVITY_TYPE;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700332 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700333 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700334 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700335 }
336
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800337 private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
338 Intent _affinityIntent, String _affinity, String _rootAffinity,
339 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
340 boolean _autoRemoveRecents, boolean _askedCompatMode, int _taskType, int _userId,
341 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
342 long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
343 boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
Winsonc809cbb2015-11-02 12:06:15 -0800344 TaskThumbnailInfo lastThumbnailInfo, int taskAffiliation, int prevTaskId,
345 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800346 int resizeMode, boolean privileged, boolean _realActivitySuspended,
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700347 boolean userSetupComplete, int minWidth, int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700348 mService = service;
Craig Mautnera228ae92014-07-09 05:44:55 -0700349 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
350 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800351 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(_userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800352 mLastThumbnailInfo = lastThumbnailInfo;
Craig Mautner21d24a22014-04-23 11:45:37 -0700353 taskId = _taskId;
354 intent = _intent;
355 affinityIntent = _affinityIntent;
356 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800357 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700358 voiceSession = null;
359 voiceInteractor = null;
360 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800361 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700362 origActivity = _origActivity;
363 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700364 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700365 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700366 askedCompatMode = _askedCompatMode;
367 taskType = _taskType;
Craig Mautner84984fa2014-06-19 11:19:20 -0700368 mTaskToReturnTo = HOME_ACTIVITY_TYPE;
Craig Mautner21d24a22014-04-23 11:45:37 -0700369 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800370 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700371 effectiveUid = _effectiveUid;
Winson Chungffa2ec62014-07-03 15:54:42 -0700372 firstActiveTime = _firstActiveTime;
Winson Chungf1fbd772014-06-24 18:06:58 -0700373 lastActiveTime = _lastActiveTime;
Craig Mautner21d24a22014-04-23 11:45:37 -0700374 lastDescription = _lastDescription;
375 mActivities = activities;
376 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700377 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700378 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700379 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700380 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700381 mPrevAffiliateTaskId = prevTaskId;
382 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700383 mCallingUid = callingUid;
384 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800385 mResizeMode = resizeMode;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700386 mPrivileged = privileged;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700387 mMinWidth = minWidth;
388 mMinHeight = minHeight;
Yorke Leebd54c2a2016-10-25 13:49:23 -0700389 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 }
391
392 void touchActiveTime() {
Winson Chung36f3f032016-09-08 23:29:43 +0000393 lastActiveTime = System.currentTimeMillis();
Winson Chungffa2ec62014-07-03 15:54:42 -0700394 if (firstActiveTime == 0) {
395 firstActiveTime = lastActiveTime;
396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 long getInactiveDuration() {
Winson Chung36f3f032016-09-08 23:29:43 +0000400 return System.currentTimeMillis() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700402
Winson Chungfee26772014-08-05 12:21:52 -0700403 /** Sets the original intent, and the calling uid and package. */
404 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700405 mCallingUid = r.launchedFromUid;
406 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700407 setIntent(r.intent, r.info);
Winson Chungfee26772014-08-05 12:21:52 -0700408 }
409
410 /** Sets the original intent, _without_ updating the calling uid or package. */
411 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700412 if (intent == null) {
413 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700414 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700415 } else if (mNeverRelinquishIdentity) {
416 return;
417 }
418
419 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700420 if (intent == null) {
421 // If this task already has an intent associated with it, don't set the root
422 // affinity -- we don't want it changing after initially set, but the initially
423 // set value may be null.
424 rootAffinity = affinity;
425 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700426 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700427 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800430 if (_intent != null) {
431 // If this Intent has a selector, we want to clear it for the
432 // recent task since it is not relevant if the user later wants
433 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700434 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800435 _intent = new Intent(_intent);
436 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700437 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800438 }
439 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700440 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 intent = _intent;
442 realActivity = _intent != null ? _intent.getComponent() : null;
443 origActivity = null;
444 } else {
445 ComponentName targetComponent = new ComponentName(
446 info.packageName, info.targetActivity);
447 if (_intent != null) {
448 Intent targetIntent = new Intent(_intent);
449 targetIntent.setComponent(targetComponent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800450 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700451 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700452 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700453 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 intent = targetIntent;
455 realActivity = targetComponent;
456 origActivity = _intent.getComponent();
457 } else {
458 intent = null;
459 realActivity = targetComponent;
460 origActivity = new ComponentName(info.packageName, info.name);
461 }
462 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700463
Craig Mautner47b20ba2014-09-17 17:23:44 -0700464 final int intentFlags = intent == null ? 0 : intent.getFlags();
465 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 // Once we are set to an Intent with this flag, we count this
467 // task as having a true root activity.
468 rootWasReset = true;
469 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700470 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000471 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
472 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700473 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700474 // If the activity itself has requested auto-remove, then just always do it.
475 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700476 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
477 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700478 // If the caller has not asked for the document to be retained, then we may
479 // want to turn on auto-remove, depending on whether the target has set its
480 // own document launch mode.
481 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
482 autoRemoveRecents = false;
483 } else {
484 autoRemoveRecents = true;
485 }
486 } else {
487 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700488 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800489 mResizeMode = info.resizeMode;
Jiaquan Hedd1e66f2016-06-15 15:15:12 -0700490 mIsOnTopLauncher = (info.flags & FLAG_ON_TOP_LAUNCHER) != 0;
Craig Mautner15df08a2015-04-01 12:17:18 -0700491 mLockTaskMode = info.lockTaskLaunchMode;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700492 mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
Craig Mautner15df08a2015-04-01 12:17:18 -0700493 setLockTaskAuth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800495
Andrii Kulian2e751b82016-03-16 16:59:32 -0700496 /** Sets the original minimal width and height. */
497 private void setMinDimensions(ActivityInfo info) {
498 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700499 mMinWidth = info.windowLayout.minWidth;
500 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700501 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700502 mMinWidth = INVALID_MIN_SIZE;
503 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700504 }
505 }
506
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800507 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700508 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800509 * record is based on (normally the root activity intent).
510 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700511 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800512 final Intent intent = new Intent(r.intent);
513 // Correct the activity intent for aliasing. The task record intent will always be based on
514 // the real activity that will be launched not the alias, so we need to use an intent with
515 // the component name pointing to the real activity not the alias in the activity record.
516 intent.setComponent(r.realActivity);
517 return this.intent.filterEquals(intent);
518 }
519
Craig Mautner84984fa2014-06-19 11:19:20 -0700520 void setTaskToReturnTo(int taskToReturnTo) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -0800521 mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
522 ? HOME_ACTIVITY_TYPE : taskToReturnTo;
Craig Mautner84984fa2014-06-19 11:19:20 -0700523 }
524
525 int getTaskToReturnTo() {
526 return mTaskToReturnTo;
527 }
528
Craig Mautnera228ae92014-07-09 05:44:55 -0700529 void setPrevAffiliate(TaskRecord prevAffiliate) {
530 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800531 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700532 }
533
534 void setNextAffiliate(TaskRecord nextAffiliate) {
535 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800536 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700537 }
538
Andrii Kulian02b7a832016-10-06 23:11:56 -0700539 ActivityStack getStack() {
540 return mStack;
541 }
542
Andrii Kulian1779e612016-10-12 21:58:25 -0700543 /** Must be used for setting parent stack because it performs configuration updates. */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700544 void setStack(ActivityStack stack) {
545 mStack = stack;
Andrii Kulian1779e612016-10-12 21:58:25 -0700546 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700547 }
548
549 /**
550 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
551 */
552 int getStackId() {
553 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
554 }
555
Andrii Kulian1779e612016-10-12 21:58:25 -0700556 @Override
557 protected int getChildCount() {
558 return 0;
559 }
560
561 @Override
562 protected ConfigurationContainer getChildAt(int index) {
563 return null;
564 }
565
566 @Override
567 protected ConfigurationContainer getParent() {
568 return mStack;
569 }
570
Craig Mautnera228ae92014-07-09 05:44:55 -0700571 // Close up recents linked list.
572 void closeRecentsChain() {
573 if (mPrevAffiliate != null) {
574 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
575 }
576 if (mNextAffiliate != null) {
577 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
578 }
579 setPrevAffiliate(null);
580 setNextAffiliate(null);
581 }
582
Winson Chung740c3ac2014-11-12 16:14:38 -0800583 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -0700584 disposeThumbnail();
585 closeRecentsChain();
586 if (inRecents) {
587 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -0800588 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700589 }
590 }
591
Craig Mautnera228ae92014-07-09 05:44:55 -0700592 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
593 closeRecentsChain();
594 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -0700595 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700596 // Find the end
597 while (taskToAffiliateWith.mNextAffiliate != null) {
598 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
599 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
600 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
601 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
602 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
603 nextRecents.setPrevAffiliate(null);
604 }
605 taskToAffiliateWith.setNextAffiliate(null);
606 break;
607 }
608 taskToAffiliateWith = nextRecents;
609 }
610 taskToAffiliateWith.setNextAffiliate(this);
611 setPrevAffiliate(taskToAffiliateWith);
612 setNextAffiliate(null);
613 }
614
Winson Chung096f36b2014-08-20 15:39:01 -0700615 /**
Winsonc809cbb2015-11-02 12:06:15 -0800616 * Sets the last thumbnail with the current task bounds and the system orientation.
Winson Chung096f36b2014-08-20 15:39:01 -0700617 * @return whether the thumbnail was set
618 */
Winsonc809cbb2015-11-02 12:06:15 -0800619 boolean setLastThumbnailLocked(Bitmap thumbnail) {
Winsonc809cbb2015-11-02 12:06:15 -0800620 int taskWidth = 0;
621 int taskHeight = 0;
622 if (mBounds != null) {
623 // Non-fullscreen tasks
624 taskWidth = mBounds.width();
625 taskHeight = mBounds.height();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700626 } else if (mStack != null) {
Winsonc809cbb2015-11-02 12:06:15 -0800627 // Fullscreen tasks
628 final Point displaySize = new Point();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700629 mStack.getDisplaySize(displaySize);
Winsonc809cbb2015-11-02 12:06:15 -0800630 taskWidth = displaySize.x;
631 taskHeight = displaySize.y;
632 } else {
633 Slog.e(TAG, "setLastThumbnailLocked() called on Task without stack");
634 }
Andrii Kulian1779e612016-10-12 21:58:25 -0700635 // We need to provide the current orientation of the display on which this task resides,
636 // not the orientation of the task.
637 final int orientation =
638 getStack().mActivityContainer.mActivityDisplay.getConfiguration().orientation;
639 return setLastThumbnailLocked(thumbnail, taskWidth, taskHeight, orientation);
Winsonc809cbb2015-11-02 12:06:15 -0800640 }
641
642 /**
643 * Sets the last thumbnail with the current task bounds.
644 * @return whether the thumbnail was set
645 */
646 private boolean setLastThumbnailLocked(Bitmap thumbnail, int taskWidth, int taskHeight,
647 int screenOrientation) {
Winson Chung096f36b2014-08-20 15:39:01 -0700648 if (mLastThumbnail != thumbnail) {
649 mLastThumbnail = thumbnail;
Winsonc809cbb2015-11-02 12:06:15 -0800650 mLastThumbnailInfo.taskWidth = taskWidth;
651 mLastThumbnailInfo.taskHeight = taskHeight;
652 mLastThumbnailInfo.screenOrientation = screenOrientation;
Winson Chung096f36b2014-08-20 15:39:01 -0700653 if (thumbnail == null) {
654 if (mLastThumbnailFile != null) {
655 mLastThumbnailFile.delete();
656 }
657 } else {
Suprabh Shukla09a88f52015-12-02 14:36:31 -0800658 mService.mRecentTasks.saveImage(thumbnail, mLastThumbnailFile.getAbsolutePath());
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700659 }
Winson Chung096f36b2014-08-20 15:39:01 -0700660 return true;
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700661 }
Winson Chung096f36b2014-08-20 15:39:01 -0700662 return false;
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700663 }
664
665 void getLastThumbnail(TaskThumbnail thumbs) {
666 thumbs.mainThumbnail = mLastThumbnail;
Winsonc809cbb2015-11-02 12:06:15 -0800667 thumbs.thumbnailInfo = mLastThumbnailInfo;
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700668 thumbs.thumbnailFileDescriptor = null;
Craig Mautnerf4f8bb72014-07-29 10:41:40 -0700669 if (mLastThumbnail == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -0800670 thumbs.mainThumbnail = mService.mRecentTasks.getImageFromWriteQueue(
Suprabh Shukla23593142015-11-03 17:31:15 -0800671 mLastThumbnailFile.getAbsolutePath());
Craig Mautnerf4f8bb72014-07-29 10:41:40 -0700672 }
Winson Chung096f36b2014-08-20 15:39:01 -0700673 // Only load the thumbnail file if we don't have a thumbnail
674 if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700675 try {
676 thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,
677 ParcelFileDescriptor.MODE_READ_ONLY);
678 } catch (IOException e) {
Dianne Hackborn9844d292013-10-04 16:44:22 -0700679 }
680 }
681 }
682
Winsonc809cbb2015-11-02 12:06:15 -0800683 /**
684 * Removes in-memory thumbnail data when the max number of in-memory task thumbnails is reached.
685 */
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700686 void freeLastThumbnail() {
687 mLastThumbnail = null;
688 }
689
Winsonc809cbb2015-11-02 12:06:15 -0800690 /**
691 * Removes all associated thumbnail data when a task is removed or pruned from recents.
692 */
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700693 void disposeThumbnail() {
Winsonc6a2da02015-11-11 18:11:59 -0800694 mLastThumbnailInfo.reset();
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700695 mLastThumbnail = null;
696 lastDescription = null;
697 }
698
Winson Chung1147c402014-05-14 11:05:00 -0700699 /** Returns the intent for the root activity for this task */
700 Intent getBaseIntent() {
701 return intent != null ? intent : affinityIntent;
702 }
703
Winson Chung3b3f4642014-04-22 10:08:18 -0700704 /** Returns the first non-finishing activity from the root. */
705 ActivityRecord getRootActivity() {
706 for (int i = 0; i < mActivities.size(); i++) {
707 final ActivityRecord r = mActivities.get(i);
708 if (r.finishing) {
709 continue;
710 }
711 return r;
712 }
713 return null;
714 }
715
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800716 ActivityRecord getTopActivity() {
717 for (int i = mActivities.size() - 1; i >= 0; --i) {
718 final ActivityRecord r = mActivities.get(i);
719 if (r.finishing) {
720 continue;
721 }
722 return r;
723 }
724 return null;
725 }
726
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -0700727 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -0700728 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -0700729 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
730 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -0700731 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -0700732 return r;
733 }
Craig Mautner6b74cb52013-09-27 17:02:21 -0700734 }
735 }
736 return null;
737 }
738
Wale Ogunwale3b232392016-05-13 15:37:13 -0700739 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -0700740 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -0700741 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
742 ActivityRecord r = mActivities.get(activityNdx);
743 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -0700744 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -0700745 continue;
746 }
747 return r;
748 }
749 }
750 return null;
751 }
752
Chong Zhang87761972016-08-22 13:53:24 -0700753 boolean okToShowLocked() {
754 // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
755 // okay to show the activity when locked.
756 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
757 || topRunningActivityLocked() != null;
758 }
759
Wale Ogunwale6d42df62015-11-05 09:50:55 -0800760 void setFrontOfTask() {
761 setFrontOfTask(null);
762 }
763
Craig Mautner3b475fe2013-12-16 15:58:31 -0800764 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Wale Ogunwale6d42df62015-11-05 09:50:55 -0800765 void setFrontOfTask(ActivityRecord newTop) {
766 // If a top candidate is suggested by the caller, go ahead and use it and mark all others
767 // as not front. This is needed in situations where the current front activity in the
768 // task isn't finished yet and we want to set the front to the activity moved to the front
769 // of the task.
770 boolean foundFront = newTop != null ? true : false;
771
Craig Mautner3b475fe2013-12-16 15:58:31 -0800772 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -0800773 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -0800774 final ActivityRecord r = mActivities.get(activityNdx);
775 if (foundFront || r.finishing) {
776 r.frontOfTask = false;
777 } else {
778 r.frontOfTask = true;
779 // Set frontOfTask false for every following activity.
780 foundFront = true;
781 }
782 }
Craig Mautner9587ee02014-06-23 15:00:10 +0000783 if (!foundFront && numActivities > 0) {
784 // All activities of this task are finishing. As we ought to have a frontOfTask
785 // activity, make the bottom activity front.
786 mActivities.get(0).frontOfTask = true;
787 }
Wale Ogunwale6d42df62015-11-05 09:50:55 -0800788 if (newTop != null) {
789 newTop.frontOfTask = true;
790 }
Craig Mautner3b475fe2013-12-16 15:58:31 -0800791 }
792
Craig Mautnerde4ef022013-04-07 19:01:33 -0700793 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -0800794 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700795 */
796 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700797 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
798 "Removing and adding activity " + newTop
799 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -0700800
Craig Mautnerde4ef022013-04-07 19:01:33 -0700801 mActivities.remove(newTop);
802 mActivities.add(newTop);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700803 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -0800804
Wale Ogunwale6d42df62015-11-05 09:50:55 -0800805 setFrontOfTask(newTop);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700806 }
807
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800808 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -0800809 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800810 }
811
812 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700813 addActivityAtIndex(mActivities.size(), r);
814 }
815
816 void addActivityAtIndex(int index, ActivityRecord r) {
Craig Mautner6170f732013-04-02 13:05:23 -0700817 // 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 -0800818 if (!mActivities.remove(r) && r.fullscreen) {
819 // Was not previously in list.
820 numFullscreen++;
821 }
Craig Mautner2c1faed2013-07-23 12:56:02 -0700822 // Only set this based on the first activity
823 if (mActivities.isEmpty()) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700824 taskType = r.mActivityType;
825 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700826 mCallingUid = r.launchedFromUid;
827 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700828 // Clamp to [1, max].
829 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
830 ActivityManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -0700831 } else {
832 // Otherwise make all added activities match this one.
Craig Mautner21d24a22014-04-23 11:45:37 -0700833 r.mActivityType = taskType;
Craig Mautner78733002013-06-10 13:54:49 -0700834 }
Wale Ogunwale3b232392016-05-13 15:37:13 -0700835
836 final int size = mActivities.size();
837
838 if (index == size && size > 0) {
839 final ActivityRecord top = mActivities.get(size - 1);
840 if (top.mTaskOverlay) {
841 // Place below the task overlay activity since the overlay activity should always
842 // be on top.
843 index--;
844 }
845 }
846
Craig Mautner77878772013-03-04 19:46:24 -0800847 mActivities.add(index, r);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700848 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -0700849 if (r.isPersistable()) {
850 mService.notifyTaskPersisterLocked(this, false);
851 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800852
853 // Sync. with window manager
854 updateOverrideConfigurationFromLaunchBounds();
855 r.positionWindowContainerAt(index);
856 r.onOverrideConfigurationSent();
Craig Mautner77878772013-03-04 19:46:24 -0800857 }
858
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800859 /** @return true if this was the last activity in the task */
860 boolean removeActivity(ActivityRecord r) {
861 if (mActivities.remove(r) && r.fullscreen) {
862 // Was previously in list.
863 numFullscreen--;
864 }
Craig Mautner21d24a22014-04-23 11:45:37 -0700865 if (r.isPersistable()) {
866 mService.notifyTaskPersisterLocked(this, false);
867 }
Wale Ogunwale89182d52016-03-11 10:38:36 -0800868
Andrii Kulian02b7a832016-10-06 23:11:56 -0700869 if (getStackId() == PINNED_STACK_ID) {
Wale Ogunwale89182d52016-03-11 10:38:36 -0800870 // We normally notify listeners of task stack changes on pause, however pinned stack
871 // activities are normally in the paused state so no notification will be sent there
872 // before the activity is removed. We send it here so instead.
Yorke Leebd54c2a2016-10-25 13:49:23 -0700873 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -0800874 }
875
Craig Mautner41326202014-06-20 14:38:21 -0700876 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -0700877 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -0700878 }
879 updateEffectiveIntent();
880 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800881 }
882
Craig Mautner41db4a72014-05-07 17:20:56 -0700883 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700884 // We will automatically remove the task either if it has explicitly asked for
885 // this, or it is empty and has never contained an activity that got shown to
886 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700887 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -0700888 }
889
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700890 /**
891 * Completely remove all activities associated with an existing
892 * task starting at a specified index.
893 */
894 final void performClearTaskAtIndexLocked(int activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700895 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700896 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700897 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700898 if (r.finishing) {
899 continue;
900 }
Andrii Kulian02b7a832016-10-06 23:11:56 -0700901 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700902 // Task was restored from persistent storage.
903 r.takeFromHistory();
904 mActivities.remove(activityNdx);
905 --activityNdx;
906 --numActivities;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700907 } else if (mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -0800908 r, Activity.RESULT_CANCELED, null, "clear-task-index", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700909 --activityNdx;
910 --numActivities;
911 }
912 }
913 }
914
915 /**
916 * Completely remove all activities associated with an existing task.
917 */
918 final void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -0700919 mReuseTask = true;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700920 performClearTaskAtIndexLocked(0);
Craig Mautner362449a2014-06-20 14:04:39 -0700921 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700922 }
923
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800924 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
925 mReuseTask = true;
926 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
927 mReuseTask = false;
928 return result;
929 }
930
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700931 /**
932 * Perform clear operation as requested by
933 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
934 * stack to the given task, then look for
935 * an instance of that activity in the stack and, if found, finish all
936 * activities on top of it and return the instance.
937 *
938 * @param newR Description of the new activity being started.
939 * @return Returns the old activity that should be continued to be used,
940 * or null if none was found.
941 */
942 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700943 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700944 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700945 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700946 if (r.finishing) {
947 continue;
948 }
949 if (r.realActivity.equals(newR.realActivity)) {
950 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -0700951 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700952
953 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -0700954 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700955 if (r.finishing) {
956 continue;
957 }
958 ActivityOptions opts = r.takeOptionsLocked();
959 if (opts != null) {
960 ret.updateOptionsLocked(opts);
961 }
Andrii Kulian02b7a832016-10-06 23:11:56 -0700962 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -0800963 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700964 --activityNdx;
965 --numActivities;
966 }
967 }
968
969 // Finally, if this is a normal launch mode (that is, not
970 // expecting onNewIntent()), then we will finish the current
971 // instance of the activity so a new fresh one can be started.
972 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +0900973 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
974 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700975 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -0700976 if (mStack != null) {
977 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -0700978 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
979 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -0700980 return null;
981 }
982 }
983
984 return ret;
985 }
986 }
987
988 return null;
989 }
990
Andrii Kulian21713ac2016-10-12 22:05:05 -0700991 TaskThumbnail getTaskThumbnailLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -0700992 if (mStack != null) {
993 final ActivityRecord resumedActivity = mStack.mResumedActivity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700994 if (resumedActivity != null && resumedActivity.task == this) {
Andrii Kulian21713ac2016-10-12 22:05:05 -0700995 final Bitmap thumbnail = resumedActivity.screenshotActivityLocked();
Winsonc809cbb2015-11-02 12:06:15 -0800996 setLastThumbnailLocked(thumbnail);
Craig Mautner21d24a22014-04-23 11:45:37 -0700997 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700998 }
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700999 final TaskThumbnail taskThumbnail = new TaskThumbnail();
1000 getLastThumbnail(taskThumbnail);
1001 return taskThumbnail;
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001002 }
1003
Andrii Kulian21713ac2016-10-12 22:05:05 -07001004 void removeTaskActivitiesLocked() {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001005 // Just remove the entire task.
1006 performClearTaskAtIndexLocked(0);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001007 }
1008
Craig Mautner432f64e2015-05-20 14:59:57 -07001009 String lockTaskAuthToString() {
1010 switch (mLockTaskAuth) {
1011 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1012 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1013 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1014 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001015 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001016 default: return "unknown=" + mLockTaskAuth;
1017 }
1018 }
1019
Craig Mautner15df08a2015-04-01 12:17:18 -07001020 void setLockTaskAuth() {
Benjamin Franz469dd582015-06-09 14:24:36 +01001021 if (!mPrivileged &&
1022 (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS ||
1023 mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1024 // Non-priv apps are not allowed to use always or never, fall back to default
1025 mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1026 }
Craig Mautner15df08a2015-04-01 12:17:18 -07001027 switch (mLockTaskMode) {
1028 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1029 mLockTaskAuth = isLockTaskWhitelistedLocked() ?
1030 LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1031 break;
1032
1033 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001034 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001035 break;
1036
1037 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001038 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001039 break;
1040
1041 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1042 mLockTaskAuth = isLockTaskWhitelistedLocked() ?
1043 LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1044 break;
1045 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001046 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1047 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001048 }
1049
1050 boolean isLockTaskWhitelistedLocked() {
Benjamin Franz6fd84cc2015-08-06 18:09:03 +01001051 String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1052 if (pkg == null) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001053 return false;
1054 }
1055 String[] packages = mService.mLockTaskPackages.get(userId);
1056 if (packages == null) {
1057 return false;
1058 }
1059 for (int i = packages.length - 1; i >= 0; --i) {
Benjamin Franz6fd84cc2015-08-06 18:09:03 +01001060 if (pkg.equals(packages[i])) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001061 return true;
1062 }
1063 }
1064 return false;
1065 }
Wale Ogunwale74e26592016-02-05 11:48:37 -08001066
Craig Mautnera82aa092013-09-13 15:34:08 -07001067 boolean isHomeTask() {
Craig Mautner84984fa2014-06-19 11:19:20 -07001068 return taskType == HOME_ACTIVITY_TYPE;
Craig Mautnera82aa092013-09-13 15:34:08 -07001069 }
1070
Wale Ogunwale74e26592016-02-05 11:48:37 -08001071 boolean isRecentsTask() {
1072 return taskType == RECENTS_ACTIVITY_TYPE;
1073 }
1074
Craig Mautner86d67a42013-05-14 10:34:38 -07001075 boolean isApplicationTask() {
Craig Mautner84984fa2014-06-19 11:19:20 -07001076 return taskType == APPLICATION_ACTIVITY_TYPE;
1077 }
1078
1079 boolean isOverHomeStack() {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001080 return mTaskToReturnTo == HOME_ACTIVITY_TYPE;
Craig Mautner1602ec22013-05-12 10:24:27 -07001081 }
1082
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001083 boolean isResizeable() {
Wale Ogunwaledf241e92016-10-13 15:14:21 -07001084 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode))
1085 && !mTemporarilyUnresizable;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001086 }
1087
skuhne@google.com322347b2016-12-02 12:54:03 -08001088 /**
1089 * Check that a given bounds matches the application requested orientation.
1090 *
1091 * @param bounds The bounds to be tested.
1092 * @return True if the requested bounds are okay for a resizing request.
1093 */
1094 boolean canResizeToBounds(Rect bounds) {
1095 if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
1096 // Note: If not on the freeform workspace, we ignore the bounds.
1097 return true;
1098 }
1099 final boolean landscape = bounds.width() > bounds.height();
1100 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1101 return mBounds == null || landscape == (mBounds.width() > mBounds.height());
1102 }
1103 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1104 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1105 }
1106
Jiaquan Hedd1e66f2016-06-15 15:15:12 -07001107 boolean isOnTopLauncher() {
1108 return isHomeTask() && mIsOnTopLauncher;
1109 }
1110
Wale Ogunwale513346d2016-01-27 10:55:01 -08001111 boolean canGoInDockedStack() {
Matthew Ng626e0cc2016-12-07 17:25:53 -08001112 return isResizeable() && mService.mSupportsSplitScreenMultiWindow &&
skuhne@google.com322347b2016-12-02 12:54:03 -08001113 !ActivityInfo.isPreserveOrientationMode(mResizeMode);
Wale Ogunwale513346d2016-01-27 10:55:01 -08001114 }
1115
Craig Mautner525f3d92013-05-07 14:01:50 -07001116 /**
1117 * Find the activity in the history stack within the given task. Returns
1118 * the index within the history at which it's found, or < 0 if not found.
1119 */
1120 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
1121 final ComponentName realActivity = r.realActivity;
1122 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1123 ActivityRecord candidate = mActivities.get(activityNdx);
1124 if (candidate.finishing) {
1125 continue;
1126 }
1127 if (candidate.realActivity.equals(realActivity)) {
1128 return candidate;
1129 }
1130 }
1131 return null;
1132 }
1133
Winson Chunga449dc02014-05-16 11:15:04 -07001134 /** Updates the last task description values. */
1135 void updateTaskDescription() {
1136 // Traverse upwards looking for any break between main task activities and
1137 // utility activities.
1138 int activityNdx;
1139 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001140 final boolean relinquish = numActivities != 0 &&
1141 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001142 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001143 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001144 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001145 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001146 // This will be the top activity for determining taskDescription. Pre-inc to
1147 // overcome initial decrement below.
1148 ++activityNdx;
1149 break;
1150 }
Winson Chunga449dc02014-05-16 11:15:04 -07001151 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001152 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001153 break;
1154 }
1155 }
1156 if (activityNdx > 0) {
1157 // Traverse downwards starting below break looking for set label, icon.
1158 // Note that if there are activities in the task but none of them set the
1159 // recent activity values, then we do not fall back to the last set
1160 // values in the TaskRecord.
1161 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001162 String iconFilename = null;
Winson Chunga449dc02014-05-16 11:15:04 -07001163 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001164 int colorBackground = 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001165 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1166 final ActivityRecord r = mActivities.get(activityNdx);
1167 if (r.taskDescription != null) {
1168 if (label == null) {
1169 label = r.taskDescription.getLabel();
1170 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001171 if (iconFilename == null) {
1172 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001173 }
1174 if (colorPrimary == 0) {
1175 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001176 }
Winson Chung1af8eda2016-02-05 17:55:56 +00001177 if (colorBackground == 0) {
1178 colorBackground = r.taskDescription.getBackgroundColor();
1179 }
Winson Chunga449dc02014-05-16 11:15:04 -07001180 }
1181 }
Winson Chung1af8eda2016-02-05 17:55:56 +00001182 lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
1183 colorBackground);
Winson Chungec396d62014-08-06 17:08:00 -07001184 // Update the task affiliation color if we are the parent of the group
1185 if (taskId == mAffiliatedTaskId) {
1186 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1187 }
Winson Chunga449dc02014-05-16 11:15:04 -07001188 }
1189 }
1190
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001191 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001192 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001193 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001194 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001195 final ActivityRecord r = mActivities.get(activityNdx);
1196 if (r.finishing) {
1197 continue;
1198 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001199 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001200 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001201 break;
1202 }
1203 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001204 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001205 }
1206
1207 void updateEffectiveIntent() {
1208 final int effectiveRootIndex = findEffectiveRootIndex();
1209 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001210 setIntent(r);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001211 }
1212
Craig Mautner21d24a22014-04-23 11:45:37 -07001213 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
Wale Ogunwaleee006da2015-03-30 14:49:25 -07001214 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
Craig Mautner21d24a22014-04-23 11:45:37 -07001215
1216 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
1217 if (realActivity != null) {
1218 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
1219 }
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001220 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
Craig Mautner21d24a22014-04-23 11:45:37 -07001221 if (origActivity != null) {
1222 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
1223 }
Dianne Hackborn79228822014-09-16 11:11:23 -07001224 // Write affinity, and root affinity if it is different from affinity.
1225 // We use the special string "@" for a null root affinity, so we can identify
1226 // later whether we were given a root affinity or should just make it the
1227 // same as the affinity.
Craig Mautner21d24a22014-04-23 11:45:37 -07001228 if (affinity != null) {
1229 out.attribute(null, ATTR_AFFINITY, affinity);
Dianne Hackborn79228822014-09-16 11:11:23 -07001230 if (!affinity.equals(rootAffinity)) {
1231 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
1232 }
1233 } else if (rootAffinity != null) {
1234 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
Craig Mautner21d24a22014-04-23 11:45:37 -07001235 }
1236 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
Dianne Hackborn13420f22014-07-18 15:43:56 -07001237 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
Craig Mautner21d24a22014-04-23 11:45:37 -07001238 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
1239 out.attribute(null, ATTR_USERID, String.valueOf(userId));
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001240 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001241 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
Craig Mautner21d24a22014-04-23 11:45:37 -07001242 out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
Winson Chungffa2ec62014-07-03 15:54:42 -07001243 out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
Winson Chungf1fbd772014-06-24 18:06:58 -07001244 out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
Craig Mautner21d24a22014-04-23 11:45:37 -07001245 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001246 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
Craig Mautner21d24a22014-04-23 11:45:37 -07001247 if (lastDescription != null) {
1248 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
1249 }
Winson Chung2cb86c72014-06-25 12:03:30 -07001250 if (lastTaskDescription != null) {
Craig Mautner648f69b2014-09-18 14:16:26 -07001251 lastTaskDescription.saveToXml(out);
Winson Chung2cb86c72014-06-25 12:03:30 -07001252 }
Winson Chung36f3f032016-09-08 23:29:43 +00001253 mLastThumbnailInfo.saveToXml(out);
Winson Chungec396d62014-08-06 17:08:00 -07001254 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
Craig Mautnera228ae92014-07-09 05:44:55 -07001255 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
1256 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
1257 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001258 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
1259 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001260 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001261 out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
Wale Ogunwale706ed792015-08-02 10:29:44 -07001262 if (mLastNonFullscreenBounds != null) {
1263 out.attribute(
1264 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001265 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001266 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
1267 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001268 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
Winson Chung2cb86c72014-06-25 12:03:30 -07001269
Craig Mautner21d24a22014-04-23 11:45:37 -07001270 if (affinityIntent != null) {
1271 out.startTag(null, TAG_AFFINITYINTENT);
1272 affinityIntent.saveToXml(out);
1273 out.endTag(null, TAG_AFFINITYINTENT);
1274 }
1275
Winson Chung36f3f032016-09-08 23:29:43 +00001276 out.startTag(null, TAG_INTENT);
1277 intent.saveToXml(out);
1278 out.endTag(null, TAG_INTENT);
Craig Mautner21d24a22014-04-23 11:45:37 -07001279
1280 final ArrayList<ActivityRecord> activities = mActivities;
1281 final int numActivities = activities.size();
1282 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
1283 final ActivityRecord r = activities.get(activityNdx);
Craig Mautner43e52ed2014-06-16 17:18:52 -07001284 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
Wale Ogunwale843bfb92015-03-27 11:06:48 -07001285 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
1286 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
Craig Mautner43e52ed2014-06-16 17:18:52 -07001287 activityNdx > 0) {
Craig Mautnerf357c0c2014-06-09 09:23:27 -07001288 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
Craig Mautner21d24a22014-04-23 11:45:37 -07001289 break;
1290 }
1291 out.startTag(null, TAG_ACTIVITY);
1292 r.saveToXml(out);
1293 out.endTag(null, TAG_ACTIVITY);
1294 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001295 }
1296
Winson Chung36f3f032016-09-08 23:29:43 +00001297 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
1298 throws IOException, XmlPullParserException {
Craig Mautner21d24a22014-04-23 11:45:37 -07001299 Intent intent = null;
1300 Intent affinityIntent = null;
Winsonc809cbb2015-11-02 12:06:15 -08001301 ArrayList<ActivityRecord> activities = new ArrayList<>();
Craig Mautner21d24a22014-04-23 11:45:37 -07001302 ComponentName realActivity = null;
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001303 boolean realActivitySuspended = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001304 ComponentName origActivity = null;
1305 String affinity = null;
Dianne Hackborn79228822014-09-16 11:11:23 -07001306 String rootAffinity = null;
1307 boolean hasRootAffinity = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001308 boolean rootHasReset = false;
Dianne Hackborn13420f22014-07-18 15:43:56 -07001309 boolean autoRemoveRecents = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001310 boolean askedCompatMode = false;
1311 int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Craig Mautner21d24a22014-04-23 11:45:37 -07001312 int userId = 0;
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001313 boolean userSetupComplete = true;
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001314 int effectiveUid = -1;
Craig Mautner21d24a22014-04-23 11:45:37 -07001315 String lastDescription = null;
Winson Chungffa2ec62014-07-03 15:54:42 -07001316 long firstActiveTime = -1;
Winson Chung2cb86c72014-06-25 12:03:30 -07001317 long lastActiveTime = -1;
Craig Mautner21d24a22014-04-23 11:45:37 -07001318 long lastTimeOnTop = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001319 boolean neverRelinquishIdentity = true;
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001320 int taskId = INVALID_TASK_ID;
Craig Mautner21d24a22014-04-23 11:45:37 -07001321 final int outerDepth = in.getDepth();
Craig Mautner648f69b2014-09-18 14:16:26 -07001322 TaskDescription taskDescription = new TaskDescription();
Winsonc809cbb2015-11-02 12:06:15 -08001323 TaskThumbnailInfo thumbnailInfo = new TaskThumbnailInfo();
Wale Ogunwale18795a22014-12-03 11:38:33 -08001324 int taskAffiliation = INVALID_TASK_ID;
Winson Chungec396d62014-08-06 17:08:00 -07001325 int taskAffiliationColor = 0;
Wale Ogunwale18795a22014-12-03 11:38:33 -08001326 int prevTaskId = INVALID_TASK_ID;
1327 int nextTaskId = INVALID_TASK_ID;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001328 int callingUid = -1;
1329 String callingPackage = "";
Wale Ogunwaled829d362016-02-10 19:24:49 -08001330 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001331 boolean privileged = false;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001332 Rect bounds = null;
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001333 int minWidth = INVALID_MIN_SIZE;
1334 int minHeight = INVALID_MIN_SIZE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001335 int persistTaskVersion = 0;
Craig Mautner21d24a22014-04-23 11:45:37 -07001336
1337 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
1338 final String attrName = in.getAttributeName(attrNdx);
1339 final String attrValue = in.getAttributeValue(attrNdx);
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001340 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
1341 attrName + " value=" + attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001342 if (ATTR_TASKID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001343 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001344 } else if (ATTR_REALACTIVITY.equals(attrName)) {
1345 realActivity = ComponentName.unflattenFromString(attrValue);
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001346 } else if (ATTR_REALACTIVITY_SUSPENDED.equals(attrName)) {
1347 realActivitySuspended = Boolean.valueOf(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001348 } else if (ATTR_ORIGACTIVITY.equals(attrName)) {
1349 origActivity = ComponentName.unflattenFromString(attrValue);
1350 } else if (ATTR_AFFINITY.equals(attrName)) {
1351 affinity = attrValue;
Dianne Hackborn79228822014-09-16 11:11:23 -07001352 } else if (ATTR_ROOT_AFFINITY.equals(attrName)) {
1353 rootAffinity = attrValue;
1354 hasRootAffinity = true;
Craig Mautner21d24a22014-04-23 11:45:37 -07001355 } else if (ATTR_ROOTHASRESET.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001356 rootHasReset = Boolean.parseBoolean(attrValue);
Dianne Hackborn13420f22014-07-18 15:43:56 -07001357 } else if (ATTR_AUTOREMOVERECENTS.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001358 autoRemoveRecents = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001359 } else if (ATTR_ASKEDCOMPATMODE.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001360 askedCompatMode = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001361 } else if (ATTR_USERID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001362 userId = Integer.parseInt(attrValue);
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001363 } else if (ATTR_USER_SETUP_COMPLETE.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001364 userSetupComplete = Boolean.parseBoolean(attrValue);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001365 } else if (ATTR_EFFECTIVE_UID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001366 effectiveUid = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001367 } else if (ATTR_TASKTYPE.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001368 taskType = Integer.parseInt(attrValue);
Winson Chungffa2ec62014-07-03 15:54:42 -07001369 } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001370 firstActiveTime = Long.parseLong(attrValue);
Winson Chungf1fbd772014-06-24 18:06:58 -07001371 } else if (ATTR_LASTACTIVETIME.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001372 lastActiveTime = Long.parseLong(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001373 } else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
1374 lastDescription = attrValue;
1375 } else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001376 lastTimeOnTop = Long.parseLong(attrValue);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001377 } else if (ATTR_NEVERRELINQUISH.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001378 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
Winsonc809cbb2015-11-02 12:06:15 -08001379 } else if (attrName.startsWith(TaskThumbnailInfo.ATTR_TASK_THUMBNAILINFO_PREFIX)) {
1380 thumbnailInfo.restoreFromXml(attrName, attrValue);
Craig Mautner648f69b2014-09-18 14:16:26 -07001381 } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
1382 taskDescription.restoreFromXml(attrName, attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001383 } else if (ATTR_TASK_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001384 taskAffiliation = Integer.parseInt(attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001385 } else if (ATTR_PREV_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001386 prevTaskId = Integer.parseInt(attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001387 } else if (ATTR_NEXT_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001388 nextTaskId = Integer.parseInt(attrValue);
Winson Chungec396d62014-08-06 17:08:00 -07001389 } else if (ATTR_TASK_AFFILIATION_COLOR.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001390 taskAffiliationColor = Integer.parseInt(attrValue);
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001391 } else if (ATTR_CALLING_UID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001392 callingUid = Integer.parseInt(attrValue);
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001393 } else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
1394 callingPackage = attrValue;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001395 } else if (ATTR_RESIZE_MODE.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001396 resizeMode = Integer.parseInt(attrValue);
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001397 } else if (ATTR_PRIVILEGED.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001398 privileged = Boolean.parseBoolean(attrValue);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001399 } else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001400 bounds = Rect.unflattenFromString(attrValue);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001401 } else if (ATTR_MIN_WIDTH.equals(attrName)) {
1402 minWidth = Integer.parseInt(attrValue);
1403 } else if (ATTR_MIN_HEIGHT.equals(attrName)) {
1404 minHeight = Integer.parseInt(attrValue);
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001405 } else if (ATTR_PERSIST_TASK_VERSION.equals(attrName)) {
1406 persistTaskVersion = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001407 } else {
1408 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
1409 }
1410 }
1411
1412 int event;
1413 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
Ben Kwa8814cf42015-07-08 10:54:56 -07001414 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001415 if (event == XmlPullParser.START_TAG) {
1416 final String name = in.getName();
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001417 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" +
1418 name);
Craig Mautner21d24a22014-04-23 11:45:37 -07001419 if (TAG_AFFINITYINTENT.equals(name)) {
1420 affinityIntent = Intent.restoreFromXml(in);
1421 } else if (TAG_INTENT.equals(name)) {
1422 intent = Intent.restoreFromXml(in);
1423 } else if (TAG_ACTIVITY.equals(name)) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08001424 ActivityRecord activity = ActivityRecord.restoreFromXml(in, stackSupervisor);
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001425 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
1426 activity);
Craig Mautner21d24a22014-04-23 11:45:37 -07001427 if (activity != null) {
1428 activities.add(activity);
1429 }
1430 } else {
1431 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
1432 XmlUtils.skipCurrentTag(in);
1433 }
1434 }
1435 }
Dianne Hackborn79228822014-09-16 11:11:23 -07001436 if (!hasRootAffinity) {
1437 rootAffinity = affinity;
1438 } else if ("@".equals(rootAffinity)) {
1439 rootAffinity = null;
1440 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001441 if (effectiveUid <= 0) {
1442 Intent checkIntent = intent != null ? intent : affinityIntent;
1443 effectiveUid = 0;
1444 if (checkIntent != null) {
1445 IPackageManager pm = AppGlobals.getPackageManager();
1446 try {
1447 ApplicationInfo ai = pm.getApplicationInfo(
1448 checkIntent.getComponent().getPackageName(),
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07001449 PackageManager.MATCH_UNINSTALLED_PACKAGES
1450 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001451 if (ai != null) {
1452 effectiveUid = ai.uid;
1453 }
1454 } catch (RemoteException e) {
1455 }
1456 }
1457 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
1458 + ": effectiveUid=" + effectiveUid);
1459 }
1460
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001461 if (persistTaskVersion < 1) {
1462 // We need to convert the resize mode of home activities saved before version one if
1463 // they are marked as RESIZE_MODE_RESIZEABLE to RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
1464 // since we didn't have that differentiation before version 1 and the system didn't
1465 // resize home activities before then.
1466 if (taskType == HOME_ACTIVITY_TYPE && resizeMode == RESIZE_MODE_RESIZEABLE) {
1467 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
1468 }
1469 }
1470
Winson Chung36f3f032016-09-08 23:29:43 +00001471 final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
Dianne Hackborn79228822014-09-16 11:11:23 -07001472 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001473 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
1474 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
Winsonc809cbb2015-11-02 12:06:15 -08001475 taskDescription, thumbnailInfo, taskAffiliation, prevTaskId, nextTaskId,
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001476 taskAffiliationColor, callingUid, callingPackage, resizeMode, privileged,
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001477 realActivitySuspended, userSetupComplete, minWidth, minHeight);
Filip Gruszczynskiaff7f132015-09-02 17:21:21 -07001478 task.updateOverrideConfiguration(bounds);
Craig Mautner21d24a22014-04-23 11:45:37 -07001479
1480 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001481 activities.get(activityNdx).task = task;
Craig Mautner21d24a22014-04-23 11:45:37 -07001482 }
1483
Wale Ogunwaleee006da2015-03-30 14:49:25 -07001484 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
Craig Mautner21d24a22014-04-23 11:45:37 -07001485 return task;
1486 }
1487
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001488 private void adjustForMinimalTaskDimensions(Rect bounds) {
1489 if (bounds == null) {
1490 return;
1491 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001492 int minWidth = mMinWidth;
1493 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001494 // If the task has no requested minimal size, we'd like to enforce a minimal size
1495 // so that the user can not render the task too small to manipulate. We don't need
1496 // to do this for the pinned stack as the bounds are controlled by the system.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001497 if (getStackId() != PINNED_STACK_ID) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001498 if (minWidth == INVALID_MIN_SIZE) {
1499 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001500 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001501 if (minHeight == INVALID_MIN_SIZE) {
1502 minHeight = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001503 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001504 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001505 final boolean adjustWidth = minWidth > bounds.width();
1506 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001507 if (!(adjustWidth || adjustHeight)) {
1508 return;
1509 }
1510
1511 if (adjustWidth) {
1512 if (mBounds != null && bounds.right == mBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001513 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001514 } else {
1515 // Either left bounds match, or neither match, or the previous bounds were
1516 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001517 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001518 }
1519 }
1520 if (adjustHeight) {
1521 if (mBounds != null && bounds.bottom == mBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001522 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001523 } else {
1524 // Either top bounds match, or neither match, or the previous bounds were
1525 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001526 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001527 }
1528 }
1529 }
1530
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001531 /**
1532 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001533 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07001534 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001535 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001536 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001537 return updateOverrideConfiguration(bounds, null /* insetBounds */);
1538 }
1539
1540 /**
1541 * Update task's override configuration based on the bounds.
1542 * @param bounds The bounds of the task.
1543 * @param insetBounds The bounds used to calculate the system insets, which is used here to
1544 * subtract the navigation bar/status bar size from the screen size reported
1545 * to the application. See {@link IActivityManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07001546 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001547 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001548 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001549 if (Objects.equals(mBounds, bounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07001550 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001551 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001552 mTmpConfig.setTo(getOverrideConfiguration());
Wale Ogunwale5f986092015-12-04 15:35:38 -08001553 final boolean oldFullscreen = mFullscreen;
Andrii Kulian1779e612016-10-12 21:58:25 -07001554 final Configuration newConfig = getOverrideConfiguration();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001555
1556 mFullscreen = bounds == null;
Wale Ogunwale706ed792015-08-02 10:29:44 -07001557 if (mFullscreen) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001558 if (mBounds != null && StackId.persistTaskBounds(mStack.mStackId)) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07001559 mLastNonFullscreenBounds = mBounds;
1560 }
1561 mBounds = null;
Andrii Kulian1779e612016-10-12 21:58:25 -07001562 newConfig.unset();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001563 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001564 mTmpRect.set(bounds);
1565 adjustForMinimalTaskDimensions(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08001566 if (mBounds == null) {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001567 mBounds = new Rect(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08001568 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001569 mBounds.set(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08001570 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001571 if (mStack == null || StackId.persistTaskBounds(mStack.mStackId)) {
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -07001572 mLastNonFullscreenBounds = mBounds;
1573 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001574 calculateOverrideConfig(newConfig, mTmpRect, insetBounds,
Andrii Kuliandaea3572016-04-08 13:20:51 -07001575 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001576 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001577 onOverrideConfigurationChanged(newConfig);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001578
1579 if (mFullscreen != oldFullscreen) {
Andrii Kulian933076d2016-03-29 17:04:42 -07001580 mService.mStackSupervisor.scheduleReportMultiWindowModeChanged(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001581 }
1582
Andrii Kulian1779e612016-10-12 21:58:25 -07001583 return !mTmpConfig.equals(newConfig);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001584 }
1585
Andrii Kuliandaea3572016-04-08 13:20:51 -07001586 private void subtractNonDecorInsets(Rect inOutBounds, Rect inInsetBounds,
1587 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001588 mTmpRect2.set(inInsetBounds);
1589 mService.mWindowManager.subtractNonDecorInsets(mTmpRect2);
1590 int leftInset = mTmpRect2.left - inInsetBounds.left;
1591 int topInset = mTmpRect2.top - inInsetBounds.top;
Andrii Kuliandaea3572016-04-08 13:20:51 -07001592 int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
1593 int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001594 inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
1595 }
1596
Andrii Kuliandaea3572016-04-08 13:20:51 -07001597 private void subtractStableInsets(Rect inOutBounds, Rect inInsetBounds,
1598 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001599 mTmpRect2.set(inInsetBounds);
1600 mService.mWindowManager.subtractStableInsets(mTmpRect2);
1601 int leftInset = mTmpRect2.left - inInsetBounds.left;
1602 int topInset = mTmpRect2.top - inInsetBounds.top;
Andrii Kuliandaea3572016-04-08 13:20:51 -07001603 int rightInset = overrideWidth ? 0 : inInsetBounds.right - mTmpRect2.right;
1604 int bottomInset = overrideHeight ? 0 : inInsetBounds.bottom - mTmpRect2.bottom;
Jorim Jaggi0a932142016-02-01 17:42:25 -08001605 inOutBounds.inset(leftInset, topInset, rightInset, bottomInset);
1606 }
1607
Andrii Kulian1779e612016-10-12 21:58:25 -07001608 /** Clears passed config and fills it with new override values. */
Andrii Kuliana8a9bc52016-10-14 11:00:13 -07001609 private void calculateOverrideConfig(Configuration config, Rect bounds, Rect insetBounds,
1610 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001611 mTmpNonDecorBounds.set(bounds);
1612 mTmpStableBounds.set(bounds);
1613 subtractNonDecorInsets(
Andrii Kuliandaea3572016-04-08 13:20:51 -07001614 mTmpNonDecorBounds, insetBounds != null ? insetBounds : bounds,
1615 overrideWidth, overrideHeight);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001616 subtractStableInsets(
Andrii Kuliandaea3572016-04-08 13:20:51 -07001617 mTmpStableBounds, insetBounds != null ? insetBounds : bounds,
1618 overrideWidth, overrideHeight);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001619
Andrii Kulian1779e612016-10-12 21:58:25 -07001620 // For calculating screenWidthDp, screenHeightDp, we use the stable inset screen area,
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001621 // i.e. the screen area without the system bars.
Andrii Kulian1779e612016-10-12 21:58:25 -07001622 // Additionally task dimensions should not be bigger than its parents dimensions.
1623 final Configuration parentConfig = getParent().getConfiguration();
1624 config.unset();
1625 final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001626 config.screenWidthDp =
Andrii Kulian1779e612016-10-12 21:58:25 -07001627 Math.min((int)(mTmpStableBounds.width() / density), parentConfig.screenWidthDp);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001628 config.screenHeightDp =
Andrii Kulian1779e612016-10-12 21:58:25 -07001629 Math.min((int)(mTmpStableBounds.height() / density), parentConfig.screenHeightDp);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001630
1631 // TODO: Orientation?
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001632 config.orientation = (config.screenWidthDp <= config.screenHeightDp)
1633 ? Configuration.ORIENTATION_PORTRAIT
1634 : Configuration.ORIENTATION_LANDSCAPE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001635
Jorim Jaggi85639432016-05-06 17:27:55 -07001636 // For calculating screen layout, we need to use the non-decor inset screen area for the
1637 // calculation for compatibility reasons, i.e. screen area without system bars that could
1638 // never go away in Honeycomb.
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001639 final int compatScreenWidthDp = (int)(mTmpNonDecorBounds.width() / density);
1640 final int compatScreenHeightDp = (int)(mTmpNonDecorBounds.height() / density);
Andrii Kulian1779e612016-10-12 21:58:25 -07001641 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
1642 // calculation with partial default.
1643 final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001644 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
Andrii Kulian1779e612016-10-12 21:58:25 -07001645 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
Jorim Jaggi85639432016-05-06 17:27:55 -07001646 config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
1647
1648 config.smallestScreenWidthDp = mService.mWindowManager.getSmallestWidthForTaskBounds(
1649 insetBounds != null ? insetBounds : bounds);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001650 }
1651
1652 /**
1653 * Using the existing configuration {@param config}, creates a new task override config such
1654 * that all the fields that are usually set in an override config are set to the ones in
1655 * {@param config}.
1656 */
1657 Configuration extractOverrideConfig(Configuration config) {
Andrii Kulian1779e612016-10-12 21:58:25 -07001658 final Configuration extracted = new Configuration();
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001659 extracted.screenWidthDp = config.screenWidthDp;
1660 extracted.screenHeightDp = config.screenHeightDp;
1661 extracted.smallestScreenWidthDp = config.smallestScreenWidthDp;
1662 extracted.orientation = config.orientation;
Andrii Kulian1779e612016-10-12 21:58:25 -07001663 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout.
1664 extracted.screenLayout = config.screenLayout & (Configuration.SCREENLAYOUT_LONG_MASK
1665 | Configuration.SCREENLAYOUT_SIZE_MASK | Configuration.SCREENLAYOUT_COMPAT_NEEDED);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001666 return extracted;
1667 }
1668
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001669 Rect updateOverrideConfigurationFromLaunchBounds() {
1670 final Rect bounds = validateBounds(getLaunchBounds());
1671 updateOverrideConfiguration(bounds);
Andrii Kulian73336d812016-03-24 12:56:08 -07001672 if (bounds != null) {
1673 bounds.set(mBounds);
1674 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001675 return bounds;
1676 }
1677
1678 static Rect validateBounds(Rect bounds) {
1679 if (bounds != null && bounds.isEmpty()) {
1680 Slog.wtf(TAG, "Received strange task bounds: " + bounds, new Throwable());
1681 return null;
1682 }
1683 return bounds;
1684 }
1685
Wale Ogunwale935e5022015-11-10 12:36:10 -08001686 /** Updates the task's bounds and override configuration to match what is expected for the
1687 * input stack. */
1688 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001689 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001690 return;
1691 }
1692
1693 if (inStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001694 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001695 throw new IllegalArgumentException("Can not position non-resizeable task="
1696 + this + " in stack=" + inStack);
1697 }
1698 if (mBounds != null) {
1699 return;
1700 }
1701 if (mLastNonFullscreenBounds != null) {
1702 updateOverrideConfiguration(mLastNonFullscreenBounds);
1703 } else {
1704 inStack.layoutTaskInStack(this, null);
1705 }
1706 } else {
1707 updateOverrideConfiguration(inStack.mBounds);
1708 }
1709 }
1710
Chong Zhang0fa656b2015-08-31 15:17:21 -07001711 /**
1712 * Returns the correct stack to use based on task type and currently set bounds,
1713 * regardless of the focused stack and current stack association of the task.
1714 * The task will be moved (and stack focus changed) later if necessary.
1715 */
1716 int getLaunchStackId() {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001717 if (isRecentsTask()) {
1718 return RECENTS_STACK_ID;
1719 }
1720 if (isHomeTask()) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07001721 return HOME_STACK_ID;
1722 }
Chong Zhang0fa656b2015-08-31 15:17:21 -07001723 if (mBounds != null) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07001724 return FREEFORM_WORKSPACE_STACK_ID;
1725 }
1726 return FULLSCREEN_WORKSPACE_STACK_ID;
1727 }
1728
1729 /** Returns the bounds that should be used to launch this task. */
1730 Rect getLaunchBounds() {
Chong Zhang75b37202015-12-04 14:16:36 -08001731 // If we're over lockscreen, forget about stack bounds and use fullscreen.
Jorim Jaggife762342016-10-13 14:33:27 +02001732 if (mService.mStackSupervisor.mKeyguardController.isKeyguardShowing()) {
Chong Zhang75b37202015-12-04 14:16:36 -08001733 return null;
1734 }
1735
Andrii Kulian02b7a832016-10-06 23:11:56 -07001736 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08001737 return null;
1738 }
1739
Andrii Kulian02b7a832016-10-06 23:11:56 -07001740 final int stackId = mStack.mStackId;
Chong Zhang7d5f5102016-01-13 10:29:24 -08001741 if (stackId == HOME_STACK_ID
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001742 || stackId == RECENTS_STACK_ID
Chong Zhang7d5f5102016-01-13 10:29:24 -08001743 || stackId == FULLSCREEN_WORKSPACE_STACK_ID
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001744 || (stackId == DOCKED_STACK_ID && !isResizeable())) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001745 return isResizeable() ? mStack.mBounds : null;
Wale Ogunwale3797c222015-10-27 14:21:58 -07001746 } else if (!StackId.persistTaskBounds(stackId)) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001747 return mStack.mBounds;
Wale Ogunwale706ed792015-08-02 10:29:44 -07001748 }
1749 return mLastNonFullscreenBounds;
1750 }
1751
Wale Ogunwale39381972015-12-17 17:15:29 -08001752 boolean canMatchRootAffinity() {
1753 // We don't allow root affinity matching on the pinned stack as no other task should
1754 // be launching in it based on affinity.
Andrii Kulian02b7a832016-10-06 23:11:56 -07001755 return rootAffinity != null && getStackId() != PINNED_STACK_ID;
Wale Ogunwale39381972015-12-17 17:15:29 -08001756 }
1757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001759 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001760 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
1761 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08001762 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001763 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07001764 if (affinity != null || rootAffinity != null) {
1765 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
1766 if (affinity == null || !affinity.equals(rootAffinity)) {
1767 pw.print(" root="); pw.println(rootAffinity);
1768 } else {
1769 pw.println();
1770 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001771 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07001772 if (voiceSession != null || voiceInteractor != null) {
1773 pw.print(prefix); pw.print("VOICE: session=0x");
1774 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
1775 pw.print(" interactor=0x");
1776 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
1777 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001778 if (intent != null) {
1779 StringBuilder sb = new StringBuilder(128);
1780 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001781 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001782 sb.append('}');
1783 pw.println(sb.toString());
1784 }
1785 if (affinityIntent != null) {
1786 StringBuilder sb = new StringBuilder(128);
1787 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001788 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001789 sb.append('}');
1790 pw.println(sb.toString());
1791 }
1792 if (origActivity != null) {
1793 pw.print(prefix); pw.print("origActivity=");
1794 pw.println(origActivity.flattenToShortString());
1795 }
1796 if (realActivity != null) {
1797 pw.print(prefix); pw.print("realActivity=");
1798 pw.println(realActivity.flattenToShortString());
1799 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07001800 if (autoRemoveRecents || isPersistable || taskType != 0 || mTaskToReturnTo != 0
1801 || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001802 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001803 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001804 pw.print(" numFullscreen="); pw.print(numFullscreen);
1805 pw.print(" taskType="); pw.print(taskType);
1806 pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo);
1807 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001808 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
1809 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001810 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
1811 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07001812 pw.print(" mReuseTask="); pw.print(mReuseTask);
1813 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001814 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08001815 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
1816 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
1817 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001818 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
1819 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
1820 pw.print(" (");
1821 if (mPrevAffiliate == null) {
1822 pw.print("null");
1823 } else {
1824 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
1825 }
1826 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
1827 pw.print(" (");
1828 if (mNextAffiliate == null) {
1829 pw.print("null");
1830 } else {
1831 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
1832 }
1833 pw.println(")");
1834 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001835 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001836 if (!askedCompatMode || !inRecents || !isAvailable) {
1837 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
1838 pw.print(" inRecents="); pw.print(inRecents);
1839 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001840 }
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001841 pw.print(prefix); pw.print("lastThumbnail="); pw.print(mLastThumbnail);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001842 pw.print(" lastThumbnailFile="); pw.println(mLastThumbnailFile);
1843 if (lastDescription != null) {
1844 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
1845 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001846 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001847 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
1848 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
1849 pw.print(" isResizeable=" + isResizeable());
Winson Chung36f3f032016-09-08 23:29:43 +00001850 pw.print(" firstActiveTime=" + lastActiveTime);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001851 pw.print(" lastActiveTime=" + lastActiveTime);
1852 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 }
1854
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001855 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001857 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07001858 if (stringName != null) {
1859 sb.append(stringName);
1860 sb.append(" U=");
1861 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08001862 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07001863 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07001864 sb.append(" sz=");
1865 sb.append(mActivities.size());
1866 sb.append('}');
1867 return sb.toString();
1868 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001869 sb.append("TaskRecord{");
1870 sb.append(Integer.toHexString(System.identityHashCode(this)));
1871 sb.append(" #");
1872 sb.append(taskId);
1873 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001874 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001875 sb.append(affinity);
1876 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001877 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001878 sb.append(intent.getComponent().flattenToShortString());
1879 } else if (affinityIntent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001880 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001881 sb.append(affinityIntent.getComponent().flattenToShortString());
1882 } else {
1883 sb.append(" ??");
1884 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07001885 stringName = sb.toString();
1886 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 }
1888}