• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2020 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 com.android.server.wm.traces.common.windowmanager.windows
18 
19 import com.android.server.wm.traces.common.Rect
20 
21 /**
22  * Represents WindowContainer classes such as DisplayContent.WindowContainers and
23  * DisplayContent.NonAppWindowContainers. This can be expanded into a specific class
24  * if we need track and assert some state in the future.
25  *
26  * This is a generic object that is reused by both Flicker and Winscope and cannot
27  * access internal Java/Android functionality
28  *
29  */
30 open class WindowContainer constructor(
31     val title: String,
32     val token: String,
33     val orientation: Int,
34     val layerId: Int,
35     _isVisible: Boolean,
36     configurationContainer: ConfigurationContainer,
37     val children: Array<WindowContainer>
38 ) : ConfigurationContainer(configurationContainer) {
39     protected constructor(
40         windowContainer: WindowContainer,
41         titleOverride: String? = null,
42         isVisibleOverride: Boolean? = null
43     ) : this(
44         titleOverride ?: windowContainer.title,
45         windowContainer.token,
46         windowContainer.orientation,
47         windowContainer.layerId,
48         isVisibleOverride ?: windowContainer.isVisible,
49         windowContainer,
50         windowContainer.children
51     )
52 
53     open val isVisible: Boolean = _isVisible
54     open val name: String = title
55     open val stableId: String get() = "${this::class.simpleName} $token $title"
56     open val isFullscreen: Boolean = false
57     open val bounds: Rect = Rect.EMPTY
58 
59     fun traverseTopDown(): List<WindowContainer> {
60         val traverseList = mutableListOf(this)
61 
62         this.children.reversed()
63             .forEach { childLayer ->
64                 traverseList.addAll(childLayer.traverseTopDown())
65             }
66 
67         return traverseList
68     }
69 
70     /**
71      * For a given WindowContainer, traverse down the hierarchy and collect all children of type
72      * [T] if the child passes the test [predicate].
73      *
74      * @param predicate Filter function
75      */
76     inline fun <reified T : WindowContainer> collectDescendants(
77         predicate: (T) -> Boolean = { true }
78     ): Array<T> {
79         val traverseList = traverseTopDown()
80 
81         return traverseList.filterIsInstance<T>()
82             .filter { predicate(it) }
83             .toTypedArray()
84     }
85 
86     override fun toString(): String {
87         if (this.title.isEmpty() || listOf("WindowContainer", "Task")
88                 .any { it.contains(this.title) }) {
89             return ""
90         }
91 
92         return "$${removeRedundancyInName(this.title)}@${this.token}"
93     }
94 
95     private fun removeRedundancyInName(name: String): String {
96         if (!name.contains('/')) {
97             return name
98         }
99 
100         val split = name.split('/')
101         val pkg = split[0]
102         var clazz = split.slice(1..split.lastIndex).joinToString("/")
103 
104         if (clazz.startsWith("$pkg.")) {
105             clazz = clazz.slice(pkg.length + 1..clazz.lastIndex)
106 
107             return "$pkg/$clazz"
108         }
109 
110         return name
111     }
112 
113     override fun equals(other: Any?): Boolean {
114         if (this === other) return true
115         if (other !is WindowContainer) return false
116 
117         if (title != other.title) return false
118         if (token != other.token) return false
119         if (orientation != other.orientation) return false
120         if (isVisible != other.isVisible) return false
121         if (name != other.name) return false
122         if (isFullscreen != other.isFullscreen) return false
123         if (bounds != other.bounds) return false
124 
125         return true
126     }
127 
128     override fun hashCode(): Int {
129         var result = title.hashCode()
130         result = 31 * result + token.hashCode()
131         result = 31 * result + orientation
132         result = 31 * result + children.contentHashCode()
133         result = 31 * result + isVisible.hashCode()
134         result = 31 * result + name.hashCode()
135         result = 31 * result + isFullscreen.hashCode()
136         result = 31 * result + bounds.hashCode()
137         return result
138     }
139 
140     override val isEmpty: Boolean
141         get() = super.isEmpty &&
142             title.isEmpty() &&
143             token.isEmpty()
144 }
145