1 /*
2  * 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.traces.wm
18 
19 import android.graphics.Rect
20 import android.graphics.Region
21 import android.tools.PlatformConsts
22 import android.tools.datatypes.Size
23 
24 /**
25  * Represents a window in the window manager hierarchy
26  *
27  * This is a generic object that is reused by both Flicker and Winscope and cannot access internal
28  * Java/Android functionality
29  */
30 class WindowState(
31     val attributes: WindowLayoutParams,
32     val displayId: Int,
33     val stackId: Int,
34     val layer: Int,
35     val isSurfaceShown: Boolean,
36     val windowType: Int,
37     val requestedSize: Size,
38     val surfacePosition: Rect?,
39     val frame: Rect,
40     val containingFrame: Rect,
41     val parentFrame: Rect,
42     val contentFrame: Rect,
43     val contentInsets: Rect,
44     val surfaceInsets: Rect,
45     val givenContentInsets: Rect,
46     val crop: Rect,
47     private val windowContainer: WindowContainer,
48     val isAppWindow: Boolean
<lambda>null49 ) : WindowContainer by windowContainer {
50     override val isVisible: Boolean = windowContainer.isVisible && attributes.alpha > 0
51 
52     override val isFullscreen: Boolean
53         get() = this.attributes.flags.and(PlatformConsts.FLAG_FULLSCREEN) > 0
54     val isStartingWindow: Boolean = windowType == PlatformConsts.WINDOW_TYPE_STARTING
55     val isExitingWindow: Boolean = windowType == PlatformConsts.WINDOW_TYPE_EXITING
56     val isDebuggerWindow: Boolean = windowType == PlatformConsts.WINDOW_TYPE_DEBUGGER
57     val isValidNavBarType: Boolean = attributes.isValidNavBarType
58 
59     val frameRegion: Region
60         get() = Region(frame)
61 
62     private fun getWindowTypeSuffix(windowType: Int): String =
63         when (windowType) {
64             PlatformConsts.WINDOW_TYPE_STARTING -> " STARTING"
65             PlatformConsts.WINDOW_TYPE_EXITING -> " EXITING"
66             PlatformConsts.WINDOW_TYPE_DEBUGGER -> " DEBUGGER"
67             else -> ""
68         }
69 
70     override fun toString(): String =
71         "${this::class.simpleName}: " +
72             "{$token $title${getWindowTypeSuffix(windowType)}} " +
73             "type=${attributes.type} cf=$containingFrame pf=$parentFrame"
74 
75     override fun equals(other: Any?): Boolean {
76         if (this === other) return true
77         if (other !is WindowState) return false
78 
79         if (attributes != other.attributes) return false
80         if (displayId != other.displayId) return false
81         if (stackId != other.stackId) return false
82         if (layer != other.layer) return false
83         if (isSurfaceShown != other.isSurfaceShown) return false
84         if (windowType != other.windowType) return false
85         if (requestedSize != other.requestedSize) return false
86         if (surfacePosition != other.surfacePosition) return false
87         if (frame != other.frame) return false
88         if (containingFrame != other.containingFrame) return false
89         if (parentFrame != other.parentFrame) return false
90         if (contentFrame != other.contentFrame) return false
91         if (contentInsets != other.contentInsets) return false
92         if (surfaceInsets != other.surfaceInsets) return false
93         if (givenContentInsets != other.givenContentInsets) return false
94         if (crop != other.crop) return false
95         if (windowContainer != other.windowContainer) return false
96         if (isAppWindow != other.isAppWindow) return false
97 
98         return true
99     }
100 
101     override fun hashCode(): Int {
102         var result = attributes.hashCode()
103         result = 31 * result + displayId
104         result = 31 * result + stackId
105         result = 31 * result + layer
106         result = 31 * result + isSurfaceShown.hashCode()
107         result = 31 * result + windowType
108         result = 31 * result + requestedSize.hashCode()
109         result = 31 * result + (surfacePosition?.hashCode() ?: 0)
110         result = 31 * result + frame.hashCode()
111         result = 31 * result + containingFrame.hashCode()
112         result = 31 * result + parentFrame.hashCode()
113         result = 31 * result + contentFrame.hashCode()
114         result = 31 * result + contentInsets.hashCode()
115         result = 31 * result + surfaceInsets.hashCode()
116         result = 31 * result + givenContentInsets.hashCode()
117         result = 31 * result + crop.hashCode()
118         result = 31 * result + windowContainer.hashCode()
119         result = 31 * result + isAppWindow.hashCode()
120         result = 31 * result + isVisible.hashCode()
121         result = 31 * result + isStartingWindow.hashCode()
122         result = 31 * result + isExitingWindow.hashCode()
123         result = 31 * result + isDebuggerWindow.hashCode()
124         result = 31 * result + isValidNavBarType.hashCode()
125         result = 31 * result + frameRegion.hashCode()
126         return result
127     }
128 }
129