Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7bc572e3 authored by Jeff DeCew's avatar Jeff DeCew Committed by Automerger Merge Worker
Browse files

Merge "Small fixes to DumpManager" into udc-dev am: 88debc70

parents e921fc5c 88debc70
Loading
Loading
Loading
Loading
+30 −20
Original line number Original line Diff line number Diff line
@@ -16,12 +16,12 @@


package com.android.systemui.dump
package com.android.systemui.dump


import android.util.ArrayMap
import com.android.systemui.Dumpable
import com.android.systemui.Dumpable
import com.android.systemui.ProtoDumpable
import com.android.systemui.ProtoDumpable
import com.android.systemui.dump.nano.SystemUIProtoDump
import com.android.systemui.dump.nano.SystemUIProtoDump
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogBuffer
import java.io.PrintWriter
import java.io.PrintWriter
import java.util.TreeMap
import javax.inject.Inject
import javax.inject.Inject
import javax.inject.Singleton
import javax.inject.Singleton


@@ -36,8 +36,9 @@ import javax.inject.Singleton
 */
 */
@Singleton
@Singleton
open class DumpManager @Inject constructor() {
open class DumpManager @Inject constructor() {
    private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = ArrayMap()
    // NOTE: Using TreeMap ensures that iteration is in a predictable & alphabetical order.
    private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = ArrayMap()
    private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = TreeMap()
    private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = TreeMap()


