1 /* 2 * Copyright (C) 2018 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 android.app; 18 19 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 20 import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED; 21 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.TestApi; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.content.ComponentName; 27 import android.content.Intent; 28 import android.content.LocusId; 29 import android.content.pm.ActivityInfo; 30 import android.content.res.Configuration; 31 import android.graphics.Point; 32 import android.graphics.Rect; 33 import android.os.Build; 34 import android.os.IBinder; 35 import android.os.Parcel; 36 import android.view.DisplayCutout; 37 import android.window.WindowContainerToken; 38 39 import java.util.ArrayList; 40 import java.util.Objects; 41 42 /** 43 * Stores information about a particular Task. 44 */ 45 public class TaskInfo { 46 private static final String TAG = "TaskInfo"; 47 48 /** 49 * The value to use when the property has not a specific value. 50 * @hide 51 */ 52 public static final int PROPERTY_VALUE_UNSET = -1; 53 54 /** 55 * The id of the user the task was running as if this is a leaf task. The id of the current 56 * running user of the system otherwise. 57 * @hide 58 */ 59 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 60 public int userId; 61 62 /** 63 * The identifier for this task. 64 */ 65 public int taskId; 66 67 /** 68 * Whether or not this task has any running activities. 69 */ 70 public boolean isRunning; 71 72 /** 73 * The base intent of the task (generally the intent that launched the task). This intent can 74 * be used to relaunch the task (if it is no longer running) or brought to the front if it is. 75 */ 76 @NonNull 77 public Intent baseIntent; 78 79 /** 80 * The component of the first activity in the task, can be considered the "application" of this 81 * task. 82 */ 83 @Nullable 84 public ComponentName baseActivity; 85 86 /** 87 * The component of the top activity in the task, currently showing to the user. 88 */ 89 @Nullable 90 public ComponentName topActivity; 91 92 /** 93 * The component of the target activity if this task was started from an activity alias. 94 * Otherwise, this is null. 95 */ 96 @Nullable 97 public ComponentName origActivity; 98 99 /** 100 * The component of the activity that started this task (may be the component of the activity 101 * alias). 102 * @hide 103 */ 104 @Nullable 105 public ComponentName realActivity; 106 107 /** 108 * The number of activities in this task (including running). 109 */ 110 public int numActivities; 111 112 /** 113 * The last time this task was active since boot (including time spent in sleep). 114 * @hide 115 */ 116 @UnsupportedAppUsage 117 public long lastActiveTime; 118 119 /** 120 * The id of the display this task is associated with. 121 * @hide 122 */ 123 public int displayId; 124 125 /** 126 * The feature id of {@link com.android.server.wm.TaskDisplayArea} this task is associated with. 127 * @hide 128 */ 129 public int displayAreaFeatureId = FEATURE_UNDEFINED; 130 131 /** 132 * The recent activity values for the highest activity in the stack to have set the values. 133 * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}. 134 */ 135 @Nullable 136 public ActivityManager.TaskDescription taskDescription; 137 138 /** 139 * The locusId of the task. 140 * @hide 141 */ 142 @Nullable 143 public LocusId mTopActivityLocusId; 144 145 /** 146 * Whether this task supports multi windowing modes based on the device settings and the 147 * root activity resizability and configuration. 148 * @hide 149 */ 150 public boolean supportsMultiWindow; 151 152 /** 153 * The resize mode of the task. See {@link ActivityInfo#resizeMode}. 154 * @hide 155 */ 156 @UnsupportedAppUsage 157 public int resizeMode; 158 159 /** 160 * The current configuration of the task. 161 * @hide 162 */ 163 @NonNull 164 @UnsupportedAppUsage 165 public final Configuration configuration = new Configuration(); 166 167 /** 168 * Used as an opaque identifier for this task. 169 * @hide 170 */ 171 @NonNull 172 public WindowContainerToken token; 173 174 /** 175 * The PictureInPictureParams for the Task, if set. 176 * @hide 177 */ 178 @Nullable 179 public PictureInPictureParams pictureInPictureParams; 180 181 /** 182 * @hide 183 */ 184 public boolean shouldDockBigOverlays; 185 186 /** 187 * The task id of the host Task of the launch-into-pip Activity, i.e., it points to the Task 188 * the launch-into-pip Activity is originated from. 189 * @hide 190 */ 191 public int launchIntoPipHostTaskId; 192 193 /** 194 * The task id of the parent Task of the launch-into-pip Activity, i.e., if task have more than 195 * one activity it will create new task for this activity, this id is the origin task id and 196 * the pip activity will be reparent to origin task when it exit pip mode. 197 * @hide 198 */ 199 public int lastParentTaskIdBeforePip; 200 201 /** 202 * The {@link Rect} copied from {@link DisplayCutout#getSafeInsets()} if the cutout is not of 203 * (LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS), 204 * {@code null} otherwise. 205 * @hide 206 */ 207 @Nullable 208 public Rect displayCutoutInsets; 209 210 /** 211 * The activity type of the top activity in this task. 212 * @hide 213 */ 214 public @WindowConfiguration.ActivityType int topActivityType; 215 216 /** 217 * The {@link ActivityInfo} of the top activity in this task. 218 * @hide 219 */ 220 @Nullable 221 public ActivityInfo topActivityInfo; 222 223 /** 224 * Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity 225 * supports), this is what the system actually uses for resizability based on other policy and 226 * developer options. 227 * @hide 228 */ 229 public boolean isResizeable; 230 231 /** 232 * Minimal width of the task when it's resizeable. 233 * @hide 234 */ 235 public int minWidth; 236 237 /** 238 * Minimal height of the task when it's resizeable. 239 * @hide 240 */ 241 public int minHeight; 242 243 /** 244 * The default minimal size of the task used when a minWidth or minHeight is not specified. 245 * @hide 246 */ 247 public int defaultMinSize; 248 249 /** 250 * Relative position of the task's top left corner in the parent container. 251 * @hide 252 */ 253 public Point positionInParent; 254 255 /** 256 * The launch cookies associated with activities in this task if any. 257 * @see ActivityOptions#setLaunchCookie(IBinder) 258 * @hide 259 */ 260 public ArrayList<IBinder> launchCookies = new ArrayList<>(); 261 262 /** 263 * The identifier of the parent task that is created by organizer, otherwise 264 * {@link ActivityTaskManager#INVALID_TASK_ID}. 265 * @hide 266 */ 267 public int parentTaskId; 268 269 /** 270 * Whether this task is focused. 271 * @hide 272 */ 273 public boolean isFocused; 274 275 /** 276 * Whether this task is visible. 277 * @hide 278 */ 279 public boolean isVisible; 280 281 /** 282 * Whether this task is request visible. 283 * @hide 284 */ 285 public boolean isVisibleRequested; 286 287 /** 288 * Whether this task is sleeping due to sleeping display. 289 * @hide 290 */ 291 public boolean isSleeping; 292 293 /** 294 * Whether the top activity fillsParent() is false 295 * @hide 296 */ 297 public boolean isTopActivityTransparent; 298 299 /** 300 * Encapsulate specific App Compat information. 301 * @hide 302 */ 303 public AppCompatTaskInfo appCompatTaskInfo = AppCompatTaskInfo.create(); 304 TaskInfo()305 TaskInfo() { 306 // Do nothing 307 } 308 TaskInfo(Parcel source)309 private TaskInfo(Parcel source) { 310 readFromParcel(source); 311 } 312 313 /** 314 * Whether this task is visible. 315 */ isVisible()316 public boolean isVisible() { 317 return isVisible; 318 } 319 320 /** @hide */ 321 @NonNull 322 @TestApi getToken()323 public WindowContainerToken getToken() { 324 return token; 325 } 326 327 /** @hide */ 328 @NonNull 329 @TestApi getConfiguration()330 public Configuration getConfiguration() { 331 return configuration; 332 } 333 334 /** @hide */ 335 @Nullable 336 @TestApi getPictureInPictureParams()337 public PictureInPictureParams getPictureInPictureParams() { 338 return pictureInPictureParams; 339 } 340 341 /** @hide */ 342 @TestApi shouldDockBigOverlays()343 public boolean shouldDockBigOverlays() { 344 return shouldDockBigOverlays; 345 } 346 347 /** @hide */ 348 @WindowConfiguration.WindowingMode getWindowingMode()349 public int getWindowingMode() { 350 return configuration.windowConfiguration.getWindowingMode(); 351 } 352 353 /** @hide */ isFreeform()354 public boolean isFreeform() { 355 return configuration.windowConfiguration.getWindowingMode() 356 == WindowConfiguration.WINDOWING_MODE_FREEFORM; 357 } 358 359 /** @hide */ 360 @WindowConfiguration.ActivityType getActivityType()361 public int getActivityType() { 362 return configuration.windowConfiguration.getActivityType(); 363 } 364 365 /** @hide */ addLaunchCookie(IBinder cookie)366 public void addLaunchCookie(IBinder cookie) { 367 if (cookie == null || launchCookies.contains(cookie)) return; 368 launchCookies.add(cookie); 369 } 370 371 /** 372 * @return {@code true} if this task contains the launch cookie. 373 * @hide 374 */ 375 @TestApi containsLaunchCookie(@onNull IBinder cookie)376 public boolean containsLaunchCookie(@NonNull IBinder cookie) { 377 return launchCookies.contains(cookie); 378 } 379 380 /** 381 * @return The parent task id of this task. 382 * @hide 383 */ 384 @TestApi getParentTaskId()385 public int getParentTaskId() { 386 return parentTaskId; 387 } 388 389 /** @hide */ 390 @TestApi hasParentTask()391 public boolean hasParentTask() { 392 return parentTaskId != INVALID_TASK_ID; 393 } 394 395 /** 396 * @return The id of the display this task is associated with. 397 * @hide 398 */ 399 @TestApi getDisplayId()400 public int getDisplayId() { 401 return displayId; 402 } 403 404 /** 405 * Returns {@code true} if the parameters that are important for task organizers are equal 406 * between this {@link TaskInfo} and {@param that}. 407 * @hide 408 */ equalsForTaskOrganizer(@ullable TaskInfo that)409 public boolean equalsForTaskOrganizer(@Nullable TaskInfo that) { 410 if (that == null) { 411 return false; 412 } 413 return topActivityType == that.topActivityType 414 && isResizeable == that.isResizeable 415 && supportsMultiWindow == that.supportsMultiWindow 416 && displayAreaFeatureId == that.displayAreaFeatureId 417 && Objects.equals(positionInParent, that.positionInParent) 418 && Objects.equals(pictureInPictureParams, that.pictureInPictureParams) 419 && Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays) 420 && Objects.equals(displayCutoutInsets, that.displayCutoutInsets) 421 && getWindowingMode() == that.getWindowingMode() 422 && configuration.uiMode == that.configuration.uiMode 423 && Objects.equals(taskDescription, that.taskDescription) 424 && isFocused == that.isFocused 425 && isVisible == that.isVisible 426 && isVisibleRequested == that.isVisibleRequested 427 && isSleeping == that.isSleeping 428 && Objects.equals(mTopActivityLocusId, that.mTopActivityLocusId) 429 && parentTaskId == that.parentTaskId 430 && Objects.equals(topActivity, that.topActivity) 431 && isTopActivityTransparent == that.isTopActivityTransparent 432 && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo); 433 } 434 435 /** 436 * @return {@code true} if parameters that are important for size compat have changed. 437 * @hide 438 */ equalsForCompatUi(@ullable TaskInfo that)439 public boolean equalsForCompatUi(@Nullable TaskInfo that) { 440 if (that == null) { 441 return false; 442 } 443 final boolean hasCompatUI = appCompatTaskInfo.hasCompatUI(); 444 return displayId == that.displayId 445 && taskId == that.taskId 446 && isFocused == that.isFocused 447 && isTopActivityTransparent == that.isTopActivityTransparent 448 && appCompatTaskInfo.equalsForCompatUi(that.appCompatTaskInfo) 449 // Bounds are important if top activity has compat controls. 450 && (!hasCompatUI || configuration.windowConfiguration.getBounds() 451 .equals(that.configuration.windowConfiguration.getBounds())) 452 && (!hasCompatUI || configuration.getLayoutDirection() 453 == that.configuration.getLayoutDirection()) 454 && (!hasCompatUI || configuration.uiMode == that.configuration.uiMode) 455 && (!hasCompatUI || isVisible == that.isVisible); 456 } 457 458 /** 459 * Reads the TaskInfo from a parcel. 460 */ readFromParcel(Parcel source)461 void readFromParcel(Parcel source) { 462 userId = source.readInt(); 463 taskId = source.readInt(); 464 displayId = source.readInt(); 465 isRunning = source.readBoolean(); 466 baseIntent = source.readTypedObject(Intent.CREATOR); 467 baseActivity = ComponentName.readFromParcel(source); 468 topActivity = ComponentName.readFromParcel(source); 469 origActivity = ComponentName.readFromParcel(source); 470 realActivity = ComponentName.readFromParcel(source); 471 472 numActivities = source.readInt(); 473 lastActiveTime = source.readLong(); 474 475 taskDescription = source.readTypedObject(ActivityManager.TaskDescription.CREATOR); 476 supportsMultiWindow = source.readBoolean(); 477 resizeMode = source.readInt(); 478 configuration.readFromParcel(source); 479 token = WindowContainerToken.CREATOR.createFromParcel(source); 480 topActivityType = source.readInt(); 481 pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR); 482 shouldDockBigOverlays = source.readBoolean(); 483 launchIntoPipHostTaskId = source.readInt(); 484 lastParentTaskIdBeforePip = source.readInt(); 485 displayCutoutInsets = source.readTypedObject(Rect.CREATOR); 486 topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR); 487 isResizeable = source.readBoolean(); 488 minWidth = source.readInt(); 489 minHeight = source.readInt(); 490 defaultMinSize = source.readInt(); 491 source.readBinderList(launchCookies); 492 positionInParent = source.readTypedObject(Point.CREATOR); 493 parentTaskId = source.readInt(); 494 isFocused = source.readBoolean(); 495 isVisible = source.readBoolean(); 496 isVisibleRequested = source.readBoolean(); 497 isSleeping = source.readBoolean(); 498 mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR); 499 displayAreaFeatureId = source.readInt(); 500 isTopActivityTransparent = source.readBoolean(); 501 appCompatTaskInfo = source.readTypedObject(AppCompatTaskInfo.CREATOR); 502 } 503 504 /** 505 * Writes the TaskInfo to a parcel. 506 */ writeToParcel(Parcel dest, int flags)507 void writeToParcel(Parcel dest, int flags) { 508 dest.writeInt(userId); 509 dest.writeInt(taskId); 510 dest.writeInt(displayId); 511 dest.writeBoolean(isRunning); 512 dest.writeTypedObject(baseIntent, 0); 513 514 ComponentName.writeToParcel(baseActivity, dest); 515 ComponentName.writeToParcel(topActivity, dest); 516 ComponentName.writeToParcel(origActivity, dest); 517 ComponentName.writeToParcel(realActivity, dest); 518 519 dest.writeInt(numActivities); 520 dest.writeLong(lastActiveTime); 521 522 dest.writeTypedObject(taskDescription, flags); 523 dest.writeBoolean(supportsMultiWindow); 524 dest.writeInt(resizeMode); 525 configuration.writeToParcel(dest, flags); 526 token.writeToParcel(dest, flags); 527 dest.writeInt(topActivityType); 528 dest.writeTypedObject(pictureInPictureParams, flags); 529 dest.writeBoolean(shouldDockBigOverlays); 530 dest.writeInt(launchIntoPipHostTaskId); 531 dest.writeInt(lastParentTaskIdBeforePip); 532 dest.writeTypedObject(displayCutoutInsets, flags); 533 dest.writeTypedObject(topActivityInfo, flags); 534 dest.writeBoolean(isResizeable); 535 dest.writeInt(minWidth); 536 dest.writeInt(minHeight); 537 dest.writeInt(defaultMinSize); 538 dest.writeBinderList(launchCookies); 539 dest.writeTypedObject(positionInParent, flags); 540 dest.writeInt(parentTaskId); 541 dest.writeBoolean(isFocused); 542 dest.writeBoolean(isVisible); 543 dest.writeBoolean(isVisibleRequested); 544 dest.writeBoolean(isSleeping); 545 dest.writeTypedObject(mTopActivityLocusId, flags); 546 dest.writeInt(displayAreaFeatureId); 547 dest.writeBoolean(isTopActivityTransparent); 548 dest.writeTypedObject(appCompatTaskInfo, flags); 549 } 550 551 @Override toString()552 public String toString() { 553 return "TaskInfo{userId=" + userId + " taskId=" + taskId 554 + " displayId=" + displayId 555 + " isRunning=" + isRunning 556 + " baseIntent=" + baseIntent + " baseActivity=" + baseActivity 557 + " topActivity=" + topActivity + " origActivity=" + origActivity 558 + " realActivity=" + realActivity 559 + " numActivities=" + numActivities 560 + " lastActiveTime=" + lastActiveTime 561 + " supportsMultiWindow=" + supportsMultiWindow 562 + " resizeMode=" + resizeMode 563 + " isResizeable=" + isResizeable 564 + " minWidth=" + minWidth 565 + " minHeight=" + minHeight 566 + " defaultMinSize=" + defaultMinSize 567 + " token=" + token 568 + " topActivityType=" + topActivityType 569 + " pictureInPictureParams=" + pictureInPictureParams 570 + " shouldDockBigOverlays=" + shouldDockBigOverlays 571 + " launchIntoPipHostTaskId=" + launchIntoPipHostTaskId 572 + " lastParentTaskIdBeforePip=" + lastParentTaskIdBeforePip 573 + " displayCutoutSafeInsets=" + displayCutoutInsets 574 + " topActivityInfo=" + topActivityInfo 575 + " launchCookies=" + launchCookies 576 + " positionInParent=" + positionInParent 577 + " parentTaskId=" + parentTaskId 578 + " isFocused=" + isFocused 579 + " isVisible=" + isVisible 580 + " isVisibleRequested=" + isVisibleRequested 581 + " isSleeping=" + isSleeping 582 + " locusId=" + mTopActivityLocusId 583 + " displayAreaFeatureId=" + displayAreaFeatureId 584 + " isTopActivityTransparent=" + isTopActivityTransparent 585 + " appCompatTaskInfo=" + appCompatTaskInfo 586 + "}"; 587 } 588 } 589