• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 update comes from a letterbox double-tap action from the user or not.
246      * @hide
247      */
248     public boolean isFromLetterboxDoubleTap;
249 
250     /**
251      * If {@link isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position or
252      * {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
253      * @hide
254      */
255     public int topActivityLetterboxVerticalPosition;
256 
257     /**
258      * If {@link isLetterboxDoubleTapEnabled} it contains the current letterbox vertical position or
259      * {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise.
260      * @hide
261      */
262     public int topActivityLetterboxHorizontalPosition;
263 
264     /**
265      * If {@link isLetterboxDoubleTapEnabled} it contains the current width of the letterboxed
266      * activity or {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise
267      * @hide
268      */
269     public int topActivityLetterboxWidth;
270 
271     /**
272      * If {@link isLetterboxDoubleTapEnabled} it contains the current height of the letterboxed
273      * activity or {@link TaskInfo.PROPERTY_VALUE_UNSET} otherwise
274      * @hide
275      */
276     public int topActivityLetterboxHeight;
277 
278     /**
279      * Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity
280      * supports), this is what the system actually uses for resizability based on other policy and
281      * developer options.
282      * @hide
283      */
284     public boolean isResizeable;
285 
286     /**
287      * Minimal width of the task when it's resizeable.
288      * @hide
289      */
290     public int minWidth;
291 
292     /**
293      * Minimal height of the task when it's resizeable.
294      * @hide
295      */
296     public int minHeight;
297 
298     /**
299      * The default minimal size of the task used when a minWidth or minHeight is not specified.
300      * @hide
301      */
302     public int defaultMinSize;
303 
304     /**
305      * Relative position of the task's top left corner in the parent container.
306      * @hide
307      */
308     public Point positionInParent;
309 
310     /**
311      * The launch cookies associated with activities in this task if any.
312      * @see ActivityOptions#setLaunchCookie(IBinder)
313      * @hide
314      */
315     public ArrayList<IBinder> launchCookies = new ArrayList<>();
316 
317     /**
318      * The identifier of the parent task that is created by organizer, otherwise
319      * {@link ActivityTaskManager#INVALID_TASK_ID}.
320      * @hide
321      */
322     public int parentTaskId;
323 
324     /**
325      * Whether this task is focused.
326      * @hide
327      */
328     public boolean isFocused;
329 
330     /**
331      * Whether this task is visible.
332      * @hide
333      */
334     public boolean isVisible;
335 
336     /**
337      * Whether this task is sleeping due to sleeping display.
338      * @hide
339      */
340     public boolean isSleeping;
341 
342     /**
343      * Camera compat control isn't shown because it's not requested by heuristics.
344      * @hide
345      */
346     public static final int CAMERA_COMPAT_CONTROL_HIDDEN = 0;
347 
348     /**
349      * Camera compat control is shown with the treatment suggested.
350      * @hide
351      */
352     public static final int CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED = 1;
353 
354     /**
355      * Camera compat control is shown to allow reverting the applied treatment.
356      * @hide
357      */
358     public static final int CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED = 2;
359 
360     /**
361      * Camera compat control is dismissed by user.
362      * @hide
363      */
364     public static final int CAMERA_COMPAT_CONTROL_DISMISSED = 3;
365 
366     /**
367      * Enum for the Camera app compat control states.
368      * @hide
369      */
370     @Retention(RetentionPolicy.SOURCE)
371     @IntDef(prefix = { "CAMERA_COMPAT_CONTROL_" }, value = {
372             CAMERA_COMPAT_CONTROL_HIDDEN,
373             CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED,
374             CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED,
375             CAMERA_COMPAT_CONTROL_DISMISSED,
376     })
377     public @interface CameraCompatControlState {};
378 
379     /**
380      * State of the Camera app compat control which is used to correct stretched viewfinder
381      * in apps that don't handle all possible configurations and changes between them correctly.
382      * @hide
383      */
384     @CameraCompatControlState
385     public int cameraCompatControlState = CAMERA_COMPAT_CONTROL_HIDDEN;
386 
TaskInfo()387     TaskInfo() {
388         // Do nothing
389     }
390 
TaskInfo(Parcel source)391     private TaskInfo(Parcel source) {
392         readFromParcel(source);
393     }
394 
395     /**
396      * Whether this task is visible.
397      */
isVisible()398     public boolean isVisible() {
399         return isVisible;
400     }
401 
402     /** @hide */
403     @NonNull
404     @TestApi
getToken()405     public WindowContainerToken getToken() {
406         return token;
407     }
408 
409     /** @hide */
410     @NonNull
411     @TestApi
getConfiguration()412     public Configuration getConfiguration() {
413         return configuration;
414     }
415 
416     /** @hide */
417     @Nullable
418     @TestApi
getPictureInPictureParams()419     public PictureInPictureParams getPictureInPictureParams() {
420         return pictureInPictureParams;
421     }
422 
423     /** @hide */
424     @TestApi
shouldDockBigOverlays()425     public boolean shouldDockBigOverlays() {
426         return shouldDockBigOverlays;
427     }
428 
429     /** @hide */
430     @WindowConfiguration.WindowingMode
getWindowingMode()431     public int getWindowingMode() {
432         return configuration.windowConfiguration.getWindowingMode();
433     }
434 
435     /** @hide */
436     @WindowConfiguration.ActivityType
getActivityType()437     public int getActivityType() {
438         return configuration.windowConfiguration.getActivityType();
439     }
440 
441     /** @hide */
addLaunchCookie(IBinder cookie)442     public void addLaunchCookie(IBinder cookie) {
443         if (cookie == null || launchCookies.contains(cookie)) return;
444         launchCookies.add(cookie);
445     }
446 
447     /** @hide */
hasCameraCompatControl()448     public boolean hasCameraCompatControl() {
449         return cameraCompatControlState != CAMERA_COMPAT_CONTROL_HIDDEN
450                 && cameraCompatControlState != CAMERA_COMPAT_CONTROL_DISMISSED;
451     }
452 
453     /** @hide */
hasCompatUI()454     public boolean hasCompatUI() {
455         return hasCameraCompatControl() || topActivityInSizeCompat
456                 || topActivityEligibleForLetterboxEducation
457                 || isLetterboxDoubleTapEnabled;
458     }
459 
460     /**
461      * @return {@code true} if this task contains the launch cookie.
462      * @hide
463      */
464     @TestApi
containsLaunchCookie(@onNull IBinder cookie)465     public boolean containsLaunchCookie(@NonNull IBinder cookie) {
466         return launchCookies.contains(cookie);
467     }
468 
469     /**
470      * @return The parent task id of this task.
471      * @hide
472      */
473     @TestApi
getParentTaskId()474     public int getParentTaskId() {
475         return parentTaskId;
476     }
477 
478     /** @hide */
479     @TestApi
hasParentTask()480     public boolean hasParentTask() {
481         return parentTaskId != INVALID_TASK_ID;
482     }
483 
484     /**
485      * Returns {@code true} if the parameters that are important for task organizers are equal
486      * between this {@link TaskInfo} and {@param that}.
487      * @hide
488      */
equalsForTaskOrganizer(@ullable TaskInfo that)489     public boolean equalsForTaskOrganizer(@Nullable TaskInfo that) {
490         if (that == null) {
491             return false;
492         }
493         return topActivityType == that.topActivityType
494                 && isResizeable == that.isResizeable
495                 && supportsMultiWindow == that.supportsMultiWindow
496                 && displayAreaFeatureId == that.displayAreaFeatureId
497                 && isFromLetterboxDoubleTap == that.isFromLetterboxDoubleTap
498                 && topActivityLetterboxVerticalPosition == that.topActivityLetterboxVerticalPosition
499                 && topActivityLetterboxWidth == that.topActivityLetterboxWidth
500                 && topActivityLetterboxHeight == that.topActivityLetterboxHeight
501                 && topActivityLetterboxHorizontalPosition
502                     == that.topActivityLetterboxHorizontalPosition
503                 && Objects.equals(positionInParent, that.positionInParent)
504                 && Objects.equals(pictureInPictureParams, that.pictureInPictureParams)
505                 && Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays)
506                 && Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
507                 && getWindowingMode() == that.getWindowingMode()
508                 && configuration.uiMode == that.configuration.uiMode
509                 && Objects.equals(taskDescription, that.taskDescription)
510                 && isFocused == that.isFocused
511                 && isVisible == that.isVisible
512                 && isSleeping == that.isSleeping
513                 && Objects.equals(mTopActivityLocusId, that.mTopActivityLocusId)
514                 && parentTaskId == that.parentTaskId
515                 && Objects.equals(topActivity, that.topActivity);
516     }
517 
518     /**
519      * @return {@code true} if parameters that are important for size compat have changed.
520      * @hide
521      */
equalsForCompatUi(@ullable TaskInfo that)522     public boolean equalsForCompatUi(@Nullable TaskInfo that) {
523         if (that == null) {
524             return false;
525         }
526         return displayId == that.displayId
527                 && taskId == that.taskId
528                 && topActivityInSizeCompat == that.topActivityInSizeCompat
529                 && isFromLetterboxDoubleTap == that.isFromLetterboxDoubleTap
530                 && topActivityEligibleForLetterboxEducation
531                     == that.topActivityEligibleForLetterboxEducation
532                 && topActivityLetterboxVerticalPosition == that.topActivityLetterboxVerticalPosition
533                 && topActivityLetterboxHorizontalPosition
534                     == that.topActivityLetterboxHorizontalPosition
535                 && topActivityLetterboxWidth == that.topActivityLetterboxWidth
536                 && topActivityLetterboxHeight == that.topActivityLetterboxHeight
537                 && cameraCompatControlState == that.cameraCompatControlState
538                 // Bounds are important if top activity has compat controls.
539                 && (!hasCompatUI() || configuration.windowConfiguration.getBounds()
540                     .equals(that.configuration.windowConfiguration.getBounds()))
541                 && (!hasCompatUI() || configuration.getLayoutDirection()
542                     == that.configuration.getLayoutDirection())
543                 && (!hasCompatUI() || configuration.uiMode == that.configuration.uiMode)
544                 && (!hasCompatUI() || isVisible == that.isVisible);
545     }
546 
547     /**
548      * Reads the TaskInfo from a parcel.
549      */
readFromParcel(Parcel source)550     void readFromParcel(Parcel source) {
551         userId = source.readInt();
552         taskId = source.readInt();
553         displayId = source.readInt();
554         isRunning = source.readBoolean();
555         baseIntent = source.readTypedObject(Intent.CREATOR);
556         baseActivity = ComponentName.readFromParcel(source);
557         topActivity = ComponentName.readFromParcel(source);
558         origActivity = ComponentName.readFromParcel(source);
559         realActivity = ComponentName.readFromParcel(source);
560 
561         numActivities = source.readInt();
562         lastActiveTime = source.readLong();
563 
564         taskDescription = source.readTypedObject(ActivityManager.TaskDescription.CREATOR);
565         supportsMultiWindow = source.readBoolean();
566         resizeMode = source.readInt();
567         configuration.readFromParcel(source);
568         token = WindowContainerToken.CREATOR.createFromParcel(source);
569         topActivityType = source.readInt();
570         pictureInPictureParams = source.readTypedObject(PictureInPictureParams.CREATOR);
571         shouldDockBigOverlays = source.readBoolean();
572         launchIntoPipHostTaskId = source.readInt();
573         lastParentTaskIdBeforePip = source.readInt();
574         displayCutoutInsets = source.readTypedObject(Rect.CREATOR);
575         topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
576         isResizeable = source.readBoolean();
577         minWidth = source.readInt();
578         minHeight = source.readInt();
579         defaultMinSize = source.readInt();
580         source.readBinderList(launchCookies);
581         positionInParent = source.readTypedObject(Point.CREATOR);
582         parentTaskId = source.readInt();
583         isFocused = source.readBoolean();
584         isVisible = source.readBoolean();
585         isSleeping = source.readBoolean();
586         topActivityInSizeCompat = source.readBoolean();
587         topActivityEligibleForLetterboxEducation = source.readBoolean();
588         mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
589         displayAreaFeatureId = source.readInt();
590         cameraCompatControlState = source.readInt();
591         isLetterboxDoubleTapEnabled = source.readBoolean();
592         isFromLetterboxDoubleTap = source.readBoolean();
593         topActivityLetterboxVerticalPosition = source.readInt();
594         topActivityLetterboxHorizontalPosition = source.readInt();
595         topActivityLetterboxWidth = source.readInt();
596         topActivityLetterboxHeight = source.readInt();
597     }
598 
599     /**
600      * Writes the TaskInfo to a parcel.
601      */
writeToParcel(Parcel dest, int flags)602     void writeToParcel(Parcel dest, int flags) {
603         dest.writeInt(userId);
604         dest.writeInt(taskId);
605         dest.writeInt(displayId);
606         dest.writeBoolean(isRunning);
607         dest.writeTypedObject(baseIntent, 0);
608 
609         ComponentName.writeToParcel(baseActivity, dest);
610         ComponentName.writeToParcel(topActivity, dest);
611         ComponentName.writeToParcel(origActivity, dest);
612         ComponentName.writeToParcel(realActivity, dest);
613 
614         dest.writeInt(numActivities);
615         dest.writeLong(lastActiveTime);
616 
617         dest.writeTypedObject(taskDescription, flags);
618         dest.writeBoolean(supportsMultiWindow);
619         dest.writeInt(resizeMode);
620         configuration.writeToParcel(dest, flags);
621         token.writeToParcel(dest, flags);
622         dest.writeInt(topActivityType);
623         dest.writeTypedObject(pictureInPictureParams, flags);
624         dest.writeBoolean(shouldDockBigOverlays);
625         dest.writeInt(launchIntoPipHostTaskId);
626         dest.writeInt(lastParentTaskIdBeforePip);
627         dest.writeTypedObject(displayCutoutInsets, flags);
628         dest.writeTypedObject(topActivityInfo, flags);
629         dest.writeBoolean(isResizeable);
630         dest.writeInt(minWidth);
631         dest.writeInt(minHeight);
632         dest.writeInt(defaultMinSize);
633         dest.writeBinderList(launchCookies);
634         dest.writeTypedObject(positionInParent, flags);
635         dest.writeInt(parentTaskId);
636         dest.writeBoolean(isFocused);
637         dest.writeBoolean(isVisible);
638         dest.writeBoolean(isSleeping);
639         dest.writeBoolean(topActivityInSizeCompat);
640         dest.writeBoolean(topActivityEligibleForLetterboxEducation);
641         dest.writeTypedObject(mTopActivityLocusId, flags);
642         dest.writeInt(displayAreaFeatureId);
643         dest.writeInt(cameraCompatControlState);
644         dest.writeBoolean(isLetterboxDoubleTapEnabled);
645         dest.writeBoolean(isFromLetterboxDoubleTap);
646         dest.writeInt(topActivityLetterboxVerticalPosition);
647         dest.writeInt(topActivityLetterboxHorizontalPosition);
648         dest.writeInt(topActivityLetterboxWidth);
649         dest.writeInt(topActivityLetterboxHeight);
650     }
651 
652     @Override
toString()653     public String toString() {
654         return "TaskInfo{userId=" + userId + " taskId=" + taskId
655                 + " displayId=" + displayId
656                 + " isRunning=" + isRunning
657                 + " baseIntent=" + baseIntent + " baseActivity=" + baseActivity
658                 + " topActivity=" + topActivity + " origActivity=" + origActivity
659                 + " realActivity=" + realActivity
660                 + " numActivities=" + numActivities
661                 + " lastActiveTime=" + lastActiveTime
662                 + " supportsMultiWindow=" + supportsMultiWindow
663                 + " resizeMode=" + resizeMode
664                 + " isResizeable=" + isResizeable
665                 + " minWidth=" + minWidth
666                 + " minHeight=" + minHeight
667                 + " defaultMinSize=" + defaultMinSize
668                 + " token=" + token
669                 + " topActivityType=" + topActivityType
670                 + " pictureInPictureParams=" + pictureInPictureParams
671                 + " shouldDockBigOverlays=" + shouldDockBigOverlays
672                 + " launchIntoPipHostTaskId=" + launchIntoPipHostTaskId
673                 + " lastParentTaskIdBeforePip=" + lastParentTaskIdBeforePip
674                 + " displayCutoutSafeInsets=" + displayCutoutInsets
675                 + " topActivityInfo=" + topActivityInfo
676                 + " launchCookies=" + launchCookies
677                 + " positionInParent=" + positionInParent
678                 + " parentTaskId=" + parentTaskId
679                 + " isFocused=" + isFocused
680                 + " isVisible=" + isVisible
681                 + " isSleeping=" + isSleeping
682                 + " topActivityInSizeCompat=" + topActivityInSizeCompat
683                 + " topActivityEligibleForLetterboxEducation= "
684                         + topActivityEligibleForLetterboxEducation
685                 + " topActivityLetterboxed= " + isLetterboxDoubleTapEnabled
686                 + " isFromDoubleTap= " + isFromLetterboxDoubleTap
687                 + " topActivityLetterboxVerticalPosition= " + topActivityLetterboxVerticalPosition
688                 + " topActivityLetterboxHorizontalPosition= "
689                         + topActivityLetterboxHorizontalPosition
690                 + " topActivityLetterboxWidth=" + topActivityLetterboxWidth
691                 + " topActivityLetterboxHeight=" + topActivityLetterboxHeight
692                 + " locusId=" + mTopActivityLocusId
693                 + " displayAreaFeatureId=" + displayAreaFeatureId
694                 + " cameraCompatControlState="
695                         + cameraCompatControlStateToString(cameraCompatControlState)
696                 + "}";
697     }
698 
699     /** @hide */
cameraCompatControlStateToString( @ameraCompatControlState int cameraCompatControlState)700     public static String cameraCompatControlStateToString(
701             @CameraCompatControlState int cameraCompatControlState) {
702         switch (cameraCompatControlState) {
703             case CAMERA_COMPAT_CONTROL_HIDDEN: return "hidden";
704             case CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED: return "treatment-suggested";
705             case CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED: return "treatment-applied";
706             case CAMERA_COMPAT_CONTROL_DISMISSED: return "dismissed";
707             default:
708                 throw new AssertionError(
709                     "Unexpected camera compat control state: " + cameraCompatControlState);
710         }
711     }
712 }
713