    /** See [registerCriticalDumpable]. */
    /** See [registerCriticalDumpable]. */
    fun registerCriticalDumpable(module: Dumpable) {
    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
    @Synchronized
    fun dumpTarget(
    fun dumpTarget(
@@ -141,19 +143,14 @@ open class DumpManager @Inject constructor() {
        args: Array<String>,
        args: Array<String>,
        tailLength: Int,
        tailLength: Int,
    ) {
    ) {
        for (dumpable in dumpables.values) {
        sequence {
            if (dumpable.name.endsWith(target)) {
            findBestTargetMatch(dumpables, target)?.let {
                dumpDumpable(dumpable, pw, args)
                yield(it.name to { dumpDumpable(it, pw, args) })
                return
            }
        }

        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
    @Synchronized
@@ -162,11 +159,8 @@ open class DumpManager @Inject constructor() {
        protoDump: SystemUIProtoDump,
        protoDump: SystemUIProtoDump,
        args: Array<String>
        args: Array<String>
    ) {
    ) {
        for (dumpable in dumpables.values) {
        findBestProtoTargetMatch(dumpables, target)?.let {
            if (dumpable.dumpable is ProtoDumpable && dumpable.name.endsWith(target)) {
            dumpProtoDumpable(it, protoDump, args)
                dumpProtoDumpable(dumpable.dumpable, protoDump, args)
                return
            }
        }
        }
    }
    }


@@ -303,6 +297,22 @@ open class DumpManager @Inject constructor() {
        val existingDumpable = dumpables[name]?.dumpable ?: buffers[name]?.dumpable
        val existingDumpable = dumpables[name]?.dumpable ?: buffers[name]?.dumpable
        return existingDumpable == null || newDumpable == existingDumpable
        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>(
private data class RegisteredDumpable<T>(
+139 −35
Original line number Original line Diff line number Diff line
@@ -60,16 +60,14 @@ class DumpManagerTest : SysuiTestCase() {


        // WHEN a dumpable is dumped explicitly
        // WHEN a dumpable is dumped explicitly
        val args = arrayOf<String>()
        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
        // THEN only the requested one has their dump() method called
        verify(dumpable1, never())
        verify(dumpable1, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable2).dump(pw, args)
        verify(dumpable2).dump(pw, args)
        verify(dumpable3, never())
        verify(dumpable3, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(buffer1, never()).dump(any(), anyInt())
        verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
        verify(buffer2, never()).dump(any(), anyInt())
        verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
    }
    }


    @Test
    @Test
@@ -82,17 +80,15 @@ class DumpManagerTest : SysuiTestCase() {
        dumpManager.registerBuffer("buffer2", buffer2)
        dumpManager.registerBuffer("buffer2", buffer2)


        // WHEN a buffer is dumped explicitly
        // 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
        // THEN only the requested one has their dump() method called
        verify(dumpable1, never())
        verify(dumpable1, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable2, never()).dump(any(), any())
        verify(dumpable2, never())
        verify(dumpable3, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable2, never())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(buffer1).dump(pw, tailLength = 14)
        verify(buffer1).dump(pw, tailLength = 14)
        verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
        verify(buffer2, never()).dump(any(), anyInt())
    }
    }


    @Test
    @Test
@@ -108,6 +104,122 @@ class DumpManagerTest : SysuiTestCase() {
        verify(dumpable1).dump(pw, args)
        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
    @Test
    fun testDumpDumpables() {
    fun testDumpDumpables() {
        // GIVEN a variety of registered dumpables and buffers
        // GIVEN a variety of registered dumpables and buffers
@@ -125,8 +237,8 @@ class DumpManagerTest : SysuiTestCase() {
        verify(dumpable1).dump(pw, args)
        verify(dumpable1).dump(pw, args)
        verify(dumpable2).dump(pw, args)
        verify(dumpable2).dump(pw, args)
        verify(dumpable3).dump(pw, args)
        verify(dumpable3).dump(pw, args)
        verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
        verify(buffer1, never()).dump(any(), anyInt())
        verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
        verify(buffer2, never()).dump(any(), anyInt())
    }
    }


    @Test
    @Test
@@ -142,12 +254,9 @@ class DumpManagerTest : SysuiTestCase() {
        dumpManager.dumpBuffers(pw, tailLength = 1)
        dumpManager.dumpBuffers(pw, tailLength = 1)


        // THEN all buffers are dumped (and no dumpables)
        // THEN all buffers are dumped (and no dumpables)
        verify(dumpable1, never())
        verify(dumpable1, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable2, never()).dump(any(), any())
        verify(dumpable2, never())
        verify(dumpable3, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable3, never())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(buffer1).dump(pw, tailLength = 1)
        verify(buffer1).dump(pw, tailLength = 1)
        verify(buffer2).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)
        // THEN only critical modules are dumped (and no buffers)
        verify(dumpable1).dump(pw, args)
        verify(dumpable1).dump(pw, args)
        verify(dumpable2).dump(pw, args)
        verify(dumpable2).dump(pw, args)
        verify(dumpable3, never())
        verify(dumpable3, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(buffer1, never()).dump(any(), anyInt())
        verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt())
        verify(buffer2, never()).dump(any(), anyInt())
        verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt())
    }
    }


    @Test
    @Test
@@ -188,10 +296,8 @@ class DumpManagerTest : SysuiTestCase() {
        dumpManager.dumpNormal(pw, args, tailLength = 2)
        dumpManager.dumpNormal(pw, args, tailLength = 2)


        // THEN the normal module and all buffers are dumped
        // THEN the normal module and all buffers are dumped
        verify(dumpable1, never())
        verify(dumpable1, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable2, never()).dump(any(), any())
        verify(dumpable2, never())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable3).dump(pw, args)
        verify(dumpable3).dump(pw, args)
        verify(buffer1).dump(pw, tailLength = 2)
        verify(buffer1).dump(pw, tailLength = 2)
        verify(buffer2).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
        // THEN the unregistered dumpables (both normal and critical) are not dumped
        verify(dumpable1).dump(pw, args)
        verify(dumpable1).dump(pw, args)
        verify(dumpable2, never())
        verify(dumpable2, never()).dump(any(), any())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
        verify(dumpable3, never()).dump(any(), any())
        verify(dumpable3, never())
            .dump(any(PrintWriter::class.java), any(Array<String>::class.java))
    }
    }
}
}