• 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     _isVisible: Boolean,
35     configurationContainer: ConfigurationContainer,
36     val children: Array<WindowContainer>
37 ) : ConfigurationContainer(configurationContainer) {
38     protected constructor(
39         windowContainer: WindowContainer,
40         titleOverride: String? = null,
41         isVisibleOverride: Boolean? = null
42     ) : this(
43         titleOverride ?: windowContainer.title,
44         windowContainer.token,
45         windowContainer.orientation,
46         isVisibleOverride ?: windowContainer.isVisible,
47         windowContainer,
48         windowContainer.children
49     )
50 
51     open val isVisible: Boolean = _isVisible
52     open val name: String = title
53     val stableId: String get() = "${this::class.simpleName} $token $title"
54     open val isFullscreen: Boolean = false
55     open val bounds: Rect = Rect.EMPTY
56 
57     val windows: Array<WindowState>
58         get() = this.collectDescendants()
59 
60     fun traverseTopDown(): List<WindowContainer> {
61         val traverseList = mutableListOf(this)
62 
63         this.children.reversed()
64             .forEach { childLayer ->
65                 traverseList.addAll(childLayer.traverseTopDown())
66             }
67 
68         return traverseList
69     }
70 
71     /**
72      * For a given WindowContainer, traverse down the hierarchy and collect all children of type
73      * [T] if the child passes the test [predicate].
74      *
75      * @param predicate Filter function
76      */
77     inline fun <reified T : WindowContainer> collectDescendants(
78         predicate: (T) -> Boolean = { true }
79     ): Array<T> {
80         val traverseList = traverseTopDown()
81 
82         return traverseList.filterIsInstance<T>()
83             .filter { predicate(it) }
84             .toTypedArray()
85     }
86 
87     override fun toString(): String {
88         if (this.title.isEmpty() || listOf("WindowContainer", "Task")
89                 .any { it.contains(this.title) }) {
90             return ""
91         }
92 
93         return "$${removeRedundancyInName(this.title)}@${this.token}"
94     }
95 
96     private fun removeRedundancyInName(name: String): String {
97         if (!name.contains('/')) {
98             return name
99         }
100 
101         val split = name.split('/')
102         val pkg = split[0]
103         var clazz = split.slice(1..split.lastIndex).joinToString("/")
104 
105         if (clazz.startsWith("$pkg.")) {
106             clazz = clazz.slice(pkg.length + 1..clazz.lastIndex)
107 
108             return "$pkg/$clazz"
109         }
110 
111         return name
112     }
113 
114     override val isEmpty: Boolean
115         get() = super.isEmpty &&
116             title.isEmpty() &&
117             token.isEmpty()
118 }
119