• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * 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.systemui.dump
18 
19 import com.android.systemui.Dumpable
20 import com.android.systemui.ProtoDumpable
21 import com.android.systemui.dump.DumpsysEntry.DumpableEntry
22 import com.android.systemui.dump.DumpsysEntry.LogBufferEntry
23 import com.android.systemui.dump.DumpsysEntry.TableLogBufferEntry
24 import com.android.systemui.log.LogBuffer
25 import com.android.systemui.log.table.TableLogBuffer
26 import java.util.TreeMap
27 import javax.inject.Inject
28 import javax.inject.Singleton
29 
30 /**
31  * Maintains a registry of things that should be dumped when a bug report is taken
32  *
33  * When a bug report is taken, SystemUI dumps various diagnostic information that we hope will be
34  * useful for the eventual readers of the bug report. Code that wishes to participate in this dump
35  * should register itself here.
36  *
37  * See [DumpHandler] for more information on how and when this information is dumped.
38  */
39 @Singleton
40 open class DumpManager @Inject constructor() {
41     // NOTE: Using TreeMap ensures that iteration is in a predictable & alphabetical order.
42     private val dumpables: MutableMap<String, DumpableEntry> = TreeMap()
43     private val buffers: MutableMap<String, LogBufferEntry> = TreeMap()
44     private val tableLogBuffers: MutableMap<String, TableLogBufferEntry> = TreeMap()
45 
46     /** See [registerCriticalDumpable]. */
registerCriticalDumpablenull47     fun registerCriticalDumpable(module: Dumpable) {
48         registerCriticalDumpable(module::class.java.name, module)
49     }
50 
51     /**
52      * Registers a dumpable to be called during the CRITICAL section of the bug report.
53      *
54      * The CRITICAL section gets very high priority during a dump, but also a very limited amount of
55      * time to do the dumping. So, please don't dump an excessive amount of stuff using CRITICAL.
56      *
57      * See [registerDumpable].
58      */
registerCriticalDumpablenull59     fun registerCriticalDumpable(name: String, module: Dumpable) {
60         registerDumpable(name, module, DumpPriority.CRITICAL)
61     }
62 
63     /** See [registerNormalDumpable]. */
registerNormalDumpablenull64     fun registerNormalDumpable(module: Dumpable) {
65         registerNormalDumpable(module::class.java.name, module)
66     }
67 
68     /**
69      * Registers a dumpable to be called during the NORMAL section of the bug report.
70      *
71      * The NORMAL section gets a lower priority during a dump, but also more time. This should be
72      * used by [LogBuffer] instances, [ProtoDumpable] instances, and any [Dumpable] instances that
73      * dump a lot of information.
74      */
registerNormalDumpablenull75     fun registerNormalDumpable(name: String, module: Dumpable) {
76         registerDumpable(name, module, DumpPriority.NORMAL)
77     }
78 
79     /**
80      * Register a dumpable to be called during a bug report.
81      *
82      * @param name The name to register the dumpable under. This is typically the qualified class
83      *   name of the thing being dumped (getClass().getName()), but can be anything as long as it
84      *   doesn't clash with an existing registration.
85      * @param priority the priority level of this dumpable, which affects at what point in the bug
86      *   report this gets dump. By default, the dumpable will be called during the CRITICAL section
87      *   of the bug report, so don't dump an excessive amount of stuff here.
88      *
89      * TODO(b/259973758): Replace all calls to this method with calls to [registerCriticalDumpable]
90      *   or [registerNormalDumpable] instead.
91      */
92     @Synchronized
93     @JvmOverloads
94     @Deprecated("Use registerCriticalDumpable or registerNormalDumpable instead")
registerDumpablenull95     fun registerDumpable(
96         name: String,
97         module: Dumpable,
98         priority: DumpPriority = DumpPriority.CRITICAL,
99     ) {
100         if (!canAssignToNameLocked(name, module)) {
101             throw IllegalArgumentException("'$name' is already registered")
102         }
103 
104         dumpables[name] = DumpableEntry(module, name, priority)
105     }
106 
107     /** Same as the above override, but automatically uses the class name as the dumpable name. */
108     @Synchronized
registerDumpablenull109     fun registerDumpable(module: Dumpable) {
110         registerDumpable(module::class.java.name, module)
111     }
112 
113     /** Unregisters a previously-registered dumpable. */
114     @Synchronized
unregisterDumpablenull115     fun unregisterDumpable(name: String) {
116         dumpables.remove(name)
117     }
118 
119     /** Register a [LogBuffer] to be dumped during a bug report. */
120     @Synchronized
registerBuffernull121     fun registerBuffer(name: String, buffer: LogBuffer) {
122         if (!canAssignToNameLocked(name, buffer)) {
123             throw IllegalArgumentException("'$name' is already registered")
124         }
125 
126         buffers[name] = LogBufferEntry(buffer, name)
127     }
128 
129     /** Register a [TableLogBuffer] to be dumped during a bugreport */
130     @Synchronized
registerTableLogBuffernull131     fun registerTableLogBuffer(name: String, buffer: TableLogBuffer) {
132         if (!canAssignToNameLocked(name, buffer)) {
133             throw IllegalArgumentException("'$name' is already registered")
134         }
135 
136         // All buffers must be priority NORMAL, not CRITICAL, because they often contain a lot of
137         // data.
138         tableLogBuffers[name] = TableLogBufferEntry(buffer, name)
139     }
140 
getDumpablesnull141     @Synchronized fun getDumpables(): Collection<DumpableEntry> = dumpables.values.toList()
142 
143     @Synchronized fun getLogBuffers(): Collection<LogBufferEntry> = buffers.values.toList()
144 
145     @Synchronized
146     fun getTableLogBuffers(): Collection<TableLogBufferEntry> = tableLogBuffers.values.toList()
147 
148     @Synchronized
149     fun freezeBuffers() {
150         for (buffer in buffers.values) {
151             buffer.buffer.freeze()
152         }
153     }
154 
155     @Synchronized
unfreezeBuffersnull156     fun unfreezeBuffers() {
157         for (buffer in buffers.values) {
158             buffer.buffer.unfreeze()
159         }
160     }
161 
canAssignToNameLockednull162     private fun canAssignToNameLocked(name: String, newDumpable: Any): Boolean {
163         val existingDumpable =
164             dumpables[name]?.dumpable ?: buffers[name]?.buffer ?: tableLogBuffers[name]?.table
165         return existingDumpable == null || newDumpable == existingDumpable
166     }
167 }
168 
169 /**
170  * The priority level for a given dumpable, which affects at what point in the bug report this gets
171  * dumped.
172  */
173 enum class DumpPriority {
174     CRITICAL,
175     NORMAL,
176 }
177