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