diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt index 6d589aac2079a..e16da89d6ec85 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt @@ -23,6 +23,9 @@ import java.io.PrintWriter import java.text.SimpleDateFormat import java.util.ArrayDeque import java.util.Locale +import java.util.concurrent.ArrayBlockingQueue +import java.util.concurrent.BlockingQueue +import kotlin.concurrent.thread /** * A simple ring buffer of recyclable log messages @@ -81,6 +84,22 @@ class LogBuffer @JvmOverloads constructor( } private val buffer: ArrayDeque = ArrayDeque() + private val echoMessageQueue: BlockingQueue? = + if (logcatEchoTracker.logInBackgroundThread) ArrayBlockingQueue(poolSize) else null + + init { + if (logcatEchoTracker.logInBackgroundThread && echoMessageQueue != null) { + thread(start = true, priority = Thread.NORM_PRIORITY) { + try { + while (true) { + echoToDesiredEndpoints(echoMessageQueue.take()) + } + } catch (e: InterruptedException) { + Thread.currentThread().interrupt() + } + } + } + } var frozen = false private set @@ -176,6 +195,22 @@ class LogBuffer @JvmOverloads constructor( buffer.removeFirst() } buffer.add(message as LogMessageImpl) + // Log in the background thread only if echoMessageQueue exists and has capacity (checking + // capacity avoids the possibility of blocking this thread) + if (echoMessageQueue != null && echoMessageQueue.remainingCapacity() > 0) { + try { + echoMessageQueue.put(message) + } catch (e: InterruptedException) { + // the background thread has been shut down, so just log on this one + echoToDesiredEndpoints(message) + } + } else { + echoToDesiredEndpoints(message) + } + } + + /** Sends message to echo after determining whether to use Logcat and/or systrace. */ + private fun echoToDesiredEndpoints(message: LogMessageImpl) { val includeInLogcat = logcatEchoTracker.isBufferLoggable(name, message.level) || logcatEchoTracker.isTagLoggable(message.tag, message.level) echo(message, toLogcat = includeInLogcat, toSystrace = systrace) diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt index 3022f4b42a42c..8cda4236bc872 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt @@ -29,4 +29,9 @@ interface LogcatEchoTracker { * Whether [tagName] should echo messages of [level] or higher to logcat. */ fun isTagLoggable(tagName: String, level: LogLevel): Boolean + + /** + * Whether to log messages in a background thread. + */ + val logInBackgroundThread: Boolean } diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt index 23942e1d6e3c5..91734cc361b0c 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt @@ -41,6 +41,7 @@ class LogcatEchoTrackerDebug private constructor( ) : LogcatEchoTracker { private val cachedBufferLevels: MutableMap = mutableMapOf() private val cachedTagLevels: MutableMap = mutableMapOf() + override val logInBackgroundThread = true companion object Factory { @JvmStatic diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt index 394f624a3e58d..1a4ad1907ff15 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt @@ -20,6 +20,8 @@ package com.android.systemui.log * Production version of [LogcatEchoTracker] that isn't configurable. */ class LogcatEchoTrackerProd : LogcatEchoTracker { + override val logInBackgroundThread = false + override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean { return level >= LogLevel.WARNING } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt index 2cb19393d2c60..0720bdb065567 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt @@ -30,6 +30,7 @@ fun logcatLogBuffer(name: String = "EchoToLogcatLogBuffer") = * A [LogcatEchoTracker] that always allows echoing to the logcat. */ class LogcatEchoTrackerAlways : LogcatEchoTracker { + override val logInBackgroundThread = false override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = true override fun isTagLoggable(tagName: String, level: LogLevel): Boolean = true }