• 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 a task in the window manager hierarchy
23  *
24  * This is a generic object that is reused by both Flicker and Winscope and cannot
25  * access internal Java/Android functionality
26  *
27  */
28 open class Task(
29     override val activityType: Int,
30     override val isFullscreen: Boolean,
31     override val bounds: Rect,
32     val taskId: Int,
33     val rootTaskId: Int,
34     val displayId: Int,
35     val lastNonFullscreenBounds: Rect,
36     val realActivity: String,
37     val origActivity: String,
38     val resizeMode: Int,
39     private val _resumedActivity: String,
40     var animatingBounds: Boolean,
41     val surfaceWidth: Int,
42     val surfaceHeight: Int,
43     val createdByOrganizer: Boolean,
44     val minWidth: Int,
45     val minHeight: Int,
46     windowContainer: WindowContainer
47 ) : WindowContainer(windowContainer) {
48     override val isVisible: Boolean = false
49     override val name: String = taskId.toString()
50     override val isEmpty: Boolean get() = tasks.isEmpty() && activities.isEmpty()
51     override val stableId: String get() = "${super.stableId} $taskId"
52 
53     val isRootTask: Boolean get() = taskId == rootTaskId
54     val tasks: Array<Task>
55         get() = this.children.reversed().filterIsInstance<Task>().toTypedArray()
56     val taskFragments: Array<TaskFragment>
57         get() = this.children.reversed().filterIsInstance<TaskFragment>().toTypedArray()
58     val activities: Array<Activity>
59         get() = this.children.reversed().filterIsInstance<Activity>().toTypedArray()
60     /** The top task in the stack.
61      */
62     // NOTE: Unlike the WindowManager internals, we dump the state from top to bottom,
63     //       so the indices are inverted
64     val topTask: Task? get() = tasks.firstOrNull()
65     val resumedActivities: Array<String> get() {
66         val result = mutableSetOf<String>()
67         if (this._resumedActivity.isNotEmpty()) {
68             result.add(this._resumedActivity)
69         }
70         val activitiesInChildren = this.tasks
71             .flatMap { it.resumedActivities.toList() }
72             .filter { it.isNotEmpty() }
73         result.addAll(activitiesInChildren)
74         return result.toTypedArray()
75     }
76 
77     fun getTask(predicate: (Task) -> Boolean) =
78         tasks.firstOrNull { predicate(it) } ?: if (predicate(this)) this else null
79 
80     fun getTask(taskId: Int) = getTask { t -> t.taskId == taskId }
81 
82     fun getActivityWithTask(predicate: (Task, Activity) -> Boolean): Activity? {
83         return activities.firstOrNull { predicate(this, it) }
84             ?: tasks.flatMap { task -> task.activities.filter { predicate(task, it) } }
85                 .firstOrNull()
86     }
87 
88     fun forAllTasks(consumer: (Task) -> Any) {
89         tasks.forEach { consumer(it) }
90     }
91 
92     fun getActivity(predicate: (Activity) -> Boolean): Activity? {
93         return activities.firstOrNull { predicate(it) }
94             ?: tasks.flatMap { it.activities.toList() }
95                 .firstOrNull { predicate(it) }
96     }
97 
98     fun getActivity(activityName: String): Activity? {
99         return getActivity { activity -> activity.title.contains(activityName) }
100     }
101 
102     fun containsActivity(activityName: String) = getActivity(activityName) != null
103 
104     override fun toString(): String {
105         return "${this::class.simpleName}: {$token $title} id=$taskId bounds=$bounds"
106     }
107 
108     override fun equals(other: Any?): Boolean {
109         if (this === other) return true
110         if (other !is Task) return false
111 
112         if (activityType != other.activityType) return false
113         if (isFullscreen != other.isFullscreen) return false
114         if (bounds != other.bounds) return false
115         if (taskId != other.taskId) return false
116         if (rootTaskId != other.rootTaskId) return false
117         if (displayId != other.displayId) return false
118         if (realActivity != other.realActivity) return false
119         if (resizeMode != other.resizeMode) return false
120         if (minWidth != other.minWidth) return false
121         if (minHeight != other.minHeight) return false
122         if (name != other.name) return false
123         if (orientation != other.orientation) return false
124         if (title != other.title) return false
125         if (token != other.token) return false
126 
127         return true
128     }
129 
130     override fun hashCode(): Int {
131         var result = super.hashCode()
132         result = 31 * result + activityType
133         result = 31 * result + isFullscreen.hashCode()
134         result = 31 * result + bounds.hashCode()
135         result = 31 * result + taskId
136         result = 31 * result + rootTaskId
137         result = 31 * result + displayId
138         result = 31 * result + lastNonFullscreenBounds.hashCode()
139         result = 31 * result + realActivity.hashCode()
140         result = 31 * result + origActivity.hashCode()
141         result = 31 * result + resizeMode
142         result = 31 * result + _resumedActivity.hashCode()
143         result = 31 * result + animatingBounds.hashCode()
144         result = 31 * result + surfaceWidth
145         result = 31 * result + surfaceHeight
146         result = 31 * result + createdByOrganizer.hashCode()
147         result = 31 * result + minWidth
148         result = 31 * result + minHeight
149         result = 31 * result + isVisible.hashCode()
150         result = 31 * result + name.hashCode()
151         return result
152     }
153 }
154