1 /* 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 17 package com.android.server.wm; 18 19 import static android.app.ActivityManager.isStartResultSuccessful; 20 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 21 import static android.app.ActivityTaskManager.INVALID_WINDOWING_MODE; 22 import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED; 23 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION; 24 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; 25 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 26 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 27 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 28 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 29 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 31 import static android.app.WindowConfiguration.activityTypeToString; 32 import static android.app.WindowConfiguration.windowingModeToString; 33 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; 34 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 35 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; 36 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME; 37 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; 38 import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; 39 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; 40 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY; 41 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY; 42 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; 43 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; 44 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; 45 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED; 46 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 47 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 48 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 49 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; 50 import static android.view.Display.DEFAULT_DISPLAY; 51 import static android.view.Display.INVALID_DISPLAY; 52 import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; 53 import static android.view.SurfaceControl.METADATA_TASK_ID; 54 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 55 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; 56 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 57 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 58 import static android.view.WindowManager.TRANSIT_CHANGE; 59 import static android.view.WindowManager.TRANSIT_CLOSE; 60 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED; 61 import static android.view.WindowManager.TRANSIT_NONE; 62 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; 63 import static android.view.WindowManager.TRANSIT_OPEN; 64 import static android.view.WindowManager.TRANSIT_TO_BACK; 65 import static android.view.WindowManager.TRANSIT_TO_FRONT; 66 import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; 67 68 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; 69 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK; 70 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS; 71 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES; 72 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS; 73 import static com.android.server.wm.ActivityRecord.State.PAUSED; 74 import static com.android.server.wm.ActivityRecord.State.PAUSING; 75 import static com.android.server.wm.ActivityRecord.State.RESUMED; 76 import static com.android.server.wm.ActivityRecord.State.STARTED; 77 import static com.android.server.wm.ActivityRecord.TRANSFER_SPLASH_SCREEN_COPYING; 78 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS; 79 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 80 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION; 81 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING; 82 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CLEANUP; 83 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS; 84 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; 85 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; 86 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION; 87 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING; 88 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; 89 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 90 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 91 import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_TASK_MSG; 92 import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME; 93 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP; 94 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; 95 import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS; 96 import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity; 97 import static com.android.server.wm.IdentifierProto.HASH_CODE; 98 import static com.android.server.wm.IdentifierProto.TITLE; 99 import static com.android.server.wm.IdentifierProto.USER_ID; 100 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED; 101 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK; 102 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE; 103 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; 104 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_PINNABLE; 105 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; 106 import static com.android.server.wm.TaskProto.AFFINITY; 107 import static com.android.server.wm.TaskProto.BOUNDS; 108 import static com.android.server.wm.TaskProto.CREATED_BY_ORGANIZER; 109 import static com.android.server.wm.TaskProto.FILLS_PARENT; 110 import static com.android.server.wm.TaskProto.HAS_CHILD_PIP_ACTIVITY; 111 import static com.android.server.wm.TaskProto.LAST_NON_FULLSCREEN_BOUNDS; 112 import static com.android.server.wm.TaskProto.ORIG_ACTIVITY; 113 import static com.android.server.wm.TaskProto.REAL_ACTIVITY; 114 import static com.android.server.wm.TaskProto.RESIZE_MODE; 115 import static com.android.server.wm.TaskProto.RESUMED_ACTIVITY; 116 import static com.android.server.wm.TaskProto.ROOT_TASK_ID; 117 import static com.android.server.wm.TaskProto.SURFACE_HEIGHT; 118 import static com.android.server.wm.TaskProto.SURFACE_WIDTH; 119 import static com.android.server.wm.TaskProto.TASK_FRAGMENT; 120 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; 121 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 122 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 123 import static com.android.server.wm.WindowContainerChildProto.TASK; 124 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK; 125 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; 126 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 127 128 import static java.lang.Integer.MAX_VALUE; 129 130 import android.annotation.IntDef; 131 import android.annotation.NonNull; 132 import android.annotation.Nullable; 133 import android.annotation.UserIdInt; 134 import android.app.Activity; 135 import android.app.ActivityManager; 136 import android.app.ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData; 137 import android.app.ActivityManager.TaskDescription; 138 import android.app.ActivityOptions; 139 import android.app.ActivityTaskManager; 140 import android.app.AppGlobals; 141 import android.app.IActivityController; 142 import android.app.PictureInPictureParams; 143 import android.app.TaskInfo; 144 import android.app.WindowConfiguration; 145 import android.content.ComponentName; 146 import android.content.Intent; 147 import android.content.pm.ActivityInfo; 148 import android.content.pm.ActivityInfo.ScreenOrientation; 149 import android.content.pm.ApplicationInfo; 150 import android.content.pm.IPackageManager; 151 import android.content.pm.PackageManager; 152 import android.content.res.Configuration; 153 import android.graphics.Matrix; 154 import android.graphics.Point; 155 import android.graphics.Rect; 156 import android.os.Binder; 157 import android.os.Debug; 158 import android.os.Handler; 159 import android.os.IBinder; 160 import android.os.Looper; 161 import android.os.Message; 162 import android.os.Process; 163 import android.os.RemoteException; 164 import android.os.SystemClock; 165 import android.os.Trace; 166 import android.os.UserHandle; 167 import android.provider.Settings; 168 import android.service.voice.IVoiceInteractionSession; 169 import android.util.ArraySet; 170 import android.util.DisplayMetrics; 171 import android.util.Slog; 172 import android.util.proto.ProtoOutputStream; 173 import android.view.DisplayInfo; 174 import android.view.InsetsSource; 175 import android.view.InsetsState; 176 import android.view.RemoteAnimationAdapter; 177 import android.view.Surface; 178 import android.view.SurfaceControl; 179 import android.view.TaskTransitionSpec; 180 import android.view.WindowManager; 181 import android.view.WindowManager.TransitionOldType; 182 import android.window.ITaskOrganizer; 183 import android.window.PictureInPictureSurfaceTransaction; 184 import android.window.StartingWindowInfo; 185 import android.window.TaskFragmentParentInfo; 186 import android.window.TaskSnapshot; 187 import android.window.WindowContainerToken; 188 189 import com.android.internal.annotations.GuardedBy; 190 import com.android.internal.annotations.VisibleForTesting; 191 import com.android.internal.app.IVoiceInteractor; 192 import com.android.internal.protolog.common.ProtoLog; 193 import com.android.internal.util.XmlUtils; 194 import com.android.internal.util.function.pooled.PooledLambda; 195 import com.android.internal.util.function.pooled.PooledPredicate; 196 import com.android.modules.utils.TypedXmlPullParser; 197 import com.android.modules.utils.TypedXmlSerializer; 198 import com.android.server.Watchdog; 199 import com.android.server.am.ActivityManagerService; 200 import com.android.server.am.AppTimeTracker; 201 import com.android.server.uri.NeededUriGrants; 202 203 import org.xmlpull.v1.XmlPullParser; 204 import org.xmlpull.v1.XmlPullParserException; 205 206 import java.io.FileDescriptor; 207 import java.io.IOException; 208 import java.io.PrintWriter; 209 import java.lang.annotation.Retention; 210 import java.lang.annotation.RetentionPolicy; 211 import java.util.ArrayList; 212 import java.util.Objects; 213 import java.util.function.Consumer; 214 import java.util.function.Predicate; 215 216 /** 217 * {@link Task} is a TaskFragment that can contain a group of activities to perform a certain job. 218 * Activities of the same task affinities usually group in the same {@link Task}. A {@link Task} 219 * can also be an entity that showing in the Recents Screen for a job that user interacted with. 220 * A {@link Task} can also contain other {@link Task}s. 221 */ 222 class Task extends TaskFragment { 223 private static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_ATM; 224 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; 225 static final String TAG_TASKS = TAG + POSTFIX_TASKS; 226 static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP; 227 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; 228 private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION; 229 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; 230 static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; 231 232 private static final String ATTR_TASKID = "task_id"; 233 private static final String TAG_INTENT = "intent"; 234 private static final String TAG_AFFINITYINTENT = "affinity_intent"; 235 private static final String ATTR_REALACTIVITY = "real_activity"; 236 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended"; 237 private static final String ATTR_ORIGACTIVITY = "orig_activity"; 238 private static final String TAG_ACTIVITY = "activity"; 239 private static final String ATTR_AFFINITY = "affinity"; 240 private static final String ATTR_ROOT_AFFINITY = "root_affinity"; 241 private static final String ATTR_ROOTHASRESET = "root_has_reset"; 242 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents"; 243 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode"; 244 private static final String ATTR_USERID = "user_id"; 245 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete"; 246 private static final String ATTR_EFFECTIVE_UID = "effective_uid"; 247 @Deprecated 248 private static final String ATTR_TASKTYPE = "task_type"; 249 private static final String ATTR_LASTDESCRIPTION = "last_description"; 250 private static final String ATTR_LASTTIMEMOVED = "last_time_moved"; 251 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity"; 252 private static final String ATTR_TASK_AFFILIATION = "task_affiliation"; 253 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation"; 254 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation"; 255 private static final String ATTR_CALLING_UID = "calling_uid"; 256 private static final String ATTR_CALLING_PACKAGE = "calling_package"; 257 private static final String ATTR_CALLING_FEATURE_ID = "calling_feature_id"; 258 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture"; 259 private static final String ATTR_RESIZE_MODE = "resize_mode"; 260 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds"; 261 private static final String ATTR_MIN_WIDTH = "min_width"; 262 private static final String ATTR_MIN_HEIGHT = "min_height"; 263 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version"; 264 private static final String ATTR_WINDOW_LAYOUT_AFFINITY = "window_layout_affinity"; 265 private static final String ATTR_LAST_SNAPSHOT_TASK_SIZE = "last_snapshot_task_size"; 266 private static final String ATTR_LAST_SNAPSHOT_CONTENT_INSETS = "last_snapshot_content_insets"; 267 private static final String ATTR_LAST_SNAPSHOT_BUFFER_SIZE = "last_snapshot_buffer_size"; 268 269 // How long to wait for all background Activities to redraw following a call to 270 // convertToTranslucent(). 271 private static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000; 272 273 // Current version of the task record we persist. Used to check if we need to run any upgrade 274 // code. 275 static final int PERSIST_TASK_VERSION = 1; 276 277 private static final int DEFAULT_MIN_TASK_SIZE_DP = 220; 278 279 /** 280 * The modes to control how root task is moved to the front when calling {@link Task#reparent}. 281 */ 282 @Retention(RetentionPolicy.SOURCE) 283 @IntDef({ 284 REPARENT_MOVE_ROOT_TASK_TO_FRONT, 285 REPARENT_KEEP_ROOT_TASK_AT_FRONT, 286 REPARENT_LEAVE_ROOT_TASK_IN_PLACE 287 }) 288 @interface ReparentMoveRootTaskMode {} 289 // Moves the root task to the front if it was not at the front 290 static final int REPARENT_MOVE_ROOT_TASK_TO_FRONT = 0; 291 // Only moves the root task to the front if it was focused or front most already 292 static final int REPARENT_KEEP_ROOT_TASK_AT_FRONT = 1; 293 // Do not move the root task as a part of reparenting 294 static final int REPARENT_LEAVE_ROOT_TASK_IN_PLACE = 2; 295 296 // The topmost Activity passed to convertToTranslucent(). When non-null it means we are 297 // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they 298 // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the 299 // Activity in mTranslucentActivityWaiting is notified via 300 // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last 301 // background activity being drawn then the same call will be made with a true value. 302 ActivityRecord mTranslucentActivityWaiting = null; 303 ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>(); 304 305 /** 306 * Set when we know we are going to be calling updateConfiguration() 307 * soon, so want to skip intermediate config checks. 308 */ 309 boolean mConfigWillChange; 310 311 /** 312 * Used to keep resumeTopActivityUncheckedLocked() from being entered recursively 313 */ 314 boolean mInResumeTopActivity = false; 315 316 /** 317 * Used to identify if the activity that is installed from device's system image. 318 */ 319 boolean mIsEffectivelySystemApp; 320 321 int mCurrentUser; 322 323 String affinity; // The affinity name for this task, or null; may change identity. 324 String rootAffinity; // Initial base affinity, or null; does not change from initial root. 325 String mWindowLayoutAffinity; // Launch param affinity of this task or null. Used when saving 326 // launch params of this task. 327 IVoiceInteractionSession voiceSession; // Voice interaction session driving task 328 IVoiceInteractor voiceInteractor; // Associated interactor to provide to app 329 Intent intent; // The original intent that started the task. Note that this value can 330 // be null. 331 Intent affinityIntent; // Intent of affinity-moved activity that started this task. 332 int effectiveUid; // The current effective uid of the identity of this task. 333 ComponentName origActivity; // The non-alias activity component of the intent. 334 ComponentName realActivity; // The actual activity component that started the task. 335 boolean realActivitySuspended; // True if the actual activity component that started the 336 // task is suspended. 337 boolean inRecents; // Actually in the recents list? 338 long lastActiveTime; // Last time this task was active in the current device session, 339 // including sleep. This time is initialized to the elapsed time when 340 // restored from disk. 341 boolean isAvailable; // Is the activity available to be launched? 342 boolean rootWasReset; // True if the intent at the root of the task had 343 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag. 344 boolean autoRemoveRecents; // If true, we should automatically remove the task from 345 // recents when activity finishes 346 boolean askedCompatMode;// Have asked the user about compat mode for this task. 347 private boolean mHasBeenVisible; // Set if any activities in the task have been visible 348 349 String stringName; // caching of toString() result. 350 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity 351 // was changed. 352 353 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE; 354 355 int mLockTaskUid = -1; // The uid of the application that called startLockTask(). 356 357 /** 358 * If non-null, the starting window should cover the associated task. It is assigned when the 359 * parent activity of starting window is put in a partial area of the task. This field will be 360 * cleared when all visible activities in this task are drawn. 361 */ 362 StartingData mSharedStartingData; 363 364 /** The process that had previously hosted the root activity of this task. 365 * Used to know that we should try harder to keep this process around, in case the 366 * user wants to return to it. */ 367 private WindowProcessController mRootProcess; 368 369 /** Takes on same value as first root activity */ 370 boolean isPersistable = false; 371 int maxRecents; 372 373 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for 374 * determining the order when restoring. */ 375 long mLastTimeMoved; 376 377 /** 378 * If it is set, the processes belong to the task will be killed when one of its activity 379 * reports that Activity#onDestroy is done and the task no longer contains perceptible 380 * components. This should only be set on a leaf task. 381 */ 382 boolean mKillProcessesOnDestroyed; 383 384 /** If original intent did not allow relinquishing task identity, save that information */ 385 private boolean mNeverRelinquishIdentity = true; 386 387 /** Avoid reentrant of {@link #removeImmediately(String)}. */ 388 private boolean mRemoving; 389 390 // Used in the unique case where we are clearing the task in order to reuse it. In that case we 391 // do not want to delete the root task when the task goes empty. 392 private boolean mReuseTask = false; 393 394 CharSequence lastDescription; // Last description captured for this item. 395 396 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent. 397 Task mPrevAffiliate; // previous task in affiliated chain. 398 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence. 399 Task mNextAffiliate; // next task in affiliated chain. 400 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence. 401 402 // For relaunching the task from recents as though it was launched by the original launcher. 403 int mCallingUid; 404 String mCallingPackage; 405 String mCallingFeatureId; 406 407 private static final Rect sTmpBounds = new Rect(); 408 409 // Last non-fullscreen bounds the task was launched in or resized to. 410 // The information is persisted and used to determine the appropriate root task to launch the 411 // task into on restore. 412 Rect mLastNonFullscreenBounds = null; 413 414 // The surface transition of the target when recents animation is finished. 415 // This is originally introduced to carry out the current surface control position and window 416 // crop when a multi-activity task enters pip with autoEnterPip enabled. In such case, 417 // the surface control of the task will be animated in Launcher and then the top activity is 418 // reparented to pinned root task. 419 // Do not forget to reset this after reparenting. 420 // TODO: remove this once the recents animation is moved to the Shell 421 PictureInPictureSurfaceTransaction mLastRecentsAnimationTransaction; 422 // The content overlay to be applied with mLastRecentsAnimationTransaction 423 // TODO: remove this once the recents animation is moved to the Shell 424 SurfaceControl mLastRecentsAnimationOverlay; 425 426 static final int LAYER_RANK_INVISIBLE = -1; 427 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible) 428 // This number will be assigned when we evaluate OOM scores for all visible tasks. 429 int mLayerRank = LAYER_RANK_INVISIBLE; 430 431 /* Unique identifier for this task. */ 432 final int mTaskId; 433 /* User for which this task was created. */ 434 // TODO: Make final 435 int mUserId; 436 437 // Id of the previous display the root task was on. 438 int mPrevDisplayId = INVALID_DISPLAY; 439 440 /** ID of the display which rotation {@link #mRotation} has. */ 441 private int mLastRotationDisplayId = INVALID_DISPLAY; 442 443 /** 444 * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was 445 * moved to a new display. 446 */ 447 @Surface.Rotation 448 private int mRotation; 449 450 int mMultiWindowRestoreWindowingMode = INVALID_WINDOWING_MODE; 451 452 /** 453 * Last requested orientation reported to DisplayContent. This is different from {@link 454 * #mOrientation} in the sense that this takes activities' requested orientation into 455 * account. Start with {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} so that we don't need 456 * to notify for activities that don't specify any orientation. 457 */ 458 int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 459 460 // For comparison with DisplayContent bounds. 461 private Rect mTmpRect = new Rect(); 462 // For handling display rotations. 463 private Rect mTmpRect2 = new Rect(); 464 465 // Resize mode of the task. See {@link ActivityInfo#resizeMode} 466 // Based on the {@link ActivityInfo#resizeMode} of the root activity. 467 int mResizeMode; 468 469 // Whether or not this task and its activities support PiP. Based on the 470 // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity. 471 boolean mSupportsPictureInPicture; 472 473 // Whether the task is currently being drag-resized 474 private boolean mDragResizing; 475 476 // This represents the last resolved activity values for this task 477 // NOTE: This value needs to be persisted with each task 478 private TaskDescription mTaskDescription; 479 480 // Information about the last snapshot that should be persisted with the task to allow SystemUI 481 // to layout without loading all the task snapshots 482 final PersistedTaskSnapshotData mLastTaskSnapshotData; 483 484 /** @see #setCanAffectSystemUiFlags */ 485 private boolean mCanAffectSystemUiFlags = true; 486 487 private static Exception sTmpException; 488 489 private boolean mForceShowForAllUsers; 490 491 /** When set, will force the task to report as invisible. */ 492 static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1; 493 static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; 494 private int mForceHiddenFlags = 0; 495 private boolean mForceTranslucent = false; 496 497 // The display category name for this task. 498 String mRequiredDisplayCategory; 499 500 // TODO(b/160201781): Revisit double invocation issue in Task#removeChild. 501 /** 502 * Skip {@link ActivityTaskSupervisor#removeTask(Task, boolean, boolean, String)} execution if 503 * {@code true} to prevent double traversal of {@link #mChildren} in a loop. 504 */ 505 boolean mInRemoveTask; 506 507 /** 508 * When set, disassociate the leaf task if relaunched and reparented it to TDA as root task if 509 * possible. 510 */ 511 boolean mReparentLeafTaskIfRelaunch; 512 513 private final AnimatingActivityRegistry mAnimatingActivityRegistry = 514 new AnimatingActivityRegistry(); 515 516 private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_TASK_MSG + 1; 517 518 private final Handler mHandler; 519 520 private class ActivityTaskHandler extends Handler { 521 ActivityTaskHandler(Looper looper)522 ActivityTaskHandler(Looper looper) { 523 super(looper); 524 } 525 526 @Override handleMessage(Message msg)527 public void handleMessage(Message msg) { 528 switch (msg.what) { 529 case TRANSLUCENT_TIMEOUT_MSG: { 530 synchronized (mAtmService.mGlobalLock) { 531 notifyActivityDrawnLocked(null); 532 } 533 } break; 534 } 535 } 536 } 537 538 private static final ResetTargetTaskHelper sResetTargetTaskHelper = new ResetTargetTaskHelper(); 539 540 private final FindRootHelper mFindRootHelper = new FindRootHelper(); 541 private class FindRootHelper implements Predicate<ActivityRecord> { 542 private ActivityRecord mRoot; 543 private boolean mIgnoreRelinquishIdentity; 544 private boolean mSetToBottomIfNone; 545 findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone)546 ActivityRecord findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) { 547 mIgnoreRelinquishIdentity = ignoreRelinquishIdentity; 548 mSetToBottomIfNone = setToBottomIfNone; 549 forAllActivities(this, false /* traverseTopToBottom */); 550 final ActivityRecord root = mRoot; 551 mRoot = null; 552 return root; 553 } 554 555 @Override test(ActivityRecord r)556 public boolean test(ActivityRecord r) { 557 if (mRoot == null && mSetToBottomIfNone) { 558 // This is the first activity we are process. Set it as the candidate root in case 559 // we don't find a better one. 560 mRoot = r; 561 } 562 563 if (r.finishing) return false; 564 565 if (mRoot == null || mRoot.finishing) { 566 // Set this as the candidate root since it isn't finishing. 567 mRoot = r; 568 } 569 570 final int uid = mRoot == r ? effectiveUid : r.info.applicationInfo.uid; 571 if (mIgnoreRelinquishIdentity 572 || (mRoot.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0 573 || (mRoot.info.applicationInfo.uid != Process.SYSTEM_UID 574 && !mRoot.info.applicationInfo.isSystemApp() 575 && mRoot.info.applicationInfo.uid != uid)) { 576 // No need to relinquish identity, end search. 577 return true; 578 } 579 580 // Relinquish to next activity 581 mRoot = r; 582 return false; 583 } 584 } 585 586 /** 587 * The TaskOrganizer which is delegated presentation of this task. If set the Task will 588 * emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers 589 * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished. 590 */ 591 ITaskOrganizer mTaskOrganizer; 592 593 /** 594 * Prevent duplicate calls to onTaskAppeared. 595 */ 596 boolean mTaskAppearedSent; 597 598 // If the sending of the task appear signal should be deferred until this flag is set back to 599 // false. 600 private boolean mDeferTaskAppear; 601 602 // Tracking cookie for the creation of this task. 603 IBinder mLaunchCookie; 604 605 // The task will be removed when TaskOrganizer, which is managing the task, is destroyed. 606 boolean mRemoveWithTaskOrganizer; 607 608 /** 609 * Reference to the pinned activity that is logically parented to this task, ie. 610 * the previous top activity within this task is put into pinned mode. 611 * This always gets cleared in pair with the ActivityRecord-to-Task link as seen in 612 * {@link ActivityRecord#clearLastParentBeforePip()}. 613 */ 614 ActivityRecord mChildPipActivity; 615 616 boolean mLastSurfaceShowing; 617 618 boolean mAlignActivityLocaleWithTask = false; 619 Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, String _rootAffinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid, String _lastDescription, long lastTimeMoved, boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription, PersistedTaskSnapshotData _lastSnapshotData, int taskAffiliation, int prevTaskId, int nextTaskId, int callingUid, String callingPackage, @Nullable String callingFeatureId, int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info, IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear, boolean _removeWithTaskOrganizer)620 private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, 621 Intent _affinityIntent, String _affinity, String _rootAffinity, 622 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, 623 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid, 624 String _lastDescription, long lastTimeMoved, boolean neverRelinquishIdentity, 625 TaskDescription _lastTaskDescription, PersistedTaskSnapshotData _lastSnapshotData, 626 int taskAffiliation, int prevTaskId, int nextTaskId, int callingUid, 627 String callingPackage, @Nullable String callingFeatureId, int resizeMode, 628 boolean supportsPictureInPicture, boolean _realActivitySuspended, 629 boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info, 630 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, 631 boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear, 632 boolean _removeWithTaskOrganizer) { 633 super(atmService, null /* fragmentToken */, _createdByOrganizer, false /* isEmbedded */); 634 635 mTaskId = _taskId; 636 mUserId = _userId; 637 mResizeMode = resizeMode; 638 mSupportsPictureInPicture = supportsPictureInPicture; 639 mTaskDescription = _lastTaskDescription != null 640 ? _lastTaskDescription 641 : new TaskDescription(); 642 mLastTaskSnapshotData = _lastSnapshotData != null 643 ? _lastSnapshotData 644 : new PersistedTaskSnapshotData(); 645 // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED). 646 setOrientation(SCREEN_ORIENTATION_UNSET); 647 affinityIntent = _affinityIntent; 648 affinity = _affinity; 649 rootAffinity = _rootAffinity; 650 voiceSession = _voiceSession; 651 voiceInteractor = _voiceInteractor; 652 realActivity = _realActivity; 653 realActivitySuspended = _realActivitySuspended; 654 origActivity = _origActivity; 655 rootWasReset = _rootWasReset; 656 isAvailable = true; 657 autoRemoveRecents = _autoRemoveRecents; 658 askedCompatMode = _askedCompatMode; 659 mUserSetupComplete = userSetupComplete; 660 effectiveUid = _effectiveUid; 661 touchActiveTime(); 662 lastDescription = _lastDescription; 663 mLastTimeMoved = lastTimeMoved; 664 mNeverRelinquishIdentity = neverRelinquishIdentity; 665 mAffiliatedTaskId = taskAffiliation; 666 mPrevAffiliateTaskId = prevTaskId; 667 mNextAffiliateTaskId = nextTaskId; 668 mCallingUid = callingUid; 669 mCallingPackage = callingPackage; 670 mCallingFeatureId = callingFeatureId; 671 mResizeMode = resizeMode; 672 if (info != null) { 673 setIntent(_intent, info); 674 setMinDimensions(info); 675 } else { 676 intent = _intent; 677 mMinWidth = minWidth; 678 mMinHeight = minHeight; 679 } 680 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity); 681 mHandler = new ActivityTaskHandler(mTaskSupervisor.mLooper); 682 mCurrentUser = mAtmService.mAmInternal.getCurrentUserId(); 683 684 mLaunchCookie = _launchCookie; 685 mDeferTaskAppear = _deferTaskAppear; 686 mRemoveWithTaskOrganizer = _removeWithTaskOrganizer; 687 EventLogTags.writeWmTaskCreated(mTaskId); 688 } 689 fromWindowContainerToken(WindowContainerToken token)690 static Task fromWindowContainerToken(WindowContainerToken token) { 691 if (token == null) return null; 692 return fromBinder(token.asBinder()).asTask(); 693 } 694 reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, Intent intent, ActivityInfo info, ActivityRecord activity)695 Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, 696 Intent intent, ActivityInfo info, ActivityRecord activity) { 697 voiceSession = _voiceSession; 698 voiceInteractor = _voiceInteractor; 699 setIntent(activity, intent, info); 700 setMinDimensions(info); 701 // Before we began to reuse a root task as the leaf task, we used to 702 // create a leaf task in this case. Therefore now we won't send out the task created 703 // notification when we decide to reuse it here, so we send out the notification below. 704 // The reason why the created notification sent out when root task is created doesn't work 705 // is that realActivity isn't set until setIntent() method above is called for the first 706 // time. Eventually this notification will be removed when we can populate those information 707 // when root task is created. 708 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(mTaskId, realActivity); 709 return this; 710 } 711 cleanUpResourcesForDestroy(WindowContainer<?> oldParent)712 private void cleanUpResourcesForDestroy(WindowContainer<?> oldParent) { 713 if (hasChild()) { 714 return; 715 } 716 717 // This task is going away, so save the last state if necessary. 718 saveLaunchingStateIfNeeded(oldParent.getDisplayContent()); 719 720 // TODO: VI what about activity? 721 final boolean isVoiceSession = voiceSession != null; 722 if (isVoiceSession) { 723 try { 724 voiceSession.taskFinished(intent, mTaskId); 725 } catch (RemoteException e) { 726 } 727 } 728 if (autoRemoveFromRecents(oldParent.asTaskFragment()) || isVoiceSession) { 729 // Task creator asked to remove this when done, or this task was a voice 730 // interaction, so it should not remain on the recent tasks list. 731 mTaskSupervisor.mRecentTasks.remove(this); 732 } 733 734 removeIfPossible("cleanUpResourcesForDestroy"); 735 } 736 737 @VisibleForTesting 738 @Override removeIfPossible()739 void removeIfPossible() { 740 removeIfPossible("removeTaskIfPossible"); 741 } 742 removeIfPossible(String reason)743 void removeIfPossible(String reason) { 744 mAtmService.getLockTaskController().clearLockedTask(this); 745 if (shouldDeferRemoval()) { 746 if (DEBUG_ROOT_TASK) Slog.i(TAG, 747 "removeTask:" + reason + " deferring removing taskId=" + mTaskId); 748 return; 749 } 750 final boolean isLeafTask = isLeafTask(); 751 removeImmediately(reason); 752 if (isLeafTask) { 753 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId); 754 755 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 756 if (taskDisplayArea != null) { 757 taskDisplayArea.onLeafTaskRemoved(mTaskId); 758 } 759 } 760 } 761 setResizeMode(int resizeMode)762 void setResizeMode(int resizeMode) { 763 if (mResizeMode == resizeMode) { 764 return; 765 } 766 mResizeMode = resizeMode; 767 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 768 mRootWindowContainer.resumeFocusedTasksTopActivities(); 769 updateTaskDescription(); 770 } 771 resize(Rect bounds, int resizeMode, boolean preserveWindow)772 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow) { 773 mAtmService.deferWindowLayout(); 774 775 try { 776 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0; 777 778 if (getParent() == null) { 779 // Task doesn't exist in window manager yet (e.g. was restored from recents). 780 // All we can do for now is update the bounds so it can be used when the task is 781 // added to window manager. 782 setBounds(bounds); 783 if (!inFreeformWindowingMode()) { 784 // re-restore the task so it can have the proper root task association. 785 mTaskSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP); 786 } 787 return true; 788 } 789 790 if (!canResizeToBounds(bounds)) { 791 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this 792 + " to bounds=" + bounds + " resizeMode=" + mResizeMode); 793 } 794 795 // Do not move the task to another root task here. 796 // This method assumes that the task is already placed in the right root task. 797 // we do not mess with that decision and we only do the resize! 798 799 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId); 800 801 // This variable holds information whether the configuration didn't change in a 802 // significant way and the activity was kept the way it was. If it's false, it means 803 // the activity had to be relaunched due to configuration change. 804 boolean kept = true; 805 if (setBounds(bounds, forced) != BOUNDS_CHANGE_NONE) { 806 final ActivityRecord r = topRunningActivityLocked(); 807 if (r != null) { 808 kept = r.ensureActivityConfiguration(0 /* globalChanges */, 809 preserveWindow); 810 // Preserve other windows for resizing because if resizing happens when there 811 // is a dialog activity in the front, the activity that still shows some 812 // content to the user will become black and cause flickers. Note in most cases 813 // this won't cause tons of irrelevant windows being preserved because only 814 // activities in this task may experience a bounds change. Configs for other 815 // activities stay the same. 816 mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow); 817 if (!kept) { 818 mRootWindowContainer.resumeFocusedTasksTopActivities(); 819 } 820 } 821 } 822 saveLaunchingStateIfNeeded(); 823 824 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 825 return kept; 826 } finally { 827 mAtmService.continueWindowLayout(); 828 } 829 } 830 831 /** Convenience method to reparent a task to the top or bottom position of the root task. */ reparent(Task preferredRootTask, boolean toTop, @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume, String reason)832 boolean reparent(Task preferredRootTask, boolean toTop, 833 @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume, 834 String reason) { 835 return reparent(preferredRootTask, toTop ? MAX_VALUE : 0, moveRootTaskMode, animate, 836 deferResume, true /* schedulePictureInPictureModeChange */, reason); 837 } 838 839 /** 840 * Reparents the task into a preferred root task, creating it if necessary. 841 * 842 * @param preferredRootTask the target root task to move this task 843 * @param position the position to place this task in the new root task 844 * @param animate whether or not we should wait for the new window created as a part of the 845 * reparenting to be drawn and animated in 846 * @param moveRootTaskMode whether or not to move the root task to the front always, only if 847 * it was previously focused & in front, or never 848 * @param deferResume whether or not to update the visibility of other tasks and root tasks 849 * that may have changed as a result of this reparenting 850 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode 851 * change. Callers may set this to false if they are explicitly scheduling PiP mode 852 * changes themselves, like during the PiP animation 853 * @param reason the caller of this reparenting 854 * @return whether the task was reparented 855 */ 856 // TODO: Inspect all call sites and change to just changing windowing mode of the root task vs. 857 // re-parenting the task. Can only be done when we are no longer using static root task Ids. reparent(Task preferredRootTask, int position, @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange, String reason)858 boolean reparent(Task preferredRootTask, int position, 859 @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume, 860 boolean schedulePictureInPictureModeChange, String reason) { 861 final ActivityTaskSupervisor supervisor = mTaskSupervisor; 862 final RootWindowContainer root = mRootWindowContainer; 863 final WindowManagerService windowManager = mAtmService.mWindowManager; 864 final Task sourceRootTask = getRootTask(); 865 final Task toRootTask = supervisor.getReparentTargetRootTask(this, preferredRootTask, 866 position == MAX_VALUE); 867 if (toRootTask == sourceRootTask) { 868 return false; 869 } 870 if (!canBeLaunchedOnDisplay(toRootTask.getDisplayId())) { 871 return false; 872 } 873 874 final ActivityRecord topActivity = getTopNonFinishingActivity(); 875 876 mAtmService.deferWindowLayout(); 877 boolean kept = true; 878 try { 879 final ActivityRecord r = topRunningActivityLocked(); 880 final boolean wasFocused = r != null && root.isTopDisplayFocusedRootTask(sourceRootTask) 881 && (topRunningActivityLocked() == r); 882 883 // In some cases the focused root task isn't the front root task. E.g. root pinned task. 884 // Whenever we are moving the top activity from the front root task we want to make 885 // sure to move the root task to the front. 886 final boolean wasFront = r != null && sourceRootTask.isTopRootTaskInDisplayArea() 887 && (sourceRootTask.topRunningActivity() == r); 888 889 final boolean moveRootTaskToFront = moveRootTaskMode == REPARENT_MOVE_ROOT_TASK_TO_FRONT 890 || (moveRootTaskMode == REPARENT_KEEP_ROOT_TASK_AT_FRONT 891 && (wasFocused || wasFront)); 892 893 reparent(toRootTask, position, moveRootTaskToFront, reason); 894 895 if (schedulePictureInPictureModeChange) { 896 // Notify of picture-in-picture mode changes 897 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceRootTask); 898 } 899 900 // If the task had focus before (or we're requested to move focus), move focus to the 901 // new root task by moving the root task to the front. 902 if (r != null && moveRootTaskToFront) { 903 // Move the root task in which we are placing the activity to the front. 904 toRootTask.moveToFront(reason); 905 906 // If the original state is resumed, there is no state change to update focused app. 907 // So here makes sure the activity focus is set if it is the top. 908 if (r.isState(RESUMED) && r == mRootWindowContainer.getTopResumedActivity()) { 909 mAtmService.setLastResumedActivityUncheckLocked(r, reason); 910 } 911 } 912 if (!animate) { 913 mTaskSupervisor.mNoAnimActivities.add(topActivity); 914 } 915 } finally { 916 mAtmService.continueWindowLayout(); 917 } 918 919 if (!deferResume) { 920 // The task might have already been running and its visibility needs to be synchronized 921 // with the visibility of the root task / windows. 922 root.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); 923 root.resumeFocusedTasksTopActivities(); 924 } 925 926 // TODO: Handle incorrect request to move before the actual move, not after. 927 supervisor.handleNonResizableTaskIfNeeded(this, preferredRootTask.getWindowingMode(), 928 mRootWindowContainer.getDefaultTaskDisplayArea(), toRootTask); 929 930 return (preferredRootTask == toRootTask); 931 } 932 touchActiveTime()933 void touchActiveTime() { 934 lastActiveTime = SystemClock.elapsedRealtime(); 935 } 936 getInactiveDuration()937 long getInactiveDuration() { 938 return SystemClock.elapsedRealtime() - lastActiveTime; 939 } 940 941 /** @see #setIntent(ActivityRecord, Intent, ActivityInfo) */ setIntent(ActivityRecord r)942 void setIntent(ActivityRecord r) { 943 setIntent(r, null /* intent */, null /* info */); 944 } 945 946 /** 947 * Sets the original intent, and the calling uid and package. 948 * 949 * @param r The activity that started the task 950 * @param intent The task info which could be different from {@code r.intent} if set. 951 * @param info The activity info which could be different from {@code r.info} if set. 952 */ setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info)953 void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) { 954 boolean updateIdentity = false; 955 if (this.intent == null) { 956 updateIdentity = true; 957 } else if (!mNeverRelinquishIdentity) { 958 final ActivityInfo activityInfo = info != null ? info : r.info; 959 updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp 960 || effectiveUid == activityInfo.applicationInfo.uid); 961 } 962 if (updateIdentity) { 963 mCallingUid = r.launchedFromUid; 964 mCallingPackage = r.launchedFromPackage; 965 mCallingFeatureId = r.launchedFromFeatureId; 966 setIntent(intent != null ? intent : r.intent, info != null ? info : r.info); 967 } 968 setLockTaskAuth(r); 969 } 970 971 /** Sets the original intent, _without_ updating the calling uid or package. */ setIntent(Intent _intent, ActivityInfo info)972 private void setIntent(Intent _intent, ActivityInfo info) { 973 if (!isLeafTask()) return; 974 975 mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0; 976 affinity = info.taskAffinity; 977 if (intent == null) { 978 // If this task already has an intent associated with it, don't set the root 979 // affinity -- we don't want it changing after initially set, but the initially 980 // set value may be null. 981 rootAffinity = affinity; 982 mRequiredDisplayCategory = info.requiredDisplayCategory; 983 } 984 effectiveUid = info.applicationInfo.uid; 985 mIsEffectivelySystemApp = info.applicationInfo.isSystemApp(); 986 stringName = null; 987 988 if (info.targetActivity == null) { 989 if (_intent != null) { 990 // If this Intent has a selector, we want to clear it for the 991 // recent task since it is not relevant if the user later wants 992 // to re-launch the app. 993 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) { 994 _intent = new Intent(_intent); 995 _intent.setSelector(null); 996 _intent.setSourceBounds(null); 997 } 998 } 999 ProtoLog.v(WM_DEBUG_TASKS, "Setting Intent of %s to %s", this, _intent); 1000 intent = _intent; 1001 realActivity = _intent != null ? _intent.getComponent() : null; 1002 origActivity = null; 1003 } else { 1004 ComponentName targetComponent = new ComponentName( 1005 info.packageName, info.targetActivity); 1006 if (_intent != null) { 1007 Intent targetIntent = new Intent(_intent); 1008 targetIntent.setSelector(null); 1009 targetIntent.setSourceBounds(null); 1010 ProtoLog.v(WM_DEBUG_TASKS, "Setting Intent of %s to target %s", this, targetIntent); 1011 intent = targetIntent; 1012 realActivity = targetComponent; 1013 origActivity = _intent.getComponent(); 1014 } else { 1015 intent = null; 1016 realActivity = targetComponent; 1017 origActivity = new ComponentName(info.packageName, info.name); 1018 } 1019 } 1020 mWindowLayoutAffinity = 1021 info.windowLayout == null ? null : info.windowLayout.windowLayoutAffinity; 1022 1023 final int intentFlags = intent == null ? 0 : intent.getFlags(); 1024 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 1025 // Once we are set to an Intent with this flag, we count this 1026 // task as having a true root activity. 1027 rootWasReset = true; 1028 } 1029 mUserId = UserHandle.getUserId(info.applicationInfo.uid); 1030 mUserSetupComplete = Settings.Secure.getIntForUser( 1031 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0; 1032 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) { 1033 // If the activity itself has requested auto-remove, then just always do it. 1034 autoRemoveRecents = true; 1035 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS)) 1036 == FLAG_ACTIVITY_NEW_DOCUMENT) { 1037 // If the caller has not asked for the document to be retained, then we may 1038 // want to turn on auto-remove, depending on whether the target has set its 1039 // own document launch mode. 1040 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) { 1041 autoRemoveRecents = false; 1042 } else { 1043 autoRemoveRecents = true; 1044 } 1045 } else { 1046 autoRemoveRecents = false; 1047 } 1048 if (mResizeMode != info.resizeMode) { 1049 mResizeMode = info.resizeMode; 1050 updateTaskDescription(); 1051 } 1052 mSupportsPictureInPicture = info.supportsPictureInPicture(); 1053 1054 // Re-adding the task to Recents once updated 1055 if (inRecents) { 1056 mTaskSupervisor.mRecentTasks.remove(this); 1057 mTaskSupervisor.mRecentTasks.add(this); 1058 } 1059 } 1060 1061 /** Sets the original minimal width and height. */ setMinDimensions(ActivityInfo info)1062 void setMinDimensions(ActivityInfo info) { 1063 if (info != null && info.windowLayout != null) { 1064 mMinWidth = info.windowLayout.minWidth; 1065 mMinHeight = info.windowLayout.minHeight; 1066 } else { 1067 mMinWidth = INVALID_MIN_SIZE; 1068 mMinHeight = INVALID_MIN_SIZE; 1069 } 1070 } 1071 1072 /** 1073 * Return true if the input activity has the same intent filter as the intent this task 1074 * record is based on (normally the root activity intent). 1075 */ isSameIntentFilter(ActivityRecord r)1076 boolean isSameIntentFilter(ActivityRecord r) { 1077 final Intent intent = new Intent(r.intent); 1078 // Make sure the component are the same if the input activity has the same real activity 1079 // as the one in the task because either one of them could be the alias activity. 1080 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) { 1081 intent.setComponent(this.intent.getComponent()); 1082 // Make sure the package name the same to prevent one of the intent is set while the 1083 // other one is not. 1084 intent.setPackage(this.intent.getPackage()); 1085 } 1086 return intent.filterEquals(this.intent); 1087 } 1088 returnsToHomeRootTask()1089 boolean returnsToHomeRootTask() { 1090 if (inMultiWindowMode() || !hasChild()) return false; 1091 if (intent != null) { 1092 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME; 1093 if ((intent.getFlags() & returnHomeFlags) != returnHomeFlags) { 1094 return false; 1095 } 1096 final Task task = getDisplayArea() != null ? getDisplayArea().getRootHomeTask() : null; 1097 return !(task != null 1098 && mAtmService.getLockTaskController().isLockTaskModeViolation(task)); 1099 } 1100 final Task bottomTask = getBottomMostTask(); 1101 return bottomTask != this && bottomTask.returnsToHomeRootTask(); 1102 } 1103 setPrevAffiliate(Task prevAffiliate)1104 void setPrevAffiliate(Task prevAffiliate) { 1105 mPrevAffiliate = prevAffiliate; 1106 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId; 1107 } 1108 setNextAffiliate(Task nextAffiliate)1109 void setNextAffiliate(Task nextAffiliate) { 1110 mNextAffiliate = nextAffiliate; 1111 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId; 1112 } 1113 1114 @Override onParentChanged(ConfigurationContainer rawNewParent, ConfigurationContainer rawOldParent)1115 void onParentChanged(ConfigurationContainer rawNewParent, ConfigurationContainer rawOldParent) { 1116 final WindowContainer<?> newParent = (WindowContainer<?>) rawNewParent; 1117 final WindowContainer<?> oldParent = (WindowContainer<?>) rawOldParent; 1118 final DisplayContent display = newParent != null ? newParent.getDisplayContent() : null; 1119 final DisplayContent oldDisplay = oldParent != null ? oldParent.getDisplayContent() : null; 1120 1121 mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY; 1122 1123 if (oldParent != null && newParent == null) { 1124 cleanUpResourcesForDestroy(oldParent); 1125 } 1126 1127 if (display != null) { 1128 // TODO(b/168037178): Chat with the erosky@ of this code to see if this really makes 1129 // sense here... 1130 // Rotations are relative to the display. This means if there are 2 displays rotated 1131 // differently (eg. 2 monitors with one landscape and one portrait), moving a root task 1132 // from one to the other could look like a rotation change. To prevent this 1133 // apparent rotation change (and corresponding bounds rotation), pretend like our 1134 // current rotation is already the same as the new display. 1135 // Note, if Task or related logic ever gets nested, this logic will need 1136 // to move to onConfigurationChanged. 1137 getConfiguration().windowConfiguration.setRotation( 1138 display.getWindowConfiguration().getRotation()); 1139 } 1140 1141 super.onParentChanged(newParent, oldParent); 1142 1143 // Call this again after super onParentChanged in-case the surface wasn't created yet 1144 // (happens when the task is first inserted into the hierarchy). It's a no-op if it 1145 // already ran fully within super.onParentChanged 1146 updateTaskOrganizerState(); 1147 1148 // TODO(b/168037178): The check for null display content and setting it to null doesn't 1149 // really make sense here... 1150 1151 // TODO(b/168037178): This is mostly taking care of the case where the stask is removing 1152 // from the display, so we should probably consolidate it there instead. 1153 1154 if (getParent() == null && mDisplayContent != null) { 1155 mDisplayContent = null; 1156 mWmService.mWindowPlacerLocked.requestTraversal(); 1157 } 1158 1159 if (oldParent != null) { 1160 final Task oldParentTask = oldParent.asTask(); 1161 if (oldParentTask != null) { 1162 forAllActivities(oldParentTask::cleanUpActivityReferences); 1163 } 1164 1165 if (oldParent.inPinnedWindowingMode() 1166 && (newParent == null || !newParent.inPinnedWindowingMode())) { 1167 // Notify if a task from the root pinned task is being removed 1168 // (or moved depending on the mode). 1169 mRootWindowContainer.notifyActivityPipModeChanged(this, null); 1170 } 1171 } 1172 1173 if (newParent != null) { 1174 // Surface of Task that will not be organized should be shown by default. 1175 // See Task#showSurfaceOnCreation 1176 if (!mCreatedByOrganizer && !canBeOrganized()) { 1177 getSyncTransaction().show(mSurfaceControl); 1178 } 1179 1180 // TODO: Ensure that this is actually necessary here 1181 // Notify the voice session if required 1182 if (voiceSession != null) { 1183 try { 1184 voiceSession.taskStarted(intent, mTaskId); 1185 } catch (RemoteException e) { 1186 } 1187 } 1188 } 1189 1190 // First time we are adding the task to the system. 1191 if (oldParent == null && newParent != null) { 1192 1193 // TODO: Super random place to be doing this, but aligns with what used to be done 1194 // before we unified Task level. Look into if this can be done in a better place. 1195 updateOverrideConfigurationFromLaunchBounds(); 1196 } 1197 1198 // Update task bounds if needed. 1199 adjustBoundsForDisplayChangeIfNeeded(getDisplayContent()); 1200 1201 mRootWindowContainer.updateUIDsPresentOnDisplay(); 1202 1203 // Ensure all animations are finished at same time in split-screen mode. 1204 forAllActivities(ActivityRecord::updateAnimatingActivityRegistry); 1205 } 1206 1207 @Override 1208 @Nullable getTopResumedActivity()1209 ActivityRecord getTopResumedActivity() { 1210 if (!isLeafTask()) { 1211 for (int i = mChildren.size() - 1; i >= 0; --i) { 1212 ActivityRecord resumedActivity = mChildren.get(i).asTask().getTopResumedActivity(); 1213 if (resumedActivity != null) { 1214 return resumedActivity; 1215 } 1216 } 1217 } 1218 1219 final ActivityRecord taskResumedActivity = getResumedActivity(); 1220 ActivityRecord topResumedActivity = null; 1221 for (int i = mChildren.size() - 1; i >= 0; --i) { 1222 final WindowContainer child = mChildren.get(i); 1223 if (child.asTaskFragment() != null) { 1224 topResumedActivity = child.asTaskFragment().getTopResumedActivity(); 1225 } else if (taskResumedActivity != null 1226 && child.asActivityRecord() == taskResumedActivity) { 1227 topResumedActivity = taskResumedActivity; 1228 } 1229 if (topResumedActivity != null) { 1230 return topResumedActivity; 1231 } 1232 } 1233 return null; 1234 } 1235 1236 @Override 1237 @Nullable getTopPausingActivity()1238 ActivityRecord getTopPausingActivity() { 1239 if (!isLeafTask()) { 1240 for (int i = mChildren.size() - 1; i >= 0; --i) { 1241 ActivityRecord pausingActivity = mChildren.get(i).asTask().getTopPausingActivity(); 1242 if (pausingActivity != null) { 1243 return pausingActivity; 1244 } 1245 } 1246 } 1247 1248 final ActivityRecord taskPausingActivity = getPausingActivity(); 1249 ActivityRecord topPausingActivity = null; 1250 for (int i = mChildren.size() - 1; i >= 0; --i) { 1251 final WindowContainer child = mChildren.get(i); 1252 if (child.asTaskFragment() != null) { 1253 topPausingActivity = child.asTaskFragment().getTopPausingActivity(); 1254 } else if (taskPausingActivity != null 1255 && child.asActivityRecord() == taskPausingActivity) { 1256 topPausingActivity = taskPausingActivity; 1257 } 1258 if (topPausingActivity != null) { 1259 return topPausingActivity; 1260 } 1261 } 1262 return null; 1263 } 1264 updateTaskMovement(boolean toTop, boolean toBottom, int position)1265 void updateTaskMovement(boolean toTop, boolean toBottom, int position) { 1266 EventLogTags.writeWmTaskMoved(mTaskId, getRootTaskId(), getDisplayId(), toTop ? 1 : 0, 1267 position); 1268 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 1269 if (taskDisplayArea != null && isLeafTask()) { 1270 taskDisplayArea.onLeafTaskMoved(this, toTop, toBottom); 1271 } 1272 if (isPersistable) { 1273 mLastTimeMoved = System.currentTimeMillis(); 1274 } 1275 if (toTop && inRecents) { 1276 // If task is in recents, ensure it is at the top 1277 mTaskSupervisor.mRecentTasks.add(this); 1278 } 1279 } 1280 1281 // Close up recents linked list. closeRecentsChain()1282 private void closeRecentsChain() { 1283 if (mPrevAffiliate != null) { 1284 mPrevAffiliate.setNextAffiliate(mNextAffiliate); 1285 } 1286 if (mNextAffiliate != null) { 1287 mNextAffiliate.setPrevAffiliate(mPrevAffiliate); 1288 } 1289 setPrevAffiliate(null); 1290 setNextAffiliate(null); 1291 } 1292 removedFromRecents()1293 void removedFromRecents() { 1294 closeRecentsChain(); 1295 if (inRecents) { 1296 inRecents = false; 1297 mAtmService.notifyTaskPersisterLocked(this, false); 1298 } 1299 1300 clearRootProcess(); 1301 1302 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents( 1303 mTaskId, mUserId); 1304 } 1305 setTaskToAffiliateWith(Task taskToAffiliateWith)1306 void setTaskToAffiliateWith(Task taskToAffiliateWith) { 1307 closeRecentsChain(); 1308 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId; 1309 // Find the end 1310 while (taskToAffiliateWith.mNextAffiliate != null) { 1311 final Task nextRecents = taskToAffiliateWith.mNextAffiliate; 1312 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) { 1313 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId=" 1314 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId); 1315 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) { 1316 nextRecents.setPrevAffiliate(null); 1317 } 1318 taskToAffiliateWith.setNextAffiliate(null); 1319 break; 1320 } 1321 taskToAffiliateWith = nextRecents; 1322 } 1323 taskToAffiliateWith.setNextAffiliate(this); 1324 setPrevAffiliate(taskToAffiliateWith); 1325 setNextAffiliate(null); 1326 } 1327 1328 /** Returns the intent for the root activity for this task */ getBaseIntent()1329 Intent getBaseIntent() { 1330 if (intent != null) return intent; 1331 if (affinityIntent != null) return affinityIntent; 1332 // Probably a task that contains other tasks, so return the intent for the top task? 1333 final Task topTask = getTopMostTask(); 1334 return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null; 1335 } 1336 1337 /** 1338 * Returns the package name which stands for this task. It is empty string if no activities 1339 * have been added to this task. 1340 */ 1341 @NonNull getBasePackageName()1342 String getBasePackageName() { 1343 final Intent intent = getBaseIntent(); 1344 if (intent == null) { 1345 return ""; 1346 } 1347 final ComponentName componentName = intent.getComponent(); 1348 return componentName != null ? componentName.getPackageName() : ""; 1349 } 1350 1351 /** Returns the first non-finishing activity from the bottom. */ getRootActivity()1352 ActivityRecord getRootActivity() { 1353 // TODO: Figure out why we historical ignore relinquish identity for this case... 1354 return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/); 1355 } 1356 getRootActivity(boolean setToBottomIfNone)1357 ActivityRecord getRootActivity(boolean setToBottomIfNone) { 1358 return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone); 1359 } 1360 getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone)1361 ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) { 1362 return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone); 1363 } 1364 topRunningActivityLocked()1365 ActivityRecord topRunningActivityLocked() { 1366 if (getParent() == null) { 1367 return null; 1368 } 1369 return getActivity(ActivityRecord::canBeTopRunning); 1370 } 1371 1372 /** 1373 * Return true if any activities in this task belongs to input uid. 1374 */ isUidPresent(int uid)1375 boolean isUidPresent(int uid) { 1376 final PooledPredicate p = PooledLambda.obtainPredicate( 1377 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid); 1378 final boolean isUidPresent = getActivity(p) != null; 1379 p.recycle(); 1380 return isUidPresent; 1381 } 1382 topActivityContainsStartingWindow()1383 ActivityRecord topActivityContainsStartingWindow() { 1384 if (getParent() == null) { 1385 return null; 1386 } 1387 return getActivity((r) -> r.getWindow(window -> 1388 window.getBaseType() == TYPE_APPLICATION_STARTING) != null); 1389 } 1390 1391 /** 1392 * Reorder the history task so that the passed activity is brought to the front. 1393 * @return whether it was actually moved (vs already being top). 1394 */ moveActivityToFront(ActivityRecord newTop)1395 final boolean moveActivityToFront(ActivityRecord newTop) { 1396 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Removing and adding activity %s to root task at top " 1397 + "callers=%s", newTop, Debug.getCallers(4)); 1398 final TaskFragment taskFragment = newTop.getTaskFragment(); 1399 boolean moved; 1400 if (taskFragment != this) { 1401 if (taskFragment.isEmbedded() && taskFragment.getNonFinishingActivityCount() == 1) { 1402 taskFragment.mClearedForReorderActivityToFront = true; 1403 } 1404 newTop.reparent(this, POSITION_TOP); 1405 moved = true; 1406 if (taskFragment.isEmbedded()) { 1407 mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController 1408 .onActivityReparentedToTask(newTop); 1409 } 1410 } else { 1411 moved = moveChildToFront(newTop); 1412 } 1413 updateEffectiveIntent(); 1414 return moved; 1415 } 1416 1417 @Override addChild(WindowContainer child, int index)1418 void addChild(WindowContainer child, int index) { 1419 index = getAdjustedChildPosition(child, index); 1420 super.addChild(child, index); 1421 1422 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this); 1423 1424 // A rootable task that is now being added to be the child of an organized task. Making 1425 // sure the root task references is keep updated. 1426 if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) { 1427 getDisplayArea().addRootTaskReferenceIfNeeded((Task) child); 1428 } 1429 1430 // Make sure the list of display UID allowlists is updated 1431 // now that this record is in a new task. 1432 mRootWindowContainer.updateUIDsPresentOnDisplay(); 1433 1434 // Only pass minimum dimensions for pure TaskFragment. Task's minimum dimensions must be 1435 // passed from Task constructor. 1436 final TaskFragment childTaskFrag = child.asTaskFragment(); 1437 if (childTaskFrag != null && childTaskFrag.asTask() == null) { 1438 childTaskFrag.setMinDimensions(mMinWidth, mMinHeight); 1439 1440 // The starting window should keep covering its task when a pure TaskFragment is added 1441 // because its bounds may not fill the task. 1442 final ActivityRecord top = getTopMostActivity(); 1443 if (top != null) { 1444 top.associateStartingWindowWithTaskIfNeeded(); 1445 } 1446 } 1447 } 1448 1449 /** Called when an {@link ActivityRecord} is added as a descendant */ onDescendantActivityAdded(boolean hadActivity, int activityType, ActivityRecord r)1450 void onDescendantActivityAdded(boolean hadActivity, int activityType, ActivityRecord r) { 1451 warnForNonLeafTask("onDescendantActivityAdded"); 1452 1453 // Only set this based on the first activity 1454 if (!hadActivity) { 1455 int activityOverrideType = 1456 r.getRequestedOverrideConfiguration().windowConfiguration.getActivityType(); 1457 if (activityOverrideType == ACTIVITY_TYPE_UNDEFINED) { 1458 // Normally non-standard activity type for the activity record will be set when the 1459 // object is created, however we delay setting the standard application type until 1460 // this point so that the task can set the type for additional activities added in 1461 // the else condition below. 1462 activityOverrideType = activityType != ACTIVITY_TYPE_UNDEFINED ? activityType 1463 : ACTIVITY_TYPE_STANDARD; 1464 // Set the Activity's requestedOverrideConfiguration directly to reduce 1465 // WC#onConfigurationChanged calls since it will be called while setting the 1466 // Task's activity type below. 1467 r.getRequestedOverrideConfiguration().windowConfiguration.setActivityType( 1468 activityOverrideType); 1469 } 1470 setActivityType(activityOverrideType); 1471 isPersistable = r.isPersistable(); 1472 mCallingUid = r.launchedFromUid; 1473 mCallingPackage = r.launchedFromPackage; 1474 mCallingFeatureId = r.launchedFromFeatureId; 1475 // Clamp to [1, max]. 1476 maxRecents = Math.min(Math.max(r.info.maxRecents, 1), 1477 ActivityTaskManager.getMaxAppRecentsLimitStatic()); 1478 } else { 1479 // Otherwise make all added activities match this one. 1480 r.setActivityType(activityType); 1481 } 1482 1483 updateEffectiveIntent(); 1484 } 1485 1486 @Override removeChild(WindowContainer child)1487 void removeChild(WindowContainer child) { 1488 removeChild(child, "removeChild"); 1489 } 1490 removeChild(WindowContainer r, String reason)1491 void removeChild(WindowContainer r, String reason) { 1492 // A rootable child task that is now being removed from an organized task. Making sure 1493 // the root task references is keep updated. 1494 if (mCreatedByOrganizer && r.asTask() != null) { 1495 getDisplayArea().removeRootTaskReferenceIfNeeded((Task) r); 1496 } 1497 if (!mChildren.contains(r)) { 1498 Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this); 1499 return; 1500 } 1501 1502 if (DEBUG_TASK_MOVEMENT) { 1503 Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason); 1504 } 1505 super.removeChild(r, false /* removeSelfIfPossible */); 1506 1507 if (inPinnedWindowingMode()) { 1508 // We normally notify listeners of task stack changes on pause, however root pinned task 1509 // activities are normally in the paused state so no notification will be sent there 1510 // before the activity is removed. We send it here so instead. 1511 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged(); 1512 } 1513 1514 if (hasChild()) { 1515 updateEffectiveIntent(); 1516 1517 // The following block can be executed multiple times if there is more than one overlay. 1518 // {@link ActivityTaskSupervisor#removeTaskByIdLocked} handles this by reverse lookup 1519 // of the task by id and exiting early if not found. 1520 if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) { 1521 // When destroying a task, tell the supervisor to remove it so that any activity it 1522 // has can be cleaned up correctly. This is currently the only place where we remove 1523 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays 1524 // state into removeChild(), we just clear the task here before the other residual 1525 // work. 1526 // TODO: If the callers to removeChild() changes such that we have multiple places 1527 // where we are destroying the task, move this back into removeChild() 1528 mTaskSupervisor.removeTask(this, false /* killProcess */, 1529 !REMOVE_FROM_RECENTS, reason); 1530 } 1531 } else if (!mReuseTask && shouldRemoveSelfOnLastChildRemoval()) { 1532 reason += ", last child = " + r + " in " + this; 1533 removeIfPossible(reason); 1534 } 1535 } 1536 1537 /** 1538 * @return whether or not there are ONLY task overlay activities in the task. 1539 * If {@param includeFinishing} is set, then don't ignore finishing activities in the 1540 * check. If there are no task overlay activities, this call returns false. 1541 */ onlyHasTaskOverlayActivities(boolean includeFinishing)1542 boolean onlyHasTaskOverlayActivities(boolean includeFinishing) { 1543 int count = 0; 1544 for (int i = getChildCount() - 1; i >= 0; i--) { 1545 final ActivityRecord r = getChildAt(i).asActivityRecord(); 1546 if (r == null) { 1547 // Has a child that is other than Activity. 1548 return false; 1549 } 1550 if (!includeFinishing && r.finishing) { 1551 continue; 1552 } 1553 if (!r.isTaskOverlay()) { 1554 return false; 1555 } 1556 count++; 1557 } 1558 return count > 0; 1559 } 1560 autoRemoveFromRecents(TaskFragment oldParentFragment)1561 private boolean autoRemoveFromRecents(TaskFragment oldParentFragment) { 1562 // We will automatically remove the task either if it has explicitly asked for 1563 // this, or it is empty and has never contained an activity that got shown to 1564 // the user, or it was being embedded in another Task. 1565 return autoRemoveRecents || (!hasChild() && !getHasBeenVisible() 1566 || (oldParentFragment != null && oldParentFragment.isEmbedded())); 1567 } 1568 clearPinnedTaskIfNeed()1569 private void clearPinnedTaskIfNeed() { 1570 // The original task is to be removed, try remove also the pinned task. 1571 if (mChildPipActivity != null && mChildPipActivity.getTask() != null) { 1572 mTaskSupervisor.removeRootTask(mChildPipActivity.getTask()); 1573 } 1574 } 1575 1576 /** Completely remove all activities associated with an existing task. */ removeActivities(String reason, boolean excludingTaskOverlay)1577 void removeActivities(String reason, boolean excludingTaskOverlay) { 1578 clearPinnedTaskIfNeed(); 1579 // Broken down into to cases to avoid object create due to capturing mStack. 1580 if (getRootTask() == null) { 1581 forAllActivities((r) -> { 1582 if (r.finishing || (excludingTaskOverlay && r.isTaskOverlay())) { 1583 return; 1584 } 1585 // Task was restored from persistent storage. 1586 r.takeFromHistory(); 1587 removeChild(r, reason); 1588 }); 1589 } else { 1590 final ArrayList<ActivityRecord> finishingActivities = new ArrayList<>(); 1591 forAllActivities(r -> { 1592 if (r.finishing || (excludingTaskOverlay && r.isTaskOverlay())) { 1593 return; 1594 } 1595 finishingActivities.add(r); 1596 }); 1597 1598 // Finish or destroy apps from the bottom to ensure that all the other activity have 1599 // been finished and the top task in another task gets resumed when a top activity is 1600 // removed. Otherwise, the next top activity could be started while the top activity 1601 // is removed, which is not necessary since the next top activity is on the same Task 1602 // and should also be removed. 1603 for (int i = finishingActivities.size() - 1; i >= 0; i--) { 1604 final ActivityRecord r = finishingActivities.get(i); 1605 1606 // Prevent the transition from being executed too early if the top activity is 1607 // resumed but the mVisibleRequested of any other activity is true, the transition 1608 // should wait until next activity resumed. 1609 if (r.isState(RESUMED) || (r.isVisible() 1610 && !mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CLOSE))) { 1611 r.finishIfPossible(reason, false /* oomAdj */); 1612 } else { 1613 r.destroyIfPossible(reason); 1614 } 1615 } 1616 } 1617 } 1618 1619 /** 1620 * Completely remove all activities associated with an existing task. 1621 */ performClearTaskForReuse(boolean excludingTaskOverlay)1622 void performClearTaskForReuse(boolean excludingTaskOverlay) { 1623 mReuseTask = true; 1624 mTaskSupervisor.beginDeferResume(); 1625 try { 1626 removeActivities("clear-task-all", excludingTaskOverlay); 1627 } finally { 1628 mTaskSupervisor.endDeferResume(); 1629 mReuseTask = false; 1630 } 1631 } 1632 performClearTop(ActivityRecord newR, int launchFlags, int[] finishCount)1633 ActivityRecord performClearTop(ActivityRecord newR, int launchFlags, int[] finishCount) { 1634 // The task should be preserved for putting new activity in case the last activity is 1635 // finished if it is normal launch mode and not single top ("clear-task-top"). 1636 mReuseTask = true; 1637 mTaskSupervisor.beginDeferResume(); 1638 final ActivityRecord result; 1639 try { 1640 result = clearTopActivities(newR, launchFlags, finishCount); 1641 } finally { 1642 mTaskSupervisor.endDeferResume(); 1643 mReuseTask = false; 1644 } 1645 return result; 1646 } 1647 1648 /** 1649 * Perform clear operation as requested by 1650 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the 1651 * root task to the given task, then look for 1652 * an instance of that activity in the root task and, if found, finish all 1653 * activities on top of it and return the instance. 1654 * 1655 * @param newR Description of the new activity being started. 1656 * @param finishCount 1-element array that will be populated with the number of activities 1657 * that have been finished. 1658 * @return Returns the existing activity in the task that performs the clear-top operation, 1659 * or {@code null} if none was found. 1660 */ clearTopActivities(ActivityRecord newR, int launchFlags, int[] finishCount)1661 private ActivityRecord clearTopActivities(ActivityRecord newR, int launchFlags, 1662 int[] finishCount) { 1663 final ActivityRecord r = findActivityInHistory(newR.mActivityComponent, newR.mUserId); 1664 if (r == null) return null; 1665 1666 final PooledPredicate f = PooledLambda.obtainPredicate( 1667 (ActivityRecord ar, ActivityRecord boundaryActivity) -> 1668 finishActivityAbove(ar, boundaryActivity, finishCount), 1669 PooledLambda.__(ActivityRecord.class), r); 1670 forAllActivities(f); 1671 f.recycle(); 1672 1673 // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we 1674 // will finish the current instance of the activity so a new fresh one can be started. 1675 if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE 1676 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0 1677 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) { 1678 if (!r.finishing) { 1679 r.finishIfPossible("clear-task-top", false /* oomAdj */); 1680 } 1681 } 1682 1683 return r; 1684 } 1685 finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity, @NonNull int[] finishCount)1686 private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity, 1687 @NonNull int[] finishCount) { 1688 // Stop operation once we reach the boundary activity. 1689 if (r == boundaryActivity) return true; 1690 1691 if (!r.finishing && !r.isTaskOverlay()) { 1692 final ActivityOptions opts = r.getOptions(); 1693 if (opts != null) { 1694 r.clearOptionsAnimation(); 1695 // TODO: Why is this updating the boundary activity vs. the current activity??? 1696 boundaryActivity.updateOptionsLocked(opts); 1697 } 1698 finishCount[0] += 1; 1699 r.finishIfPossible("clear-task-stack", false /* oomAdj */); 1700 } 1701 1702 return false; 1703 } 1704 lockTaskAuthToString()1705 String lockTaskAuthToString() { 1706 switch (mLockTaskAuth) { 1707 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK"; 1708 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE"; 1709 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE"; 1710 case LOCK_TASK_AUTH_ALLOWLISTED: return "LOCK_TASK_AUTH_ALLOWLISTED"; 1711 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV"; 1712 default: return "unknown=" + mLockTaskAuth; 1713 } 1714 } 1715 setLockTaskAuth()1716 void setLockTaskAuth() { 1717 setLockTaskAuth(getRootActivity()); 1718 } 1719 setLockTaskAuth(@ullable ActivityRecord r)1720 private void setLockTaskAuth(@Nullable ActivityRecord r) { 1721 mLockTaskAuth = mAtmService.getLockTaskController().getLockTaskAuth(r, this); 1722 ProtoLog.d(WM_DEBUG_LOCKTASK, "setLockTaskAuth: task=%s mLockTaskAuth=%s", this, 1723 lockTaskAuthToString()); 1724 } 1725 supportsFreeform()1726 boolean supportsFreeform() { 1727 return supportsFreeformInDisplayArea(getDisplayArea()); 1728 } 1729 1730 /** 1731 * @return whether this task supports freeform multi-window if it is in the given 1732 * {@link TaskDisplayArea}. 1733 */ supportsFreeformInDisplayArea(@ullable TaskDisplayArea tda)1734 boolean supportsFreeformInDisplayArea(@Nullable TaskDisplayArea tda) { 1735 return mAtmService.mSupportsFreeformWindowManagement 1736 && supportsMultiWindowInDisplayArea(tda); 1737 } 1738 1739 /** 1740 * Check whether this task can be launched on the specified display. 1741 * 1742 * @param displayId Target display id. 1743 * @return {@code true} if either it is the default display or this activity can be put on a 1744 * secondary display. 1745 */ canBeLaunchedOnDisplay(int displayId)1746 boolean canBeLaunchedOnDisplay(int displayId) { 1747 return mTaskSupervisor.canPlaceEntityOnDisplay(displayId, 1748 -1 /* don't check PID */, -1 /* don't check UID */, this); 1749 } 1750 1751 /** 1752 * Check that a given bounds matches the application requested orientation. 1753 * 1754 * @param bounds The bounds to be tested. 1755 * @return True if the requested bounds are okay for a resizing request. 1756 */ canResizeToBounds(Rect bounds)1757 private boolean canResizeToBounds(Rect bounds) { 1758 if (bounds == null || !inFreeformWindowingMode()) { 1759 // Note: If not on the freeform workspace, we ignore the bounds. 1760 return true; 1761 } 1762 final boolean landscape = bounds.width() > bounds.height(); 1763 final Rect configBounds = getRequestedOverrideBounds(); 1764 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) { 1765 return configBounds.isEmpty() 1766 || landscape == (configBounds.width() > configBounds.height()); 1767 } 1768 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape) 1769 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape); 1770 } 1771 1772 /** 1773 * @return {@code true} if the task is being cleared for the purposes of being reused. 1774 */ isClearingToReuseTask()1775 boolean isClearingToReuseTask() { 1776 return mReuseTask; 1777 } 1778 1779 /** 1780 * Find the activity in the history task within the given task. Returns 1781 * the index within the history at which it's found, or < 0 if not found. 1782 */ findActivityInHistory(ComponentName component, int userId)1783 ActivityRecord findActivityInHistory(ComponentName component, int userId) { 1784 final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory, 1785 PooledLambda.__(ActivityRecord.class), component, userId); 1786 final ActivityRecord r = getActivity(p); 1787 p.recycle(); 1788 return r; 1789 } 1790 matchesActivityInHistory( ActivityRecord r, ComponentName activityComponent, int userId)1791 private static boolean matchesActivityInHistory( 1792 ActivityRecord r, ComponentName activityComponent, int userId) { 1793 return !r.finishing && r.mActivityComponent.equals(activityComponent) 1794 && r.mUserId == userId; 1795 } 1796 1797 /** Updates the last task description values. */ updateTaskDescription()1798 void updateTaskDescription() { 1799 final ActivityRecord root = getRootActivity(true); 1800 if (root == null) return; 1801 1802 final TaskDescription taskDescription = new TaskDescription(); 1803 final PooledPredicate f = PooledLambda.obtainPredicate( 1804 Task::setTaskDescriptionFromActivityAboveRoot, 1805 PooledLambda.__(ActivityRecord.class), root, taskDescription); 1806 forAllActivities(f); 1807 f.recycle(); 1808 taskDescription.setResizeMode(mResizeMode); 1809 taskDescription.setMinWidth(mMinWidth); 1810 taskDescription.setMinHeight(mMinHeight); 1811 setTaskDescription(taskDescription); 1812 mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged( 1813 getTaskInfo()); 1814 1815 final WindowContainer parent = getParent(); 1816 if (parent != null) { 1817 final Task t = parent.asTask(); 1818 if (t != null) { 1819 t.updateTaskDescription(); 1820 } 1821 } 1822 1823 dispatchTaskInfoChangedIfNeeded(false /* force */); 1824 } 1825 setTaskDescriptionFromActivityAboveRoot( ActivityRecord r, ActivityRecord root, TaskDescription td)1826 private static boolean setTaskDescriptionFromActivityAboveRoot( 1827 ActivityRecord r, ActivityRecord root, TaskDescription td) { 1828 if (!r.isTaskOverlay() && r.taskDescription != null) { 1829 final TaskDescription atd = r.taskDescription; 1830 if (td.getLabel() == null) { 1831 td.setLabel(atd.getLabel()); 1832 } 1833 if (td.getRawIcon() == null) { 1834 td.setIcon(atd.getRawIcon()); 1835 } 1836 if (td.getIconFilename() == null) { 1837 td.setIconFilename(atd.getIconFilename()); 1838 } 1839 if (td.getPrimaryColor() == 0) { 1840 td.setPrimaryColor(atd.getPrimaryColor()); 1841 } 1842 if (td.getBackgroundColor() == 0) { 1843 td.setBackgroundColor(atd.getBackgroundColor()); 1844 } 1845 if (td.getStatusBarColor() == 0) { 1846 td.setStatusBarColor(atd.getStatusBarColor()); 1847 td.setEnsureStatusBarContrastWhenTransparent( 1848 atd.getEnsureStatusBarContrastWhenTransparent()); 1849 } 1850 if (td.getStatusBarAppearance() == 0) { 1851 td.setStatusBarAppearance(atd.getStatusBarAppearance()); 1852 } 1853 if (td.getNavigationBarColor() == 0) { 1854 td.setNavigationBarColor(atd.getNavigationBarColor()); 1855 td.setEnsureNavigationBarContrastWhenTransparent( 1856 atd.getEnsureNavigationBarContrastWhenTransparent()); 1857 } 1858 if (td.getBackgroundColorFloating() == 0) { 1859 td.setBackgroundColorFloating(atd.getBackgroundColorFloating()); 1860 } 1861 } 1862 1863 // End search once we get to root. 1864 return r == root; 1865 } 1866 1867 // TODO (AM refactor): Invoke automatically when there is a change in children 1868 @VisibleForTesting updateEffectiveIntent()1869 void updateEffectiveIntent() { 1870 final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/); 1871 if (root != null) { 1872 setIntent(root); 1873 // Update the task description when the activities change 1874 updateTaskDescription(); 1875 } 1876 } 1877 setLastNonFullscreenBounds(Rect bounds)1878 void setLastNonFullscreenBounds(Rect bounds) { 1879 if (mLastNonFullscreenBounds == null) { 1880 mLastNonFullscreenBounds = new Rect(bounds); 1881 } else { 1882 mLastNonFullscreenBounds.set(bounds); 1883 } 1884 } 1885 onConfigurationChangedInner(Configuration newParentConfig)1886 private void onConfigurationChangedInner(Configuration newParentConfig) { 1887 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so 1888 // restore the last recorded non-fullscreen bounds. 1889 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds(); 1890 boolean nextPersistTaskBounds = 1891 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds(); 1892 if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_UNDEFINED) { 1893 nextPersistTaskBounds = newParentConfig.windowConfiguration.persistTaskBounds(); 1894 } 1895 // Only restore to the last non-fullscreen bounds when the requested override bounds 1896 // have not been explicitly set already. 1897 nextPersistTaskBounds &= 1898 (getRequestedOverrideConfiguration().windowConfiguration.getBounds() == null 1899 || getRequestedOverrideConfiguration().windowConfiguration.getBounds().isEmpty()); 1900 if (!prevPersistTaskBounds && nextPersistTaskBounds 1901 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) { 1902 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop. 1903 getRequestedOverrideConfiguration().windowConfiguration 1904 .setBounds(mLastNonFullscreenBounds); 1905 } 1906 1907 final int prevWinMode = getWindowingMode(); 1908 mTmpPrevBounds.set(getBounds()); 1909 final boolean wasInMultiWindowMode = inMultiWindowMode(); 1910 final boolean wasInPictureInPicture = inPinnedWindowingMode(); 1911 super.onConfigurationChanged(newParentConfig); 1912 // Only need to update surface size here since the super method will handle updating 1913 // surface position. 1914 updateSurfaceSize(getSyncTransaction()); 1915 1916 final boolean pipChanging = wasInPictureInPicture != inPinnedWindowingMode(); 1917 if (pipChanging) { 1918 mTaskSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, getRootTask()); 1919 } else if (wasInMultiWindowMode != inMultiWindowMode()) { 1920 mTaskSupervisor.scheduleUpdateMultiWindowMode(this); 1921 } 1922 1923 if (shouldStartChangeTransition(prevWinMode, mTmpPrevBounds)) { 1924 initializeChangeTransition(mTmpPrevBounds); 1925 } 1926 1927 // If the configuration supports persistent bounds (eg. Freeform), keep track of the 1928 // current (non-fullscreen) bounds for persistence. 1929 if (getWindowConfiguration().persistTaskBounds()) { 1930 final Rect currentBounds = getRequestedOverrideBounds(); 1931 if (!currentBounds.isEmpty()) { 1932 setLastNonFullscreenBounds(currentBounds); 1933 } 1934 } 1935 1936 if (pipChanging && wasInPictureInPicture 1937 && !mTransitionController.isShellTransitionsEnabled()) { 1938 // If the top activity is changing from PiP to fullscreen with fixed rotation, 1939 // clear the crop and rotation matrix of task because fixed rotation will handle 1940 // the transformation on activity level. This also avoids flickering caused by the 1941 // latency of fullscreen task organizer configuring the surface. 1942 final ActivityRecord r = topRunningActivity(); 1943 if (r != null && mDisplayContent.isFixedRotationLaunchingApp(r)) { 1944 resetSurfaceControlTransforms(); 1945 } 1946 } 1947 1948 saveLaunchingStateIfNeeded(); 1949 final boolean taskOrgChanged = updateTaskOrganizerState(); 1950 if (taskOrgChanged) { 1951 updateSurfacePosition(getSyncTransaction()); 1952 if (!isOrganized()) { 1953 // Surface-size update was skipped before (since internally it no-ops if 1954 // isOrganized() is true); however, now that this is not organized, the surface 1955 // size needs to be updated by WM. 1956 updateSurfaceSize(getSyncTransaction()); 1957 } 1958 } 1959 // If the task organizer has changed, then it will already be receiving taskAppeared with 1960 // the latest task-info thus the task-info won't have changed. 1961 if (!taskOrgChanged) { 1962 dispatchTaskInfoChangedIfNeeded(false /* force */); 1963 } 1964 } 1965 1966 @Override onConfigurationChanged(Configuration newParentConfig)1967 public void onConfigurationChanged(Configuration newParentConfig) { 1968 if (mDisplayContent != null 1969 && mDisplayContent.mPinnedTaskController.isFreezingTaskConfig(this)) { 1970 // It happens when animating from fullscreen to PiP with orientation change. Because 1971 // the activity in this pinned task is in fullscreen windowing mode (see 1972 // RootWindowContainer#moveActivityToPinnedRootTask) and the activity will be set to 1973 // pinned mode after the animation is done, the configuration change by orientation 1974 // change is just an intermediate state that should be ignored to avoid flickering. 1975 return; 1976 } 1977 // Calling Task#onConfigurationChanged() for leaf task since the ops in this method are 1978 // particularly for root tasks, like preventing bounds changes when inheriting certain 1979 // windowing mode. 1980 if (!isRootTask()) { 1981 onConfigurationChangedInner(newParentConfig); 1982 return; 1983 } 1984 1985 final int prevWindowingMode = getWindowingMode(); 1986 final boolean prevIsAlwaysOnTop = isAlwaysOnTop(); 1987 final int prevRotation = getWindowConfiguration().getRotation(); 1988 final Rect newBounds = mTmpRect; 1989 // Initialize the new bounds by previous bounds as the input and output for calculating 1990 // override bounds in pinned (pip) or split-screen mode. 1991 getBounds(newBounds); 1992 1993 onConfigurationChangedInner(newParentConfig); 1994 1995 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 1996 if (taskDisplayArea == null) { 1997 return; 1998 } 1999 2000 if (prevWindowingMode != getWindowingMode()) { 2001 taskDisplayArea.onRootTaskWindowingModeChanged(this); 2002 } 2003 2004 if (!isOrganized() && !getRequestedOverrideBounds().isEmpty() && mDisplayContent != null) { 2005 // If the parent (display) has rotated, rotate our bounds to best-fit where their 2006 // bounds were on the pre-rotated display. 2007 final int newRotation = getWindowConfiguration().getRotation(); 2008 final boolean rotationChanged = prevRotation != newRotation; 2009 if (rotationChanged) { 2010 mDisplayContent.rotateBounds(prevRotation, newRotation, newBounds); 2011 setBounds(newBounds); 2012 } 2013 } 2014 2015 if (prevIsAlwaysOnTop != isAlwaysOnTop()) { 2016 // Since always on top is only on when the root task is freeform or pinned, the state 2017 // can be toggled when the windowing mode changes. We must make sure the root task is 2018 // placed properly when always on top state changes. 2019 taskDisplayArea.positionChildAt(POSITION_TOP, this, false /* includingParents */); 2020 } 2021 } 2022 resolveLeafTaskOnlyOverrideConfigs(Configuration newParentConfig, Rect previousBounds)2023 void resolveLeafTaskOnlyOverrideConfigs(Configuration newParentConfig, Rect previousBounds) { 2024 if (!isLeafTask()) { 2025 return; 2026 } 2027 2028 int windowingMode = 2029 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode(); 2030 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 2031 windowingMode = newParentConfig.windowConfiguration.getWindowingMode(); 2032 } 2033 // Commit the resolved windowing mode so the canSpecifyOrientation won't get the old 2034 // mode that may cause the bounds to be miscalculated, e.g. letterboxed. 2035 getConfiguration().windowConfiguration.setWindowingMode(windowingMode); 2036 Rect outOverrideBounds = getResolvedOverrideConfiguration().windowConfiguration.getBounds(); 2037 2038 if (windowingMode == WINDOWING_MODE_FULLSCREEN) { 2039 if (!mCreatedByOrganizer) { 2040 // Use empty bounds to indicate "fill parent". 2041 outOverrideBounds.setEmpty(); 2042 } 2043 // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if 2044 // the parent or display is smaller than the size, the content may be cropped. 2045 return; 2046 } 2047 2048 adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig); 2049 if (windowingMode == WINDOWING_MODE_FREEFORM) { 2050 computeFreeformBounds(outOverrideBounds, newParentConfig); 2051 return; 2052 } 2053 } 2054 adjustForMinimalTaskDimensions(@onNull Rect bounds, @NonNull Rect previousBounds, @NonNull Configuration parentConfig)2055 void adjustForMinimalTaskDimensions(@NonNull Rect bounds, @NonNull Rect previousBounds, 2056 @NonNull Configuration parentConfig) { 2057 int minWidth = mMinWidth; 2058 int minHeight = mMinHeight; 2059 // If the task has no requested minimal size, we'd like to enforce a minimal size 2060 // so that the user can not render the task fragment too small to manipulate. We don't need 2061 // to do this for the root pinned task as the bounds are controlled by the system. 2062 if (!inPinnedWindowingMode()) { 2063 // Use Display specific min sizes when there is one associated with this Task. 2064 final int defaultMinSizeDp = mDisplayContent == null 2065 ? DEFAULT_MIN_TASK_SIZE_DP : mDisplayContent.mMinSizeOfResizeableTaskDp; 2066 final float density = (float) parentConfig.densityDpi / DisplayMetrics.DENSITY_DEFAULT; 2067 final int defaultMinSize = (int) (defaultMinSizeDp * density); 2068 2069 if (minWidth == INVALID_MIN_SIZE) { 2070 minWidth = defaultMinSize; 2071 } 2072 if (minHeight == INVALID_MIN_SIZE) { 2073 minHeight = defaultMinSize; 2074 } 2075 } 2076 if (bounds.isEmpty()) { 2077 // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they 2078 // do, we can just skip. 2079 final Rect parentBounds = parentConfig.windowConfiguration.getBounds(); 2080 if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) { 2081 return; 2082 } 2083 bounds.set(parentBounds); 2084 } 2085 final boolean adjustWidth = minWidth > bounds.width(); 2086 final boolean adjustHeight = minHeight > bounds.height(); 2087 if (!(adjustWidth || adjustHeight)) { 2088 return; 2089 } 2090 2091 if (adjustWidth) { 2092 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) { 2093 bounds.left = bounds.right - minWidth; 2094 } else { 2095 // Either left bounds match, or neither match, or the previous bounds were 2096 // fullscreen and we default to keeping left. 2097 bounds.right = bounds.left + minWidth; 2098 } 2099 } 2100 if (adjustHeight) { 2101 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) { 2102 bounds.top = bounds.bottom - minHeight; 2103 } else { 2104 // Either top bounds match, or neither match, or the previous bounds were 2105 // fullscreen and we default to keeping top. 2106 bounds.bottom = bounds.top + minHeight; 2107 } 2108 } 2109 } 2110 2111 /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FREEFORM}. */ computeFreeformBounds(@onNull Rect outBounds, @NonNull Configuration newParentConfig)2112 private void computeFreeformBounds(@NonNull Rect outBounds, 2113 @NonNull Configuration newParentConfig) { 2114 // by policy, make sure the window remains within parent somewhere 2115 final float density = 2116 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT; 2117 final Rect parentBounds = 2118 new Rect(newParentConfig.windowConfiguration.getBounds()); 2119 final DisplayContent display = getDisplayContent(); 2120 if (display != null) { 2121 // If a freeform window moves below system bar, there is no way to move it again 2122 // by touch. Because its caption is covered by system bar. So we exclude them 2123 // from root task bounds. and then caption will be shown inside stable area. 2124 final Rect stableBounds = new Rect(); 2125 display.getStableRect(stableBounds); 2126 parentBounds.intersect(stableBounds); 2127 } 2128 2129 fitWithinBounds(outBounds, parentBounds, 2130 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP), 2131 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP)); 2132 2133 // Prevent to overlap caption with stable insets. 2134 final int offsetTop = parentBounds.top - outBounds.top; 2135 if (offsetTop > 0) { 2136 outBounds.offset(0, offsetTop); 2137 } 2138 } 2139 2140 /** 2141 * Adjusts bounds to stay within root task bounds. 2142 * 2143 * Since bounds might be outside of root task bounds, this method tries to move the bounds in 2144 * a way that keep them unchanged, but be contained within the root task bounds. 2145 * 2146 * @param bounds Bounds to be adjusted. 2147 * @param rootTaskBounds Bounds within which the other bounds should remain. 2148 * @param overlapPxX The amount of px required to be visible in the X dimension. 2149 * @param overlapPxY The amount of px required to be visible in the Y dimension. 2150 */ fitWithinBounds(Rect bounds, Rect rootTaskBounds, int overlapPxX, int overlapPxY)2151 private static void fitWithinBounds(Rect bounds, Rect rootTaskBounds, int overlapPxX, 2152 int overlapPxY) { 2153 if (rootTaskBounds == null || rootTaskBounds.isEmpty() || rootTaskBounds.contains(bounds)) { 2154 return; 2155 } 2156 2157 // For each side of the parent (eg. left), check if the opposing side of the window (eg. 2158 // right) is at least overlap pixels away. If less, offset the window by that difference. 2159 int horizontalDiff = 0; 2160 // If window is smaller than overlap, use it's smallest dimension instead 2161 int overlapLR = Math.min(overlapPxX, bounds.width()); 2162 if (bounds.right < (rootTaskBounds.left + overlapLR)) { 2163 horizontalDiff = overlapLR - (bounds.right - rootTaskBounds.left); 2164 } else if (bounds.left > (rootTaskBounds.right - overlapLR)) { 2165 horizontalDiff = -(overlapLR - (rootTaskBounds.right - bounds.left)); 2166 } 2167 int verticalDiff = 0; 2168 int overlapTB = Math.min(overlapPxY, bounds.width()); 2169 if (bounds.bottom < (rootTaskBounds.top + overlapTB)) { 2170 verticalDiff = overlapTB - (bounds.bottom - rootTaskBounds.top); 2171 } else if (bounds.top > (rootTaskBounds.bottom - overlapTB)) { 2172 verticalDiff = -(overlapTB - (rootTaskBounds.bottom - bounds.top)); 2173 } 2174 bounds.offset(horizontalDiff, verticalDiff); 2175 } 2176 shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds)2177 private boolean shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds) { 2178 if (!(isLeafTask() || mCreatedByOrganizer) || !canStartChangeTransition()) { 2179 return false; 2180 } 2181 final int newWinMode = getWindowingMode(); 2182 if (mTransitionController.inTransition(this)) { 2183 final Rect newBounds = getConfiguration().windowConfiguration.getBounds(); 2184 return prevWinMode != newWinMode || prevBounds.width() != newBounds.width() 2185 || prevBounds.height() != newBounds.height(); 2186 } 2187 // Only do an animation into and out-of freeform mode for now. Other mode 2188 // transition animations are currently handled by system-ui. 2189 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM); 2190 } 2191 2192 @Override migrateToNewSurfaceControl(SurfaceControl.Transaction t)2193 void migrateToNewSurfaceControl(SurfaceControl.Transaction t) { 2194 super.migrateToNewSurfaceControl(t); 2195 mLastSurfaceSize.x = 0; 2196 mLastSurfaceSize.y = 0; 2197 updateSurfaceSize(t); 2198 } 2199 updateSurfaceSize(SurfaceControl.Transaction transaction)2200 void updateSurfaceSize(SurfaceControl.Transaction transaction) { 2201 if (mSurfaceControl == null || isOrganized()) { 2202 return; 2203 } 2204 2205 // Apply crop to root tasks only and clear the crops of the descendant tasks. 2206 int width = 0; 2207 int height = 0; 2208 if (isRootTask()) { 2209 final Rect taskBounds = getBounds(); 2210 width = taskBounds.width(); 2211 height = taskBounds.height(); 2212 } 2213 if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) { 2214 return; 2215 } 2216 transaction.setWindowCrop(mSurfaceControl, width, height); 2217 mLastSurfaceSize.set(width, height); 2218 } 2219 2220 @VisibleForTesting getLastSurfaceSize()2221 Point getLastSurfaceSize() { 2222 return mLastSurfaceSize; 2223 } 2224 2225 @VisibleForTesting isInChangeTransition()2226 boolean isInChangeTransition() { 2227 return mSurfaceFreezer.hasLeash() || AppTransition.isChangeTransitOld(mTransit); 2228 } 2229 2230 @Override getFreezeSnapshotTarget()2231 public SurfaceControl getFreezeSnapshotTarget() { 2232 if (!mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CHANGE)) { 2233 return null; 2234 } 2235 // Skip creating snapshot if this transition is controlled by a remote animator which 2236 // doesn't need it. 2237 final ArraySet<Integer> activityTypes = new ArraySet<>(); 2238 activityTypes.add(getActivityType()); 2239 final RemoteAnimationAdapter adapter = 2240 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride( 2241 this, TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE, activityTypes); 2242 if (adapter != null && !adapter.getChangeNeedsSnapshot()) { 2243 return null; 2244 } 2245 return getSurfaceControl(); 2246 } 2247 2248 @Override writeIdentifierToProto(ProtoOutputStream proto, long fieldId)2249 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) { 2250 final long token = proto.start(fieldId); 2251 proto.write(HASH_CODE, System.identityHashCode(this)); 2252 proto.write(USER_ID, mUserId); 2253 proto.write(TITLE, intent != null && intent.getComponent() != null 2254 ? intent.getComponent().flattenToShortString() : "Task"); 2255 proto.end(token); 2256 } 2257 2258 /** 2259 * Saves launching state if necessary so that we can launch the activity to its latest state. 2260 */ saveLaunchingStateIfNeeded()2261 private void saveLaunchingStateIfNeeded() { 2262 saveLaunchingStateIfNeeded(getDisplayContent()); 2263 } 2264 saveLaunchingStateIfNeeded(DisplayContent display)2265 private void saveLaunchingStateIfNeeded(DisplayContent display) { 2266 if (!isLeafTask()) { 2267 return; 2268 } 2269 2270 if (!getHasBeenVisible()) { 2271 // Not ever visible to user. 2272 return; 2273 } 2274 2275 final int windowingMode = getWindowingMode(); 2276 if (windowingMode != WINDOWING_MODE_FULLSCREEN 2277 && windowingMode != WINDOWING_MODE_FREEFORM) { 2278 return; 2279 } 2280 2281 // Don't persist state if Task Display Area isn't in freeform mode. Then the task will be 2282 // launched back to its last state in a freeform Task Display Area when it's launched in a 2283 // freeform Task Display Area next time. 2284 if (getTaskDisplayArea() == null 2285 || getTaskDisplayArea().getWindowingMode() != WINDOWING_MODE_FREEFORM) { 2286 return; 2287 } 2288 2289 // Saves the new state so that we can launch the activity at the same location. 2290 mTaskSupervisor.mLaunchParamsPersister.saveTask(this, display); 2291 } 2292 updateOverrideConfigurationFromLaunchBounds()2293 Rect updateOverrideConfigurationFromLaunchBounds() { 2294 // If the task is controlled by another organized task, do not set override 2295 // configurations and let its parent (organized task) to control it; 2296 final Task rootTask = getRootTask(); 2297 final Rect bounds = rootTask != this && rootTask.isOrganized() ? null : getLaunchBounds(); 2298 setBounds(bounds); 2299 if (bounds != null && !bounds.isEmpty()) { 2300 // TODO: Review if we actually want to do this - we are setting the launch bounds 2301 // directly here. 2302 bounds.set(getRequestedOverrideBounds()); 2303 } 2304 return bounds; 2305 } 2306 2307 /** Returns the bounds that should be used to launch this task. */ getLaunchBounds()2308 Rect getLaunchBounds() { 2309 final Task rootTask = getRootTask(); 2310 if (rootTask == null) { 2311 return null; 2312 } 2313 2314 final int windowingMode = getWindowingMode(); 2315 if (!isActivityTypeStandardOrUndefined() 2316 || windowingMode == WINDOWING_MODE_FULLSCREEN) { 2317 return isResizeable() ? rootTask.getRequestedOverrideBounds() : null; 2318 } else if (!getWindowConfiguration().persistTaskBounds()) { 2319 return rootTask.getRequestedOverrideBounds(); 2320 } 2321 return mLastNonFullscreenBounds; 2322 } 2323 setRootProcess(WindowProcessController proc)2324 void setRootProcess(WindowProcessController proc) { 2325 clearRootProcess(); 2326 if (intent != null 2327 && (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) { 2328 mRootProcess = proc; 2329 mRootProcess.addRecentTask(this); 2330 } 2331 } 2332 clearRootProcess()2333 void clearRootProcess() { 2334 if (mRootProcess != null) { 2335 mRootProcess.removeRecentTask(this); 2336 mRootProcess = null; 2337 } 2338 } 2339 2340 /** @return Id of root task. */ getRootTaskId()2341 int getRootTaskId() { 2342 return getRootTask().mTaskId; 2343 } 2344 2345 /** @return the first organized task. */ 2346 @Nullable getOrganizedTask()2347 Task getOrganizedTask() { 2348 if (isOrganized()) { 2349 return this; 2350 } 2351 final WindowContainer parent = getParent(); 2352 if (parent == null) { 2353 return null; 2354 } 2355 final Task parentTask = parent.asTask(); 2356 return parentTask == null ? null : parentTask.getOrganizedTask(); 2357 } 2358 2359 /** @return the first create-by-organizer task. */ 2360 @Nullable getCreatedByOrganizerTask()2361 Task getCreatedByOrganizerTask() { 2362 if (mCreatedByOrganizer) { 2363 return this; 2364 } 2365 final WindowContainer parent = getParent(); 2366 if (parent == null) { 2367 return null; 2368 } 2369 final Task parentTask = parent.asTask(); 2370 return parentTask == null ? null : parentTask.getCreatedByOrganizerTask(); 2371 } 2372 2373 /** @return the first adjacent task of this task or its parent. */ 2374 @Nullable getAdjacentTask()2375 Task getAdjacentTask() { 2376 final TaskFragment adjacentTaskFragment = getAdjacentTaskFragment(); 2377 if (adjacentTaskFragment != null && adjacentTaskFragment.asTask() != null) { 2378 return adjacentTaskFragment.asTask(); 2379 } 2380 2381 final WindowContainer parent = getParent(); 2382 if (parent == null || parent.asTask() == null) { 2383 return null; 2384 } 2385 2386 return parent.asTask().getAdjacentTask(); 2387 } 2388 2389 // TODO(task-merge): Figure out what's the right thing to do for places that used it. isRootTask()2390 boolean isRootTask() { 2391 return getRootTask() == this; 2392 } 2393 isLeafTask()2394 boolean isLeafTask() { 2395 for (int i = mChildren.size() - 1; i >= 0; --i) { 2396 if (mChildren.get(i).asTask() != null) { 2397 return false; 2398 } 2399 } 2400 return true; 2401 } 2402 2403 /** Return the top-most leaf-task under this one, or this task if it is a leaf. */ getTopLeafTask()2404 public Task getTopLeafTask() { 2405 for (int i = mChildren.size() - 1; i >= 0; --i) { 2406 final Task child = mChildren.get(i).asTask(); 2407 if (child == null) continue; 2408 return child.getTopLeafTask(); 2409 } 2410 return this; 2411 } 2412 getDescendantTaskCount()2413 int getDescendantTaskCount() { 2414 final int[] currentCount = {0}; 2415 forAllLeafTasks(t -> currentCount[0]++, false /* traverseTopToBottom */); 2416 return currentCount[0]; 2417 } 2418 2419 /** 2420 * Find next proper focusable root task and make it focused. 2421 * @return The root task that now got the focus, {@code null} if none found. 2422 */ adjustFocusToNextFocusableTask(String reason)2423 Task adjustFocusToNextFocusableTask(String reason) { 2424 return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */, 2425 true /* moveDisplayToTop */); 2426 } 2427 2428 /** Return the next focusable task by looking from the siblings and parent tasks */ getNextFocusableTask(boolean allowFocusSelf)2429 private Task getNextFocusableTask(boolean allowFocusSelf) { 2430 final WindowContainer parent = getParent(); 2431 if (parent == null) { 2432 return null; 2433 } 2434 2435 final Task focusableTask = parent.getTask((task) -> (allowFocusSelf || task != this) 2436 && ((Task) task).isFocusableAndVisible()); 2437 if (focusableTask == null && parent.asTask() != null) { 2438 return parent.asTask().getNextFocusableTask(allowFocusSelf); 2439 } else { 2440 return focusableTask; 2441 } 2442 } 2443 2444 /** 2445 * Find next proper focusable task and make it focused. 2446 * @param reason The reason of making the adjustment. 2447 * @param allowFocusSelf Is the focus allowed to remain on the same task. 2448 * @param moveDisplayToTop Whether to move display to top while making the task focused. 2449 * @return The root task that now got the focus, {@code null} if none found. 2450 */ adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf, boolean moveDisplayToTop)2451 Task adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf, 2452 boolean moveDisplayToTop) { 2453 Task focusableTask = getNextFocusableTask(allowFocusSelf); 2454 if (focusableTask == null) { 2455 focusableTask = mRootWindowContainer.getNextFocusableRootTask(this, !allowFocusSelf); 2456 } 2457 if (focusableTask == null) { 2458 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 2459 if (taskDisplayArea != null) { 2460 // Clear the recorded task since there is no next focusable task. 2461 taskDisplayArea.clearPreferredTopFocusableRootTask(); 2462 } 2463 return null; 2464 } 2465 2466 final Task rootTask = focusableTask.getRootTask(); 2467 if (!moveDisplayToTop) { 2468 // There may be multiple task layers above this task, so when relocating the task to the 2469 // top, we should move this task and each of its parent task that below display area to 2470 // the top of each layer. 2471 WindowContainer parent = focusableTask.getParent(); 2472 WindowContainer next = focusableTask; 2473 do { 2474 parent.positionChildAt(POSITION_TOP, next, false /* includingParents */); 2475 next = parent; 2476 parent = next.getParent(); 2477 } while (next.asTask() != null && parent != null); 2478 return rootTask; 2479 } 2480 2481 final String myReason = reason + " adjustFocusToNextFocusableTask"; 2482 final ActivityRecord top = focusableTask.topRunningActivity(); 2483 if (focusableTask.isActivityTypeHome() && (top == null || !top.isVisibleRequested())) { 2484 // If we will be focusing on the root home task next and its current top activity isn't 2485 // visible, then use the move the root home task to top to make the activity visible. 2486 focusableTask.getDisplayArea().moveHomeActivityToTop(myReason); 2487 return rootTask; 2488 } 2489 2490 // Move the entire hierarchy to top with updating global top resumed activity 2491 // and focused application if needed. 2492 focusableTask.moveToFront(myReason); 2493 // Top display focused root task is changed, update top resumed activity if needed. 2494 if (rootTask.getTopResumedActivity() != null) { 2495 mTaskSupervisor.updateTopResumedActivityIfNeeded(reason); 2496 } 2497 return rootTask; 2498 } 2499 2500 /** Calculate the minimum possible position for a task that can be shown to the user. 2501 * The minimum position will be above all other tasks that can't be shown. 2502 * @param minPosition The minimum position the caller is suggesting. 2503 * We will start adjusting up from here. 2504 * @param size The size of the current task list. 2505 */ 2506 // TODO: Move user to their own window container. computeMinUserPosition(int minPosition, int size)2507 private int computeMinUserPosition(int minPosition, int size) { 2508 while (minPosition < size) { 2509 final WindowContainer child = mChildren.get(minPosition); 2510 final boolean canShow = child.showToCurrentUser(); 2511 if (canShow) { 2512 break; 2513 } 2514 minPosition++; 2515 } 2516 return minPosition; 2517 } 2518 2519 /** Calculate the maximum possible position for a task that can't be shown to the user. 2520 * The maximum position will be below all other tasks that can be shown. 2521 * @param maxPosition The maximum position the caller is suggesting. 2522 * We will start adjusting down from here. 2523 */ 2524 // TODO: Move user to their own window container. computeMaxUserPosition(int maxPosition)2525 private int computeMaxUserPosition(int maxPosition) { 2526 while (maxPosition > 0) { 2527 final WindowContainer child = mChildren.get(maxPosition); 2528 final boolean canShow = child.showToCurrentUser(); 2529 if (!canShow) { 2530 break; 2531 } 2532 maxPosition--; 2533 } 2534 return maxPosition; 2535 } 2536 getAdjustedChildPosition(WindowContainer wc, int suggestedPosition)2537 private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) { 2538 final boolean canShowChild = wc.showToCurrentUser(); 2539 2540 final int size = mChildren.size(); 2541 2542 // Figure-out min/max possible position depending on if child can show for current user. 2543 int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0; 2544 int maxPosition = minPosition; 2545 if (size > 0) { 2546 maxPosition = (canShowChild) ? size - 1 : computeMaxUserPosition(size - 1); 2547 } 2548 2549 // Factor in always-on-top children in max possible position. 2550 if (!wc.isAlwaysOnTop()) { 2551 // We want to place all non-always-on-top containers below always-on-top ones. 2552 while (maxPosition > minPosition) { 2553 if (!mChildren.get(maxPosition).isAlwaysOnTop()) break; 2554 --maxPosition; 2555 } 2556 } 2557 2558 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid. 2559 if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) { 2560 return POSITION_BOTTOM; 2561 } else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) { 2562 return POSITION_TOP; 2563 } 2564 2565 // Increase the maxPosition because children size will grow once wc is added. 2566 if (!hasChild(wc)) { 2567 ++maxPosition; 2568 } 2569 2570 // Reset position based on minimum/maximum possible positions. 2571 return Math.min(Math.max(suggestedPosition, minPosition), maxPosition); 2572 } 2573 2574 @Override positionChildAt(int position, WindowContainer child, boolean includingParents)2575 void positionChildAt(int position, WindowContainer child, boolean includingParents) { 2576 final boolean toTop = position >= (mChildren.size() - 1); 2577 position = getAdjustedChildPosition(child, position); 2578 super.positionChildAt(position, child, includingParents); 2579 2580 // Log positioning. 2581 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child 2582 + " position=" + position + " parent=" + this); 2583 2584 final Task task = child.asTask(); 2585 if (task != null) { 2586 task.updateTaskMovement(toTop, position == POSITION_BOTTOM, position); 2587 } 2588 } 2589 2590 @Override removeImmediately()2591 void removeImmediately() { 2592 removeImmediately("removeTask"); 2593 } 2594 2595 @Override removeImmediately(String reason)2596 void removeImmediately(String reason) { 2597 if (DEBUG_ROOT_TASK) Slog.i(TAG, "removeTask:" + reason + " removing taskId=" + mTaskId); 2598 if (mRemoving) { 2599 return; 2600 } 2601 mRemoving = true; 2602 2603 EventLogTags.writeWmTaskRemoved(mTaskId, getRootTaskId(), getDisplayId(), reason); 2604 clearPinnedTaskIfNeed(); 2605 if (mChildPipActivity != null) { 2606 mChildPipActivity.clearLastParentBeforePip(); 2607 } 2608 // If applicable let the TaskOrganizer know the Task is vanishing. 2609 setTaskOrganizer(null); 2610 2611 super.removeImmediately(); 2612 mRemoving = false; 2613 } 2614 2615 // TODO: Consolidate this with Task.reparent() reparent(Task rootTask, int position, boolean moveParents, String reason)2616 void reparent(Task rootTask, int position, boolean moveParents, String reason) { 2617 if (DEBUG_ROOT_TASK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId 2618 + " from rootTask=" + getRootTask()); 2619 EventLogTags.writeWmTaskRemoved(mTaskId, getRootTaskId(), getDisplayId(), 2620 "reParentTask:" + reason); 2621 2622 reparent(rootTask, position); 2623 2624 rootTask.positionChildAt(position, this, moveParents); 2625 } 2626 setBounds(Rect bounds, boolean forceResize)2627 public int setBounds(Rect bounds, boolean forceResize) { 2628 final int boundsChanged = setBounds(bounds); 2629 2630 if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) { 2631 onResize(); 2632 return BOUNDS_CHANGE_SIZE | boundsChanged; 2633 } 2634 2635 return boundsChanged; 2636 } 2637 2638 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */ 2639 @Override setBounds(Rect bounds)2640 public int setBounds(Rect bounds) { 2641 if (isRootTask()) { 2642 return setBounds(getRequestedOverrideBounds(), bounds); 2643 } 2644 2645 int rotation = Surface.ROTATION_0; 2646 final DisplayContent displayContent = getRootTask() != null 2647 ? getRootTask().getDisplayContent() : null; 2648 if (displayContent != null) { 2649 rotation = displayContent.getDisplayInfo().rotation; 2650 } 2651 2652 final int boundsChange = super.setBounds(bounds); 2653 mRotation = rotation; 2654 updateSurfacePositionNonOrganized(); 2655 return boundsChange; 2656 } 2657 2658 /** Sets the requested bounds regardless of the windowing mode. */ setBoundsUnchecked(@onNull Rect bounds)2659 int setBoundsUnchecked(@NonNull Rect bounds) { 2660 final int boundsChange = super.setBounds(bounds); 2661 updateSurfaceBounds(); 2662 return boundsChange; 2663 } 2664 2665 @Override isCompatible(int windowingMode, int activityType)2666 public boolean isCompatible(int windowingMode, int activityType) { 2667 // TODO: Should we just move this to ConfigurationContainer? 2668 if (activityType == ACTIVITY_TYPE_UNDEFINED) { 2669 // Undefined activity types end up in a standard root task once the root task is 2670 // created on a display, so they should be considered compatible. 2671 activityType = ACTIVITY_TYPE_STANDARD; 2672 } 2673 return super.isCompatible(windowingMode, activityType); 2674 } 2675 2676 @Override onDescendantOrientationChanged(WindowContainer requestingContainer)2677 public boolean onDescendantOrientationChanged(WindowContainer requestingContainer) { 2678 if (super.onDescendantOrientationChanged(requestingContainer)) { 2679 return true; 2680 } 2681 2682 // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill 2683 // it if possible. 2684 if (getParent() != null) { 2685 onConfigurationChanged(getParent().getConfiguration()); 2686 return true; 2687 } 2688 return false; 2689 } 2690 2691 @Override handlesOrientationChangeFromDescendant(@creenOrientation int orientation)2692 boolean handlesOrientationChangeFromDescendant(@ScreenOrientation int orientation) { 2693 if (!super.handlesOrientationChangeFromDescendant(orientation)) { 2694 return false; 2695 } 2696 2697 // At task level, we want to check canSpecifyOrientation() based on the top activity type. 2698 // Do this only on leaf Task, so that the result is not affecting by the sibling leaf Task. 2699 // Otherwise, root Task will use the result from the top leaf Task, and all its child 2700 // leaf Tasks will rely on that from super.handlesOrientationChangeFromDescendant(). 2701 if (!isLeafTask()) { 2702 return true; 2703 } 2704 2705 // Check for leaf Task. 2706 // Display won't rotate for the orientation request if the Task/TaskDisplayArea 2707 // can't specify orientation. 2708 return canSpecifyOrientation() && getDisplayArea().canSpecifyOrientation(orientation); 2709 } 2710 2711 @Override onDisplayChanged(DisplayContent dc)2712 void onDisplayChanged(DisplayContent dc) { 2713 final boolean isRootTask = isRootTask(); 2714 if (!isRootTask && !mCreatedByOrganizer) { 2715 adjustBoundsForDisplayChangeIfNeeded(dc); 2716 } 2717 super.onDisplayChanged(dc); 2718 if (isLeafTask()) { 2719 final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY; 2720 mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged( 2721 mTaskId, displayId); 2722 } 2723 if (isRootTask()) { 2724 updateSurfaceBounds(); 2725 } 2726 sendTaskFragmentParentInfoChangedIfNeeded(); 2727 } 2728 isResizeable()2729 boolean isResizeable() { 2730 return isResizeable(/* checkPictureInPictureSupport */ true); 2731 } 2732 isResizeable(boolean checkPictureInPictureSupport)2733 boolean isResizeable(boolean checkPictureInPictureSupport) { 2734 final boolean forceResizable = mAtmService.mForceResizableActivities 2735 && getActivityType() == ACTIVITY_TYPE_STANDARD; 2736 return forceResizable || ActivityInfo.isResizeableMode(mResizeMode) 2737 || (mSupportsPictureInPicture && checkPictureInPictureSupport); 2738 } 2739 2740 /** 2741 * Tests if the orientation should be preserved upon user interactive resizig operations. 2742 2743 * @return true if orientation should not get changed upon resizing operation. 2744 */ preserveOrientationOnResize()2745 boolean preserveOrientationOnResize() { 2746 return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY 2747 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY 2748 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; 2749 } 2750 cropWindowsToRootTaskBounds()2751 boolean cropWindowsToRootTaskBounds() { 2752 // Don't crop HOME/RECENTS windows to root task bounds. This is because in split-screen 2753 // they extend past their root task and sysui uses the root task surface to control 2754 // cropping. 2755 // TODO(b/158242495): get rid of this when drag/drop can use surface bounds. 2756 if (isActivityTypeHomeOrRecents()) { 2757 // Make sure this is the top-most non-organizer root task (if not top-most, it means 2758 // another translucent task could be above this, so this needs to stay cropped. 2759 final Task rootTask = getRootTask(); 2760 final Task topNonOrgTask = 2761 rootTask.mCreatedByOrganizer ? rootTask.getTopMostTask() : rootTask; 2762 if (this == topNonOrgTask || isDescendantOf(topNonOrgTask)) { 2763 return false; 2764 } 2765 } 2766 return isResizeable(); 2767 } 2768 2769 @Override getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, Rect outSurfaceInsets)2770 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, 2771 Rect outSurfaceInsets) { 2772 // If this task has its adjacent task, it means they should animate together. Use display 2773 // bounds for them could move same as full screen task. 2774 if (getAdjacentTask() != null) { 2775 super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); 2776 return; 2777 } 2778 2779 final WindowState windowState = getTopVisibleAppMainWindow(); 2780 if (windowState != null) { 2781 windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); 2782 } else { 2783 super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); 2784 } 2785 } 2786 2787 /** 2788 * Calculate the maximum visible area of this task. If the task has only one app, 2789 * the result will be visible frame of that app. If the task has more than one apps, 2790 * we search from top down if the next app got different visible area. 2791 * 2792 * This effort is to handle the case where some task (eg. GMail composer) might pop up 2793 * a dialog that's different in size from the activity below, in which case we should 2794 * be dimming the entire task area behind the dialog. 2795 * 2796 * @param out the union of visible bounds. 2797 */ getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop)2798 private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) { 2799 // skip hidden (or about to hide) apps 2800 if (token.mIsExiting || !token.isClientVisible() || !token.isVisibleRequested()) { 2801 return; 2802 } 2803 final WindowState win = token.findMainWindow(); 2804 if (win == null) { 2805 return; 2806 } 2807 if (!foundTop[0]) { 2808 foundTop[0] = true; 2809 out.setEmpty(); 2810 } 2811 2812 final Rect visibleFrame = sTmpBounds; 2813 final WindowManager.LayoutParams attrs = win.mAttrs; 2814 visibleFrame.set(win.getFrame()); 2815 visibleFrame.inset(win.getInsetsStateWithVisibilityOverride().calculateVisibleInsets( 2816 visibleFrame, attrs.type, win.getActivityType(), attrs.softInputMode, 2817 attrs.flags)); 2818 out.union(visibleFrame); 2819 } 2820 2821 /** Bounds of the task to be used for dimming, as well as touch related tests. */ getDimBounds(Rect out)2822 void getDimBounds(Rect out) { 2823 if (isRootTask()) { 2824 getBounds(out); 2825 return; 2826 } 2827 2828 final Task rootTask = getRootTask(); 2829 if (inFreeformWindowingMode()) { 2830 boolean[] foundTop = { false }; 2831 forAllActivities(a -> { getMaxVisibleBounds(a, out, foundTop); }); 2832 if (foundTop[0]) { 2833 return; 2834 } 2835 } 2836 2837 if (!matchParentBounds()) { 2838 // When minimizing the root docked task when going home, we don't adjust the task bounds 2839 // so we need to intersect the task bounds with the root task bounds here.. 2840 rootTask.getBounds(mTmpRect); 2841 mTmpRect.intersect(getBounds()); 2842 out.set(mTmpRect); 2843 } else { 2844 out.set(getBounds()); 2845 } 2846 return; 2847 } 2848 2849 /** 2850 * Account for specified insets to crop the animation bounds by to avoid the animation 2851 * occurring over "out of bounds" regions 2852 * 2853 * For example this is used to make sure the tasks are cropped to be fully above the expanded 2854 * taskbar when animating. 2855 * 2856 * TEMPORARY FIELD (b/202383002) 2857 * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays 2858 * or when shell transitions are fully enabled 2859 * 2860 * @param animationBounds The animation bounds to adjust to account for the custom spec insets. 2861 */ adjustAnimationBoundsForTransition(Rect animationBounds)2862 void adjustAnimationBoundsForTransition(Rect animationBounds) { 2863 TaskTransitionSpec spec = mWmService.mTaskTransitionSpec; 2864 if (spec != null) { 2865 final InsetsState state = 2866 getDisplayContent().getInsetsStateController().getRawInsetsState(); 2867 for (int i = state.sourceSize() - 1; i >= 0; i--) { 2868 final InsetsSource source = state.sourceAt(i); 2869 if (source.hasFlags(FLAG_INSETS_ROUNDED_CORNER)) { 2870 animationBounds.inset(source.calculateVisibleInsets(animationBounds)); 2871 } 2872 } 2873 } 2874 } 2875 setDragResizing(boolean dragResizing)2876 void setDragResizing(boolean dragResizing) { 2877 if (mDragResizing != dragResizing) { 2878 // No need to check if allowed if it's leaving dragResize 2879 if (dragResizing 2880 && !(getRootTask().getWindowingMode() == WINDOWING_MODE_FREEFORM)) { 2881 Slog.e(TAG, "Drag resize isn't allowed for root task id=" + getRootTaskId()); 2882 return; 2883 } 2884 mDragResizing = dragResizing; 2885 resetDragResizingChangeReported(); 2886 } 2887 } 2888 isDragResizing()2889 boolean isDragResizing() { 2890 return mDragResizing; 2891 } 2892 adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent)2893 void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) { 2894 if (displayContent == null) { 2895 return; 2896 } 2897 if (getRequestedOverrideBounds().isEmpty()) { 2898 return; 2899 } 2900 final int displayId = displayContent.getDisplayId(); 2901 final int newRotation = displayContent.getDisplayInfo().rotation; 2902 if (displayId != mLastRotationDisplayId) { 2903 // This task is on a display that it wasn't on. There is no point to keep the relative 2904 // position if display rotations for old and new displays are different. Just keep these 2905 // values. 2906 mLastRotationDisplayId = displayId; 2907 mRotation = newRotation; 2908 return; 2909 } 2910 2911 if (mRotation == newRotation) { 2912 // Rotation didn't change. We don't need to adjust the bounds to keep the relative 2913 // position. 2914 return; 2915 } 2916 2917 // Device rotation changed. 2918 // - We don't want the task to move around on the screen when this happens, so update the 2919 // task bounds so it stays in the same place. 2920 // - Rotate the bounds and notify activity manager if the task can be resized independently 2921 // from its root task. The root task will take care of task rotation for the other case. 2922 mTmpRect2.set(getBounds()); 2923 2924 if (!getWindowConfiguration().canResizeTask()) { 2925 setBounds(mTmpRect2); 2926 return; 2927 } 2928 2929 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2); 2930 if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) { 2931 mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION); 2932 } 2933 } 2934 2935 /** Cancels any running app transitions associated with the task. */ cancelTaskWindowTransition()2936 void cancelTaskWindowTransition() { 2937 for (int i = mChildren.size() - 1; i >= 0; --i) { 2938 mChildren.get(i).cancelAnimation(); 2939 } 2940 } 2941 showForAllUsers()2942 boolean showForAllUsers() { 2943 if (mChildren.isEmpty()) return false; 2944 final ActivityRecord r = getTopNonFinishingActivity(); 2945 return r != null && r.mShowForAllUsers; 2946 } 2947 2948 @Override showToCurrentUser()2949 boolean showToCurrentUser() { 2950 return mForceShowForAllUsers || showForAllUsers() 2951 || mWmService.isUserVisible(getTopMostTask().mUserId); 2952 } 2953 setForceShowForAllUsers(boolean forceShowForAllUsers)2954 void setForceShowForAllUsers(boolean forceShowForAllUsers) { 2955 mForceShowForAllUsers = forceShowForAllUsers; 2956 } 2957 2958 /** Returns the top-most activity that occludes the given one, or {@code null} if none. */ 2959 @Nullable getOccludingActivityAbove(ActivityRecord activity)2960 ActivityRecord getOccludingActivityAbove(ActivityRecord activity) { 2961 final ActivityRecord top = getActivity(r -> { 2962 if (r == activity) { 2963 // Reached the given activity, return the activity to stop searching. 2964 return true; 2965 } 2966 2967 if (!r.occludesParent()) { 2968 return false; 2969 } 2970 2971 TaskFragment parent = r.getTaskFragment(); 2972 if (parent == activity.getTaskFragment()) { 2973 // Found it. This activity on top of the given activity on the same TaskFragment. 2974 return true; 2975 } 2976 if (parent != null && parent.asTask() != null) { 2977 // Found it. This activity is the direct child of a leaf Task. 2978 return true; 2979 } 2980 // The candidate activity is being embedded. Checking if the bounds of the containing 2981 // TaskFragment equals to the outer TaskFragment. 2982 TaskFragment grandParent = parent.getParent().asTaskFragment(); 2983 while (grandParent != null) { 2984 if (!parent.getBounds().equals(grandParent.getBounds())) { 2985 // Not occluding the grandparent. 2986 break; 2987 } 2988 if (grandParent.asTask() != null) { 2989 // Found it. The activity occludes its parent TaskFragment and the parent 2990 // TaskFragment also occludes its parent all the way up. 2991 return true; 2992 } 2993 parent = grandParent; 2994 grandParent = parent.getParent().asTaskFragment(); 2995 } 2996 return false; 2997 }); 2998 return top != activity ? top : null; 2999 } 3000 3001 @Override makeAnimationLeash()3002 public SurfaceControl.Builder makeAnimationLeash() { 3003 return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId); 3004 } 3005 shouldAnimate()3006 boolean shouldAnimate() { 3007 /** 3008 * Animations are handled by the TaskOrganizer implementation. 3009 */ 3010 if (isOrganized()) { 3011 return false; 3012 } 3013 // Don't animate while the task runs recents animation but only if we are in the mode 3014 // where we cancel with deferred screenshot, which means that the controller has 3015 // transformed the task. 3016 final RecentsAnimationController controller = mWmService.getRecentsAnimationController(); 3017 if (controller != null && controller.isAnimatingTask(this) 3018 && controller.shouldDeferCancelUntilNextTransition()) { 3019 return false; 3020 } 3021 return true; 3022 } 3023 3024 @Override setInitialSurfaceControlProperties(SurfaceControl.Builder b)3025 void setInitialSurfaceControlProperties(SurfaceControl.Builder b) { 3026 b.setEffectLayer().setMetadata(METADATA_TASK_ID, mTaskId); 3027 super.setInitialSurfaceControlProperties(b); 3028 } 3029 3030 /** Checking if self or its child tasks are animated by recents animation. */ isAnimatingByRecents()3031 boolean isAnimatingByRecents() { 3032 return isAnimating(CHILDREN, ANIMATION_TYPE_RECENTS) 3033 || mTransitionController.isTransientHide(this); 3034 } 3035 getTopVisibleAppMainWindow()3036 WindowState getTopVisibleAppMainWindow() { 3037 final ActivityRecord activity = getTopVisibleActivity(); 3038 return activity != null ? activity.findMainWindow() : null; 3039 } 3040 topRunningNonDelayedActivityLocked(ActivityRecord notTop)3041 ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) { 3042 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunningNonDelayed 3043 , PooledLambda.__(ActivityRecord.class), notTop); 3044 final ActivityRecord r = getActivity(p); 3045 p.recycle(); 3046 return r; 3047 } 3048 isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop)3049 private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) { 3050 return !r.delayedResume && r != notTop && r.canBeTopRunning(); 3051 } 3052 3053 /** 3054 * This is a simplified version of topRunningActivity that provides a number of 3055 * optional skip-over modes. It is intended for use with the ActivityController hook only. 3056 * 3057 * @param token If non-null, any history records matching this token will be skipped. 3058 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID. 3059 * 3060 * @return Returns the HistoryRecord of the next activity on the root task. 3061 */ topRunningActivity(IBinder token, int taskId)3062 ActivityRecord topRunningActivity(IBinder token, int taskId) { 3063 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunning, 3064 PooledLambda.__(ActivityRecord.class), taskId, token); 3065 final ActivityRecord r = getActivity(p); 3066 p.recycle(); 3067 return r; 3068 } 3069 isTopRunning(ActivityRecord r, int taskId, IBinder notTop)3070 private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) { 3071 return r.getTask().mTaskId != taskId && r.token != notTop && r.canBeTopRunning(); 3072 } 3073 getTopFullscreenActivity()3074 ActivityRecord getTopFullscreenActivity() { 3075 return getActivity((r) -> { 3076 final WindowState win = r.findMainWindow(); 3077 return (win != null && win.mAttrs.isFullscreen()); 3078 }); 3079 } 3080 3081 /** 3082 * Return the top visible requested activity. The activity has been requested to be visible, 3083 * but it's possible that the activity has just been created, so no window is yet attached to 3084 * this activity. 3085 */ getTopVisibleActivity()3086 ActivityRecord getTopVisibleActivity() { 3087 return getActivity((r) -> !r.mIsExiting && r.isClientVisible() && r.isVisibleRequested()); 3088 } 3089 3090 /** 3091 * Return the top visible activity. The activity has a window on which contents are drawn. 3092 * However it's possible that the activity has already been requested to be invisible, but the 3093 * visibility is not yet committed. 3094 */ getTopRealVisibleActivity()3095 ActivityRecord getTopRealVisibleActivity() { 3096 return getActivity((r) -> !r.mIsExiting && r.isClientVisible() && r.isVisible()); 3097 } 3098 getTopWaitSplashScreenActivity()3099 ActivityRecord getTopWaitSplashScreenActivity() { 3100 return getActivity((r) -> { 3101 return r.mHandleExitSplashScreen 3102 && r.mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_COPYING; 3103 }); 3104 } 3105 3106 void setTaskDescription(TaskDescription taskDescription) { 3107 mTaskDescription = taskDescription; 3108 } 3109 3110 void onSnapshotChanged(TaskSnapshot snapshot) { 3111 mLastTaskSnapshotData.set(snapshot); 3112 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged( 3113 mTaskId, snapshot); 3114 } 3115 3116 TaskDescription getTaskDescription() { 3117 return mTaskDescription; 3118 } 3119 3120 @Override 3121 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) { 3122 final int count = mChildren.size(); 3123 boolean isLeafTask = true; 3124 if (traverseTopToBottom) { 3125 for (int i = count - 1; i >= 0; --i) { 3126 final Task child = mChildren.get(i).asTask(); 3127 if (child != null) { 3128 isLeafTask = false; 3129 child.forAllLeafTasks(callback, traverseTopToBottom); 3130 } 3131 } 3132 } else { 3133 for (int i = 0; i < count; i++) { 3134 final Task child = mChildren.get(i).asTask(); 3135 if (child != null) { 3136 isLeafTask = false; 3137 child.forAllLeafTasks(callback, traverseTopToBottom); 3138 } 3139 } 3140 } 3141 if (isLeafTask) callback.accept(this); 3142 } 3143 3144 @Override 3145 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) { 3146 super.forAllTasks(callback, traverseTopToBottom); 3147 callback.accept(this); 3148 } 3149 3150 @Override 3151 void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) { 3152 if (isRootTask()) { 3153 callback.accept(this); 3154 } 3155 } 3156 3157 @Override 3158 boolean forAllTasks(Predicate<Task> callback) { 3159 if (super.forAllTasks(callback)) return true; 3160 return callback.test(this); 3161 } 3162 3163 @Override 3164 boolean forAllLeafTasks(Predicate<Task> callback) { 3165 boolean isLeafTask = true; 3166 for (int i = mChildren.size() - 1; i >= 0; --i) { 3167 final Task child = mChildren.get(i).asTask(); 3168 if (child != null) { 3169 isLeafTask = false; 3170 if (child.forAllLeafTasks(callback)) { 3171 return true; 3172 } 3173 } 3174 } 3175 if (isLeafTask) { 3176 return callback.test(this); 3177 } 3178 return false; 3179 } 3180 3181 /** Iterates through all leaf task fragments and the leaf tasks. */ 3182 void forAllLeafTasksAndLeafTaskFragments(final Consumer<TaskFragment> callback, 3183 boolean traverseTopToBottom) { 3184 forAllLeafTasks(task -> { 3185 if (task.isLeafTaskFragment()) { 3186 callback.accept(task); 3187 return; 3188 } 3189 3190 // A leaf task that may contains both activities and task fragments. 3191 boolean consumed = false; 3192 if (traverseTopToBottom) { 3193 for (int i = task.mChildren.size() - 1; i >= 0; --i) { 3194 final WindowContainer child = task.mChildren.get(i); 3195 if (child.asTaskFragment() != null) { 3196 child.forAllLeafTaskFragments(callback, traverseTopToBottom); 3197 } else if (child.asActivityRecord() != null && !consumed) { 3198 callback.accept(task); 3199 consumed = true; 3200 } 3201 } 3202 } else { 3203 for (int i = 0; i < task.mChildren.size(); i++) { 3204 final WindowContainer child = task.mChildren.get(i); 3205 if (child.asTaskFragment() != null) { 3206 child.forAllLeafTaskFragments(callback, traverseTopToBottom); 3207 } else if (child.asActivityRecord() != null && !consumed) { 3208 callback.accept(task); 3209 consumed = true; 3210 } 3211 } 3212 } 3213 }, traverseTopToBottom); 3214 } 3215 3216 @Override 3217 boolean forAllRootTasks(Predicate<Task> callback, boolean traverseTopToBottom) { 3218 return isRootTask() ? callback.test(this) : false; 3219 } 3220 3221 @Override 3222 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) { 3223 final Task t = super.getTask(callback, traverseTopToBottom); 3224 if (t != null) return t; 3225 return callback.test(this) ? this : null; 3226 } 3227 3228 @Nullable 3229 @Override 3230 Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) { 3231 return isRootTask() && callback.test(this) ? this : null; 3232 } 3233 3234 /** 3235 * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI 3236 * flags. See {@link WindowState#canAffectSystemUiFlags()}. 3237 */ 3238 void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) { 3239 mCanAffectSystemUiFlags = canAffectSystemUiFlags; 3240 } 3241 3242 /** 3243 * @see #setCanAffectSystemUiFlags 3244 */ 3245 boolean canAffectSystemUiFlags() { 3246 return mCanAffectSystemUiFlags; 3247 } 3248 3249 void dontAnimateDimExit() { 3250 mDimmer.dontAnimateExit(); 3251 } 3252 3253 String getName() { 3254 return "Task=" + mTaskId; 3255 } 3256 3257 @Override 3258 Dimmer getDimmer() { 3259 // If the window is in multi-window mode, we want to dim at the Task level to ensure the dim 3260 // bounds match the area the app lives in 3261 if (inMultiWindowMode()) { 3262 return mDimmer; 3263 } 3264 3265 // If we're not at the root task level, we want to keep traversing through the parents to 3266 // find the root. 3267 // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}. 3268 // If true, we want to get the Dimmer from the level above since we don't want to animate 3269 // the dim with the Task. 3270 if (!isRootTask() || isTranslucent(null)) { 3271 return super.getDimmer(); 3272 } 3273 3274 return mDimmer; 3275 } 3276 3277 @Override 3278 void prepareSurfaces() { 3279 mDimmer.resetDimStates(); 3280 super.prepareSurfaces(); 3281 3282 final Rect dimBounds = mDimmer.getDimBounds(); 3283 if (dimBounds != null) { 3284 getDimBounds(dimBounds); 3285 3286 // Bounds need to be relative, as the dim layer is a child. 3287 if (inFreeformWindowingMode()) { 3288 getBounds(mTmpRect); 3289 dimBounds.offsetTo(dimBounds.left - mTmpRect.left, dimBounds.top - mTmpRect.top); 3290 } else { 3291 dimBounds.offsetTo(0, 0); 3292 } 3293 } 3294 3295 final SurfaceControl.Transaction t = getSyncTransaction(); 3296 3297 if (dimBounds != null && mDimmer.updateDims(t)) { 3298 scheduleAnimation(); 3299 } 3300 3301 // Let organizer manage task visibility for shell transition. So don't change it's 3302 // visibility during collecting. 3303 if (mTransitionController.isCollecting() && mCreatedByOrganizer) { 3304 return; 3305 } 3306 3307 // We intend to let organizer manage task visibility but it doesn't 3308 // have enough information until we finish shell transitions. 3309 // In the mean time we do an easy fix here. 3310 final boolean visible = isVisible(); 3311 final boolean show = visible || isAnimating(TRANSITION | PARENTS | CHILDREN); 3312 if (mSurfaceControl != null) { 3313 if (show != mLastSurfaceShowing) { 3314 t.setVisibility(mSurfaceControl, show); 3315 } 3316 } 3317 // Only show the overlay if the task has other visible children 3318 if (mOverlayHost != null) { 3319 mOverlayHost.setVisibility(t, visible); 3320 } 3321 mLastSurfaceShowing = show; 3322 } 3323 3324 @Override 3325 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter, 3326 @TransitionOldType int transit, boolean isVoiceInteraction, 3327 @Nullable ArrayList<WindowContainer> sources) { 3328 final RecentsAnimationController control = mWmService.getRecentsAnimationController(); 3329 if (control != null) { 3330 // We let the transition to be controlled by RecentsAnimation, and callback task's 3331 // RemoteAnimationTarget for remote runner to animate. 3332 if (enter && !isActivityTypeHomeOrRecents()) { 3333 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, 3334 "applyAnimationUnchecked, control: %s, task: %s, transit: %s", 3335 control, asTask(), AppTransition.appTransitionOldToString(transit)); 3336 final int size = sources != null ? sources.size() : 0; 3337 control.addTaskToTargets(this, (type, anim) -> { 3338 for (int i = 0; i < size; ++i) { 3339 sources.get(i).onAnimationFinished(type, anim); 3340 } 3341 }); 3342 } 3343 } else { 3344 super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources); 3345 } 3346 } 3347 3348 @Override 3349 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 3350 super.dump(pw, prefix, dumpAll); 3351 mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix); 3352 } 3353 3354 3355 /** 3356 * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the 3357 * task info will not include any extras or clip data. 3358 */ 3359 void fillTaskInfo(TaskInfo info) { 3360 fillTaskInfo(info, true /* stripExtras */); 3361 } 3362 3363 void fillTaskInfo(TaskInfo info, boolean stripExtras) { 3364 fillTaskInfo(info, stripExtras, getDisplayArea()); 3365 } 3366 3367 /** 3368 * Fills in a {@link TaskInfo} with information from this task. 3369 * 3370 * @param tda consider whether this Task can be put in multi window as it will be attached to 3371 * the give {@link TaskDisplayArea}. 3372 */ 3373 void fillTaskInfo(TaskInfo info, boolean stripExtras, @Nullable TaskDisplayArea tda) { 3374 info.launchCookies.clear(); 3375 info.addLaunchCookie(mLaunchCookie); 3376 final ActivityRecord top = mTaskSupervisor.mTaskInfoHelper.fillAndReturnTop(this, info); 3377 3378 info.userId = isLeafTask() ? mUserId : mCurrentUser; 3379 info.taskId = mTaskId; 3380 info.displayId = getDisplayId(); 3381 info.displayAreaFeatureId = tda != null ? tda.mFeatureId : FEATURE_UNDEFINED; 3382 final Intent baseIntent = getBaseIntent(); 3383 // Make a copy of base intent because this is like a snapshot info. 3384 // Besides, {@link RecentTasks#getRecentTasksImpl} may modify it. 3385 final int baseIntentFlags = baseIntent == null ? 0 : baseIntent.getFlags(); 3386 info.baseIntent = baseIntent == null 3387 ? new Intent() 3388 : stripExtras ? baseIntent.cloneFilter() : new Intent(baseIntent); 3389 info.baseIntent.setFlags(baseIntentFlags); 3390 3391 info.isRunning = top != null; 3392 info.topActivity = top != null ? top.mActivityComponent : null; 3393 info.origActivity = origActivity; 3394 info.realActivity = realActivity; 3395 info.lastActiveTime = lastActiveTime; 3396 info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription()); 3397 info.supportsMultiWindow = supportsMultiWindowInDisplayArea(tda); 3398 info.configuration.setTo(getConfiguration()); 3399 // Update to the task's current activity type and windowing mode which may differ from the 3400 // window configuration 3401 info.configuration.windowConfiguration.setActivityType(getActivityType()); 3402 info.configuration.windowConfiguration.setWindowingMode(getWindowingMode()); 3403 info.token = mRemoteToken.toWindowContainerToken(); 3404 3405 //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child 3406 // order changes. 3407 final Task topTask = top != null ? top.getTask() : this; 3408 info.resizeMode = topTask.mResizeMode; 3409 info.topActivityType = topTask.getActivityType(); 3410 info.displayCutoutInsets = topTask.getDisplayCutoutInsets(); 3411 info.isResizeable = isResizeable(); 3412 info.minWidth = mMinWidth; 3413 info.minHeight = mMinHeight; 3414 info.defaultMinSize = mDisplayContent == null 3415 ? DEFAULT_MIN_TASK_SIZE_DP : mDisplayContent.mMinSizeOfResizeableTaskDp; 3416 info.positionInParent = getRelativePosition(); 3417 3418 info.topActivityInfo = top != null ? top.info : null; 3419 info.pictureInPictureParams = getPictureInPictureParams(top); 3420 info.launchIntoPipHostTaskId = (info.pictureInPictureParams != null 3421 && info.pictureInPictureParams.isLaunchIntoPip() 3422 && top.getLastParentBeforePip() != null) 3423 ? top.getLastParentBeforePip().mTaskId : INVALID_TASK_ID; 3424 info.lastParentTaskIdBeforePip = top != null && top.getLastParentBeforePip() != null 3425 ? top.getLastParentBeforePip().mTaskId : INVALID_TASK_ID; 3426 info.shouldDockBigOverlays = top != null && top.shouldDockBigOverlays; 3427 info.mTopActivityLocusId = top != null ? top.getLocusId() : null; 3428 3429 final boolean isTopActivityResumed = top != null 3430 && top.getOrganizedTask() == this && top.isState(RESUMED); 3431 final boolean isTopActivityVisible = top != null 3432 && top.getOrganizedTask() == this && top.isVisible(); 3433 // Whether the direct top activity is in size compat mode 3434 info.topActivityInSizeCompat = isTopActivityVisible && top.inSizeCompatMode(); 3435 if (info.topActivityInSizeCompat 3436 && mWmService.mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) { 3437 // We hide the restart button in case of transparent activities. 3438 info.topActivityInSizeCompat = top.fillsParent(); 3439 } 3440 // Whether the direct top activity is eligible for letterbox education. 3441 info.topActivityEligibleForLetterboxEducation = isTopActivityResumed 3442 && top.isEligibleForLetterboxEducation(); 3443 // Whether the direct top activity requested showing camera compat control. 3444 info.cameraCompatControlState = isTopActivityResumed 3445 ? top.getCameraCompatControlState() 3446 : TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN; 3447 3448 final Task parentTask = getParent() != null ? getParent().asTask() : null; 3449 info.parentTaskId = parentTask != null && parentTask.mCreatedByOrganizer 3450 ? parentTask.mTaskId 3451 : INVALID_TASK_ID; 3452 info.isFocused = isFocused(); 3453 info.isVisible = hasVisibleChildren(); 3454 info.isVisibleRequested = isVisibleRequested(); 3455 info.isSleeping = shouldSleepActivities(); 3456 info.isLetterboxDoubleTapEnabled = top != null 3457 && top.mLetterboxUiController.isLetterboxDoubleTapEducationEnabled(); 3458 info.topActivityLetterboxVerticalPosition = TaskInfo.PROPERTY_VALUE_UNSET; 3459 info.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET; 3460 info.topActivityLetterboxWidth = TaskInfo.PROPERTY_VALUE_UNSET; 3461 info.topActivityLetterboxHeight = TaskInfo.PROPERTY_VALUE_UNSET; 3462 info.isUserFullscreenOverrideEnabled = top != null 3463 && top.mLetterboxUiController.shouldApplyUserFullscreenOverride(); 3464 info.isTopActivityTransparent = top != null && !top.fillsParent(); 3465 info.isFromLetterboxDoubleTap = top != null && top.mLetterboxUiController.isFromDoubleTap(); 3466 if (info.isLetterboxDoubleTapEnabled) { 3467 info.topActivityLetterboxWidth = top.getBounds().width(); 3468 info.topActivityLetterboxHeight = top.getBounds().height(); 3469 if (info.topActivityLetterboxWidth < info.topActivityLetterboxHeight) { 3470 // Pillarboxed 3471 info.topActivityLetterboxHorizontalPosition = 3472 top.mLetterboxUiController.getLetterboxPositionForHorizontalReachability(); 3473 } else { 3474 // Letterboxed 3475 info.topActivityLetterboxVerticalPosition = 3476 top.mLetterboxUiController.getLetterboxPositionForVerticalReachability(); 3477 } 3478 } 3479 // User Aspect Ratio Settings is enabled if the app is not in SCM 3480 info.topActivityEligibleForUserAspectRatioButton = top != null 3481 && !info.topActivityInSizeCompat 3482 && top.mLetterboxUiController.shouldEnableUserAspectRatioSettings(); 3483 info.topActivityBoundsLetterboxed = top != null && top.areBoundsLetterboxed(); 3484 } 3485 3486 /** 3487 * Removes the activity info if the activity belongs to a different uid, which is 3488 * different from the app that hosts the task. 3489 */ 3490 static void trimIneffectiveInfo(Task task, TaskInfo info) { 3491 final ActivityRecord baseActivity = task.getActivity(r -> !r.finishing, 3492 false /* traverseTopToBottom */); 3493 final int baseActivityUid = 3494 baseActivity != null ? baseActivity.getUid() : task.effectiveUid; 3495 3496 if (info.topActivityInfo != null 3497 && task.effectiveUid != info.topActivityInfo.applicationInfo.uid) { 3498 // Making a copy to prevent eliminating the info in the original ActivityRecord. 3499 info.topActivityInfo = new ActivityInfo(info.topActivityInfo); 3500 info.topActivityInfo.applicationInfo = 3501 new ApplicationInfo(info.topActivityInfo.applicationInfo); 3502 3503 // Strip the sensitive info. 3504 info.topActivity = new ComponentName("", ""); 3505 info.topActivityInfo.packageName = ""; 3506 info.topActivityInfo.taskAffinity = ""; 3507 info.topActivityInfo.processName = ""; 3508 info.topActivityInfo.name = ""; 3509 info.topActivityInfo.parentActivityName = ""; 3510 info.topActivityInfo.targetActivity = ""; 3511 info.topActivityInfo.splitName = ""; 3512 info.topActivityInfo.applicationInfo.className = ""; 3513 info.topActivityInfo.applicationInfo.credentialProtectedDataDir = ""; 3514 info.topActivityInfo.applicationInfo.dataDir = ""; 3515 info.topActivityInfo.applicationInfo.deviceProtectedDataDir = ""; 3516 info.topActivityInfo.applicationInfo.manageSpaceActivityName = ""; 3517 info.topActivityInfo.applicationInfo.nativeLibraryDir = ""; 3518 info.topActivityInfo.applicationInfo.nativeLibraryRootDir = ""; 3519 info.topActivityInfo.applicationInfo.processName = ""; 3520 info.topActivityInfo.applicationInfo.publicSourceDir = ""; 3521 info.topActivityInfo.applicationInfo.scanPublicSourceDir = ""; 3522 info.topActivityInfo.applicationInfo.scanSourceDir = ""; 3523 info.topActivityInfo.applicationInfo.sourceDir = ""; 3524 info.topActivityInfo.applicationInfo.taskAffinity = ""; 3525 info.topActivityInfo.applicationInfo.name = ""; 3526 info.topActivityInfo.applicationInfo.packageName = ""; 3527 } 3528 3529 if (task.effectiveUid != baseActivityUid) { 3530 info.baseActivity = new ComponentName("", ""); 3531 } 3532 } 3533 3534 @Nullable PictureInPictureParams getPictureInPictureParams() { 3535 final Task topTask = getTopMostTask(); 3536 if (topTask == null) return null; 3537 return getPictureInPictureParams(topTask.getTopMostActivity()); 3538 } 3539 3540 private static @Nullable PictureInPictureParams getPictureInPictureParams(ActivityRecord top) { 3541 return (top == null || top.pictureInPictureArgs.empty()) 3542 ? null : new PictureInPictureParams(top.pictureInPictureArgs); 3543 } 3544 3545 private boolean shouldDockBigOverlays() { 3546 final ActivityRecord topMostActivity = getTopMostActivity(); 3547 return topMostActivity != null && topMostActivity.shouldDockBigOverlays; 3548 } 3549 3550 Rect getDisplayCutoutInsets() { 3551 if (mDisplayContent == null || getDisplayInfo().displayCutout == null) return null; 3552 final WindowState w = getTopVisibleAppMainWindow(); 3553 final int displayCutoutMode = w == null 3554 ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 3555 : w.getAttrs().layoutInDisplayCutoutMode; 3556 return (displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 3557 || displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES) 3558 ? null : getDisplayInfo().displayCutout.getSafeInsets(); 3559 } 3560 3561 /** 3562 * Returns a {@link TaskInfo} with information from this task. 3563 */ 3564 ActivityManager.RunningTaskInfo getTaskInfo() { 3565 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo(); 3566 fillTaskInfo(info); 3567 return info; 3568 } 3569 3570 /** 3571 * Returns a {@link StartingWindowInfo} with information from this task and the target activity. 3572 * @param activity Target activity which to show the starting window. 3573 */ 3574 StartingWindowInfo getStartingWindowInfo(ActivityRecord activity) { 3575 final StartingWindowInfo info = new StartingWindowInfo(); 3576 info.taskInfo = getTaskInfo(); 3577 info.targetActivityInfo = info.taskInfo.topActivityInfo != null 3578 && activity.info != info.taskInfo.topActivityInfo 3579 ? activity.info : null; 3580 info.isKeyguardOccluded = 3581 mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY); 3582 3583 info.startingWindowTypeParameter = activity.mStartingData != null 3584 ? activity.mStartingData.mTypeParams 3585 : (StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED 3586 | StartingWindowInfo.TYPE_PARAMETER_WINDOWLESS); 3587 if ((info.startingWindowTypeParameter 3588 & StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED) != 0) { 3589 final WindowState topMainWin = getWindow(w -> w.mAttrs.type == TYPE_BASE_APPLICATION); 3590 if (topMainWin != null) { 3591 info.mainWindowLayoutParams = topMainWin.getAttrs(); 3592 info.requestedVisibleTypes = topMainWin.getRequestedVisibleTypes(); 3593 } 3594 } 3595 // If the developer has persist a different configuration, we need to override it to the 3596 // starting window because persisted configuration does not effect to Task. 3597 info.taskInfo.configuration.setTo(activity.getConfiguration()); 3598 final ActivityRecord topFullscreenActivity = getTopFullscreenActivity(); 3599 if (topFullscreenActivity != null) { 3600 final WindowState topFullscreenOpaqueWindow = 3601 topFullscreenActivity.getTopFullscreenOpaqueWindow(); 3602 if (topFullscreenOpaqueWindow != null) { 3603 info.topOpaqueWindowInsetsState = 3604 topFullscreenOpaqueWindow.getInsetsStateWithVisibilityOverride(); 3605 info.topOpaqueWindowLayoutParams = topFullscreenOpaqueWindow.getAttrs(); 3606 } 3607 } 3608 return info; 3609 } 3610 3611 /** 3612 * Returns the {@link TaskFragmentParentInfo} which will send to the client 3613 * {@link android.window.TaskFragmentOrganizer} 3614 */ 3615 TaskFragmentParentInfo getTaskFragmentParentInfo() { 3616 return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(), 3617 shouldBeVisible(null /* starting */)); 3618 } 3619 3620 @Override 3621 protected boolean onChildVisibleRequestedChanged(@Nullable WindowContainer child) { 3622 if (!super.onChildVisibleRequestedChanged(child)) return false; 3623 sendTaskFragmentParentInfoChangedIfNeeded(); 3624 return true; 3625 } 3626 3627 void sendTaskFragmentParentInfoChangedIfNeeded() { 3628 if (!isLeafTask()) { 3629 // Only send parent info changed event for leaf task. 3630 return; 3631 } 3632 final TaskFragment childOrganizedTf = 3633 getTaskFragment(TaskFragment::isOrganizedTaskFragment); 3634 if (childOrganizedTf != null) { 3635 childOrganizedTf.sendTaskFragmentParentInfoChanged(); 3636 } 3637 } 3638 3639 boolean isTaskId(int taskId) { 3640 return mTaskId == taskId; 3641 } 3642 3643 @Override 3644 Task asTask() { 3645 // I'm a task! 3646 return this; 3647 } 3648 3649 ActivityRecord isInTask(ActivityRecord r) { 3650 if (r == null) { 3651 return null; 3652 } 3653 if (r.isDescendantOf(this)) { 3654 return r; 3655 } 3656 return null; 3657 } 3658 3659 void dump(PrintWriter pw, String prefix) { 3660 pw.print(prefix); pw.print("userId="); pw.print(mUserId); 3661 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid); 3662 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid); 3663 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete); 3664 pw.print(" mCallingPackage="); pw.print(mCallingPackage); 3665 pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId); 3666 if (affinity != null || rootAffinity != null) { 3667 pw.print(prefix); pw.print("affinity="); pw.print(affinity); 3668 if (affinity == null || !affinity.equals(rootAffinity)) { 3669 pw.print(" root="); pw.println(rootAffinity); 3670 } else { 3671 pw.println(); 3672 } 3673 } 3674 if (mWindowLayoutAffinity != null) { 3675 pw.print(prefix); pw.print("windowLayoutAffinity="); pw.println(mWindowLayoutAffinity); 3676 } 3677 if (voiceSession != null || voiceInteractor != null) { 3678 pw.print(prefix); pw.print("VOICE: session=0x"); 3679 pw.print(Integer.toHexString(System.identityHashCode(voiceSession))); 3680 pw.print(" interactor=0x"); 3681 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor))); 3682 } 3683 if (intent != null) { 3684 StringBuilder sb = new StringBuilder(128); 3685 sb.append(prefix); sb.append("intent={"); 3686 intent.toShortString(sb, false, true, false, false); 3687 sb.append('}'); 3688 pw.println(sb.toString()); 3689 } 3690 if (affinityIntent != null) { 3691 StringBuilder sb = new StringBuilder(128); 3692 sb.append(prefix); sb.append("affinityIntent={"); 3693 affinityIntent.toShortString(sb, false, true, false, false); 3694 sb.append('}'); 3695 pw.println(sb.toString()); 3696 } 3697 if (origActivity != null) { 3698 pw.print(prefix); pw.print("origActivity="); 3699 pw.println(origActivity.flattenToShortString()); 3700 } 3701 if (realActivity != null) { 3702 pw.print(prefix); pw.print("mActivityComponent="); 3703 pw.println(realActivity.flattenToShortString()); 3704 } 3705 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) { 3706 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents); 3707 pw.print(" isPersistable="); pw.print(isPersistable); 3708 pw.print(" activityType="); pw.println(getActivityType()); 3709 } 3710 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask 3711 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) { 3712 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset); 3713 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity); 3714 pw.print(" mReuseTask="); pw.print(mReuseTask); 3715 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString()); 3716 } 3717 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID 3718 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID 3719 || mNextAffiliate != null) { 3720 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId); 3721 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId); 3722 pw.print(" ("); 3723 if (mPrevAffiliate == null) { 3724 pw.print("null"); 3725 } else { 3726 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate))); 3727 } 3728 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId); 3729 pw.print(" ("); 3730 if (mNextAffiliate == null) { 3731 pw.print("null"); 3732 } else { 3733 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate))); 3734 } 3735 pw.println(")"); 3736 } 3737 pw.print(prefix); pw.print("Activities="); pw.println(mChildren); 3738 if (!askedCompatMode || !inRecents || !isAvailable) { 3739 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode); 3740 pw.print(" inRecents="); pw.print(inRecents); 3741 pw.print(" isAvailable="); pw.println(isAvailable); 3742 } 3743 if (lastDescription != null) { 3744 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription); 3745 } 3746 if (mRootProcess != null) { 3747 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess); 3748 } 3749 if (mSharedStartingData != null) { 3750 pw.println(prefix + "mSharedStartingData=" + mSharedStartingData); 3751 } 3752 if (mKillProcessesOnDestroyed) { 3753 pw.println(prefix + "mKillProcessesOnDestroyed=true"); 3754 } 3755 pw.print(prefix); pw.print("taskId=" + mTaskId); 3756 pw.println(" rootTaskId=" + getRootTaskId()); 3757 pw.print(prefix); pw.println("hasChildPipActivity=" + (mChildPipActivity != null)); 3758 pw.print(prefix); pw.print("mHasBeenVisible="); pw.println(getHasBeenVisible()); 3759 pw.print(prefix); pw.print("mResizeMode="); 3760 pw.print(ActivityInfo.resizeModeToString(mResizeMode)); 3761 pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture); 3762 pw.print(" isResizeable="); pw.println(isResizeable()); 3763 pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime); 3764 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)"); 3765 } 3766 3767 @Override 3768 String toFullString() { 3769 final StringBuilder sb = new StringBuilder(192); 3770 sb.append(this); 3771 sb.setLength(sb.length() - 1); // Remove tail '}'. 3772 sb.append(" U="); 3773 sb.append(mUserId); 3774 final Task rootTask = getRootTask(); 3775 if (rootTask != this) { 3776 sb.append(" rootTaskId="); 3777 sb.append(rootTask.mTaskId); 3778 } 3779 sb.append(" visible="); 3780 sb.append(shouldBeVisible(null /* starting */)); 3781 sb.append(" visibleRequested="); 3782 sb.append(isVisibleRequested()); 3783 sb.append(" mode="); 3784 sb.append(windowingModeToString(getWindowingMode())); 3785 sb.append(" translucent="); 3786 sb.append(isTranslucent(null /* starting */)); 3787 sb.append(" sz="); 3788 sb.append(getChildCount()); 3789 sb.append('}'); 3790 return sb.toString(); 3791 } 3792 3793 @Override 3794 public String toString() { 3795 if (stringName != null) return stringName; 3796 StringBuilder sb = new StringBuilder(128); 3797 sb.append("Task{"); 3798 sb.append(Integer.toHexString(System.identityHashCode(this))); 3799 sb.append(" #"); 3800 sb.append(mTaskId); 3801 sb.append(" type=" + activityTypeToString(getActivityType())); 3802 if (affinity != null) { 3803 sb.append(" A="); 3804 sb.append(affinity); 3805 } else if (intent != null && intent.getComponent() != null) { 3806 sb.append(" I="); 3807 sb.append(intent.getComponent().flattenToShortString()); 3808 } else if (affinityIntent != null && affinityIntent.getComponent() != null) { 3809 sb.append(" aI="); 3810 sb.append(affinityIntent.getComponent().flattenToShortString()); 3811 } 3812 sb.append('}'); 3813 return stringName = sb.toString(); 3814 } 3815 3816 /** 3817 * Saves this {@link Task} to XML using given serializer. 3818 */ 3819 void saveToXml(TypedXmlSerializer out) throws Exception { 3820 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this); 3821 3822 out.attributeInt(null, ATTR_TASKID, mTaskId); 3823 if (realActivity != null) { 3824 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString()); 3825 } 3826 out.attributeBoolean(null, ATTR_REALACTIVITY_SUSPENDED, realActivitySuspended); 3827 if (origActivity != null) { 3828 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString()); 3829 } 3830 // Write affinity, and root affinity if it is different from affinity. 3831 // We use the special string "@" for a null root affinity, so we can identify 3832 // later whether we were given a root affinity or should just make it the 3833 // same as the affinity. 3834 if (affinity != null) { 3835 out.attribute(null, ATTR_AFFINITY, affinity); 3836 if (!affinity.equals(rootAffinity)) { 3837 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@"); 3838 } 3839 } else if (rootAffinity != null) { 3840 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@"); 3841 } 3842 if (mWindowLayoutAffinity != null) { 3843 out.attribute(null, ATTR_WINDOW_LAYOUT_AFFINITY, mWindowLayoutAffinity); 3844 } 3845 out.attributeBoolean(null, ATTR_ROOTHASRESET, rootWasReset); 3846 out.attributeBoolean(null, ATTR_AUTOREMOVERECENTS, autoRemoveRecents); 3847 out.attributeBoolean(null, ATTR_ASKEDCOMPATMODE, askedCompatMode); 3848 out.attributeInt(null, ATTR_USERID, mUserId); 3849 out.attributeBoolean(null, ATTR_USER_SETUP_COMPLETE, mUserSetupComplete); 3850 out.attributeInt(null, ATTR_EFFECTIVE_UID, effectiveUid); 3851 out.attributeLong(null, ATTR_LASTTIMEMOVED, mLastTimeMoved); 3852 out.attributeBoolean(null, ATTR_NEVERRELINQUISH, mNeverRelinquishIdentity); 3853 if (lastDescription != null) { 3854 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString()); 3855 } 3856 if (getTaskDescription() != null) { 3857 getTaskDescription().saveToXml(out); 3858 } 3859 out.attributeInt(null, ATTR_TASK_AFFILIATION, mAffiliatedTaskId); 3860 out.attributeInt(null, ATTR_PREV_AFFILIATION, mPrevAffiliateTaskId); 3861 out.attributeInt(null, ATTR_NEXT_AFFILIATION, mNextAffiliateTaskId); 3862 out.attributeInt(null, ATTR_CALLING_UID, mCallingUid); 3863 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage); 3864 out.attribute(null, ATTR_CALLING_FEATURE_ID, 3865 mCallingFeatureId == null ? "" : mCallingFeatureId); 3866 out.attributeInt(null, ATTR_RESIZE_MODE, mResizeMode); 3867 out.attributeBoolean(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE, mSupportsPictureInPicture); 3868 if (mLastNonFullscreenBounds != null) { 3869 out.attribute( 3870 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString()); 3871 } 3872 out.attributeInt(null, ATTR_MIN_WIDTH, mMinWidth); 3873 out.attributeInt(null, ATTR_MIN_HEIGHT, mMinHeight); 3874 out.attributeInt(null, ATTR_PERSIST_TASK_VERSION, PERSIST_TASK_VERSION); 3875 3876 if (mLastTaskSnapshotData.taskSize != null) { 3877 out.attribute(null, ATTR_LAST_SNAPSHOT_TASK_SIZE, 3878 mLastTaskSnapshotData.taskSize.flattenToString()); 3879 } 3880 if (mLastTaskSnapshotData.contentInsets != null) { 3881 out.attribute(null, ATTR_LAST_SNAPSHOT_CONTENT_INSETS, 3882 mLastTaskSnapshotData.contentInsets.flattenToString()); 3883 } 3884 if (mLastTaskSnapshotData.bufferSize != null) { 3885 out.attribute(null, ATTR_LAST_SNAPSHOT_BUFFER_SIZE, 3886 mLastTaskSnapshotData.bufferSize.flattenToString()); 3887 } 3888 3889 if (affinityIntent != null) { 3890 out.startTag(null, TAG_AFFINITYINTENT); 3891 affinityIntent.saveToXml(out); 3892 out.endTag(null, TAG_AFFINITYINTENT); 3893 } 3894 3895 if (intent != null) { 3896 out.startTag(null, TAG_INTENT); 3897 intent.saveToXml(out); 3898 out.endTag(null, TAG_INTENT); 3899 } 3900 3901 sTmpException = null; 3902 final PooledPredicate f = PooledLambda.obtainPredicate(Task::saveActivityToXml, 3903 PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out); 3904 forAllActivities(f); 3905 f.recycle(); 3906 if (sTmpException != null) { 3907 throw sTmpException; 3908 } 3909 } 3910 3911 private static boolean saveActivityToXml( 3912 ActivityRecord r, ActivityRecord first, TypedXmlSerializer out) { 3913 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() 3914 || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT 3915 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) 3916 && r != first) { 3917 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET). 3918 return true; 3919 } 3920 try { 3921 out.startTag(null, TAG_ACTIVITY); 3922 r.saveToXml(out); 3923 out.endTag(null, TAG_ACTIVITY); 3924 return false; 3925 } catch (Exception e) { 3926 sTmpException = e; 3927 return true; 3928 } 3929 } 3930 3931 static Task restoreFromXml(TypedXmlPullParser in, ActivityTaskSupervisor taskSupervisor) 3932 throws IOException, XmlPullParserException { 3933 Intent intent = null; 3934 Intent affinityIntent = null; 3935 ArrayList<ActivityRecord> activities = new ArrayList<>(); 3936 ComponentName realActivity = null; 3937 boolean realActivitySuspended = false; 3938 ComponentName origActivity = null; 3939 String affinity = null; 3940 String rootAffinity = null; 3941 boolean hasRootAffinity = false; 3942 String windowLayoutAffinity = null; 3943 boolean rootHasReset = false; 3944 boolean autoRemoveRecents = false; 3945 boolean askedCompatMode = false; 3946 int taskType = 0; 3947 int userId = 0; 3948 boolean userSetupComplete = true; 3949 int effectiveUid = -1; 3950 String lastDescription = null; 3951 long lastTimeOnTop = 0; 3952 boolean neverRelinquishIdentity = true; 3953 int taskId = INVALID_TASK_ID; 3954 final int outerDepth = in.getDepth(); 3955 TaskDescription taskDescription = new TaskDescription(); 3956 PersistedTaskSnapshotData lastSnapshotData = new PersistedTaskSnapshotData(); 3957 int taskAffiliation = INVALID_TASK_ID; 3958 int prevTaskId = INVALID_TASK_ID; 3959 int nextTaskId = INVALID_TASK_ID; 3960 int callingUid = -1; 3961 String callingPackage = ""; 3962 String callingFeatureId = null; 3963 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE; 3964 boolean supportsPictureInPicture = false; 3965 Rect lastNonFullscreenBounds = null; 3966 int minWidth = INVALID_MIN_SIZE; 3967 int minHeight = INVALID_MIN_SIZE; 3968 int persistTaskVersion = 0; 3969 3970 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) { 3971 final String attrName = in.getAttributeName(attrNdx); 3972 final String attrValue = in.getAttributeValue(attrNdx); 3973 if (TaskPersister.DEBUG) { 3974 Slog.d(TaskPersister.TAG, "Task: attribute name=" + attrName + " value=" 3975 + attrValue); 3976 } 3977 switch (attrName) { 3978 case ATTR_TASKID: 3979 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue); 3980 break; 3981 case ATTR_REALACTIVITY: 3982 realActivity = ComponentName.unflattenFromString(attrValue); 3983 break; 3984 case ATTR_REALACTIVITY_SUSPENDED: 3985 realActivitySuspended = Boolean.valueOf(attrValue); 3986 break; 3987 case ATTR_ORIGACTIVITY: 3988 origActivity = ComponentName.unflattenFromString(attrValue); 3989 break; 3990 case ATTR_AFFINITY: 3991 affinity = attrValue; 3992 break; 3993 case ATTR_ROOT_AFFINITY: 3994 rootAffinity = attrValue; 3995 hasRootAffinity = true; 3996 break; 3997 case ATTR_WINDOW_LAYOUT_AFFINITY: 3998 windowLayoutAffinity = attrValue; 3999 break; 4000 case ATTR_ROOTHASRESET: 4001 rootHasReset = Boolean.parseBoolean(attrValue); 4002 break; 4003 case ATTR_AUTOREMOVERECENTS: 4004 autoRemoveRecents = Boolean.parseBoolean(attrValue); 4005 break; 4006 case ATTR_ASKEDCOMPATMODE: 4007 askedCompatMode = Boolean.parseBoolean(attrValue); 4008 break; 4009 case ATTR_USERID: 4010 userId = Integer.parseInt(attrValue); 4011 break; 4012 case ATTR_USER_SETUP_COMPLETE: 4013 userSetupComplete = Boolean.parseBoolean(attrValue); 4014 break; 4015 case ATTR_EFFECTIVE_UID: 4016 effectiveUid = Integer.parseInt(attrValue); 4017 break; 4018 case ATTR_TASKTYPE: 4019 taskType = Integer.parseInt(attrValue); 4020 break; 4021 case ATTR_LASTDESCRIPTION: 4022 lastDescription = attrValue; 4023 break; 4024 case ATTR_LASTTIMEMOVED: 4025 lastTimeOnTop = Long.parseLong(attrValue); 4026 break; 4027 case ATTR_NEVERRELINQUISH: 4028 neverRelinquishIdentity = Boolean.parseBoolean(attrValue); 4029 break; 4030 case ATTR_TASK_AFFILIATION: 4031 taskAffiliation = Integer.parseInt(attrValue); 4032 break; 4033 case ATTR_PREV_AFFILIATION: 4034 prevTaskId = Integer.parseInt(attrValue); 4035 break; 4036 case ATTR_NEXT_AFFILIATION: 4037 nextTaskId = Integer.parseInt(attrValue); 4038 break; 4039 case ATTR_CALLING_UID: 4040 callingUid = Integer.parseInt(attrValue); 4041 break; 4042 case ATTR_CALLING_PACKAGE: 4043 callingPackage = attrValue; 4044 break; 4045 case ATTR_CALLING_FEATURE_ID: 4046 callingFeatureId = attrValue; 4047 break; 4048 case ATTR_RESIZE_MODE: 4049 resizeMode = Integer.parseInt(attrValue); 4050 break; 4051 case ATTR_SUPPORTS_PICTURE_IN_PICTURE: 4052 supportsPictureInPicture = Boolean.parseBoolean(attrValue); 4053 break; 4054 case ATTR_NON_FULLSCREEN_BOUNDS: 4055 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue); 4056 break; 4057 case ATTR_MIN_WIDTH: 4058 minWidth = Integer.parseInt(attrValue); 4059 break; 4060 case ATTR_MIN_HEIGHT: 4061 minHeight = Integer.parseInt(attrValue); 4062 break; 4063 case ATTR_PERSIST_TASK_VERSION: 4064 persistTaskVersion = Integer.parseInt(attrValue); 4065 break; 4066 case ATTR_LAST_SNAPSHOT_TASK_SIZE: 4067 lastSnapshotData.taskSize = Point.unflattenFromString(attrValue); 4068 break; 4069 case ATTR_LAST_SNAPSHOT_CONTENT_INSETS: 4070 lastSnapshotData.contentInsets = Rect.unflattenFromString(attrValue); 4071 break; 4072 case ATTR_LAST_SNAPSHOT_BUFFER_SIZE: 4073 lastSnapshotData.bufferSize = Point.unflattenFromString(attrValue); 4074 break; 4075 default: 4076 if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) { 4077 Slog.w(TAG, "Task: Unknown attribute=" + attrName); 4078 } 4079 } 4080 } 4081 taskDescription.restoreFromXml(in); 4082 4083 int event; 4084 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) 4085 && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) { 4086 if (event == XmlPullParser.START_TAG) { 4087 final String name = in.getName(); 4088 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: START_TAG name=" + name); 4089 if (TAG_AFFINITYINTENT.equals(name)) { 4090 affinityIntent = Intent.restoreFromXml(in); 4091 } else if (TAG_INTENT.equals(name)) { 4092 intent = Intent.restoreFromXml(in); 4093 } else if (TAG_ACTIVITY.equals(name)) { 4094 ActivityRecord activity = 4095 ActivityRecord.restoreFromXml(in, taskSupervisor); 4096 if (TaskPersister.DEBUG) { 4097 Slog.d(TaskPersister.TAG, "Task: activity=" + activity); 4098 } 4099 if (activity != null) { 4100 activities.add(activity); 4101 } 4102 } else { 4103 Slog.e(TAG, "restoreTask: Unexpected name=" + name); 4104 XmlUtils.skipCurrentTag(in); 4105 } 4106 } 4107 } 4108 if (!hasRootAffinity) { 4109 rootAffinity = affinity; 4110 } else if ("@".equals(rootAffinity)) { 4111 rootAffinity = null; 4112 } 4113 if (effectiveUid <= 0) { 4114 Intent checkIntent = intent != null ? intent : affinityIntent; 4115 effectiveUid = 0; 4116 if (checkIntent != null) { 4117 IPackageManager pm = AppGlobals.getPackageManager(); 4118 try { 4119 ApplicationInfo ai = pm.getApplicationInfo( 4120 checkIntent.getComponent().getPackageName(), 4121 PackageManager.MATCH_UNINSTALLED_PACKAGES 4122 | PackageManager.MATCH_DISABLED_COMPONENTS, userId); 4123 if (ai != null) { 4124 effectiveUid = ai.uid; 4125 } 4126 } catch (RemoteException e) { 4127 } 4128 } 4129 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent 4130 + ": effectiveUid=" + effectiveUid); 4131 } 4132 4133 if (persistTaskVersion < 1) { 4134 // We need to convert the resize mode of home activities saved before version one if 4135 // they are marked as RESIZE_MODE_RESIZEABLE to 4136 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation 4137 // before version 1 and the system didn't resize home activities before then. 4138 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) { 4139 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; 4140 } 4141 } else { 4142 // This activity has previously marked itself explicitly as both resizeable and 4143 // supporting picture-in-picture. Since there is no longer a requirement for 4144 // picture-in-picture activities to be resizeable, we can mark this simply as 4145 // resizeable and supporting picture-in-picture separately. 4146 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) { 4147 resizeMode = RESIZE_MODE_RESIZEABLE; 4148 supportsPictureInPicture = true; 4149 } 4150 } 4151 4152 final Task task = new Task.Builder(taskSupervisor.mService) 4153 .setTaskId(taskId) 4154 .setIntent(intent) 4155 .setAffinityIntent(affinityIntent) 4156 .setAffinity(affinity) 4157 .setRootAffinity(rootAffinity) 4158 .setRealActivity(realActivity) 4159 .setOrigActivity(origActivity) 4160 .setRootWasReset(rootHasReset) 4161 .setAutoRemoveRecents(autoRemoveRecents) 4162 .setAskedCompatMode(askedCompatMode) 4163 .setUserId(userId) 4164 .setEffectiveUid(effectiveUid) 4165 .setLastDescription(lastDescription) 4166 .setLastTimeMoved(lastTimeOnTop) 4167 .setNeverRelinquishIdentity(neverRelinquishIdentity) 4168 .setLastTaskDescription(taskDescription) 4169 .setLastSnapshotData(lastSnapshotData) 4170 .setTaskAffiliation(taskAffiliation) 4171 .setPrevAffiliateTaskId(prevTaskId) 4172 .setNextAffiliateTaskId(nextTaskId) 4173 .setCallingUid(callingUid) 4174 .setCallingPackage(callingPackage) 4175 .setCallingFeatureId(callingFeatureId) 4176 .setResizeMode(resizeMode) 4177 .setSupportsPictureInPicture(supportsPictureInPicture) 4178 .setRealActivitySuspended(realActivitySuspended) 4179 .setUserSetupComplete(userSetupComplete) 4180 .setMinWidth(minWidth) 4181 .setMinHeight(minHeight) 4182 .buildInner(); 4183 task.mLastNonFullscreenBounds = lastNonFullscreenBounds; 4184 task.setBounds(lastNonFullscreenBounds); 4185 task.mWindowLayoutAffinity = windowLayoutAffinity; 4186 if (activities.size() > 0) { 4187 // We need to add the task into hierarchy before adding child to it. 4188 final DisplayContent dc = 4189 taskSupervisor.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY); 4190 dc.getDefaultTaskDisplayArea().addChild(task, POSITION_BOTTOM); 4191 4192 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4193 task.addChild(activities.get(activityNdx)); 4194 } 4195 } 4196 4197 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task); 4198 return task; 4199 } 4200 4201 @Override 4202 boolean isOrganized() { 4203 return mTaskOrganizer != null; 4204 } 4205 4206 private boolean canBeOrganized() { 4207 // All root tasks can be organized 4208 if (isRootTask() || mCreatedByOrganizer) { 4209 return true; 4210 } 4211 4212 // Task could be organized if it's the direct child of a task created by organizer. 4213 final Task parentTask = getParent().asTask(); 4214 return parentTask != null && parentTask.mCreatedByOrganizer; 4215 } 4216 4217 @Override 4218 boolean showSurfaceOnCreation() { 4219 return false; 4220 } 4221 4222 @Override 4223 protected void reparentSurfaceControl(SurfaceControl.Transaction t, SurfaceControl newParent) { 4224 /** 4225 * Avoid reparenting SurfaceControl of the organized tasks that are always on top, since 4226 * the surfaces should be controlled by the organizer itself, like bubbles. 4227 */ 4228 if (isOrganized() && isAlwaysOnTop()) { 4229 return; 4230 } 4231 super.reparentSurfaceControl(t, newParent); 4232 } 4233 4234 void setHasBeenVisible(boolean hasBeenVisible) { 4235 mHasBeenVisible = hasBeenVisible; 4236 if (!hasBeenVisible || mDeferTaskAppear) { 4237 return; 4238 } 4239 sendTaskAppeared(); 4240 for (WindowContainer<?> parent = getParent(); parent != null; parent = parent.getParent()) { 4241 final Task parentTask = parent.asTask(); 4242 if (parentTask == null) { 4243 break; 4244 } 4245 parentTask.setHasBeenVisible(true); 4246 } 4247 } 4248 4249 4250 boolean getHasBeenVisible() { 4251 return mHasBeenVisible; 4252 } 4253 4254 void setDeferTaskAppear(boolean deferTaskAppear) { 4255 final boolean wasDeferred = mDeferTaskAppear; 4256 mDeferTaskAppear = deferTaskAppear; 4257 if (wasDeferred && !deferTaskAppear) { 4258 sendTaskAppeared(); 4259 } 4260 } 4261 4262 /** In the case that these conditions are true, we want to send the Task to the organizer: 4263 * 1. An organizer has been set 4264 * 2. The Task was created by the organizer 4265 * or 4266 * 2a. We have a SurfaceControl 4267 * 2b. We have finished drawing 4268 * Any time any of these conditions are updated, the updating code should call 4269 * sendTaskAppeared. 4270 */ 4271 boolean taskAppearedReady() { 4272 if (mTaskOrganizer == null) { 4273 return false; 4274 } 4275 4276 if (mDeferTaskAppear) { 4277 return false; 4278 } 4279 4280 if (mCreatedByOrganizer) { 4281 return true; 4282 } 4283 4284 return mSurfaceControl != null && getHasBeenVisible(); 4285 } 4286 4287 private void sendTaskAppeared() { 4288 if (mTaskOrganizer != null) { 4289 mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this); 4290 } 4291 } 4292 4293 private void sendTaskVanished(ITaskOrganizer organizer) { 4294 if (organizer != null) { 4295 mAtmService.mTaskOrganizerController.onTaskVanished(organizer, this); 4296 } 4297 } 4298 4299 @VisibleForTesting 4300 boolean setTaskOrganizer(ITaskOrganizer organizer) { 4301 return setTaskOrganizer(organizer, false /* skipTaskAppeared */); 4302 } 4303 4304 @VisibleForTesting 4305 boolean setTaskOrganizer(ITaskOrganizer organizer, boolean skipTaskAppeared) { 4306 if (mTaskOrganizer == organizer) { 4307 return false; 4308 } 4309 4310 ITaskOrganizer prevOrganizer = mTaskOrganizer; 4311 // Update the new task organizer before calling sendTaskVanished since it could result in 4312 // a new SurfaceControl getting created that would notify the old organizer about it. 4313 mTaskOrganizer = organizer; 4314 // Let the old organizer know it has lost control. 4315 sendTaskVanished(prevOrganizer); 4316 4317 if (mTaskOrganizer != null) { 4318 if (!skipTaskAppeared) { 4319 sendTaskAppeared(); 4320 } 4321 } else { 4322 // No longer managed by any organizer. 4323 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 4324 if (taskDisplayArea != null) { 4325 taskDisplayArea.removeLaunchRootTask(this); 4326 } 4327 setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */); 4328 if (mCreatedByOrganizer) { 4329 removeImmediately("setTaskOrganizer"); 4330 } 4331 } 4332 4333 return true; 4334 } 4335 4336 boolean updateTaskOrganizerState() { 4337 return updateTaskOrganizerState(false /* skipTaskAppeared */); 4338 } 4339 4340 /** 4341 * Called when the task state changes (ie. from windowing mode change) an the task organizer 4342 * state should also be updated. 4343 * 4344 * @param skipTaskAppeared Skips calling taskAppeared for the new organizer if it has changed 4345 * @return {@code true} if task organizer changed. 4346 */ 4347 boolean updateTaskOrganizerState(boolean skipTaskAppeared) { 4348 if (getSurfaceControl() == null) { 4349 // Can't call onTaskAppeared without a surfacecontrol, so defer this until next one 4350 // is created. 4351 return false; 4352 } 4353 if (!canBeOrganized()) { 4354 return setTaskOrganizer(null); 4355 } 4356 4357 final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController; 4358 final ITaskOrganizer organizer = controller.getTaskOrganizer(); 4359 // Do not change to different organizer if the task is created by organizer because only 4360 // the creator knows how to manage it. 4361 if (mCreatedByOrganizer && mTaskOrganizer != null && organizer != null 4362 && mTaskOrganizer != organizer) { 4363 return false; 4364 } 4365 return setTaskOrganizer(organizer, skipTaskAppeared); 4366 } 4367 4368 @Override 4369 void setSurfaceControl(SurfaceControl sc) { 4370 super.setSurfaceControl(sc); 4371 // If the TaskOrganizer was set before we created the SurfaceControl, we need to 4372 // emit the callbacks now. 4373 sendTaskAppeared(); 4374 } 4375 4376 /** 4377 * @return {@code true} if the task is currently focused or one of its children is focused. 4378 */ 4379 boolean isFocused() { 4380 if (mDisplayContent == null || mDisplayContent.mFocusedApp == null) { 4381 return false; 4382 } 4383 final Task focusedTask = mDisplayContent.mFocusedApp.getTask(); 4384 return focusedTask == this || (focusedTask != null && focusedTask.getParent() == this); 4385 } 4386 4387 /** 4388 * @return true if the task is visible and has at least one visible child. 4389 */ 4390 private boolean hasVisibleChildren() { 4391 if (!isAttached() || isForceHidden()) { 4392 return false; 4393 } 4394 4395 return getActivity(ActivityRecord::isVisible) != null; 4396 } 4397 4398 /** 4399 * Called on the task when it gained or lost focus. 4400 * @param hasFocus 4401 */ 4402 void onAppFocusChanged(boolean hasFocus) { 4403 dispatchTaskInfoChangedIfNeeded(false /* force */); 4404 final Task parentTask = getParent().asTask(); 4405 if (parentTask != null) parentTask.dispatchTaskInfoChangedIfNeeded(false /* force */); 4406 4407 mAtmService.getTaskChangeNotificationController().notifyTaskFocusChanged(mTaskId, hasFocus); 4408 } 4409 4410 void onPictureInPictureParamsChanged() { 4411 if (inPinnedWindowingMode()) { 4412 dispatchTaskInfoChangedIfNeeded(true /* force */); 4413 } 4414 } 4415 4416 void onShouldDockBigOverlaysChanged() { 4417 dispatchTaskInfoChangedIfNeeded(true /* force */); 4418 } 4419 4420 /** Called when the top activity in the Root Task enters or exits size compat mode. */ 4421 void onSizeCompatActivityChanged() { 4422 // Trigger TaskInfoChanged to update the size compat restart button. 4423 dispatchTaskInfoChangedIfNeeded(true /* force */); 4424 } 4425 4426 /** 4427 * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this 4428 * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy 4429 * to resize, and it will defer the transaction until that resize frame completes. 4430 */ 4431 void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) { 4432 setMainWindowSizeChangeTransaction(t, this); 4433 forAllWindows(WindowState::requestRedrawForSync, true); 4434 } 4435 4436 private void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t, Task origin) { 4437 // This is only meaningful on an activity's task, so put it on the top one. 4438 ActivityRecord topActivity = getTopNonFinishingActivity(); 4439 Task leaf = topActivity != null ? topActivity.getTask() : null; 4440 if (leaf == null) { 4441 return; 4442 } 4443 if (leaf != this) { 4444 leaf.setMainWindowSizeChangeTransaction(t, origin); 4445 return; 4446 } 4447 final WindowState w = getTopVisibleAppMainWindow(); 4448 if (w != null) { 4449 w.applyWithNextDraw((d) -> { 4450 d.merge(t); 4451 }); 4452 } else { 4453 t.apply(); 4454 } 4455 } 4456 4457 /** 4458 * Sets/unsets the forced-hidden state flag for this task depending on {@param set}. 4459 * @return Whether the force hidden state changed 4460 */ 4461 boolean setForceHidden(int flags, boolean set) { 4462 int newFlags = mForceHiddenFlags; 4463 if (set) { 4464 newFlags |= flags; 4465 } else { 4466 newFlags &= ~flags; 4467 } 4468 if (mForceHiddenFlags == newFlags) { 4469 return false; 4470 } 4471 4472 final boolean wasHidden = isForceHidden(); 4473 final boolean wasVisible = isVisible(); 4474 mForceHiddenFlags = newFlags; 4475 final boolean nowHidden = isForceHidden(); 4476 if (wasHidden != nowHidden) { 4477 final String reason = "setForceHidden"; 4478 if (wasVisible && nowHidden) { 4479 // Move this visible task to back when the task is forced hidden 4480 moveToBack(reason, null); 4481 } else if (isAlwaysOnTop()) { 4482 // Move this always-on-top task to front when no longer hidden 4483 moveToFront(reason); 4484 } 4485 } 4486 return true; 4487 } 4488 4489 void setForceTranslucent(boolean set) { 4490 mForceTranslucent = set; 4491 } 4492 4493 @Override 4494 public boolean isAlwaysOnTop() { 4495 return !isForceHidden() && super.isAlwaysOnTop(); 4496 } 4497 4498 /** 4499 * @return whether this task is always on top without taking visibility into account. 4500 */ 4501 public boolean isAlwaysOnTopWhenVisible() { 4502 return super.isAlwaysOnTop(); 4503 } 4504 4505 @Override 4506 protected boolean isForceHidden() { 4507 return mForceHiddenFlags != 0; 4508 } 4509 4510 boolean isForceHiddenForPinnedTask() { 4511 return (mForceHiddenFlags & FLAG_FORCE_HIDDEN_FOR_PINNED_TASK) != 0; 4512 } 4513 4514 @Override 4515 protected boolean isForceTranslucent() { 4516 return mForceTranslucent; 4517 } 4518 4519 @Override 4520 long getProtoFieldId() { 4521 return TASK; 4522 } 4523 4524 @Override 4525 public void setWindowingMode(int windowingMode) { 4526 // Calling Task#setWindowingMode() for leaf task since this is the a specialization of 4527 // {@link #setWindowingMode(int)} for root task. 4528 if (!isRootTask()) { 4529 super.setWindowingMode(windowingMode); 4530 return; 4531 } 4532 4533 setWindowingMode(windowingMode, false /* creating */); 4534 } 4535 4536 /** 4537 * Specialization of {@link #setWindowingMode(int)} for this subclass. 4538 * 4539 * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending 4540 * on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the 4541 * previous non-transient mode if this root task is currently in a transient mode. 4542 * @param creating {@code true} if this is being run during task construction. 4543 */ 4544 void setWindowingMode(int preferredWindowingMode, boolean creating) { 4545 mWmService.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction( 4546 preferredWindowingMode, creating)); 4547 } 4548 4549 private void setWindowingModeInSurfaceTransaction(int preferredWindowingMode, 4550 boolean creating) { 4551 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 4552 if (taskDisplayArea == null) { 4553 Slog.d(TAG, "taskDisplayArea is null, bail early"); 4554 return; 4555 } 4556 final int currentMode = getWindowingMode(); 4557 final Task topTask = getTopMostTask(); 4558 int windowingMode = preferredWindowingMode; 4559 4560 // Need to make sure windowing mode is supported. If we in the process of creating the 4561 // root task no need to resolve the windowing mode again as it is already resolved to the 4562 // right mode. 4563 if (!creating) { 4564 if (!taskDisplayArea.isValidWindowingMode(windowingMode, null /* ActivityRecord */, 4565 topTask)) { 4566 windowingMode = WINDOWING_MODE_UNDEFINED; 4567 } 4568 } 4569 4570 if (currentMode == windowingMode) { 4571 // You are already in the window mode, so we can skip most of the work below. However, 4572 // it's possible that we have inherited the current windowing mode from a parent. So, 4573 // fulfill this method's contract by setting the override mode directly. 4574 getRequestedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode); 4575 return; 4576 } 4577 4578 final ActivityRecord topActivity = getTopNonFinishingActivity(); 4579 4580 // For now, assume that the root task's windowing mode is what will actually be used 4581 // by it's activities. In the future, there may be situations where this doesn't 4582 // happen; so at that point, this message will need to handle that. 4583 int likelyResolvedMode = windowingMode; 4584 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 4585 final ConfigurationContainer parent = getParent(); 4586 likelyResolvedMode = parent != null ? parent.getWindowingMode() 4587 : WINDOWING_MODE_FULLSCREEN; 4588 } 4589 if (currentMode == WINDOWING_MODE_PINNED) { 4590 // In the case that we've disabled affecting the SysUI flags as a part of seamlessly 4591 // transferring the transform on the leash to the task, reset this state once we're 4592 // moving out of pip 4593 setCanAffectSystemUiFlags(true); 4594 // Turn on userLeaveHint so other app can enter PiP mode. 4595 mTaskSupervisor.mUserLeaving = true; 4596 // Allow entering PiP from current top most activity when we are leaving PiP. 4597 final Task topFocused = mRootWindowContainer.getTopDisplayFocusedRootTask(); 4598 if (topFocused != null) { 4599 final ActivityRecord ar = topFocused.getTopResumedActivity(); 4600 enableEnterPipOnTaskSwitch(ar, null /* toFrontTask */, ar, null /* opts */); 4601 } 4602 mRootWindowContainer.notifyActivityPipModeChanged(this, null); 4603 } 4604 if (likelyResolvedMode == WINDOWING_MODE_PINNED) { 4605 if (taskDisplayArea.getRootPinnedTask() != null) { 4606 // Can only have 1 pip at a time, so replace an existing pip 4607 taskDisplayArea.getRootPinnedTask().dismissPip(); 4608 } 4609 } 4610 if (likelyResolvedMode != WINDOWING_MODE_FULLSCREEN 4611 && topActivity != null && !topActivity.noDisplay 4612 && topActivity.canForceResizeNonResizable(likelyResolvedMode)) { 4613 // Inform the user that they are starting an app that may not work correctly in 4614 // multi-window mode. 4615 final String packageName = topActivity.info.applicationInfo.packageName; 4616 mAtmService.getTaskChangeNotificationController().notifyActivityForcedResizable( 4617 topTask.mTaskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName); 4618 } 4619 4620 mAtmService.deferWindowLayout(); 4621 try { 4622 if (topActivity != null) { 4623 mTaskSupervisor.mNoAnimActivities.add(topActivity); 4624 } 4625 super.setWindowingMode(windowingMode); 4626 4627 if (currentMode == WINDOWING_MODE_PINNED && topActivity != null) { 4628 // Try reparent pinned activity back to its original task after 4629 // onConfigurationChanged cascade finishes. This is done on Task level instead of 4630 // {@link ActivityRecord#onConfigurationChanged(Configuration)} since when we exit 4631 // PiP, we set final windowing mode on the ActivityRecord first and then on its 4632 // Task when the exit PiP transition finishes. Meanwhile, the exit transition is 4633 // always performed on its original task, reparent immediately in ActivityRecord 4634 // breaks it. 4635 if (topActivity.getLastParentBeforePip() != null) { 4636 // Do not reparent if the pinned task is in removal, indicated by the 4637 // force hidden flag. 4638 if (!isForceHidden()) { 4639 final Task lastParentBeforePip = topActivity.getLastParentBeforePip(); 4640 if (lastParentBeforePip.isAttached()) { 4641 topActivity.reparent(lastParentBeforePip, 4642 lastParentBeforePip.getChildCount() /* top */, 4643 "movePinnedActivityToOriginalTask"); 4644 final DisplayContent dc = topActivity.getDisplayContent(); 4645 if (dc != null && dc.isFixedRotationLaunchingApp(topActivity)) { 4646 // Expanding pip into new rotation, so create a rotation leash 4647 // until the display is rotated. 4648 topActivity.getOrCreateFixedRotationLeash( 4649 topActivity.getSyncTransaction()); 4650 } 4651 lastParentBeforePip.moveToFront("movePinnedActivityToOriginalTask"); 4652 } 4653 } 4654 } 4655 // Resume app-switches-allowed flag when exiting from pinned mode since 4656 // it does not follow the ActivityStarter path. 4657 if (topActivity.shouldBeVisible()) { 4658 mAtmService.resumeAppSwitches(); 4659 } 4660 } 4661 4662 if (creating) { 4663 // Nothing else to do if we don't have a window container yet. E.g. call from ctor. 4664 return; 4665 } 4666 4667 // From fullscreen to PiP. 4668 if (topActivity != null && currentMode == WINDOWING_MODE_FULLSCREEN 4669 && windowingMode == WINDOWING_MODE_PINNED 4670 && !mTransitionController.isShellTransitionsEnabled()) { 4671 mDisplayContent.mPinnedTaskController 4672 .deferOrientationChangeForEnteringPipFromFullScreenIfNeeded(); 4673 } 4674 } finally { 4675 mAtmService.continueWindowLayout(); 4676 } 4677 4678 if (!mTaskSupervisor.isRootVisibilityUpdateDeferred()) { 4679 mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); 4680 mRootWindowContainer.resumeFocusedTasksTopActivities(); 4681 } 4682 } 4683 4684 /** 4685 * Abort an incomplete pip-entry. If left in this state, it will cover everything but remain 4686 * paused. If this is needed, there is a bug -- this should only be used for recovery. 4687 */ 4688 void abortPipEnter(ActivityRecord top) { 4689 // an incomplete state has the task PINNED but the activity not. 4690 if (!inPinnedWindowingMode() || top.inPinnedWindowingMode() || !canMoveTaskToBack(this)) { 4691 return; 4692 } 4693 final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */, 4694 mTransitionController, mWmService.mSyncEngine); 4695 mTransitionController.moveToCollecting(transition); 4696 mTransitionController.requestStartTransition(transition, this, null /* remoteTransition */, 4697 null /* displayChange */); 4698 if (top.getLastParentBeforePip() != null) { 4699 final Task lastParentBeforePip = top.getLastParentBeforePip(); 4700 if (lastParentBeforePip.isAttached()) { 4701 top.reparent(lastParentBeforePip, lastParentBeforePip.getChildCount() /* top */, 4702 "movePinnedActivityToOriginalTask"); 4703 } 4704 } 4705 if (isAttached()) { 4706 setWindowingMode(WINDOWING_MODE_UNDEFINED); 4707 moveTaskToBackInner(this); 4708 } 4709 if (top.isAttached()) { 4710 top.setWindowingMode(WINDOWING_MODE_UNDEFINED); 4711 } 4712 } 4713 4714 void resumeNextFocusAfterReparent() { 4715 adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */, 4716 true /* moveDisplayToTop */); 4717 mRootWindowContainer.resumeFocusedTasksTopActivities(); 4718 // Update visibility of activities before notifying WM. This way it won't try to resize 4719 // windows that are no longer visible. 4720 mRootWindowContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, 4721 !PRESERVE_WINDOWS); 4722 } 4723 4724 final boolean isOnHomeDisplay() { 4725 return getDisplayId() == DEFAULT_DISPLAY; 4726 } 4727 4728 void moveToFront(String reason) { 4729 moveToFront(reason, null); 4730 } 4731 4732 /** 4733 * @param reason The reason for moving the root task to the front. 4734 * @param task If non-null, the task will be moved to the top of the root task. 4735 */ 4736 @VisibleForTesting 4737 void moveToFront(String reason, Task task) { 4738 if (!isAttached()) { 4739 return; 4740 } 4741 mTransitionController.recordTaskOrder(this); 4742 4743 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 4744 4745 if (!isActivityTypeHome() && returnsToHomeRootTask()) { 4746 // Make sure the root home task is behind this root task since that is where we 4747 // should return to when this root task is no longer visible. 4748 taskDisplayArea.moveHomeRootTaskToFront(reason + " returnToHome"); 4749 } 4750 4751 final Task lastFocusedTask = isRootTask() ? taskDisplayArea.getFocusedRootTask() : null; 4752 if (task == null) { 4753 task = this; 4754 } 4755 task.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */); 4756 taskDisplayArea.updateLastFocusedRootTask(lastFocusedTask, reason); 4757 } 4758 4759 /** 4760 * This moves 'task' to the back of this task and also recursively moves this task to the back 4761 * of its parents (if applicable). 4762 * 4763 * @param reason The reason for moving the root task to the back. 4764 * @param task If non-null, the task will be moved to the bottom of the root task. 4765 **/ 4766 void moveToBack(String reason, Task task) { 4767 if (!isAttached()) { 4768 return; 4769 } 4770 final TaskDisplayArea displayArea = getDisplayArea(); 4771 if (!mCreatedByOrganizer) { 4772 // If this is just a normal task, so move to back of parent and then move 'task' to 4773 // back of this. 4774 final WindowContainer parent = getParent(); 4775 final Task parentTask = parent != null ? parent.asTask() : null; 4776 if (parentTask != null) { 4777 parentTask.moveToBack(reason, this); 4778 } else { 4779 final Task lastFocusedTask = displayArea.getFocusedRootTask(); 4780 displayArea.positionChildAt(POSITION_BOTTOM, this, false /*includingParents*/); 4781 displayArea.updateLastFocusedRootTask(lastFocusedTask, reason); 4782 } 4783 if (task != null && task != this) { 4784 positionChildAtBottom(task); 4785 } 4786 return; 4787 } 4788 if (task == null || task == this) { 4789 return; 4790 } 4791 // This is a created-by-organizer task. In this case, let the organizer deal with this 4792 // task's ordering. However, we still need to move 'task' to back. The intention is that 4793 // this ends up behind the home-task so that it is made invisible; so, if the home task 4794 // is not a child of this, reparent 'task' to the back of the home task's actual parent. 4795 displayArea.positionTaskBehindHome(task); 4796 } 4797 4798 // TODO: Should each user have there own root tasks? 4799 @Override 4800 void switchUser(int userId) { 4801 if (mCurrentUser == userId) { 4802 return; 4803 } 4804 mCurrentUser = userId; 4805 4806 super.switchUser(userId); 4807 if (!isRootTask() && showToCurrentUser()) { 4808 getParent().positionChildAt(POSITION_TOP, this, false /*includeParents*/); 4809 } 4810 } 4811 4812 void minimalResumeActivityLocked(ActivityRecord r) { 4813 ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (starting new instance) " 4814 + "callers=%s", r, Debug.getCallers(5)); 4815 r.setState(RESUMED, "minimalResumeActivityLocked"); 4816 r.completeResumeLocked(); 4817 } 4818 4819 void checkReadyForSleep() { 4820 if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) { 4821 mTaskSupervisor.checkReadyForSleepLocked(true /* allowDelay */); 4822 } 4823 } 4824 4825 /** 4826 * Tries to put the activities in the root task to sleep. 4827 * 4828 * If the root task is not in a state where its activities can be put to sleep, this function 4829 * will start any necessary actions to move the root task into such a state. It is expected 4830 * that this function get called again when those actions complete. 4831 * 4832 * @param shuttingDown true when the called because the device is shutting down. 4833 * @return true if the root task finished going to sleep, false if the root task only started 4834 * the process of going to sleep (checkReadyForSleep will be called when that process finishes). 4835 */ 4836 boolean goToSleepIfPossible(boolean shuttingDown) { 4837 final int[] sleepInProgress = {0}; 4838 forAllLeafTasksAndLeafTaskFragments(taskFragment -> { 4839 if (!taskFragment.sleepIfPossible(shuttingDown)) { 4840 sleepInProgress[0]++; 4841 } 4842 }, true /* traverseTopToBottom */); 4843 return sleepInProgress[0] == 0; 4844 } 4845 4846 boolean isTopRootTaskInDisplayArea() { 4847 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 4848 return taskDisplayArea != null && taskDisplayArea.isTopRootTask(this); 4849 } 4850 4851 /** 4852 * @return {@code true} if this is the focused root task on its current display, {@code false} 4853 * otherwise. 4854 */ 4855 boolean isFocusedRootTaskOnDisplay() { 4856 return mDisplayContent != null && this == mDisplayContent.getFocusedRootTask(); 4857 } 4858 4859 /** 4860 * Make sure that all activities that need to be visible in the root task (that is, they 4861 * currently can be seen by the user) actually are and update their configuration. 4862 * @param starting The top most activity in the task. 4863 * The activity is either starting or resuming. 4864 * Caller should ensure starting activity is visible. 4865 * @param preserveWindows Flag indicating whether windows should be preserved when updating 4866 * configuration in {@link EnsureActivitiesVisibleHelper}. 4867 * @param configChanges Parts of the configuration that changed for this activity for evaluating 4868 * if the screen should be frozen as part of 4869 * {@link EnsureActivitiesVisibleHelper}. 4870 * 4871 */ 4872 void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges, 4873 boolean preserveWindows) { 4874 ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */); 4875 } 4876 4877 /** 4878 * Ensure visibility with an option to also update the configuration of visible activities. 4879 * @see #ensureActivitiesVisible(ActivityRecord, int, boolean) 4880 * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) 4881 * @param starting The top most activity in the task. 4882 * The activity is either starting or resuming. 4883 * Caller should ensure starting activity is visible. 4884 * @param notifyClients Flag indicating whether the visibility updates should be sent to the 4885 * clients in {@link EnsureActivitiesVisibleHelper}. 4886 * @param preserveWindows Flag indicating whether windows should be preserved when updating 4887 * configuration in {@link EnsureActivitiesVisibleHelper}. 4888 * @param configChanges Parts of the configuration that changed for this activity for evaluating 4889 * if the screen should be frozen as part of 4890 * {@link EnsureActivitiesVisibleHelper}. 4891 */ 4892 // TODO: Should be re-worked based on the fact that each task as a root task in most cases. 4893 void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges, 4894 boolean preserveWindows, boolean notifyClients) { 4895 mTaskSupervisor.beginActivityVisibilityUpdate(); 4896 try { 4897 forAllLeafTasks(task -> { 4898 task.updateActivityVisibilities(starting, configChanges, preserveWindows, 4899 notifyClients); 4900 }, true /* traverseTopToBottom */); 4901 4902 if (mTranslucentActivityWaiting != null && 4903 mUndrawnActivitiesBelowTopTranslucent.isEmpty()) { 4904 // Nothing is getting drawn or everything was already visible, don't wait for 4905 // timeout. 4906 notifyActivityDrawnLocked(null); 4907 } 4908 } finally { 4909 mTaskSupervisor.endActivityVisibilityUpdate(); 4910 } 4911 } 4912 4913 void checkTranslucentActivityWaiting(ActivityRecord top) { 4914 if (mTranslucentActivityWaiting != top) { 4915 mUndrawnActivitiesBelowTopTranslucent.clear(); 4916 if (mTranslucentActivityWaiting != null) { 4917 // Call the callback with a timeout indication. 4918 notifyActivityDrawnLocked(null); 4919 mTranslucentActivityWaiting = null; 4920 } 4921 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 4922 } 4923 } 4924 4925 void convertActivityToTranslucent(ActivityRecord r) { 4926 mTranslucentActivityWaiting = r; 4927 mUndrawnActivitiesBelowTopTranslucent.clear(); 4928 mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT); 4929 } 4930 4931 /** 4932 * Called as activities below the top translucent activity are redrawn. When the last one is 4933 * redrawn notify the top activity by calling 4934 * {@link Activity#onTranslucentConversionComplete}. 4935 * 4936 * @param r The most recent background activity to be drawn. Or, if r is null then a timeout 4937 * occurred and the activity will be notified immediately. 4938 */ 4939 void notifyActivityDrawnLocked(ActivityRecord r) { 4940 if ((r == null) 4941 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) && 4942 mUndrawnActivitiesBelowTopTranslucent.isEmpty())) { 4943 // The last undrawn activity below the top has just been drawn. If there is an 4944 // opaque activity at the top, notify it that it can become translucent safely now. 4945 final ActivityRecord waitingActivity = mTranslucentActivityWaiting; 4946 mTranslucentActivityWaiting = null; 4947 mUndrawnActivitiesBelowTopTranslucent.clear(); 4948 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 4949 4950 if (waitingActivity != null) { 4951 mWmService.setWindowOpaqueLocked(waitingActivity.token, false); 4952 if (waitingActivity.attachedToProcess()) { 4953 try { 4954 waitingActivity.app.getThread().scheduleTranslucentConversionComplete( 4955 waitingActivity.token, r != null); 4956 } catch (RemoteException e) { 4957 } 4958 } 4959 } 4960 } 4961 } 4962 4963 /** 4964 * Ensure that the top activity in the root task is resumed. 4965 * 4966 * @param prev The previously resumed activity, for when in the process 4967 * of pausing; can be null to call from elsewhere. 4968 * @param options Activity options. 4969 * @param deferPause When {@code true}, this will not pause back tasks. 4970 * 4971 * @return Returns true if something is being resumed, or false if 4972 * nothing happened. 4973 * 4974 * NOTE: It is not safe to call this method directly as it can cause an activity in a 4975 * non-focused root task to be resumed. 4976 * Use {@link RootWindowContainer#resumeFocusedTasksTopActivities} to resume the 4977 * right activity for the current system state. 4978 */ 4979 @GuardedBy("mService") 4980 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options, 4981 boolean deferPause) { 4982 if (mInResumeTopActivity) { 4983 // Don't even start recursing. 4984 return false; 4985 } 4986 4987 boolean someActivityResumed = false; 4988 try { 4989 // Protect against recursion. 4990 mInResumeTopActivity = true; 4991 4992 if (isLeafTask()) { 4993 if (isFocusableAndVisible()) { 4994 someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause); 4995 } 4996 } else { 4997 int idx = mChildren.size() - 1; 4998 while (idx >= 0) { 4999 final Task child = (Task) getChildAt(idx--); 5000 if (!child.isTopActivityFocusable()) { 5001 continue; 5002 } 5003 if (child.getVisibility(null /* starting */) 5004 != TASK_FRAGMENT_VISIBILITY_VISIBLE) { 5005 if (child.topRunningActivity() == null) { 5006 // Skip the task if no running activity and continue resuming next task. 5007 continue; 5008 } 5009 // Otherwise, assuming everything behind this task should also be invisible. 5010 break; 5011 } 5012 5013 someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options, 5014 deferPause); 5015 // Doing so in order to prevent IndexOOB since hierarchy might changes while 5016 // resuming activities, for example dismissing split-screen while starting 5017 // non-resizeable activity. 5018 if (idx >= mChildren.size()) { 5019 idx = mChildren.size() - 1; 5020 } 5021 } 5022 } 5023 5024 // When resuming the top activity, it may be necessary to pause the top activity (for 5025 // example, returning to the lock screen. We suppress the normal pause logic in 5026 // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the 5027 // end. We call the {@link ActivityTaskSupervisor#checkReadyForSleepLocked} again here 5028 // to ensure any necessary pause logic occurs. In the case where the Activity will be 5029 // shown regardless of the lock screen, the call to 5030 // {@link ActivityTaskSupervisor#checkReadyForSleepLocked} is skipped. 5031 final ActivityRecord next = topRunningActivity(true /* focusableOnly */); 5032 if (next == null || !next.canTurnScreenOn()) { 5033 checkReadyForSleep(); 5034 } 5035 } finally { 5036 mInResumeTopActivity = false; 5037 } 5038 5039 return someActivityResumed; 5040 } 5041 5042 /** @see #resumeTopActivityUncheckedLocked(ActivityRecord, ActivityOptions, boolean) */ 5043 @GuardedBy("mService") 5044 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { 5045 return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */); 5046 } 5047 5048 @GuardedBy("mService") 5049 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options, 5050 boolean deferPause) { 5051 if (!mAtmService.isBooting() && !mAtmService.isBooted()) { 5052 // Not ready yet! 5053 return false; 5054 } 5055 5056 final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */); 5057 if (topActivity == null) { 5058 // There are no activities left in this task, let's look somewhere else. 5059 return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options); 5060 } 5061 5062 final boolean[] resumed = new boolean[1]; 5063 final TaskFragment topFragment = topActivity.getTaskFragment(); 5064 resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause); 5065 forAllLeafTaskFragments(f -> { 5066 if (topFragment == f) { 5067 return; 5068 } 5069 if (!f.canBeResumed(null /* starting */)) { 5070 return; 5071 } 5072 resumed[0] |= f.resumeTopActivity(prev, options, deferPause); 5073 }, true); 5074 return resumed[0]; 5075 } 5076 5077 /** 5078 * Resume the next eligible activity in a focusable root task when this one does not have any 5079 * running activities left. The focus will be adjusted to the next focusable root task and 5080 * top running activities will be resumed in all focusable root tasks. However, if the 5081 * current root task is a root home task - we have to keep it focused, start and resume a 5082 * home activity on the current display instead to make sure that the display is not empty. 5083 */ 5084 private boolean resumeNextFocusableActivityWhenRootTaskIsEmpty(ActivityRecord prev, 5085 ActivityOptions options) { 5086 final String reason = "noMoreActivities"; 5087 5088 if (!isActivityTypeHome()) { 5089 final Task nextFocusedTask = adjustFocusToNextFocusableTask(reason); 5090 if (nextFocusedTask != null) { 5091 // Try to move focus to the next visible root task with a running activity if this 5092 // root task is not covering the entire screen or is on a secondary display with 5093 // no home root task. 5094 return mRootWindowContainer.resumeFocusedTasksTopActivities(nextFocusedTask, 5095 prev, null /* targetOptions */); 5096 } 5097 } 5098 5099 // If the current root task is a root home task, or if focus didn't switch to a different 5100 // root task - just start up the Launcher... 5101 ActivityOptions.abort(options); 5102 ProtoLog.d(WM_DEBUG_STATES, "resumeNextFocusableActivityWhenRootTaskIsEmpty: %s, " 5103 + "go home", reason); 5104 return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea()); 5105 } 5106 5107 void startActivityLocked(ActivityRecord r, @Nullable Task topTask, boolean newTask, 5108 boolean isTaskSwitch, ActivityOptions options, @Nullable ActivityRecord sourceRecord) { 5109 final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate(topTask); 5110 Task rTask = r.getTask(); 5111 final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront(); 5112 final boolean isOrhasTask = rTask == this || hasChild(rTask); 5113 // mLaunchTaskBehind tasks get placed at the back of the task stack. 5114 if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) { 5115 // Last activity in task had been removed or ActivityManagerService is reusing task. 5116 // Insert or replace. 5117 // Might not even be in. 5118 positionChildAtTop(rTask); 5119 } 5120 Task task = null; 5121 if (!newTask && isOrhasTask && !r.shouldBeVisible()) { 5122 ActivityOptions.abort(options); 5123 return; 5124 } 5125 5126 // Place a new activity at top of root task, so it is next to interact with the user. 5127 5128 // If we are not placing the new activity frontmost, we do not want to deliver the 5129 // onUserLeaving callback to the actual frontmost activity 5130 final Task activityTask = r.getTask(); 5131 if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) { 5132 mTaskSupervisor.mUserLeaving = false; 5133 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 5134 "startActivity() behind front, mUserLeaving=false"); 5135 } 5136 5137 task = activityTask; 5138 5139 // Slot the activity into the history root task and proceed 5140 ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s " 5141 + "callers: %s", r, task, new RuntimeException("here").fillInStackTrace()); 5142 5143 if (isActivityTypeHomeOrRecents() && getActivityBelow(r) == null) { 5144 // If this is the first activity, don't do any fancy animations, 5145 // because there is nothing for it to animate on top of. 5146 ActivityOptions.abort(options); 5147 return; 5148 } 5149 5150 if (!allowMoveToFront) { 5151 // The transition animation and starting window are not needed if 5152 // {@code allowMoveToFront} is false, because the activity won't be visible. 5153 ActivityOptions.abort(options); 5154 return; 5155 } 5156 5157 final DisplayContent dc = mDisplayContent; 5158 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 5159 "Prepare open transition: starting " + r); 5160 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 5161 dc.prepareAppTransition(TRANSIT_NONE); 5162 mTaskSupervisor.mNoAnimActivities.add(r); 5163 mTransitionController.setNoAnimation(r); 5164 } else { 5165 dc.prepareAppTransition(TRANSIT_OPEN); 5166 mTaskSupervisor.mNoAnimActivities.remove(r); 5167 } 5168 if (newTask && !r.mLaunchTaskBehind) { 5169 // If a new task is being launched, then mark the existing top activity as 5170 // supporting picture-in-picture while pausing only if the starting activity 5171 // would not be considered an overlay on top of the current activity 5172 // (eg. not fullscreen, or the assistant) 5173 enableEnterPipOnTaskSwitch(pipCandidate, 5174 null /* toFrontTask */, r, options); 5175 } 5176 boolean doShow = true; 5177 if (newTask) { 5178 // Even though this activity is starting fresh, we still need 5179 // to reset it to make sure we apply affinities to move any 5180 // existing activities from other tasks in to it. 5181 // If the caller has requested that the target task be 5182 // reset, then do so. 5183 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 5184 resetTaskIfNeeded(r, r); 5185 doShow = topRunningNonDelayedActivityLocked(null) == r; 5186 } 5187 } else if (options != null && options.getAnimationType() 5188 == ActivityOptions.ANIM_SCENE_TRANSITION) { 5189 doShow = false; 5190 } 5191 if (options != null && options.getDisableStartingWindow()) { 5192 doShow = false; 5193 } 5194 if (r.mLaunchTaskBehind) { 5195 // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we 5196 // tell WindowManager that r is visible even though it is at the back of the root 5197 // task. 5198 r.setVisibility(true); 5199 ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 5200 // If launching behind, the app will start regardless of what's above it, so mark it 5201 // as unknown even before prior `pause`. This also prevents a race between set-ready 5202 // and activityPause. Launch-behind is basically only used for dream now. 5203 if (!r.isVisibleRequested()) { 5204 r.notifyUnknownVisibilityLaunchedForKeyguardTransition(); 5205 } 5206 // Go ahead to execute app transition for this activity since the app transition 5207 // will not be triggered through the resume channel. 5208 mDisplayContent.executeAppTransition(); 5209 } else if (SHOW_APP_STARTING_PREVIEW && doShow) { 5210 // Figure out if we are transitioning from another activity that is 5211 // "has the same starting icon" as the next one. This allows the 5212 // window manager to keep the previous window it had previously 5213 // created, if it still had one. 5214 Task baseTask = r.getTask(); 5215 final ActivityRecord prev = baseTask.getActivity( 5216 a -> a.mStartingData != null && a.showToCurrentUser()); 5217 mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask, 5218 isTaskSwitch, sourceRecord); 5219 } 5220 } 5221 5222 /** On Task switch, finds the top activity that supports PiP. */ 5223 @Nullable 5224 static ActivityRecord findEnterPipOnTaskSwitchCandidate(@Nullable Task topTask) { 5225 if (topTask == null) { 5226 return null; 5227 } 5228 final ActivityRecord[] candidate = new ActivityRecord[1]; 5229 topTask.forAllLeafTaskFragments(tf -> { 5230 // Find the top activity that may enter Pip while pausing. 5231 final ActivityRecord topActivity = tf.getTopNonFinishingActivity(); 5232 if (topActivity != null && topActivity.isState(RESUMED, PAUSING) 5233 && topActivity.supportsPictureInPicture()) { 5234 candidate[0] = topActivity; 5235 return true; 5236 } 5237 return false; 5238 }); 5239 return candidate[0]; 5240 } 5241 5242 /** 5243 * When switching to another Task, marks the currently PiP candidate activity as supporting to 5244 * enter PiP while it is pausing (if supported). Only one of {@param toFrontTask} or 5245 * {@param toFrontActivity} should be set. 5246 */ 5247 private static void enableEnterPipOnTaskSwitch(@Nullable ActivityRecord pipCandidate, 5248 @Nullable Task toFrontTask, @Nullable ActivityRecord toFrontActivity, 5249 @Nullable ActivityOptions opts) { 5250 if (pipCandidate == null) { 5251 return; 5252 } 5253 if (opts != null && opts.disallowEnterPictureInPictureWhileLaunching()) { 5254 // Ensure the caller has requested not to trigger auto-enter PiP 5255 return; 5256 } 5257 if (pipCandidate.inPinnedWindowingMode()) { 5258 // Ensure that we do not trigger entering PiP an activity on the root pinned task. 5259 return; 5260 } 5261 final Task targetRootTask = toFrontTask != null ? toFrontTask.getRootTask() 5262 : toFrontActivity != null ? toFrontActivity.getRootTask() : null; 5263 if (targetRootTask == null) { 5264 Slog.e(TAG, "No root task for enter pip, both to front task and activity are null?"); 5265 return; 5266 } 5267 final boolean isTransient = opts != null && opts.getTransientLaunch() 5268 || (targetRootTask.mTransitionController.isTransientHide(targetRootTask)); 5269 5270 // Ensure the task/activity being brought forward is not the assistant and is not transient 5271 // nor transient hide target. In the case of transient-launch, we want to wait until the end 5272 // of the transition and only allow to enter pip on task switch after the transient launch 5273 // was committed. 5274 pipCandidate.supportsEnterPipOnTaskSwitch = !targetRootTask.isActivityTypeAssistant() 5275 && !isTransient; 5276 } 5277 5278 /** 5279 * Reset the task by reparenting the activities that have same affinity to the task or 5280 * reparenting the activities that have different affinityies out of the task, while these 5281 * activities allow task reparenting. 5282 * 5283 * @param taskTop Top activity of the task might be reset. 5284 * @param newActivity The activity that going to be started. 5285 * @return The non-finishing top activity of the task after reset or the original task top 5286 * activity if all activities within the task are finishing. 5287 */ 5288 ActivityRecord resetTaskIfNeeded(ActivityRecord taskTop, ActivityRecord newActivity) { 5289 final boolean forceReset = 5290 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0; 5291 final Task task = taskTop.getTask(); 5292 5293 // If ActivityOptions are moved out and need to be aborted or moved to taskTop. 5294 final ActivityOptions topOptions; 5295 5296 // Set the task to be reused, so the TaskFragment#mClearedTaskForReuse can be set if the 5297 // embedded activities are finished while reset task. 5298 mReuseTask = true; 5299 try { 5300 topOptions = sResetTargetTaskHelper.process(task, forceReset); 5301 } finally { 5302 mReuseTask = false; 5303 } 5304 5305 if (mChildren.contains(task)) { 5306 final ActivityRecord newTop = task.getTopNonFinishingActivity(); 5307 if (newTop != null) { 5308 taskTop = newTop; 5309 } 5310 } 5311 5312 if (topOptions != null) { 5313 // If we got some ActivityOptions from an activity on top that 5314 // was removed from the task, propagate them to the new real top. 5315 taskTop.updateOptionsLocked(topOptions); 5316 } 5317 5318 return taskTop; 5319 } 5320 5321 /** 5322 * Finish the topmost activity that belongs to the crashed app. We may also finish the activity 5323 * that requested launch of the crashed one to prevent launch-crash loop. 5324 * @param app The app that crashed. 5325 * @param reason Reason to perform this action. 5326 * @return The task that was finished in this root task, {@code null} if top running activity 5327 * does not belong to the crashed app. 5328 */ 5329 final Task finishTopCrashedActivityLocked(WindowProcessController app, String reason) { 5330 final ActivityRecord r = topRunningActivity(); 5331 if (r == null || r.app != app) { 5332 return null; 5333 } 5334 if (r.isActivityTypeHome() && mAtmService.mHomeProcess == app) { 5335 // Home activities should not be force-finished as we have nothing else to go 5336 // back to. AppErrors will get to it after two crashes in MIN_CRASH_INTERVAL. 5337 Slog.w(TAG, " Not force finishing home activity " 5338 + r.intent.getComponent().flattenToShortString()); 5339 return null; 5340 } 5341 Slog.w(TAG, " Force finishing activity " 5342 + r.intent.getComponent().flattenToShortString()); 5343 Task finishedTask = r.getTask(); 5344 mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED); 5345 r.finishIfPossible(reason, false /* oomAdj */); 5346 5347 // Also terminate any activities below it that aren't yet stopped, to avoid a situation 5348 // where one will get re-start our crashing activity once it gets resumed again. 5349 final ActivityRecord activityBelow = getActivityBelow(r); 5350 if (activityBelow != null) { 5351 if (activityBelow.isState(STARTED, RESUMED, PAUSING, PAUSED)) { 5352 if (!activityBelow.isActivityTypeHome() 5353 || mAtmService.mHomeProcess != activityBelow.app) { 5354 Slog.w(TAG, " Force finishing activity " 5355 + activityBelow.intent.getComponent().flattenToShortString()); 5356 activityBelow.finishIfPossible(reason, false /* oomAdj */); 5357 } 5358 } 5359 } 5360 5361 return finishedTask; 5362 } 5363 5364 void finishIfVoiceTask(IBinder binder) { 5365 if (voiceSession != null && voiceSession.asBinder() == binder) { 5366 forAllActivities((r) -> { 5367 if (r.finishing) return; 5368 r.finishIfPossible("finish-voice", false /* oomAdj */); 5369 mAtmService.updateOomAdj(); 5370 }); 5371 } else { 5372 // Check if any of the activities are using voice 5373 final PooledPredicate f = PooledLambda.obtainPredicate( 5374 Task::finishIfVoiceActivity, PooledLambda.__(ActivityRecord.class), 5375 binder); 5376 forAllActivities(f); 5377 f.recycle(); 5378 } 5379 } 5380 5381 private static boolean finishIfVoiceActivity(ActivityRecord r, IBinder binder) { 5382 if (r.voiceSession == null || r.voiceSession.asBinder() != binder) return false; 5383 // Inform of cancellation 5384 r.clearVoiceSessionLocked(); 5385 try { 5386 r.app.getThread().scheduleLocalVoiceInteractionStarted(r.token, null); 5387 } catch (RemoteException re) { 5388 // Ok Boomer... 5389 } 5390 r.mAtmService.finishRunningVoiceLocked(); 5391 return true; 5392 } 5393 5394 /** @return true if the root task behind this one is a standard activity type. */ 5395 private boolean inFrontOfStandardRootTask() { 5396 final TaskDisplayArea taskDisplayArea = getDisplayArea(); 5397 if (taskDisplayArea == null) { 5398 return false; 5399 } 5400 final boolean[] hasFound = new boolean[1]; 5401 final Task rootTaskBehind = taskDisplayArea.getRootTask( 5402 // From top to bottom, find the one behind this Task. 5403 task -> { 5404 if (hasFound[0]) { 5405 return true; 5406 } 5407 if (task == this) { 5408 // The next one is our target. 5409 hasFound[0] = true; 5410 } 5411 return false; 5412 }); 5413 return rootTaskBehind != null && rootTaskBehind.isActivityTypeStandard(); 5414 } 5415 5416 boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) { 5417 // Basic case: for simple app-centric recents, we need to recreate 5418 // the task if the affinity has changed. 5419 5420 final String affinity = ActivityRecord.computeTaskAffinity(destAffinity, srec.getUid()); 5421 if (srec == null || srec.getTask().affinity == null 5422 || !srec.getTask().affinity.equals(affinity)) { 5423 return true; 5424 } 5425 // Document-centric case: an app may be split in to multiple documents; 5426 // they need to re-create their task if this current activity is the root 5427 // of a document, unless simply finishing it will return them to the 5428 // correct app behind. 5429 final Task task = srec.getTask(); 5430 if (srec.isRootOfTask() && task.getBaseIntent() != null 5431 && task.getBaseIntent().isDocument()) { 5432 // Okay, this activity is at the root of its task. What to do, what to do... 5433 if (!inFrontOfStandardRootTask()) { 5434 // Finishing won't return to an application, so we need to recreate. 5435 return true; 5436 } 5437 // We now need to get the task below it to determine what to do. 5438 final Task prevTask = getTaskBelow(task); 5439 if (prevTask == null) { 5440 Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec); 5441 return false; 5442 } 5443 if (!task.affinity.equals(prevTask.affinity)) { 5444 // These are different apps, so need to recreate. 5445 return true; 5446 } 5447 } 5448 return false; 5449 } 5450 5451 boolean navigateUpTo(ActivityRecord srec, Intent destIntent, String resolvedType, 5452 NeededUriGrants destGrants, int resultCode, Intent resultData, 5453 NeededUriGrants resultGrants) { 5454 if (!srec.attachedToProcess()) { 5455 // Nothing to do if the caller is not attached, because this method should be called 5456 // from an alive activity. 5457 return false; 5458 } 5459 final Task task = srec.getTask(); 5460 if (!srec.isDescendantOf(this)) { 5461 return false; 5462 } 5463 5464 ActivityRecord parent = task.getActivityBelow(srec); 5465 boolean foundParentInTask = false; 5466 final ComponentName dest = destIntent.getComponent(); 5467 if (task.getBottomMostActivity() != srec && dest != null) { 5468 final ActivityRecord candidate = task.getActivity( 5469 (ar) -> ar.info.packageName.equals(dest.getPackageName()) 5470 && ar.info.name.equals(dest.getClassName()), srec, 5471 false /*includeBoundary*/, true /*traverseTopToBottom*/); 5472 if (candidate != null) { 5473 parent = candidate; 5474 foundParentInTask = true; 5475 } 5476 } 5477 5478 // TODO: There is a dup. of this block of code in ActivityTaskManagerService.finishActivity 5479 // We should consolidate. 5480 IActivityController controller = mAtmService.mController; 5481 if (controller != null) { 5482 ActivityRecord next = topRunningActivity(srec.token, INVALID_TASK_ID); 5483 if (next != null) { 5484 // ask watcher if this is allowed 5485 boolean resumeOK = true; 5486 try { 5487 resumeOK = controller.activityResuming(next.packageName); 5488 } catch (RemoteException e) { 5489 mAtmService.mController = null; 5490 Watchdog.getInstance().setActivityController(null); 5491 } 5492 5493 if (!resumeOK) { 5494 return false; 5495 } 5496 } 5497 } 5498 final long origId = Binder.clearCallingIdentity(); 5499 5500 final int[] resultCodeHolder = new int[1]; 5501 resultCodeHolder[0] = resultCode; 5502 final Intent[] resultDataHolder = new Intent[1]; 5503 resultDataHolder[0] = resultData; 5504 final NeededUriGrants[] resultGrantsHolder = new NeededUriGrants[1]; 5505 resultGrantsHolder[0] = resultGrants; 5506 final ActivityRecord finalParent = parent; 5507 task.forAllActivities((ar) -> { 5508 if (ar == finalParent) return true; 5509 5510 ar.finishIfPossible(resultCodeHolder[0], resultDataHolder[0], resultGrantsHolder[0], 5511 "navigate-up", true /* oomAdj */); 5512 // Only return the supplied result for the first activity finished 5513 resultCodeHolder[0] = Activity.RESULT_CANCELED; 5514 resultDataHolder[0] = null; 5515 return false; 5516 }, srec, true, true); 5517 resultCode = resultCodeHolder[0]; 5518 resultData = resultDataHolder[0]; 5519 5520 if (parent != null && foundParentInTask) { 5521 final int callingUid = srec.info.applicationInfo.uid; 5522 // TODO(b/64750076): Check if calling pid should really be -1. 5523 final int res = mAtmService.getActivityStartController() 5524 .obtainStarter(destIntent, "navigateUpTo") 5525 .setResolvedType(resolvedType) 5526 .setUserId(srec.mUserId) 5527 .setCaller(srec.app.getThread()) 5528 .setResultTo(parent.token) 5529 .setIntentGrants(destGrants) 5530 .setCallingPid(-1) 5531 .setCallingUid(callingUid) 5532 .setCallingPackage(srec.packageName) 5533 .setCallingFeatureId(parent.launchedFromFeatureId) 5534 .setRealCallingPid(-1) 5535 .setRealCallingUid(callingUid) 5536 .setComponentSpecified(true) 5537 .execute(); 5538 foundParentInTask = isStartResultSuccessful(res); 5539 if (res == ActivityManager.START_SUCCESS) { 5540 parent.finishIfPossible(resultCode, resultData, resultGrants, 5541 "navigate-top", true /* oomAdj */); 5542 } 5543 } 5544 Binder.restoreCallingIdentity(origId); 5545 return foundParentInTask; 5546 } 5547 5548 void removeLaunchTickMessages() { 5549 forAllActivities(ActivityRecord::removeLaunchTickRunnable); 5550 } 5551 5552 private void updateTransitLocked(@WindowManager.TransitionType int transit, 5553 ActivityOptions options) { 5554 if (options != null) { 5555 ActivityRecord r = topRunningActivity(); 5556 if (r != null && !r.isState(RESUMED)) { 5557 r.updateOptionsLocked(options); 5558 } else { 5559 ActivityOptions.abort(options); 5560 } 5561 } 5562 mDisplayContent.prepareAppTransition(transit); 5563 } 5564 5565 final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options, 5566 AppTimeTracker timeTracker, String reason) { 5567 moveTaskToFront(tr, noAnimation, options, timeTracker, !DEFER_RESUME, reason); 5568 } 5569 5570 final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options, 5571 AppTimeTracker timeTracker, boolean deferResume, String reason) { 5572 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr); 5573 5574 final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate( 5575 getDisplayArea().getTopRootTask()); 5576 5577 if (tr != this && !tr.isDescendantOf(this)) { 5578 // nothing to do! 5579 if (noAnimation) { 5580 ActivityOptions.abort(options); 5581 } else { 5582 updateTransitLocked(TRANSIT_TO_FRONT, options); 5583 } 5584 return; 5585 } 5586 5587 if (timeTracker != null) { 5588 // The caller wants a time tracker associated with this task. 5589 tr.forAllActivities(a -> { a.appTimeTracker = timeTracker; }); 5590 } 5591 5592 try { 5593 // Defer updating the IME target since the new IME target will try to get computed 5594 // before updating all closing and opening apps, which can cause the ime target to 5595 // get calculated incorrectly. 5596 mDisplayContent.deferUpdateImeTarget(); 5597 5598 // Don't refocus if invisible to current user 5599 final ActivityRecord top = tr.getTopNonFinishingActivity(); 5600 if (top == null || !top.showToCurrentUser()) { 5601 positionChildAtTop(tr); 5602 if (top != null) { 5603 mTaskSupervisor.mRecentTasks.add(top.getTask()); 5604 } 5605 ActivityOptions.abort(options); 5606 return; 5607 } 5608 5609 // Set focus to the top running activity of this task and move all its parents to top. 5610 top.moveFocusableActivityToTop(reason); 5611 5612 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr); 5613 if (noAnimation) { 5614 mDisplayContent.prepareAppTransition(TRANSIT_NONE); 5615 mTaskSupervisor.mNoAnimActivities.add(top); 5616 ActivityOptions.abort(options); 5617 } else { 5618 updateTransitLocked(TRANSIT_TO_FRONT, options); 5619 } 5620 5621 // If a new task is moved to the front, then mark the existing top activity as 5622 // supporting 5623 5624 // picture-in-picture while paused only if the task would not be considered an oerlay 5625 // on top 5626 // of the current activity (eg. not fullscreen, or the assistant) 5627 enableEnterPipOnTaskSwitch(pipCandidate, tr, null /* toFrontActivity */, options); 5628 5629 if (!deferResume) { 5630 mRootWindowContainer.resumeFocusedTasksTopActivities(); 5631 } 5632 } finally { 5633 mDisplayContent.continueUpdateImeTarget(); 5634 } 5635 } 5636 5637 private boolean canMoveTaskToBack(Task task) { 5638 // In LockTask mode, moving a locked task to the back of the root task may expose unlocked 5639 // ones. Therefore we need to check if this operation is allowed. 5640 if (!mAtmService.getLockTaskController().canMoveTaskToBack(task)) { 5641 return false; 5642 } 5643 5644 // If we have a watcher, preflight the move before committing to it. First check 5645 // for *other* available tasks, but if none are available, then try again allowing the 5646 // current task to be selected. 5647 if (isTopRootTaskInDisplayArea() && mAtmService.mController != null) { 5648 ActivityRecord next = topRunningActivity(null, task.mTaskId); 5649 if (next == null) { 5650 next = topRunningActivity(null, INVALID_TASK_ID); 5651 } 5652 if (next != null) { 5653 // ask watcher if this is allowed 5654 boolean moveOK = true; 5655 try { 5656 moveOK = mAtmService.mController.activityResuming(next.packageName); 5657 } catch (RemoteException e) { 5658 mAtmService.mController = null; 5659 Watchdog.getInstance().setActivityController(null); 5660 } 5661 if (!moveOK) { 5662 return false; 5663 } 5664 } 5665 } 5666 return true; 5667 } 5668 5669 /** 5670 * Worker method for rearranging history task. Implements the function of moving all 5671 * activities for a specific task (gathering them if disjoint) into a single group at the 5672 * bottom of the root task. 5673 * 5674 * If a watcher is installed, the action is preflighted and the watcher has an opportunity 5675 * to premeptively cancel the move. 5676 * 5677 * If this is a pinned task, it will be removed instead of rearranged. 5678 * 5679 * @param tr The task to collect and move to the bottom. 5680 * @return Returns true if the move completed, false if not. 5681 */ 5682 boolean moveTaskToBack(Task tr) { 5683 Slog.i(TAG, "moveTaskToBack: " + tr); 5684 5685 if (!canMoveTaskToBack(tr)) return false; 5686 5687 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" 5688 + tr.mTaskId); 5689 5690 if (mTransitionController.isShellTransitionsEnabled()) { 5691 final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */, 5692 mTransitionController, mWmService.mSyncEngine); 5693 // Guarantee that this gets its own transition by queueing on SyncEngine 5694 mTransitionController.startCollectOrQueue(transition, 5695 (deferred) -> { 5696 // Need to check again if deferred since the system might 5697 // be in a different state. 5698 if (!isAttached() || (deferred && !canMoveTaskToBack(tr))) { 5699 Slog.e(TAG, "Failed to move task to back after saying we could: " 5700 + tr.mTaskId); 5701 transition.abort(); 5702 return; 5703 } 5704 mTransitionController.requestStartTransition(transition, tr, 5705 null /* remoteTransition */, null /* displayChange */); 5706 mTransitionController.collect(tr); 5707 moveTaskToBackInner(tr); 5708 }); 5709 } else { 5710 // Skip the transition for pinned task. 5711 if (!inPinnedWindowingMode()) { 5712 mDisplayContent.prepareAppTransition(TRANSIT_TO_BACK); 5713 } 5714 moveTaskToBackInner(tr); 5715 } 5716 return true; 5717 } 5718 5719 private boolean moveTaskToBackInner(@NonNull Task task) { 5720 if (mTransitionController.isShellTransitionsEnabled()) { 5721 // Preventing from update surface position for WindowState if configuration changed, 5722 // because the position is depends on WindowFrame, so update the position before 5723 // relayout will only update it to "old" position. 5724 mAtmService.deferWindowLayout(); 5725 } 5726 try { 5727 moveToBack("moveTaskToBackInner", task); 5728 5729 if (inPinnedWindowingMode()) { 5730 mTaskSupervisor.removeRootTask(this); 5731 return true; 5732 } 5733 5734 mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */, 5735 mDisplayContent.mDisplayId, false /* markFrozenIfConfigChanged */, 5736 false /* deferResume */); 5737 } finally { 5738 if (mTransitionController.isShellTransitionsEnabled()) { 5739 mAtmService.continueWindowLayout(); 5740 } 5741 } 5742 ActivityRecord topActivity = getDisplayArea().topRunningActivity(); 5743 Task topRootTask = topActivity.getRootTask(); 5744 if (topRootTask != null && topRootTask != this && topActivity.isState(RESUMED)) { 5745 // Usually resuming a top activity triggers the next app transition, but nothing's got 5746 // resumed in this case, so we need to execute it explicitly. 5747 mDisplayContent.executeAppTransition(); 5748 mDisplayContent.setFocusedApp(topActivity); 5749 } else { 5750 mRootWindowContainer.resumeFocusedTasksTopActivities(); 5751 } 5752 return true; 5753 } 5754 5755 boolean willActivityBeVisible(IBinder token) { 5756 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 5757 if (r == null) { 5758 return false; 5759 } 5760 5761 if (!r.shouldBeVisible()) return false; 5762 5763 if (r.finishing) Slog.e(TAG, "willActivityBeVisible: Returning false," 5764 + " would have returned true for r=" + r); 5765 return !r.finishing; 5766 } 5767 5768 void unhandledBackLocked() { 5769 final ActivityRecord topActivity = getTopMostActivity(); 5770 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, 5771 "Performing unhandledBack(): top activity: " + topActivity); 5772 if (topActivity != null) { 5773 topActivity.finishIfPossible("unhandled-back", true /* oomAdj */); 5774 } 5775 } 5776 5777 boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, 5778 String dumpPackage, final boolean needSep) { 5779 return dump(" ", fd, pw, dumpAll, dumpClient, dumpPackage, needSep, null /* header */); 5780 } 5781 5782 @Override 5783 void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) { 5784 super.dumpInner(prefix, pw, dumpAll, dumpPackage); 5785 if (mCreatedByOrganizer) { 5786 pw.println(prefix + " mCreatedByOrganizer=true"); 5787 } 5788 if (mLastNonFullscreenBounds != null) { 5789 pw.print(prefix); pw.print(" mLastNonFullscreenBounds="); 5790 pw.println(mLastNonFullscreenBounds); 5791 } 5792 if (isLeafTask()) { 5793 pw.println(prefix + " isSleeping=" + shouldSleepActivities()); 5794 printThisActivity(pw, getTopPausingActivity(), dumpPackage, false, 5795 prefix + " topPausingActivity=", null); 5796 printThisActivity(pw, getTopResumedActivity(), dumpPackage, false, 5797 prefix + " topResumedActivity=", null); 5798 if (mMinWidth != INVALID_MIN_SIZE || mMinHeight != INVALID_MIN_SIZE) { 5799 pw.print(prefix); pw.print(" mMinWidth="); pw.print(mMinWidth); 5800 pw.print(" mMinHeight="); pw.println(mMinHeight); 5801 } 5802 } 5803 } 5804 5805 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name, @UserIdInt int userId) { 5806 ArrayList<ActivityRecord> activities = new ArrayList<>(); 5807 5808 if ("all".equals(name)) { 5809 forAllActivities((Consumer<ActivityRecord>) activities::add); 5810 } else if ("top".equals(name)) { 5811 final ActivityRecord topActivity = getTopMostActivity(); 5812 if (topActivity != null) { 5813 activities.add(topActivity); 5814 } 5815 } else { 5816 ActivityManagerService.ItemMatcher matcher = new ActivityManagerService.ItemMatcher(); 5817 matcher.build(name); 5818 5819 forAllActivities((r) -> { 5820 if (matcher.match(r, r.intent.getComponent())) { 5821 activities.add(r); 5822 } 5823 }); 5824 } 5825 if (userId != UserHandle.USER_ALL) { 5826 for (int i = activities.size() - 1; i >= 0; --i) { 5827 if (activities.get(i).mUserId != userId) { 5828 activities.remove(i); 5829 } 5830 } 5831 } 5832 return activities; 5833 } 5834 5835 ActivityRecord restartPackage(String packageName) { 5836 ActivityRecord starting = topRunningActivity(); 5837 5838 // All activities that came from the package must be 5839 // restarted as if there was a config change. 5840 forAllActivities(r -> { 5841 if (!r.info.packageName.equals(packageName)) return; 5842 r.forceNewConfig = true; 5843 if (starting != null && r == starting && r.isVisibleRequested()) { 5844 r.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT); 5845 } 5846 }); 5847 5848 return starting; 5849 } 5850 5851 Task reuseOrCreateTask(ActivityInfo info, Intent intent, boolean toTop) { 5852 return reuseOrCreateTask(info, intent, null /*voiceSession*/, null /*voiceInteractor*/, 5853 toTop, null /*activity*/, null /*source*/, null /*options*/); 5854 } 5855 5856 // TODO: Can be removed once we change callpoints creating root tasks to be creating tasks. 5857 /** Either returns this current task to be re-used or creates a new child task. */ 5858 Task reuseOrCreateTask(ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, 5859 IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity, 5860 ActivityRecord source, ActivityOptions options) { 5861 5862 Task task; 5863 if (canReuseAsLeafTask()) { 5864 // This root task will only contain one task, so just return itself since all root 5865 // tasks ara now tasks and all tasks are now root tasks. 5866 task = reuseAsLeafTask(voiceSession, voiceInteractor, intent, info, activity); 5867 } else { 5868 // Create child task since this root task can contain multiple tasks. 5869 final int taskId = activity != null 5870 ? mTaskSupervisor.getNextTaskIdForUser(activity.mUserId) 5871 : mTaskSupervisor.getNextTaskIdForUser(); 5872 final int activityType = getActivityType(); 5873 task = new Task.Builder(mAtmService) 5874 .setTaskId(taskId) 5875 .setActivityInfo(info) 5876 .setActivityOptions(options) 5877 .setIntent(intent) 5878 .setVoiceSession(voiceSession) 5879 .setVoiceInteractor(voiceInteractor) 5880 .setOnTop(toTop) 5881 .setParent(this) 5882 .build(); 5883 } 5884 5885 int displayId = getDisplayId(); 5886 if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY; 5887 final boolean isLockscreenShown = mAtmService.mTaskSupervisor.getKeyguardController() 5888 .isKeyguardOrAodShowing(displayId); 5889 if (!mTaskSupervisor.getLaunchParamsController() 5890 .layoutTask(task, info.windowLayout, activity, source, options) 5891 && !getRequestedOverrideBounds().isEmpty() 5892 && task.isResizeable() && !isLockscreenShown) { 5893 task.setBounds(getRequestedOverrideBounds()); 5894 } 5895 5896 return task; 5897 } 5898 5899 /** Return {@code true} if this task can be reused as leaf task. */ 5900 private boolean canReuseAsLeafTask() { 5901 // Cannot be reused as leaf task if this task is created by organizer or having child tasks. 5902 if (mCreatedByOrganizer || !isLeafTask()) { 5903 return false; 5904 } 5905 5906 // Existing Tasks can be reused if a new root task will be created anyway. 5907 final int windowingMode = getWindowingMode(); 5908 final int activityType = getActivityType(); 5909 return DisplayContent.alwaysCreateRootTask(windowingMode, activityType); 5910 } 5911 5912 void addChild(WindowContainer child, final boolean toTop, boolean showForAllUsers) { 5913 Task task = child.asTask(); 5914 try { 5915 if (task != null) { 5916 task.setForceShowForAllUsers(showForAllUsers); 5917 } 5918 // We only want to move the parents to the parents if we are creating this task at the 5919 // top of its root task. 5920 addChild(child, toTop ? MAX_VALUE : 0, toTop /*moveParents*/); 5921 } finally { 5922 if (task != null) { 5923 task.setForceShowForAllUsers(false); 5924 } 5925 } 5926 } 5927 5928 public void setAlwaysOnTop(boolean alwaysOnTop) { 5929 // {@link #isAwaysonTop} overrides the original behavior which also evaluates if this 5930 // task is force hidden, so super.isAlwaysOnTop() is used here to see whether the 5931 // alwaysOnTop attributes should be updated. 5932 if (super.isAlwaysOnTop() == alwaysOnTop) { 5933 return; 5934 } 5935 super.setAlwaysOnTop(alwaysOnTop); 5936 // positionChildAtTop() must be called even when always on top gets turned off because we 5937 // need to make sure that the root task is moved from among always on top windows to 5938 // below other always on top windows. Since the position the root task should be inserted 5939 // into is calculated properly in {@link DisplayContent#getTopInsertPosition()} in both 5940 // cases, we can just request that the root task is put at top here. 5941 // Don't bother moving task to top if this task is force hidden and invisible to user. 5942 if (!isForceHidden()) { 5943 getDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */); 5944 } 5945 } 5946 5947 void dismissPip() { 5948 if (!isActivityTypeStandardOrUndefined()) { 5949 throw new IllegalArgumentException( 5950 "You can't move tasks from non-standard root tasks."); 5951 } 5952 if (getWindowingMode() != WINDOWING_MODE_PINNED) { 5953 throw new IllegalArgumentException( 5954 "Can't exit pinned mode if it's not pinned already."); 5955 } 5956 5957 mWmService.inSurfaceTransaction(() -> { 5958 final Task task = getBottomMostTask(); 5959 setWindowingMode(WINDOWING_MODE_UNDEFINED); 5960 5961 // Task could have been removed from the hierarchy due to windowing mode change 5962 // where its only child is reparented back to their original parent task. 5963 if (isAttached()) { 5964 getDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */); 5965 } 5966 5967 mTaskSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, this); 5968 }); 5969 } 5970 5971 private int setBounds(Rect existing, Rect bounds) { 5972 if (equivalentBounds(existing, bounds)) { 5973 return BOUNDS_CHANGE_NONE; 5974 } 5975 5976 return setBoundsUnchecked(!inMultiWindowMode() ? null : bounds); 5977 } 5978 5979 @Override 5980 public void getBounds(Rect bounds) { 5981 bounds.set(getBounds()); 5982 } 5983 5984 /** 5985 * Put a Task in this root task. Used for adding only. 5986 * When task is added to top of the root task, the entire branch of the hierarchy (including 5987 * root task and display) will be brought to top. 5988 * @param child The child to add. 5989 * @param position Target position to add the task to. 5990 */ 5991 private void addChild(WindowContainer child, int position, boolean moveParents) { 5992 // Add child task. 5993 addChild(child, null); 5994 5995 // Move child to a proper position, as some restriction for position might apply. 5996 positionChildAt(position, child, moveParents /* includingParents */); 5997 } 5998 5999 void positionChildAtTop(Task child) { 6000 if (child == null) { 6001 // TODO: Fix the call-points that cause this to happen. 6002 return; 6003 } 6004 6005 if (child == this) { 6006 // TODO: Fix call-points 6007 moveToFront("positionChildAtTop"); 6008 return; 6009 } 6010 6011 positionChildAt(POSITION_TOP, child, true /* includingParents */); 6012 } 6013 6014 void positionChildAtBottom(Task child) { 6015 // If there are other focusable root tasks on the display, the z-order of the display 6016 // should not be changed just because a task was placed at the bottom. E.g. if it is 6017 // moving the topmost task to bottom, the next focusable root task on the same display 6018 // should be focused. 6019 final Task nextFocusableRootTask = getDisplayArea().getNextFocusableRootTask( 6020 child.getRootTask(), true /* ignoreCurrent */); 6021 positionChildAtBottom(child, nextFocusableRootTask == null /* includingParents */); 6022 } 6023 6024 @VisibleForTesting 6025 void positionChildAtBottom(Task child, boolean includingParents) { 6026 if (child == null) { 6027 // TODO: Fix the call-points that cause this to happen. 6028 return; 6029 } 6030 6031 positionChildAt(POSITION_BOTTOM, child, includingParents); 6032 } 6033 6034 @Override 6035 void onChildPositionChanged(WindowContainer child) { 6036 dispatchTaskInfoChangedIfNeeded(false /* force */); 6037 6038 if (!mChildren.contains(child)) { 6039 return; 6040 } 6041 if (child.asTask() != null) { 6042 // Non-root task position changed. 6043 mRootWindowContainer.invalidateTaskLayers(); 6044 } 6045 } 6046 6047 void reparent(TaskDisplayArea newParent, boolean onTop) { 6048 if (newParent == null) { 6049 throw new IllegalArgumentException("Task can't reparent to null " + this); 6050 } 6051 6052 if (getParent() == newParent) { 6053 throw new IllegalArgumentException("Task=" + this + " already child of " + newParent); 6054 } 6055 6056 if (canBeLaunchedOnDisplay(newParent.getDisplayId())) { 6057 reparent(newParent, onTop ? POSITION_TOP : POSITION_BOTTOM); 6058 if (isLeafTask()) { 6059 newParent.onLeafTaskMoved(this, onTop, !onTop); 6060 } 6061 } else { 6062 Slog.w(TAG, "Task=" + this + " can't reparent to " + newParent); 6063 } 6064 } 6065 6066 void setLastRecentsAnimationTransaction(@NonNull PictureInPictureSurfaceTransaction transaction, 6067 @Nullable SurfaceControl overlay) { 6068 mLastRecentsAnimationTransaction = new PictureInPictureSurfaceTransaction(transaction); 6069 mLastRecentsAnimationOverlay = overlay; 6070 } 6071 6072 void clearLastRecentsAnimationTransaction(boolean forceRemoveOverlay) { 6073 if (forceRemoveOverlay && mLastRecentsAnimationOverlay != null) { 6074 getPendingTransaction().remove(mLastRecentsAnimationOverlay); 6075 } 6076 mLastRecentsAnimationTransaction = null; 6077 mLastRecentsAnimationOverlay = null; 6078 // reset also the crop and transform introduced by mLastRecentsAnimationTransaction 6079 resetSurfaceControlTransforms(); 6080 } 6081 6082 void resetSurfaceControlTransforms() { 6083 getSyncTransaction().setMatrix(mSurfaceControl, Matrix.IDENTITY_MATRIX, new float[9]) 6084 .setWindowCrop(mSurfaceControl, null) 6085 .setShadowRadius(mSurfaceControl, 0) 6086 .setCornerRadius(mSurfaceControl, 0); 6087 } 6088 6089 void maybeApplyLastRecentsAnimationTransaction() { 6090 if (mLastRecentsAnimationTransaction != null) { 6091 final SurfaceControl.Transaction tx = getPendingTransaction(); 6092 if (mLastRecentsAnimationOverlay != null) { 6093 tx.reparent(mLastRecentsAnimationOverlay, mSurfaceControl); 6094 } 6095 PictureInPictureSurfaceTransaction.apply(mLastRecentsAnimationTransaction, 6096 mSurfaceControl, tx); 6097 // If we are transferring the transform from the root task entering PIP, then also show 6098 // the new task immediately 6099 tx.show(mSurfaceControl); 6100 mLastRecentsAnimationTransaction = null; 6101 mLastRecentsAnimationOverlay = null; 6102 } 6103 } 6104 6105 private void updateSurfaceBounds() { 6106 updateSurfaceSize(getSyncTransaction()); 6107 updateSurfacePositionNonOrganized(); 6108 scheduleAnimation(); 6109 } 6110 6111 private Point getRelativePosition() { 6112 Point position = new Point(); 6113 getRelativePosition(position); 6114 return position; 6115 } 6116 6117 boolean shouldIgnoreInput() { 6118 if (mAtmService.mHasLeanbackFeature && inPinnedWindowingMode() 6119 && !isFocusedRootTaskOnDisplay()) { 6120 // Preventing Picture-in-Picture root task from receiving input on TVs. 6121 return true; 6122 } 6123 return false; 6124 } 6125 6126 /** 6127 * Simply check and give warning logs if this is not operated on leaf task. 6128 */ 6129 private void warnForNonLeafTask(String func) { 6130 if (!isLeafTask()) { 6131 Slog.w(TAG, func + " on non-leaf task " + this); 6132 } 6133 } 6134 6135 public DisplayInfo getDisplayInfo() { 6136 return mDisplayContent.getDisplayInfo(); 6137 } 6138 6139 AnimatingActivityRegistry getAnimatingActivityRegistry() { 6140 return mAnimatingActivityRegistry; 6141 } 6142 6143 @Override 6144 void executeAppTransition(ActivityOptions options) { 6145 mDisplayContent.executeAppTransition(); 6146 ActivityOptions.abort(options); 6147 } 6148 6149 boolean shouldSleepActivities() { 6150 final DisplayContent display = mDisplayContent; 6151 final boolean isKeyguardGoingAway = (mDisplayContent != null) 6152 ? mDisplayContent.isKeyguardGoingAway() 6153 : mRootWindowContainer.getDefaultDisplay().isKeyguardGoingAway(); 6154 6155 // Do not sleep activities in this root task if we're marked as focused and the keyguard 6156 // is in the process of going away. 6157 if (isKeyguardGoingAway && isFocusedRootTaskOnDisplay() 6158 // Avoid resuming activities on secondary displays since we don't want bubble 6159 // activities to be resumed while bubble is still collapsed. 6160 // TODO(b/113840485): Having keyguard going away state for secondary displays. 6161 && display.isDefaultDisplay) { 6162 return false; 6163 } 6164 6165 return display != null ? display.isSleeping() : mAtmService.isSleepingLocked(); 6166 } 6167 6168 private Rect getRawBounds() { 6169 return super.getBounds(); 6170 } 6171 6172 void dispatchTaskInfoChangedIfNeeded(boolean force) { 6173 if (isOrganized()) { 6174 mAtmService.mTaskOrganizerController.onTaskInfoChanged(this, force); 6175 } 6176 } 6177 6178 void setReparentLeafTaskIfRelaunch(boolean reparentLeafTaskIfRelaunch) { 6179 if (isOrganized()) { 6180 mReparentLeafTaskIfRelaunch = reparentLeafTaskIfRelaunch; 6181 } 6182 } 6183 6184 /** 6185 * Return true if the activityInfo has the same requiredDisplayCategory as this task. 6186 */ 6187 boolean isSameRequiredDisplayCategory(@NonNull ActivityInfo info) { 6188 return mRequiredDisplayCategory != null && mRequiredDisplayCategory.equals( 6189 info.requiredDisplayCategory) 6190 || (mRequiredDisplayCategory == null && info.requiredDisplayCategory == null); 6191 } 6192 6193 @Override 6194 public void dumpDebug(ProtoOutputStream proto, long fieldId, 6195 @WindowTraceLogLevel int logLevel) { 6196 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) { 6197 return; 6198 } 6199 6200 final long token = proto.start(fieldId); 6201 6202 proto.write(TaskProto.ID, mTaskId); 6203 proto.write(ROOT_TASK_ID, getRootTaskId()); 6204 6205 if (getTopResumedActivity() != null) { 6206 getTopResumedActivity().writeIdentifierToProto(proto, RESUMED_ACTIVITY); 6207 } 6208 if (realActivity != null) { 6209 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString()); 6210 } 6211 if (origActivity != null) { 6212 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString()); 6213 } 6214 proto.write(RESIZE_MODE, mResizeMode); 6215 proto.write(FILLS_PARENT, matchParentBounds()); 6216 getRawBounds().dumpDebug(proto, BOUNDS); 6217 6218 if (mLastNonFullscreenBounds != null) { 6219 mLastNonFullscreenBounds.dumpDebug(proto, LAST_NON_FULLSCREEN_BOUNDS); 6220 } 6221 6222 if (mSurfaceControl != null) { 6223 proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth()); 6224 proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight()); 6225 } 6226 6227 proto.write(CREATED_BY_ORGANIZER, mCreatedByOrganizer); 6228 proto.write(AFFINITY, affinity); 6229 proto.write(HAS_CHILD_PIP_ACTIVITY, mChildPipActivity != null); 6230 6231 super.dumpDebug(proto, TASK_FRAGMENT, logLevel); 6232 6233 proto.end(token); 6234 } 6235 6236 static class Builder { 6237 private final ActivityTaskManagerService mAtmService; 6238 private WindowContainer mParent; 6239 private int mTaskId; 6240 private Intent mIntent; 6241 private Intent mAffinityIntent; 6242 private String mAffinity; 6243 private String mRootAffinity; 6244 private ComponentName mRealActivity; 6245 private ComponentName mOrigActivity; 6246 private boolean mRootWasReset; 6247 private boolean mAutoRemoveRecents; 6248 private boolean mAskedCompatMode; 6249 private int mUserId; 6250 private int mEffectiveUid; 6251 private String mLastDescription; 6252 private long mLastTimeMoved; 6253 private boolean mNeverRelinquishIdentity; 6254 private TaskDescription mLastTaskDescription; 6255 private PersistedTaskSnapshotData mLastSnapshotData; 6256 private int mTaskAffiliation; 6257 private int mPrevAffiliateTaskId = INVALID_TASK_ID; 6258 private int mNextAffiliateTaskId = INVALID_TASK_ID; 6259 private int mCallingUid; 6260 private String mCallingPackage; 6261 private String mCallingFeatureId; 6262 private int mResizeMode; 6263 private boolean mSupportsPictureInPicture; 6264 private boolean mRealActivitySuspended; 6265 private boolean mUserSetupComplete; 6266 private int mMinWidth = INVALID_MIN_SIZE; 6267 private int mMinHeight = INVALID_MIN_SIZE; 6268 private ActivityInfo mActivityInfo; 6269 private ActivityOptions mActivityOptions; 6270 private IVoiceInteractionSession mVoiceSession; 6271 private IVoiceInteractor mVoiceInteractor; 6272 private int mActivityType; 6273 private int mWindowingMode = WINDOWING_MODE_UNDEFINED; 6274 private boolean mCreatedByOrganizer; 6275 private boolean mDeferTaskAppear; 6276 private IBinder mLaunchCookie; 6277 private boolean mOnTop; 6278 private boolean mHasBeenVisible; 6279 private boolean mRemoveWithTaskOrganizer; 6280 6281 /** 6282 * Records the source task that requesting to build a new task, used to determine which of 6283 * the adjacent roots should be launch root of the new task. 6284 */ 6285 private Task mSourceTask; 6286 6287 /** 6288 * Records launch flags to apply when launching new task. 6289 */ 6290 private int mLaunchFlags; 6291 6292 Builder(ActivityTaskManagerService atm) { 6293 mAtmService = atm; 6294 } 6295 6296 Builder setParent(WindowContainer parent) { 6297 mParent = parent; 6298 return this; 6299 } 6300 6301 Builder setSourceTask(Task sourceTask) { 6302 mSourceTask = sourceTask; 6303 return this; 6304 } 6305 6306 Builder setLaunchFlags(int launchFlags) { 6307 mLaunchFlags = launchFlags; 6308 return this; 6309 } 6310 6311 Builder setTaskId(int taskId) { 6312 mTaskId = taskId; 6313 return this; 6314 } 6315 6316 Builder setIntent(Intent intent) { 6317 mIntent = intent; 6318 return this; 6319 } 6320 6321 Builder setRealActivity(ComponentName realActivity) { 6322 mRealActivity = realActivity; 6323 return this; 6324 } 6325 6326 Builder setEffectiveUid(int effectiveUid) { 6327 mEffectiveUid = effectiveUid; 6328 return this; 6329 } 6330 6331 Builder setMinWidth(int minWidth) { 6332 mMinWidth = minWidth; 6333 return this; 6334 } 6335 6336 Builder setMinHeight(int minHeight) { 6337 mMinHeight = minHeight; 6338 return this; 6339 } 6340 6341 Builder setActivityInfo(ActivityInfo info) { 6342 mActivityInfo = info; 6343 return this; 6344 } 6345 6346 Builder setActivityOptions(ActivityOptions opts) { 6347 mActivityOptions = opts; 6348 return this; 6349 } 6350 6351 Builder setVoiceSession(IVoiceInteractionSession voiceSession) { 6352 mVoiceSession = voiceSession; 6353 return this; 6354 } 6355 6356 Builder setActivityType(int activityType) { 6357 mActivityType = activityType; 6358 return this; 6359 } 6360 6361 int getActivityType() { 6362 return mActivityType; 6363 } 6364 6365 Builder setWindowingMode(int windowingMode) { 6366 mWindowingMode = windowingMode; 6367 return this; 6368 } 6369 6370 int getWindowingMode() { 6371 return mWindowingMode; 6372 } 6373 6374 Builder setCreatedByOrganizer(boolean createdByOrganizer) { 6375 mCreatedByOrganizer = createdByOrganizer; 6376 return this; 6377 } 6378 6379 boolean getCreatedByOrganizer() { 6380 return mCreatedByOrganizer; 6381 } 6382 6383 Builder setDeferTaskAppear(boolean defer) { 6384 mDeferTaskAppear = defer; 6385 return this; 6386 } 6387 6388 Builder setLaunchCookie(IBinder launchCookie) { 6389 mLaunchCookie = launchCookie; 6390 return this; 6391 } 6392 6393 Builder setOnTop(boolean onTop) { 6394 mOnTop = onTop; 6395 return this; 6396 } 6397 6398 Builder setHasBeenVisible(boolean hasBeenVisible) { 6399 mHasBeenVisible = hasBeenVisible; 6400 return this; 6401 } 6402 6403 Builder setRemoveWithTaskOrganizer(boolean removeWithTaskOrganizer) { 6404 mRemoveWithTaskOrganizer = removeWithTaskOrganizer; 6405 return this; 6406 } 6407 6408 private Builder setUserId(int userId) { 6409 mUserId = userId; 6410 return this; 6411 } 6412 6413 private Builder setLastTimeMoved(long lastTimeMoved) { 6414 mLastTimeMoved = lastTimeMoved; 6415 return this; 6416 } 6417 6418 private Builder setNeverRelinquishIdentity(boolean neverRelinquishIdentity) { 6419 mNeverRelinquishIdentity = neverRelinquishIdentity; 6420 return this; 6421 } 6422 6423 private Builder setCallingUid(int callingUid) { 6424 mCallingUid = callingUid; 6425 return this; 6426 } 6427 6428 private Builder setCallingPackage(String callingPackage) { 6429 mCallingPackage = callingPackage; 6430 return this; 6431 } 6432 6433 private Builder setResizeMode(int resizeMode) { 6434 mResizeMode = resizeMode; 6435 return this; 6436 } 6437 6438 private Builder setSupportsPictureInPicture(boolean supportsPictureInPicture) { 6439 mSupportsPictureInPicture = supportsPictureInPicture; 6440 return this; 6441 } 6442 6443 private Builder setUserSetupComplete(boolean userSetupComplete) { 6444 mUserSetupComplete = userSetupComplete; 6445 return this; 6446 } 6447 6448 private Builder setTaskAffiliation(int taskAffiliation) { 6449 mTaskAffiliation = taskAffiliation; 6450 return this; 6451 } 6452 6453 private Builder setPrevAffiliateTaskId(int prevAffiliateTaskId) { 6454 mPrevAffiliateTaskId = prevAffiliateTaskId; 6455 return this; 6456 } 6457 6458 private Builder setNextAffiliateTaskId(int nextAffiliateTaskId) { 6459 mNextAffiliateTaskId = nextAffiliateTaskId; 6460 return this; 6461 } 6462 6463 private Builder setCallingFeatureId(String callingFeatureId) { 6464 mCallingFeatureId = callingFeatureId; 6465 return this; 6466 } 6467 6468 private Builder setRealActivitySuspended(boolean realActivitySuspended) { 6469 mRealActivitySuspended = realActivitySuspended; 6470 return this; 6471 } 6472 6473 private Builder setLastDescription(String lastDescription) { 6474 mLastDescription = lastDescription; 6475 return this; 6476 } 6477 6478 private Builder setLastTaskDescription(TaskDescription lastTaskDescription) { 6479 mLastTaskDescription = lastTaskDescription; 6480 return this; 6481 } 6482 6483 private Builder setLastSnapshotData(PersistedTaskSnapshotData lastSnapshotData) { 6484 mLastSnapshotData = lastSnapshotData; 6485 return this; 6486 } 6487 6488 private Builder setOrigActivity(ComponentName origActivity) { 6489 mOrigActivity = origActivity; 6490 return this; 6491 } 6492 6493 private Builder setRootWasReset(boolean rootWasReset) { 6494 mRootWasReset = rootWasReset; 6495 return this; 6496 } 6497 6498 private Builder setAutoRemoveRecents(boolean autoRemoveRecents) { 6499 mAutoRemoveRecents = autoRemoveRecents; 6500 return this; 6501 } 6502 6503 private Builder setAskedCompatMode(boolean askedCompatMode) { 6504 mAskedCompatMode = askedCompatMode; 6505 return this; 6506 } 6507 6508 private Builder setAffinityIntent(Intent affinityIntent) { 6509 mAffinityIntent = affinityIntent; 6510 return this; 6511 } 6512 6513 private Builder setAffinity(String affinity) { 6514 mAffinity = affinity; 6515 return this; 6516 } 6517 6518 private Builder setRootAffinity(String rootAffinity) { 6519 mRootAffinity = rootAffinity; 6520 return this; 6521 } 6522 6523 private Builder setVoiceInteractor(IVoiceInteractor voiceInteractor) { 6524 mVoiceInteractor = voiceInteractor; 6525 return this; 6526 } 6527 6528 private void validateRootTask(TaskDisplayArea tda) { 6529 if (mActivityType == ACTIVITY_TYPE_UNDEFINED && !mCreatedByOrganizer) { 6530 // Can't have an undefined root task type yet...so re-map to standard. Anyone 6531 // that wants anything else should be passing it in anyways...except for the task 6532 // organizer. 6533 mActivityType = ACTIVITY_TYPE_STANDARD; 6534 } 6535 6536 if (mActivityType != ACTIVITY_TYPE_STANDARD 6537 && mActivityType != ACTIVITY_TYPE_UNDEFINED) { 6538 // For now there can be only one root task of a particular non-standard activity 6539 // type on a display. So, get that ignoring whatever windowing mode it is 6540 // currently in. 6541 Task rootTask = tda.getRootTask(WINDOWING_MODE_UNDEFINED, mActivityType); 6542 if (rootTask != null) { 6543 throw new IllegalArgumentException("Root task=" + rootTask + " of activityType=" 6544 + mActivityType + " already on display=" + tda 6545 + ". Can't have multiple."); 6546 } 6547 } 6548 6549 if (!TaskDisplayArea.isWindowingModeSupported(mWindowingMode, 6550 mAtmService.mSupportsMultiWindow, 6551 mAtmService.mSupportsFreeformWindowManagement, 6552 mAtmService.mSupportsPictureInPicture)) { 6553 throw new IllegalArgumentException("Can't create root task for unsupported " 6554 + "windowingMode=" + mWindowingMode); 6555 } 6556 6557 if (mWindowingMode == WINDOWING_MODE_PINNED 6558 && mActivityType != ACTIVITY_TYPE_STANDARD) { 6559 throw new IllegalArgumentException( 6560 "Root task with pinned windowing mode cannot with " 6561 + "non-standard activity type."); 6562 } 6563 6564 if (mWindowingMode == WINDOWING_MODE_PINNED && tda.getRootPinnedTask() != null) { 6565 // Only 1 root task can be PINNED at a time, so dismiss the existing one 6566 tda.getRootPinnedTask().dismissPip(); 6567 } 6568 6569 if (mIntent != null) { 6570 mLaunchFlags |= mIntent.getFlags(); 6571 } 6572 6573 // Task created by organizer are added as root. 6574 final Task launchRootTask = mCreatedByOrganizer 6575 ? null : tda.getLaunchRootTask(mWindowingMode, mActivityType, mActivityOptions, 6576 mSourceTask, mLaunchFlags); 6577 if (launchRootTask != null) { 6578 // Since this task will be put into a root task, its windowingMode will be 6579 // inherited. 6580 mWindowingMode = WINDOWING_MODE_UNDEFINED; 6581 mParent = launchRootTask; 6582 } 6583 6584 mTaskId = tda.getNextRootTaskId(); 6585 } 6586 6587 Task build() { 6588 if (mParent != null && mParent instanceof TaskDisplayArea) { 6589 validateRootTask((TaskDisplayArea) mParent); 6590 } 6591 6592 if (mActivityInfo == null) { 6593 mActivityInfo = new ActivityInfo(); 6594 mActivityInfo.applicationInfo = new ApplicationInfo(); 6595 } 6596 6597 mUserId = UserHandle.getUserId(mActivityInfo.applicationInfo.uid); 6598 mTaskAffiliation = mTaskId; 6599 mLastTimeMoved = System.currentTimeMillis(); 6600 mNeverRelinquishIdentity = true; 6601 mCallingUid = mActivityInfo.applicationInfo.uid; 6602 mCallingPackage = mActivityInfo.packageName; 6603 mResizeMode = mActivityInfo.resizeMode; 6604 mSupportsPictureInPicture = mActivityInfo.supportsPictureInPicture(); 6605 if (!mRemoveWithTaskOrganizer && mActivityOptions != null) { 6606 mRemoveWithTaskOrganizer = mActivityOptions.getRemoveWithTaskOranizer(); 6607 } 6608 6609 final Task task = buildInner(); 6610 task.mHasBeenVisible = mHasBeenVisible; 6611 6612 // Set activity type before adding the root task to TaskDisplayArea, so home task can 6613 // be cached, see TaskDisplayArea#addRootTaskReferenceIfNeeded(). 6614 if (mActivityType != ACTIVITY_TYPE_UNDEFINED) { 6615 task.setActivityType(mActivityType); 6616 } 6617 6618 if (mParent != null) { 6619 if (mParent instanceof Task) { 6620 final Task parentTask = (Task) mParent; 6621 parentTask.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM, 6622 (mActivityInfo.flags & FLAG_SHOW_FOR_ALL_USERS) != 0); 6623 } else { 6624 mParent.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM); 6625 } 6626 } 6627 6628 // Set windowing mode after attached to display area or it abort silently. 6629 if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { 6630 task.setWindowingMode(mWindowingMode, true /* creating */); 6631 } 6632 return task; 6633 } 6634 6635 /** Don't use {@link Builder#buildInner()} directly. This is only used by XML parser. */ 6636 @VisibleForTesting 6637 Task buildInner() { 6638 return new Task(mAtmService, mTaskId, mIntent, mAffinityIntent, mAffinity, 6639 mRootAffinity, mRealActivity, mOrigActivity, mRootWasReset, mAutoRemoveRecents, 6640 mAskedCompatMode, mUserId, mEffectiveUid, mLastDescription, mLastTimeMoved, 6641 mNeverRelinquishIdentity, mLastTaskDescription, mLastSnapshotData, 6642 mTaskAffiliation, mPrevAffiliateTaskId, mNextAffiliateTaskId, mCallingUid, 6643 mCallingPackage, mCallingFeatureId, mResizeMode, mSupportsPictureInPicture, 6644 mRealActivitySuspended, mUserSetupComplete, mMinWidth, mMinHeight, 6645 mActivityInfo, mVoiceSession, mVoiceInteractor, mCreatedByOrganizer, 6646 mLaunchCookie, mDeferTaskAppear, mRemoveWithTaskOrganizer); 6647 } 6648 } 6649 6650 @Override 6651 void updateOverlayInsetsState(WindowState originalChange) { 6652 super.updateOverlayInsetsState(originalChange); 6653 if (originalChange != getTopVisibleAppMainWindow()) { 6654 return; 6655 } 6656 if (mOverlayHost != null) { 6657 final InsetsState s = originalChange.getInsetsState(true); 6658 getBounds(mTmpRect); 6659 mOverlayHost.dispatchInsetsChanged(s, mTmpRect); 6660 } 6661 } 6662 } 6663