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