Merge "Small fixes to DumpManager" into udc-dev

This commit is contained in:
Jeff DeCew
2023-05-01 16:28:29 +00:00
committed by Android (Google) Code Review
2 changed files with 169 additions and 55 deletions

View File

@@ -16,12 +16,12 @@
package com.android.systemui.dump
import android.util.ArrayMap
import com.android.systemui.Dumpable
import com.android.systemui.ProtoDumpable
import com.android.systemui.dump.nano.SystemUIProtoDump
import com.android.systemui.plugins.log.LogBuffer
import java.io.PrintWriter
import java.util.TreeMap
import javax.inject.Inject
import javax.inject.Singleton
@@ -36,8 +36,9 @@ import javax.inject.Singleton
*/
@Singleton
open class DumpManager @Inject constructor() {
private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = ArrayMap()
private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = ArrayMap()
// NOTE: Using TreeMap ensures that iteration is in a predictable & alphabetical order.
private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = TreeMap()
private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = TreeMap()
/** See [registerCriticalDumpable]. */
fun registerCriticalDumpable(module: Dumpable) {
@@ -132,7 +133,8 @@ open class DumpManager @Inject constructor() {
}
/**
* Dumps the first dumpable or buffer whose registered name ends with [target]
* Dumps the alphabetically first, shortest-named dumpable or buffer whose registered name ends
* with [target].
*/
@Synchronized
fun dumpTarget(
@@ -141,19 +143,14 @@ open class DumpManager @Inject constructor() {
args: Array<String>,
tailLength: Int,
) {
for (dumpable in dumpables.values) {
if (dumpable.name.endsWith(target)) {
dumpDumpable(dumpable, pw, args)
return
sequence {
findBestTargetMatch(dumpables, target)?.let {
yield(it.name to { dumpDumpable(it, pw, args) })
}
}
for (buffer in buffers.values) {
if (buffer.name.endsWith(target)) {
dumpBuffer(buffer, pw, tailLength)
return
findBestTargetMatch(buffers, target)?.let {
yield(it.name to { dumpBuffer(it, pw, tailLength) })
}
}
}.sortedBy { it.first }.minByOrNull { it.first.length }?.second?.invoke()
}
@Synchronized
@@ -162,11 +159,8 @@ open class DumpManager @Inject constructor() {
protoDump: SystemUIProtoDump,
args: Array<String>
) {
for (dumpable in dumpables.values) {
if (dumpable.dumpable is ProtoDumpable && dumpable.name.endsWith(target)) {
dumpProtoDumpable(dumpable.dumpable, protoDump, args)
return
}
findBestProtoTargetMatch(dumpables, target)?.let {
dumpProtoDumpable(it, protoDump, args)
}
}
@@ -303,6 +297,22 @@ open class DumpManager @Inject constructor() {
val existingDumpable = dumpables[name]?.dumpable ?: buffers[name]?.dumpable
return existingDumpable == null || newDumpable == existingDumpable
}
private fun <V : Any> findBestTargetMatch(map: Map<String, V>, target: String): V? = map
.asSequence()
.filter { it.key.endsWith(target) }
.minByOrNull { it.key.length }
?.value
private fun findBestProtoTargetMatch(
map: Map<String, RegisteredDumpable<Dumpable>>,
target: String
): ProtoDumpable? = map
.asSequence()
.filter { it.key.endsWith(target) }
.filter { it.value.dumpable is ProtoDumpable }
.minByOrNull { it.key.length }
?.value?.dumpable as? ProtoDumpable
}
private data class RegisteredDumpable<T>(

View File

@@ -60,16 +60,14 @@ class DumpManagerTest : SysuiTestCase() {
// WHEN a dumpable is dumped explicitly
val args = arrayOf<String>()
dumpManager.dumpTarget("dumpable2", pw, arrayOf(), tailLength = 0)
dumpManager.dumpTarget("dumpable2", pw, args, tailLength = 0)
// THEN only the requested one has their dump() method called
verify(dumpable1, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2).dump(pw, args)
verify(dumpable3, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
verify(dumpable3, never()).dump(any(), any())
verify(buffer1, never()).dump(any(), anyInt())
verify(buffer2, never()).dump(any(), anyInt())
}
@Test
@@ -82,17 +80,15 @@ class DumpManagerTest : SysuiTestCase() {
dumpManager.registerBuffer("buffer2", buffer2)
// WHEN a buffer is dumped explicitly
dumpManager.dumpTarget("buffer1", pw, arrayOf(), tailLength = 14)
val args = arrayOf<String>()
dumpManager.dumpTarget("buffer1", pw, args, tailLength = 14)
// THEN only the requested one has their dump() method called
verify(dumpable1, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable2, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable2, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2, never()).dump(any(), any())
verify(dumpable3, never()).dump(any(), any())
verify(buffer1).dump(pw, tailLength = 14)
verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
verify(buffer2, never()).dump(any(), anyInt())
}
@Test
@@ -108,6 +104,122 @@ class DumpManagerTest : SysuiTestCase() {
verify(dumpable1).dump(pw, args)
}
@Test
fun testDumpTarget_selectsShortestNamedDumpable() {
// GIVEN a variety of registered dumpables and buffers
dumpManager.registerCriticalDumpable("first-dumpable", dumpable1)
dumpManager.registerCriticalDumpable("scnd-dumpable", dumpable2)
dumpManager.registerCriticalDumpable("third-dumpable", dumpable3)
// WHEN a dumpable is dumped by a suffix that matches multiple options
val args = arrayOf<String>()
dumpManager.dumpTarget("dumpable", pw, args, tailLength = 0)
// THEN the matching dumpable with the shorter name is dumped
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2).dump(pw, args)
verify(dumpable3, never()).dump(any(), any())
}
@Test
fun testDumpTarget_selectsShortestNamedBuffer() {
// GIVEN a variety of registered dumpables and buffers
dumpManager.registerBuffer("first-buffer", buffer1)
dumpManager.registerBuffer("scnd-buffer", buffer2)
// WHEN a dumpable is dumped by a suffix that matches multiple options
val args = arrayOf<String>()
dumpManager.dumpTarget("buffer", pw, args, tailLength = 14)
// THEN the matching buffer with the shorter name is dumped
verify(buffer1, never()).dump(any(), anyInt())
verify(buffer2).dump(pw, tailLength = 14)
}
@Test
fun testDumpTarget_selectsShortestNamedMatch_dumpable() {
// GIVEN a variety of registered dumpables and buffers
dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
dumpManager.registerBuffer("big-buffer1", buffer1)
dumpManager.registerBuffer("big-buffer2", buffer2)
// WHEN a dumpable is dumped by a suffix that matches multiple options
val args = arrayOf<String>()
dumpManager.dumpTarget("2", pw, args, tailLength = 14)
// THEN the matching dumpable with the shorter name is dumped
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2).dump(pw, args)
verify(dumpable3, never()).dump(any(), any())
verify(buffer1, never()).dump(any(), anyInt())
verify(buffer2, never()).dump(any(), anyInt())
}
@Test
fun testDumpTarget_selectsShortestNamedMatch_buffer() {
// GIVEN a variety of registered dumpables and buffers
dumpManager.registerCriticalDumpable("dumpable1", dumpable1)
dumpManager.registerCriticalDumpable("dumpable2", dumpable2)
dumpManager.registerCriticalDumpable("dumpable3", dumpable3)
dumpManager.registerBuffer("buffer1", buffer1)
dumpManager.registerBuffer("buffer2", buffer2)
// WHEN a dumpable is dumped by a suffix that matches multiple options
val args = arrayOf<String>()
dumpManager.dumpTarget("2", pw, args, tailLength = 14)
// THEN the matching buffer with the shorter name is dumped
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2, never()).dump(any(), any())
verify(dumpable3, never()).dump(any(), any())
verify(buffer1, never()).dump(any(), anyInt())
verify(buffer2).dump(pw, tailLength = 14)
}
@Test
fun testDumpTarget_selectsTheAlphabeticallyFirstShortestMatch_dumpable() {
// GIVEN a variety of registered dumpables and buffers
dumpManager.registerCriticalDumpable("d1x", dumpable1)
dumpManager.registerCriticalDumpable("d2x", dumpable2)
dumpManager.registerCriticalDumpable("a3x", dumpable3)
dumpManager.registerBuffer("ab1x", buffer1)
dumpManager.registerBuffer("b2x", buffer2)
// WHEN a dumpable is dumped by a suffix that matches multiple options
val args = arrayOf<String>()
dumpManager.dumpTarget("x", pw, args, tailLength = 14)
// THEN the alphabetically first dumpable/buffer (of the 3 letter names) is dumped
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2, never()).dump(any(), any())
verify(dumpable3).dump(pw, args)
verify(buffer1, never()).dump(any(), anyInt())
verify(buffer2, never()).dump(any(), anyInt())
}
@Test
fun testDumpTarget_selectsTheAlphabeticallyFirstShortestMatch_buffer() {
// GIVEN a variety of registered dumpables and buffers
dumpManager.registerCriticalDumpable("d1x", dumpable1)
dumpManager.registerCriticalDumpable("d2x", dumpable2)
dumpManager.registerCriticalDumpable("az1x", dumpable3)
dumpManager.registerBuffer("b1x", buffer1)
dumpManager.registerBuffer("b2x", buffer2)
// WHEN a dumpable is dumped by a suffix that matches multiple options
val args = arrayOf<String>()
dumpManager.dumpTarget("x", pw, args, tailLength = 14)
// THEN the alphabetically first dumpable/buffer (of the 3 letter names) is dumped
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2, never()).dump(any(), any())
verify(dumpable3, never()).dump(any(), any())
verify(buffer1).dump(pw, tailLength = 14)
verify(buffer2, never()).dump(any(), anyInt())
}
@Test
fun testDumpDumpables() {
// GIVEN a variety of registered dumpables and buffers
@@ -125,8 +237,8 @@ class DumpManagerTest : SysuiTestCase() {
verify(dumpable1).dump(pw, args)
verify(dumpable2).dump(pw, args)
verify(dumpable3).dump(pw, args)
verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
verify(buffer1, never()).dump(any(), anyInt())
verify(buffer2, never()).dump(any(), anyInt())
}
@Test
@@ -142,12 +254,9 @@ class DumpManagerTest : SysuiTestCase() {
dumpManager.dumpBuffers(pw, tailLength = 1)
// THEN all buffers are dumped (and no dumpables)
verify(dumpable1, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable2, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable3, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2, never()).dump(any(), any())
verify(dumpable3, never()).dump(any(), any())
verify(buffer1).dump(pw, tailLength = 1)
verify(buffer2).dump(pw, tailLength = 1)
}
@@ -168,10 +277,9 @@ class DumpManagerTest : SysuiTestCase() {
// THEN only critical modules are dumped (and no buffers)
verify(dumpable1).dump(pw, args)
verify(dumpable2).dump(pw, args)
verify(dumpable3, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
verify(dumpable3, never()).dump(any(), any())
verify(buffer1, never()).dump(any(), anyInt())
verify(buffer2, never()).dump(any(), anyInt())
}
@Test
@@ -188,10 +296,8 @@ class DumpManagerTest : SysuiTestCase() {
dumpManager.dumpNormal(pw, args, tailLength = 2)
// THEN the normal module and all buffers are dumped
verify(dumpable1, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable2, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable1, never()).dump(any(), any())
verify(dumpable2, never()).dump(any(), any())
verify(dumpable3).dump(pw, args)
verify(buffer1).dump(pw, tailLength = 2)
verify(buffer2).dump(pw, tailLength = 2)
@@ -213,9 +319,7 @@ class DumpManagerTest : SysuiTestCase() {
// THEN the unregistered dumpables (both normal and critical) are not dumped
verify(dumpable1).dump(pw, args)
verify(dumpable2, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable3, never())
.dump(any(PrintWriter::class.java), any(Array<String>::class.java))
verify(dumpable2, never()).dump(any(), any())
verify(dumpable3, never()).dump(any(), any())
}
}