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