• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 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.tools.device.traces.parsers.wm
18 
19 import android.app.nano.WindowConfigurationProto
20 import android.content.nano.ConfigurationProto
21 import android.graphics.nano.RectProto
22 import android.tools.common.PlatformConsts
23 import android.tools.common.Rotation
24 import android.tools.common.datatypes.Insets
25 import android.tools.common.datatypes.Rect
26 import android.tools.common.datatypes.Size
27 import android.tools.common.traces.wm.Activity
28 import android.tools.common.traces.wm.Configuration
29 import android.tools.common.traces.wm.ConfigurationContainer
30 import android.tools.common.traces.wm.DisplayArea
31 import android.tools.common.traces.wm.DisplayContent
32 import android.tools.common.traces.wm.DisplayCutout
33 import android.tools.common.traces.wm.IWindowContainer
34 import android.tools.common.traces.wm.KeyguardControllerState
35 import android.tools.common.traces.wm.RootWindowContainer
36 import android.tools.common.traces.wm.Task
37 import android.tools.common.traces.wm.TaskFragment
38 import android.tools.common.traces.wm.WindowConfiguration
39 import android.tools.common.traces.wm.WindowContainer
40 import android.tools.common.traces.wm.WindowLayoutParams
41 import android.tools.common.traces.wm.WindowManagerPolicy
42 import android.tools.common.traces.wm.WindowManagerState
43 import android.tools.common.traces.wm.WindowManagerTraceEntryBuilder
44 import android.tools.common.traces.wm.WindowState
45 import android.tools.common.traces.wm.WindowToken
46 import android.view.Surface
47 import android.view.nano.DisplayCutoutProto
48 import android.view.nano.ViewProtoEnums
49 import android.view.nano.WindowLayoutParamsProto
50 import com.android.server.wm.nano.ActivityRecordProto
51 import com.android.server.wm.nano.AppTransitionProto
52 import com.android.server.wm.nano.ConfigurationContainerProto
53 import com.android.server.wm.nano.DisplayAreaProto
54 import com.android.server.wm.nano.DisplayContentProto
55 import com.android.server.wm.nano.KeyguardControllerProto
56 import com.android.server.wm.nano.RootWindowContainerProto
57 import com.android.server.wm.nano.TaskFragmentProto
58 import com.android.server.wm.nano.TaskProto
59 import com.android.server.wm.nano.WindowContainerChildProto
60 import com.android.server.wm.nano.WindowContainerProto
61 import com.android.server.wm.nano.WindowManagerPolicyProto
62 import com.android.server.wm.nano.WindowManagerServiceDumpProto
63 import com.android.server.wm.nano.WindowStateProto
64 import com.android.server.wm.nano.WindowTokenProto
65 
66 /** Helper class to create a new WM state */
67 class WindowManagerStateBuilder {
68     private var computedZCounter = 0
69     private var realToElapsedTimeOffsetNanos = 0L
70     private var where = ""
71     private var timestamp = 0L
72     private var proto: WindowManagerServiceDumpProto? = null
73 
74     fun withRealTimeOffset(value: Long) = apply { realToElapsedTimeOffsetNanos = value }
75 
76     fun atPlace(_where: String) = apply { where = _where }
77 
78     fun forTimestamp(value: Long) = apply { timestamp = value }
79 
80     fun forProto(value: WindowManagerServiceDumpProto) = apply { proto = value }
81 
82     fun build(): WindowManagerState {
83         val proto = proto
84         requireNotNull(proto) { "Proto object not specified" }
85 
86         computedZCounter = 0
87         return WindowManagerTraceEntryBuilder()
88             .setElapsedTimestamp(timestamp.toString())
89             .setPolicy(createWindowManagerPolicy(proto.policy))
90             .setFocusedApp(proto.focusedApp)
91             .setFocusedDisplayId(proto.focusedDisplayId)
92             .setFocusedWindow(proto.focusedWindow?.title ?: "")
93             .setInputMethodWindowAppToken(
94                 if (proto.inputMethodWindow != null) {
95                     Integer.toHexString(proto.inputMethodWindow.hashCode)
96                 } else {
97                     ""
98                 }
99             )
100             .setIsHomeRecentsComponent(proto.rootWindowContainer.isHomeRecentsComponent)
101             .setIsDisplayFrozen(proto.displayFrozen)
102             .setPendingActivities(
103                 proto.rootWindowContainer.pendingActivities.map { it.title }.toTypedArray()
104             )
105             .setRoot(createRootWindowContainer(proto.rootWindowContainer))
106             .setKeyguardControllerState(
107                 createKeyguardControllerState(proto.rootWindowContainer.keyguardController)
108             )
109             .setWhere(where)
110             .setRealToElapsedTimeOffsetNs(realToElapsedTimeOffsetNanos.toString())
111             .build()
112     }
113 
114     private fun createWindowManagerPolicy(proto: WindowManagerPolicyProto): WindowManagerPolicy {
115         return WindowManagerPolicy.from(
116             focusedAppToken = proto.focusedAppToken ?: "",
117             forceStatusBar = proto.forceStatusBar,
118             forceStatusBarFromKeyguard = proto.forceStatusBarFromKeyguard,
119             keyguardDrawComplete = proto.keyguardDrawComplete,
120             keyguardOccluded = proto.keyguardOccluded,
121             keyguardOccludedChanged = proto.keyguardOccludedChanged,
122             keyguardOccludedPending = proto.keyguardOccludedPending,
123             lastSystemUiFlags = proto.lastSystemUiFlags,
124             orientation = proto.orientation,
125             rotation = Rotation.getByValue(proto.rotation),
126             rotationMode = proto.rotationMode,
127             screenOnFully = proto.screenOnFully,
128             windowManagerDrawComplete = proto.windowManagerDrawComplete
129         )
130     }
131 
132     private fun createRootWindowContainer(proto: RootWindowContainerProto): RootWindowContainer {
133         return RootWindowContainer(
134             createWindowContainer(
135                 proto.windowContainer,
136                 proto.windowContainer.children.mapNotNull { p ->
137                     createWindowContainerChild(p, isActivityInTree = false)
138                 }
139             )
140                 ?: error("Window container should not be null")
141         )
142     }
143 
144     private fun createKeyguardControllerState(
145         proto: KeyguardControllerProto?
146     ): KeyguardControllerState {
147         return KeyguardControllerState.from(
148             isAodShowing = proto?.aodShowing ?: false,
149             isKeyguardShowing = proto?.keyguardShowing ?: false,
150             keyguardOccludedStates =
151                 proto?.keyguardOccludedStates?.associate { it.displayId to it.keyguardOccluded }
152                     ?: emptyMap()
153         )
154     }
155 
156     private fun createWindowContainerChild(
157         proto: WindowContainerChildProto,
158         isActivityInTree: Boolean
159     ): IWindowContainer? {
160         return createDisplayContent(proto.displayContent, isActivityInTree)
161             ?: createDisplayArea(proto.displayArea, isActivityInTree)
162                 ?: createTask(proto.task, isActivityInTree)
163                 ?: createTaskFragment(proto.taskFragment, isActivityInTree)
164                 ?: createActivity(proto.activity)
165                 ?: createWindowToken(proto.windowToken, isActivityInTree)
166                 ?: createWindowState(proto.window, isActivityInTree)
167                 ?: createWindowContainer(proto.windowContainer, children = emptyList())
168     }
169 
170     private fun createDisplayContent(
171         proto: DisplayContentProto?,
172         isActivityInTree: Boolean
173     ): DisplayContent? {
174         return if (proto == null) {
175             null
176         } else {
177             DisplayContent(
178                 id = proto.id,
179                 focusedRootTaskId = proto.focusedRootTaskId,
180                 resumedActivity = proto.resumedActivity?.title ?: "",
181                 singleTaskInstance = proto.singleTaskInstance,
182                 defaultPinnedStackBounds = proto.pinnedTaskController?.defaultBounds?.toRect()
183                         ?: Rect.EMPTY,
184                 pinnedStackMovementBounds = proto.pinnedTaskController?.movementBounds?.toRect()
185                         ?: Rect.EMPTY,
186                 displayRect =
187                     Rect.from(
188                         0,
189                         0,
190                         proto.displayInfo?.logicalWidth ?: 0,
191                         proto.displayInfo?.logicalHeight ?: 0
192                     ),
193                 appRect =
194                     Rect.from(
195                         0,
196                         0,
197                         proto.displayInfo?.appWidth ?: 0,
198                         proto.displayInfo?.appHeight ?: 0
199                     ),
200                 dpi = proto.dpi,
201                 flags = proto.displayInfo?.flags ?: 0,
202                 stableBounds = proto.displayFrames?.stableBounds?.toRect() ?: Rect.EMPTY,
203                 surfaceSize = proto.surfaceSize,
204                 focusedApp = proto.focusedApp,
205                 lastTransition =
206                     appTransitionToString(proto.appTransition?.lastUsedAppTransition ?: 0),
207                 appTransitionState = appStateToString(proto.appTransition?.appTransitionState ?: 0),
208                 rotation =
209                     Rotation.getByValue(proto.displayRotation?.rotation ?: Surface.ROTATION_0),
210                 lastOrientation = proto.displayRotation?.lastOrientation ?: 0,
211                 cutout = createDisplayCutout(proto.displayInfo?.cutout),
212                 windowContainer =
213                     createWindowContainer(
214                         proto.rootDisplayArea.windowContainer,
215                         proto.rootDisplayArea.windowContainer.children.mapNotNull { p ->
216                             createWindowContainerChild(p, isActivityInTree)
217                         },
218                         nameOverride = proto.displayInfo?.name ?: ""
219                     )
220                         ?: error("Window container should not be null")
221             )
222         }
223     }
224 
225     private fun createDisplayArea(
226         proto: DisplayAreaProto?,
227         isActivityInTree: Boolean
228     ): DisplayArea? {
229         return if (proto == null) {
230             null
231         } else {
232             DisplayArea(
233                 isTaskDisplayArea = proto.isTaskDisplayArea,
234                 windowContainer =
235                     createWindowContainer(
236                         proto.windowContainer,
237                         proto.windowContainer.children.mapNotNull { p ->
238                             createWindowContainerChild(p, isActivityInTree)
239                         }
240                     )
241                         ?: error("Window container should not be null")
242             )
243         }
244     }
245 
246     private fun createTask(proto: TaskProto?, isActivityInTree: Boolean): Task? {
247         return if (proto == null) {
248             null
249         } else {
250             Task(
251                 activityType = proto.taskFragment?.activityType ?: proto.activityType,
252                 isFullscreen = proto.fillsParent,
253                 bounds = proto.bounds.toRect(),
254                 taskId = proto.id,
255                 rootTaskId = proto.rootTaskId,
256                 displayId = proto.taskFragment?.displayId ?: proto.displayId,
257                 lastNonFullscreenBounds = proto.lastNonFullscreenBounds?.toRect() ?: Rect.EMPTY,
258                 realActivity = proto.realActivity,
259                 origActivity = proto.origActivity,
260                 resizeMode = proto.resizeMode,
261                 _resumedActivity = proto.resumedActivity?.title ?: "",
262                 animatingBounds = proto.animatingBounds,
263                 surfaceWidth = proto.surfaceWidth,
264                 surfaceHeight = proto.surfaceHeight,
265                 createdByOrganizer = proto.createdByOrganizer,
266                 minWidth = proto.taskFragment?.minWidth ?: proto.minWidth,
267                 minHeight = proto.taskFragment?.minHeight ?: proto.minHeight,
268                 windowContainer =
269                     createWindowContainer(
270                         proto.taskFragment?.windowContainer ?: proto.windowContainer,
271                         if (proto.taskFragment != null) {
272                             proto.taskFragment.windowContainer.children.mapNotNull { p ->
273                                 createWindowContainerChild(p, isActivityInTree)
274                             }
275                         } else {
276                             proto.windowContainer.children.mapNotNull { p ->
277                                 createWindowContainerChild(p, isActivityInTree)
278                             }
279                         }
280                     )
281                         ?: error("Window container should not be null")
282             )
283         }
284     }
285 
286     private fun createTaskFragment(
287         proto: TaskFragmentProto?,
288         isActivityInTree: Boolean
289     ): TaskFragment? {
290         return if (proto == null) {
291             null
292         } else {
293             TaskFragment(
294                 activityType = proto.activityType,
295                 displayId = proto.displayId,
296                 minWidth = proto.minWidth,
297                 minHeight = proto.minHeight,
298                 windowContainer =
299                     createWindowContainer(
300                         proto.windowContainer,
301                         proto.windowContainer.children.mapNotNull { p ->
302                             createWindowContainerChild(p, isActivityInTree)
303                         }
304                     )
305                         ?: error("Window container should not be null")
306             )
307         }
308     }
309 
310     private fun createActivity(proto: ActivityRecordProto?): Activity? {
311         return if (proto == null) {
312             null
313         } else {
314             Activity(
315                 state = proto.state,
316                 frontOfTask = proto.frontOfTask,
317                 procId = proto.procId,
318                 isTranslucent = proto.translucent,
319                 windowContainer =
320                     createWindowContainer(
321                         proto.windowToken.windowContainer,
322                         proto.windowToken.windowContainer.children.mapNotNull { p ->
323                             createWindowContainerChild(p, isActivityInTree = true)
324                         },
325                         nameOverride = proto.name
326                     )
327                         ?: error("Window container should not be null")
328             )
329         }
330     }
331 
332     private fun createWindowToken(
333         proto: WindowTokenProto?,
334         isActivityInTree: Boolean
335     ): WindowToken? {
336         return if (proto == null) {
337             null
338         } else {
339             WindowToken(
340                 createWindowContainer(
341                     proto.windowContainer,
342                     proto.windowContainer.children.mapNotNull { p ->
343                         createWindowContainerChild(p, isActivityInTree)
344                     }
345                 )
346                     ?: error("Window container should not be null")
347             )
348         }
349     }
350 
351     private fun createWindowState(
352         proto: WindowStateProto?,
353         isActivityInTree: Boolean
354     ): WindowState? {
355         return if (proto == null) {
356             null
357         } else {
358             val identifierName = proto.windowContainer.identifier?.title ?: ""
359             WindowState(
360                 attributes = createWindowLayerParams(proto.attributes),
361                 displayId = proto.displayId,
362                 stackId = proto.stackId,
363                 layer = proto.animator?.surface?.layer ?: 0,
364                 isSurfaceShown = proto.animator?.surface?.shown ?: false,
365                 windowType =
366                     when {
367                         identifierName.startsWith(PlatformConsts.STARTING_WINDOW_PREFIX) ->
368                             PlatformConsts.WINDOW_TYPE_STARTING
369                         proto.animatingExit -> PlatformConsts.WINDOW_TYPE_EXITING
370                         identifierName.startsWith(PlatformConsts.DEBUGGER_WINDOW_PREFIX) ->
371                             PlatformConsts.WINDOW_TYPE_STARTING
372                         else -> 0
373                     },
374                 requestedSize = Size.from(proto.requestedWidth, proto.requestedHeight),
375                 surfacePosition = proto.surfacePosition?.toRect(),
376                 frame = proto.windowFrames?.frame?.toRect() ?: Rect.EMPTY,
377                 containingFrame = proto.windowFrames?.containingFrame?.toRect() ?: Rect.EMPTY,
378                 parentFrame = proto.windowFrames?.parentFrame?.toRect() ?: Rect.EMPTY,
379                 contentFrame = proto.windowFrames?.contentFrame?.toRect() ?: Rect.EMPTY,
380                 contentInsets = proto.windowFrames?.contentInsets?.toRect() ?: Rect.EMPTY,
381                 surfaceInsets = proto.surfaceInsets?.toRect() ?: Rect.EMPTY,
382                 givenContentInsets = proto.givenContentInsets?.toRect() ?: Rect.EMPTY,
383                 crop = proto.animator?.lastClipRect?.toRect() ?: Rect.EMPTY,
384                 windowContainer =
385                     createWindowContainer(
386                         proto.windowContainer,
387                         proto.windowContainer.children.mapNotNull { p ->
388                             createWindowContainerChild(p, isActivityInTree)
389                         },
390                         nameOverride =
391                             getWindowTitle(
392                                 when {
393                                     // Existing code depends on the prefix being removed
394                                     identifierName.startsWith(
395                                         PlatformConsts.STARTING_WINDOW_PREFIX
396                                     ) ->
397                                         identifierName.substring(
398                                             PlatformConsts.STARTING_WINDOW_PREFIX.length
399                                         )
400                                     identifierName.startsWith(
401                                         PlatformConsts.DEBUGGER_WINDOW_PREFIX
402                                     ) ->
403                                         identifierName.substring(
404                                             PlatformConsts.DEBUGGER_WINDOW_PREFIX.length
405                                         )
406                                     else -> identifierName
407                                 }
408                             )
409                     )
410                         ?: error("Window container should not be null"),
411                 isAppWindow = isActivityInTree
412             )
413         }
414     }
415 
416     private fun createWindowLayerParams(proto: WindowLayoutParamsProto?): WindowLayoutParams {
417         return WindowLayoutParams.from(
418             type = proto?.type ?: 0,
419             x = proto?.x ?: 0,
420             y = proto?.y ?: 0,
421             width = proto?.width ?: 0,
422             height = proto?.height ?: 0,
423             horizontalMargin = proto?.horizontalMargin ?: 0f,
424             verticalMargin = proto?.verticalMargin ?: 0f,
425             gravity = proto?.gravity ?: 0,
426             softInputMode = proto?.softInputMode ?: 0,
427             format = proto?.format ?: 0,
428             windowAnimations = proto?.windowAnimations ?: 0,
429             alpha = proto?.alpha ?: 0f,
430             screenBrightness = proto?.screenBrightness ?: 0f,
431             buttonBrightness = proto?.buttonBrightness ?: 0f,
432             rotationAnimation = proto?.rotationAnimation ?: 0,
433             preferredRefreshRate = proto?.preferredRefreshRate ?: 0f,
434             preferredDisplayModeId = proto?.preferredDisplayModeId ?: 0,
435             hasSystemUiListeners = proto?.hasSystemUiListeners ?: false,
436             inputFeatureFlags = proto?.inputFeatureFlags ?: 0,
437             userActivityTimeout = proto?.userActivityTimeout ?: 0,
438             colorMode = proto?.colorMode ?: 0,
439             flags = proto?.flags ?: 0,
440             privateFlags = proto?.privateFlags ?: 0,
441             systemUiVisibilityFlags = proto?.systemUiVisibilityFlags ?: 0,
442             subtreeSystemUiVisibilityFlags = proto?.subtreeSystemUiVisibilityFlags ?: 0,
443             appearance = proto?.appearance ?: 0,
444             behavior = proto?.behavior ?: 0,
445             fitInsetsTypes = proto?.fitInsetsTypes ?: 0,
446             fitInsetsSides = proto?.fitInsetsSides ?: 0,
447             fitIgnoreVisibility = proto?.fitIgnoreVisibility ?: false
448         )
449     }
450 
451     private fun createConfigurationContainer(
452         proto: ConfigurationContainerProto?
453     ): ConfigurationContainer {
454         return ConfigurationContainer.from(
455             overrideConfiguration = createConfiguration(proto?.overrideConfiguration),
456             fullConfiguration = createConfiguration(proto?.fullConfiguration),
457             mergedOverrideConfiguration = createConfiguration(proto?.mergedOverrideConfiguration)
458         )
459     }
460 
461     private fun createConfiguration(proto: ConfigurationProto?): Configuration? {
462         return if (proto == null) {
463             null
464         } else {
465             Configuration.from(
466                 windowConfiguration =
467                     if (proto.windowConfiguration != null) {
468                         createWindowConfiguration(proto.windowConfiguration)
469                     } else {
470                         null
471                     },
472                 densityDpi = proto.densityDpi,
473                 orientation = proto.orientation,
474                 screenHeightDp = proto.screenHeightDp,
475                 screenWidthDp = proto.screenWidthDp,
476                 smallestScreenWidthDp = proto.smallestScreenWidthDp,
477                 screenLayout = proto.screenLayout,
478                 uiMode = proto.uiMode
479             )
480         }
481     }
482 
483     private fun createWindowConfiguration(proto: WindowConfigurationProto): WindowConfiguration {
484         return WindowConfiguration.from(
485             appBounds = proto.appBounds?.toRect(),
486             bounds = proto.bounds?.toRect(),
487             maxBounds = proto.maxBounds?.toRect(),
488             windowingMode = proto.windowingMode,
489             activityType = proto.activityType
490         )
491     }
492 
493     private fun createWindowContainer(
494         proto: WindowContainerProto?,
495         children: List<IWindowContainer>,
496         nameOverride: String? = null,
497         visibleOverride: Boolean? = null
498     ): IWindowContainer? {
499         return if (proto == null) {
500             null
501         } else {
502             WindowContainer(
503                 title = nameOverride ?: proto.identifier?.title ?: "",
504                 token = proto.identifier?.hashCode?.toString(16) ?: "",
505                 orientation = proto.orientation,
506                 _isVisible = visibleOverride ?: proto.visible,
507                 configurationContainer = createConfigurationContainer(proto.configurationContainer),
508                 layerId = proto.surfaceControl?.layerId ?: 0,
509                 _children = children.toTypedArray(),
510                 computedZ = computedZCounter++
511             )
512         }
513     }
514 
515     private fun createDisplayCutout(proto: DisplayCutoutProto?): DisplayCutout? {
516         return if (proto == null) {
517             null
518         } else {
519             DisplayCutout.from(
520                 proto.insets?.toInsets() ?: Insets.EMPTY,
521                 proto.boundLeft?.toRect() ?: Rect.EMPTY,
522                 proto.boundTop?.toRect() ?: Rect.EMPTY,
523                 proto.boundRight?.toRect() ?: Rect.EMPTY,
524                 proto.boundBottom?.toRect() ?: Rect.EMPTY,
525                 proto.waterfallInsets?.toInsets() ?: Insets.EMPTY
526             )
527         }
528     }
529 
530     private fun appTransitionToString(transition: Int): String {
531         return when (transition) {
532             ViewProtoEnums.TRANSIT_UNSET -> "TRANSIT_UNSET"
533             ViewProtoEnums.TRANSIT_NONE -> "TRANSIT_NONE"
534             ViewProtoEnums.TRANSIT_ACTIVITY_OPEN -> TRANSIT_ACTIVITY_OPEN
535             ViewProtoEnums.TRANSIT_ACTIVITY_CLOSE -> TRANSIT_ACTIVITY_CLOSE
536             ViewProtoEnums.TRANSIT_TASK_OPEN -> TRANSIT_TASK_OPEN
537             ViewProtoEnums.TRANSIT_TASK_CLOSE -> TRANSIT_TASK_CLOSE
538             ViewProtoEnums.TRANSIT_TASK_TO_FRONT -> "TRANSIT_TASK_TO_FRONT"
539             ViewProtoEnums.TRANSIT_TASK_TO_BACK -> "TRANSIT_TASK_TO_BACK"
540             ViewProtoEnums.TRANSIT_WALLPAPER_CLOSE -> TRANSIT_WALLPAPER_CLOSE
541             ViewProtoEnums.TRANSIT_WALLPAPER_OPEN -> TRANSIT_WALLPAPER_OPEN
542             ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_OPEN -> TRANSIT_WALLPAPER_INTRA_OPEN
543             ViewProtoEnums.TRANSIT_WALLPAPER_INTRA_CLOSE -> TRANSIT_WALLPAPER_INTRA_CLOSE
544             ViewProtoEnums.TRANSIT_TASK_OPEN_BEHIND -> "TRANSIT_TASK_OPEN_BEHIND"
545             ViewProtoEnums.TRANSIT_ACTIVITY_RELAUNCH -> "TRANSIT_ACTIVITY_RELAUNCH"
546             ViewProtoEnums.TRANSIT_DOCK_TASK_FROM_RECENTS -> "TRANSIT_DOCK_TASK_FROM_RECENTS"
547             ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY -> TRANSIT_KEYGUARD_GOING_AWAY
548             ViewProtoEnums.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER ->
549                 TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
550             ViewProtoEnums.TRANSIT_KEYGUARD_OCCLUDE -> TRANSIT_KEYGUARD_OCCLUDE
551             ViewProtoEnums.TRANSIT_KEYGUARD_UNOCCLUDE -> TRANSIT_KEYGUARD_UNOCCLUDE
552             ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN -> TRANSIT_TRANSLUCENT_ACTIVITY_OPEN
553             ViewProtoEnums.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE -> TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE
554             ViewProtoEnums.TRANSIT_CRASHING_ACTIVITY_CLOSE -> "TRANSIT_CRASHING_ACTIVITY_CLOSE"
555             else -> error("Invalid lastUsedAppTransition")
556         }
557     }
558 
559     private fun appStateToString(appState: Int): String {
560         return when (appState) {
561             AppTransitionProto.APP_STATE_IDLE -> "APP_STATE_IDLE"
562             AppTransitionProto.APP_STATE_READY -> "APP_STATE_READY"
563             AppTransitionProto.APP_STATE_RUNNING -> "APP_STATE_RUNNING"
564             AppTransitionProto.APP_STATE_TIMEOUT -> "APP_STATE_TIMEOUT"
565             else -> error("Invalid AppTransitionState")
566         }
567     }
568 
569     private fun RectProto.toRect() = Rect.from(this.left, this.top, this.right, this.bottom)
570 
571     private fun RectProto.toInsets() = Insets.from(this.left, this.top, this.right, this.bottom)
572 
573     companion object {
574         private const val TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN"
575         private const val TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE"
576         private const val TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN"
577         private const val TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE"
578         private const val TRANSIT_WALLPAPER_OPEN = "TRANSIT_WALLPAPER_OPEN"
579         private const val TRANSIT_WALLPAPER_CLOSE = "TRANSIT_WALLPAPER_CLOSE"
580         private const val TRANSIT_WALLPAPER_INTRA_OPEN = "TRANSIT_WALLPAPER_INTRA_OPEN"
581         private const val TRANSIT_WALLPAPER_INTRA_CLOSE = "TRANSIT_WALLPAPER_INTRA_CLOSE"
582         private const val TRANSIT_KEYGUARD_GOING_AWAY = "TRANSIT_KEYGUARD_GOING_AWAY"
583         private const val TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
584             "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER"
585         private const val TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE"
586         private const val TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE"
587         private const val TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN"
588         private const val TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE"
589 
590         private fun getWindowTitle(title: String): String {
591             return when {
592                 // Existing code depends on the prefix being removed
593                 title.startsWith(PlatformConsts.STARTING_WINDOW_PREFIX) ->
594                     title.substring(PlatformConsts.STARTING_WINDOW_PREFIX.length)
595                 title.startsWith(PlatformConsts.DEBUGGER_WINDOW_PREFIX) ->
596                     title.substring(PlatformConsts.DEBUGGER_WINDOW_PREFIX.length)
597                 else -> title
598             }
599         }
600     }
601 }
602