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.IntDef;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.TestApi;
26 import android.compat.annotation.UnsupportedAppUsage;
27 import android.content.ComponentName;
28 import android.content.Intent;
29 import android.content.LocusId;
30 import android.content.pm.ActivityInfo;
31 import android.content.res.Configuration;
32 import android.graphics.Point;
33 import android.graphics.Rect;
34 import android.os.Build;
35 import android.os.IBinder;
36 import android.os.Parcel;
37 import android.view.DisplayCutout;
38 import android.window.WindowContainerToken;
39 
40 import java.lang.annotation.Retention;
41 import java.lang.annotation.RetentionPolicy;
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 value to use when the property has not a specific value.
53      * @hide
54      */
55     public static final int PROPERTY_VALUE_UNSET = -1;
56 
57     /**
58      * The id of the user the task was running as if this is a leaf task. The id of the current
59      * running user of the system otherwise.
60      * @hide
61      */
62     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
63     public int userId;
64 
65     /**
66      * The identifier for this task.
67      */
68     public int taskId;
69 
70     /**
71      * Whether or not this task has any running activities.
72      */
73     public boolean isRunning;
74 
75     /**
76      * The base intent of the task (generally the intent that launched the task). This intent can
77      * be used to relaunch the task (if it is no longer running) or brought to the front if it is.
78      */
79     @NonNull
80     public Intent baseIntent;
81 
82     /**
83      * The component of the first activity in the task, can be considered the "application" of this
84      * task.
85      */
86     @Nullable
87     public ComponentName baseActivity;
88 
89     /**
90      * The component of the top activity in the task, currently showing to the user.
91      */
92     @Nullable
93     public ComponentName topActivity;
94 
95     /**
96      * The component of the target activity if this task was started from an activity alias.
97      * Otherwise, this is null.
98      */
99     @Nullable
100     public ComponentName origActivity;
101 
102     /**
103      * The component of the activity that started this task (may be the component of the activity
104      * alias).
105      * @hide
106      */
107     @Nullable
108     public ComponentName realActivity;
109 
110     /**
111      * The number of activities in this task (including running).
112      */
113     public int numActivities;
114 
115     /**
116      * The last time this task was active since boot (including time spent in sleep).
117      * @hide
118      */
119     @UnsupportedAppUsage
120     public long lastActiveTime;
121 
122     /**
123      * The id of the display this task is associated with.
124      * @hide
125      */
126     public int displayId;
127 
128     /**
129      * The feature id of {@link com.android.server.wm.TaskDisplayArea} this task is associated with.
130      * @hide
131      */
132     public int displayAreaFeatureId = FEATURE_UNDEFINED;
133 
134     /**
135      * The recent activity values for the highest activity in the stack to have set the values.
136      * {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.
137      */
138     @Nullable
139     public ActivityManager.TaskDescription taskDescription;
140 
141     /**
142      * The locusId of the task.
143      * @hide
144      */
145     @Nullable
146     public LocusId mTopActivityLocusId;
147 
148     /**
149      * Whether this task supports multi windowing modes based on the device settings and the
150      * root activity resizability and configuration.
151      * @hide
152      */
153     public boolean supportsMultiWindow;
154 
155     /**
156      * The resize mode of the task. See {@link ActivityInfo#resizeMode}.
157      * @hide
158      */
159     @UnsupportedAppUsage
160     public int resizeMode;
161 
162     /**
163      * The current configuration of the task.
164      * @hide
165      */
166     @NonNull
167     @UnsupportedAppUsage
168     public final Configuration configuration = new Configuration();
169 
170     /**
171      * Used as an opaque identifier for this task.
172      * @hide
173      */
174     @NonNull
175     public WindowContainerToken token;
176 
177     /**
178      * The PictureInPictureParams for the Task, if set.
179      * @hide
180      */
181     @Nullable
182     public PictureInPictureParams pictureInPictureParams;
183 
184     /**
185      * @hide
186      */
187     public boolean shouldDockBigOverlays;
188 
189     /**
190      * The task id of the host Task of the launch-into-pip Activity, i.e., it points to the Task
191      * the launch-into-pip Activity is originated from.
192      * @hide
193      */
194     public int launchIntoPipHostTaskId;
195 
196     /**
197      * The task id of the parent Task of the launch-into-pip Activity, i.e., if task have more than
198      * one activity it will create new task for this activity, this id is the origin task id and
199      * the pip activity will be reparent to origin task when it exit pip mode.
200      * @hide
201      */
202     public int lastParentTaskIdBeforePip;
203 
204     /**
205      * The {@link Rect} copied from {@link DisplayCutout#getSafeInsets()} if the cutout is not of
206      * (LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS),
207      * {@code null} otherwise.
208      * @hide
209      */
210     @Nullable
211     public Rect displayCutoutInsets;
212 
213     /**
214      * The activity type of the top activity in this task.
215      * @hide
216      */
217     public @WindowConfiguration.ActivityType int topActivityType;
218 
219     /**
220      * The {@link ActivityInfo} of the top activity in this task.
221      * @hide
222      */
223     @Nullable
224     public ActivityInfo topActivityInfo;
225 
226     /**
227      * Whether the direct top activity is in size compat mode on foreground.
228      * @hide
229      */
230     public boolean topActivityInSizeCompat;
231 
232     /**
233      * Whether the direct top activity is eligible for letterbox education.
234      * @hide
235      */
236     public boolean topActivityEligibleForLetterboxEducation;
237 
238     /**
239      * Whether the double tap is enabled
240      * @hide
241      */
242     public boolean isLetterboxDoubleTapEnabled;
243 
244     /**
245      * Whether the user aspect ratio settings button is enabled
246      * @hide
247      */
248     public boolean topActivityEligibleForUserAspectRatioButton;
249 
250     /**
251      * Whether the user has forced the activity to be fullscreen through the user aspect ratio
252      * settings.
253      * @hide
254      */
255     public boolean isUserFullscreenOverrideEnabled;
256 
257     /**
258      * Whether the top activity fillsParent() is false
259      * @hide
260      */
261     public boolean isTopActivityTransparent;
262 
263     /**
264      * Hint about the letterbox state of the top activity.
265      * @hide
266      */
267     public boolean topActivityBoundsLetterboxed;
268 
269     /**
270      * Whether the update comes from a letterbox double-tap action from the user or not.
271      * @hide
272      */
273     public boolean isFromLetterboxDoubleTap;
274 
275     /**
276      * If {@link isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position or
277      * {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
278      * @hide
279      */
280     public int topActivityLetterboxVerticalPosition;
281 
282     /**
283      * If {@link isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position or
284      * {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
285      * @hide
286      */
287     public int topActivityLetterboxHorizontalPosition;
288 
289     /**
290      * If {@link isLetterboxDoubleTapEnabled} it contains the current width of the letterboxed
291      * activity or {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise
292      * @hide
293      */
294     public int topActivityLetterboxWidth;
295 
296     /**
297      * If {@link isLetterboxDoubleTapEnabled} it contains the current height of the letterboxed
298      * activity or {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise
299      * @hide
300      */
301     public int topActivityLetterboxHeight;
302 
303     /**
304      * Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity
305      * supports), this is what the system actually uses for resizability based on other policy and
306      * developer options.
307      * @hide
308      */
309     public boolean isResizeable;
310 
311     /**
312      * Minimal width of the task when it's resizeable.
313      * @hide
314      */
315     public int minWidth;
316 
317     /**
318      * Minimal height of the task when it's resizeable.
319      * @hide
320      */
321     public int minHeight;
322 
323     /**
324      * The default minimal size of the task used when a minWidth or minHeight is not specified.
325      * @hide
326      */
327     public int defaultMinSize;
328 
329     /**
330      * Relative position of the task's top left corner in the parent container.
331      * @hide
332      */
333     public Point positionInParent;
334 
335     /**
336      * The launch cookies associated with activities in this task if any.
337      * @see ActivityOptions#setLaunchCookie(IBinder)
338      * @hide
339      */
340     public ArrayList<IBinder> launchCookies = new ArrayList<>();
341 
342     /**
343      * The identifier of the parent task that is created by organizer, otherwise
344      * {@link ActivityTaskManager#INVALID_TASK_ID}.
345      * @hide
346      */
347     public int parentTaskId;
348 
349     /**
350      * Whether this task is focused.
351      * @hide
352      */
353     public boolean isFocused;
354 
355     /**
356      * Whether this task is visible.
357      * @hide
358      */
359     public boolean isVisible;
360 
361     /**
362      * Whether this task is request visible.
363      * @hide
364      */
365     public boolean isVisibleRequested;
366 
367     /**
368      * Whether this task is sleeping due to sleeping display.
369      * @hide
370      */
371     public boolean isSleeping;
372 
373     /**
374      * Camera compat control isn't shown because it's not requested by heuristics.
375      * @hide
376      */
377     public static final int CAMERA_COMPAT_CONTROL_HIDDEN = 0;
378 
379     /**
380      * Camera compat control is shown with the treatment suggested.
381      * @hide
382      */
383     public static final int CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED = 1;
384 
385     /**
386      * Camera compat control is shown to allow reverting the applied treatment.
387      * @hide
388      */
389     public static final int CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED = 2;
390 
391     /**
392      * Camera compat control is dismissed by user.
393      * @hide
394      */
395     public static final int CAMERA_COMPAT_CONTROL_DISMISSED = 3;
396 
397     /**
398      * Enum for the Camera app compat control states.
399      * @hide
400      */
401     @Retention(RetentionPolicy.SOURCE)
402     @IntDef(prefix = { "CAMERA_COMPAT_CONTROL_" }, value = {
403             CAMERA_COMPAT_CONTROL_HIDDEN,
404             CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED,
405             CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED,
406             CAMERA_COMPAT_CONTROL_DISMISSED,
407     })
408     public @interface CameraCompatControlState {};
409 
410     /**
411      * State of the Camera app compat control which is used to correct stretched viewfinder
412      * in apps that don't handle all possible configurations and changes between them correctly.
413      * @hide
414      */
415     @CameraCompatControlState
416     public int cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
417 
TaskInfo()418     TaskInfo() {
419         // Do nothing
420     }
421 
TaskInfo(Parcel source)422     private TaskInfo(Parcel source) {
423         readFromParcel(source);
424     }
425 
426     /**
427      * Whether this task is visible.
428      */
isVisible()429     public boolean isVisible() {
430         return isVisible;
431     }
432 
433     /** @hide */
434     @NonNull
435     @TestApi
getToken()436     public WindowContainerToken getToken() {
437         return token;
438     }
439 
440     /** @hide */
441     @NonNull
442     @TestApi
getConfiguration()443     public Configuration getConfiguration() {
444         return configuration;
445     }
446 
447     /** @hide */
448     @Nullable
449     @TestApi
getPictureInPictureParams()450     public PictureInPictureParams getPictureInPictureParams() {
451         return pictureInPictureParams;
452     }
453 
454     /** @hide */
455     @TestApi
shouldDockBigOverlays()456     public boolean shouldDockBigOverlays() {
457         return shouldDockBigOverlays;
458     }
459 
460     /** @hide */
461     @WindowConfiguration.WindowingMode
getWindowingMode()462     public int getWindowingMode() {
463         return configuration.windowConfiguration.getWindowingMode();
464     }
465 
466     /** @hide */
467     @WindowConfiguration.ActivityType
getActivityType()468     public int getActivityType() {
469         return configuration.windowConfiguration.getActivityType();
470     }
471 
472     /** @hide */
addLaunchCookie(IBinder cookie)473     public void addLaunchCookie(IBinder cookie) {
474         if (cookie == null || launchCookies.contains(cookie)) return;
475         launchCookies.add(cookie);
476     }
477 
478     /** @hide */
hasCameraCompatControl()479     public boolean hasCameraCompatControl() {
480         return cameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN
481                 && cameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED;
482     }
483 
484     /** @hide */
hasCompatUI()485     public boolean hasCompatUI() {
486         return hasCameraCompatControl() || topActivityInSizeCompat
487                 || topActivityEligibleForLetterboxEducation
488                 || isLetterboxDoubleTapEnabled
489                 || topActivityEligibleForUserAspectRatioButton;
490     }
491 
492     /**
493      * @return {@code true} if this task contains the launch cookie.
494      * @hide
495      */
496     @TestApi
containsLaunchCookie(@onNull IBinder cookie)497     public boolean containsLaunchCookie(@NonNull IBinder cookie) {
498         return launchCookies.contains(cookie);
499     }
500 
501     /**
502      * @return The parent task id of this task.
503      * @hide
504      */
505     @TestApi
getParentTaskId()506     public int getParentTaskId() {
507         return parentTaskId;
508     }
509 
510     /** @hide */
511     @TestApi
hasParentTask()512     public boolean hasParentTask() {
513         return parentTaskId != INVALID_TASK_ID;
514     }
515 
516     /**
517      * @return The id of the display this task is associated with.
518      * @hide
519      */
520     @TestApi
getDisplayId()521     public int getDisplayId() {
522         return displayId;
523     }
524 
525     /**
526      * Returns {@code true} if the parameters that are important for task organizers are equal
527      * between this {@link TaskInfo} and {@param that}.
528      * @hide
529      */
equalsForTaskOrganizer(@ullable TaskInfo that)530     public boolean equalsForTaskOrganizer(@Nullable TaskInfo that) {
531         if (that == null) {
532             return false;
533         }
534         return topActivityType == that.topActivityType
535                 && isResizeable == that.isResizeable
536                 && supportsMultiWindow == that.supportsMultiWindow
537                 && displayAreaFeatureId == that.displayAreaFeatureId
538                 && isFromLetterboxDoubleTap == that.isFromLetterboxDoubleTap
539                 && topActivityEligibleForUserAspectRatioButton
540                     == that.topActivityEligibleForUserAspectRatioButton
541                 && topActivityLetterboxVerticalPosition == that.topActivityLetterboxVerticalPosition
542                 && topActivityLetterboxWidth == that.topActivityLetterboxWidth
543                 && topActivityLetterboxHeight == that.topActivityLetterboxHeight
544                 && topActivityLetterboxHorizontalPosition
545                     == that.topActivityLetterboxHorizontalPosition
546                 && Objects.equals(positionInParent, that.positionInParent)
547                 && Objects.equals(pictureInPictureParams, that.pictureInPictureParams)
548                 && Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays)
549                 && Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
550                 && getWindowingMode() == that.getWindowingMode()
551                 && configuration.uiMode == that.configuration.uiMode
552                 && Objects.equals(taskDescription, that.taskDescription)
553                 && isFocused == that.isFocused
554                 && isVisible == that.isVisible
555                 && isVisibleRequested == that.isVisibleRequested
556                 && isSleeping == that.isSleeping
557                 && Objects.equals(mTopActivityLocusId, that.mTopActivityLocusId)
558                 && parentTaskId == that.parentTaskId
559                 && Objects.equals(topActivity, that.topActivity)
560                 && isUserFullscreenOverrideEnabled == that.isUserFullscreenOverrideEnabled
561                 && isTopActivityTransparent == that.isTopActivityTransparent;
562     }
563 
564     /**
565      * @return {@code true} if parameters that are important for size compat have changed.
566      * @hide
567      */
equalsForCompatUi(@ullable TaskInfo that)568     public boolean equalsForCompatUi(@Nullable TaskInfo that) {
569         if (that == null) {
570             return false;
571         }
572         return displayId == that.displayId
573                 && taskId == that.taskId
574                 && topActivityInSizeCompat == that.topActivityInSizeCompat
575                 && isFromLetterboxDoubleTap == that.isFromLetterboxDoubleTap
576                 && topActivityEligibleForUserAspectRatioButton
577                     == that.topActivityEligibleForUserAspectRatioButton
578                 && topActivityEligibleForLetterboxEducation
579                     == that.topActivityEligibleForLetterboxEducation
580                 && topActivityLetterboxVerticalPosition == that.topActivityLetterboxVerticalPosition
581                 && topActivityLetterboxHorizontalPosition
582                     == that.topActivityLetterboxHorizontalPosition
583                 && topActivityLetterboxWidth == that.topActivityLetterboxWidth
584                 && topActivityLetterboxHeight == that.topActivityLetterboxHeight
585                 && cameraCompatControlState == that.cameraCompatControlState
586                 // Bounds are important if top activity has compat controls.
587                 && (!hasCompatUI() || configuration.windowConfiguration.getBounds()
588                     .equals(that.configuration.windowConfiguration.getBounds()))
589                 && (!hasCompatUI() || configuration.getLayoutDirection()
590                     == that.configuration.getLayoutDirection())
591                 && (!hasCompatUI() || configuration.uiMode == that.configuration.uiMode)
592                 && (!hasCompatUI() || isVisible == that.isVisible)
593                 && isFocused == that.isFocused
594                 && isUserFullscreenOverrideEnabled == that.isUserFullscreenOverrideEnabled
595                 && isTopActivityTransparent == that.isTopActivityTransparent;
596     }
597 
598     /**
599      * Reads the TaskInfo from a parcel.
600      */
readFromParcel(Parcel source)601     void readFromParcel(Parcel source) {
602         userId = source.readInt();
603         taskId = source.readInt();
604         displayId = source.readInt();
605         isRunning = source.readBoolean();
606         baseIntent = source.readTypedObject(Intent.CREATOR);
607         baseActivity = ComponentName.readFromParcel(source);
608         topActivity = ComponentName.readFromParcel(source);
609         origActivity = ComponentName.readFromParcel(source);
610         realActivity = ComponentName.readFromParcel(source);
611 
612         numActivities = source.readInt();
613         lastActiveTime = source.readLong();
614 
615         taskDescription = source.readTypedObject(ActivityManager.TaskDescription.CREATOR);
616         supportsMultiWindow = source.readBoolean();
617         resizeMode = source.readInt();
618         configuration.readFromParcel(source);
619         token = WindowContainerToken.CREATOR.createFromParcel(source);
620         topActivityType = source.readInt();
621         pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR);
622         shouldDockBigOverlays = source.readBoolean();
623         launchIntoPipHostTaskId = source.readInt();
624         lastParentTaskIdBeforePip = source.readInt();
625         displayCutoutInsets = source.readTypedObject(Rect.CREATOR);
626         topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
627         isResizeable = source.readBoolean();
628         minWidth = source.readInt();
629         minHeight = source.readInt();
630         defaultMinSize = source.readInt();
631         source.readBinderList(launchCookies);
632         positionInParent = source.readTypedObject(Point.CREATOR);
633         parentTaskId = source.readInt();
634         isFocused = source.readBoolean();
635         isVisible = source.readBoolean();
636         isVisibleRequested = source.readBoolean();
637         isSleeping = source.readBoolean();
638         topActivityInSizeCompat = source.readBoolean();
639         topActivityEligibleForLetterboxEducation = source.readBoolean();
640         mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
641         displayAreaFeatureId = source.readInt();
642         cameraCompatControlState = source.readInt();
643         isLetterboxDoubleTapEnabled = source.readBoolean();
644         topActivityEligibleForUserAspectRatioButton = source.readBoolean();
645         topActivityBoundsLetterboxed = source.readBoolean();
646         isFromLetterboxDoubleTap = source.readBoolean();
647         topActivityLetterboxVerticalPosition = source.readInt();
648         topActivityLetterboxHorizontalPosition = source.readInt();
649         topActivityLetterboxWidth = source.readInt();
650         topActivityLetterboxHeight = source.readInt();
651         isUserFullscreenOverrideEnabled = source.readBoolean();
652         isTopActivityTransparent = source.readBoolean();
653     }
654 
655     /**
656      * Writes the TaskInfo to a parcel.
657      */
writeToParcel(Parcel dest, int flags)658     void writeToParcel(Parcel dest, int flags) {
659         dest.writeInt(userId);
660         dest.writeInt(taskId);
661         dest.writeInt(displayId);
662         dest.writeBoolean(isRunning);
663         dest.writeTypedObject(baseIntent, 0);
664 
665         ComponentName.writeToParcel(baseActivity, dest);
666         ComponentName.writeToParcel(topActivity, dest);
667         ComponentName.writeToParcel(origActivity, dest);
668         ComponentName.writeToParcel(realActivity, dest);
669 
670         dest.writeInt(numActivities);
671         dest.writeLong(lastActiveTime);
672 
673         dest.writeTypedObject(taskDescription, flags);
674         dest.writeBoolean(supportsMultiWindow);
675         dest.writeInt(resizeMode);
676         configuration.writeToParcel(dest, flags);
677         token.writeToParcel(dest, flags);
678         dest.writeInt(topActivityType);
679         dest.writeTypedObject(pictureInPictureParams, flags);
680         dest.writeBoolean(shouldDockBigOverlays);
681         dest.writeInt(launchIntoPipHostTaskId);
682         dest.writeInt(lastParentTaskIdBeforePip);
683         dest.writeTypedObject(displayCutoutInsets, flags);
684         dest.writeTypedObject(topActivityInfo, flags);
685         dest.writeBoolean(isResizeable);
686         dest.writeInt(minWidth);
687         dest.writeInt(minHeight);
688         dest.writeInt(defaultMinSize);
689         dest.writeBinderList(launchCookies);
690         dest.writeTypedObject(positionInParent, flags);
691         dest.writeInt(parentTaskId);
692         dest.writeBoolean(isFocused);
693         dest.writeBoolean(isVisible);
694         dest.writeBoolean(isVisibleRequested);
695         dest.writeBoolean(isSleeping);
696         dest.writeBoolean(topActivityInSizeCompat);
697         dest.writeBoolean(topActivityEligibleForLetterboxEducation);
698         dest.writeTypedObject(mTopActivityLocusId, flags);
699         dest.writeInt(displayAreaFeatureId);
700         dest.writeInt(cameraCompatControlState);
701         dest.writeBoolean(isLetterboxDoubleTapEnabled);
702         dest.writeBoolean(topActivityEligibleForUserAspectRatioButton);
703         dest.writeBoolean(topActivityBoundsLetterboxed);
704         dest.writeBoolean(isFromLetterboxDoubleTap);
705         dest.writeInt(topActivityLetterboxVerticalPosition);
706         dest.writeInt(topActivityLetterboxHorizontalPosition);
707         dest.writeInt(topActivityLetterboxWidth);
708         dest.writeInt(topActivityLetterboxHeight);
709         dest.writeBoolean(isUserFullscreenOverrideEnabled);
710         dest.writeBoolean(isTopActivityTransparent);
711     }
712 
713     @Override
toString()714     public String toString() {
715         return "TaskInfo{userId=" + userId + " taskId=" + taskId
716                 + " displayId=" + displayId
717                 + " isRunning=" + isRunning
718                 + " baseIntent=" + baseIntent + " baseActivity=" + baseActivity
719                 + " topActivity=" + topActivity + " origActivity=" + origActivity
720                 + " realActivity=" + realActivity
721                 + " numActivities=" + numActivities
722                 + " lastActiveTime=" + lastActiveTime
723                 + " supportsMultiWindow=" + supportsMultiWindow
724                 + " resizeMode=" + resizeMode
725                 + " isResizeable=" + isResizeable
726                 + " minWidth=" + minWidth
727                 + " minHeight=" + minHeight
728                 + " defaultMinSize=" + defaultMinSize
729                 + " token=" + token
730                 + " topActivityType=" + topActivityType
731                 + " pictureInPictureParams=" + pictureInPictureParams
732                 + " shouldDockBigOverlays=" + shouldDockBigOverlays
733                 + " launchIntoPipHostTaskId=" + launchIntoPipHostTaskId
734                 + " lastParentTaskIdBeforePip=" + lastParentTaskIdBeforePip
735                 + " displayCutoutSafeInsets=" + displayCutoutInsets
736                 + " topActivityInfo=" + topActivityInfo
737                 + " launchCookies=" + launchCookies
738                 + " positionInParent=" + positionInParent
739                 + " parentTaskId=" + parentTaskId
740                 + " isFocused=" + isFocused
741                 + " isVisible=" + isVisible
742                 + " isVisibleRequested=" + isVisibleRequested
743                 + " isSleeping=" + isSleeping
744                 + " topActivityInSizeCompat=" + topActivityInSizeCompat
745                 + " topActivityEligibleForLetterboxEducation= "
746                         + topActivityEligibleForLetterboxEducation
747                 + " isLetterboxDoubleTapEnabled= " + isLetterboxDoubleTapEnabled
748                 + " topActivityEligibleForUserAspectRatioButton= "
749                 + topActivityEligibleForUserAspectRatioButton
750                 + " topActivityBoundsLetterboxed= " + topActivityBoundsLetterboxed
751                 + " isFromLetterboxDoubleTap= " + isFromLetterboxDoubleTap
752                 + " topActivityLetterboxVerticalPosition= " + topActivityLetterboxVerticalPosition
753                 + " topActivityLetterboxHorizontalPosition= "
754                         + topActivityLetterboxHorizontalPosition
755                 + " topActivityLetterboxWidth=" + topActivityLetterboxWidth
756                 + " topActivityLetterboxHeight=" + topActivityLetterboxHeight
757                 + " isUserFullscreenOverrideEnabled=" + isUserFullscreenOverrideEnabled
758                 + " isTopActivityTransparent=" + isTopActivityTransparent
759                 + " locusId=" + mTopActivityLocusId
760                 + " displayAreaFeatureId=" + displayAreaFeatureId
761                 + " cameraCompatControlState="
762                         + cameraCompatControlStateToString(cameraCompatControlState)
763                 + "}";
764     }
765 
766     /** @hide */
cameraCompatControlStateToString( @ameraCompatControlState int cameraCompatControlState)767     public static String cameraCompatControlStateToString(
768             @CameraCompatControlState int cameraCompatControlState) {
769         switch (cameraCompatControlState) {
770             case CAMERA_COMPAT_CONTROL_HIDDEN: return "hidden";
771             case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED: return "treatment-suggested";
772             case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED: return "treatment-applied";
773             case CAMERA_COMPAT_CONTROL_DISMISSED: return "dismissed";
774             default:
775                 throw new AssertionError(
776                     "Unexpected camera compat control state: " + cameraCompatControlState);
777         }
778     }
779 }
780