Merge changes from topic "b221419865" into tm-dev am: 4682c6576c am: 6b4f3a7474

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17592154

Change-Id: Ic6df49ce50e77501868750225667947ef7d6b85e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
index 6d589aa..e16da89 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.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 @@
     }
 
     private val buffer: ArrayDeque<LogMessageImpl> = ArrayDeque()
+    private val echoMessageQueue: BlockingQueue<LogMessageImpl>? =
+            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 @@
             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 3022f4b..8cda423 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 @@
      * 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 23942e1..91734cc 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 @@
 ) : LogcatEchoTracker {
     private val cachedBufferLevels: MutableMap<String, LogLevel> = mutableMapOf()
     private val cachedTagLevels: MutableMap<String, LogLevel> = 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 394f624..1a4ad19 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 @@
  * 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 2cb1939..0720bdb 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 @@
  * 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
 }