Revert^2 "Move LogBuffer and related to SystemUILogLib."
d738e282ed923b2beefeb30fcbec005aec2097d9
Change-Id: I93a842bdd9eca25a3bdca941232068a96bcf788d
diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp
index e306d4a..1008d37 100644
--- a/packages/SystemUI/plugin/Android.bp
+++ b/packages/SystemUI/plugin/Android.bp
@@ -34,10 +34,10 @@
static_libs: [
"androidx.annotation_annotation",
- "error_prone_annotations",
"PluginCoreLib",
"SystemUIAnimationLib",
"SystemUICommon",
+ "SystemUILogLib",
],
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index ca3e710..7bf139e 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -18,8 +18,8 @@
import android.graphics.drawable.Drawable
import android.view.View
import com.android.internal.annotations.Keep
+import com.android.systemui.log.LogBuffer
import com.android.systemui.plugins.annotations.ProvidesInterface
-import com.android.systemui.plugins.log.LogBuffer
import java.io.PrintWriter
import java.util.Locale
import java.util.TimeZone
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLogger.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLogger.kt
deleted file mode 100644
index f95b187..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLogger.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-import com.google.errorprone.annotations.CompileTimeConstant
-
-/**
- * Handy for adding basic logging with CompileTimeConstant strings - so logging with no variables.
- * Most likely you want to delegate it to [ConstantStringsLoggerImpl].
- */
-interface ConstantStringsLogger {
- fun v(@CompileTimeConstant msg: String)
-
- fun d(@CompileTimeConstant msg: String)
-
- fun w(@CompileTimeConstant msg: String)
-
- fun e(@CompileTimeConstant msg: String)
-}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLoggerImpl.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLoggerImpl.kt
deleted file mode 100644
index 91b39e6..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLoggerImpl.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-import com.google.errorprone.annotations.CompileTimeConstant
-
-class ConstantStringsLoggerImpl(val buffer: LogBuffer, val tag: String) : ConstantStringsLogger {
- override fun v(@CompileTimeConstant msg: String) = buffer.log(tag, LogLevel.VERBOSE, msg)
-
- override fun d(@CompileTimeConstant msg: String) = buffer.log(tag, LogLevel.DEBUG, msg)
-
- override fun w(@CompileTimeConstant msg: String) = buffer.log(tag, LogLevel.WARNING, msg)
-
- override fun e(@CompileTimeConstant msg: String) = buffer.log(tag, LogLevel.ERROR, msg)
-}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
deleted file mode 100644
index 0a7ccc5..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-import android.os.Trace
-import android.util.Log
-import com.android.systemui.common.buffer.RingBuffer
-import com.google.errorprone.annotations.CompileTimeConstant
-import java.io.PrintWriter
-import java.util.concurrent.ArrayBlockingQueue
-import java.util.concurrent.BlockingQueue
-import kotlin.concurrent.thread
-import kotlin.math.max
-
-/**
- * A simple ring buffer of recyclable log messages
- *
- * The goal of this class is to enable logging that is both extremely chatty and extremely
- * lightweight. If done properly, logging a message will not result in any heap allocations or
- * string generation. Messages are only converted to strings if the log is actually dumped (usually
- * as the result of taking a bug report).
- *
- * You can dump the entire buffer at any time by running:
- * ```
- * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService <bufferName>
- * ```
- *
- * ...where `bufferName` is the (case-sensitive) [name] passed to the constructor.
- *
- * By default, only messages of WARN level or higher are echoed to logcat, but this can be adjusted
- * locally (usually for debugging purposes).
- *
- * To enable logcat echoing for an entire buffer:
- * ```
- * $ adb shell settings put global systemui/buffer/<bufferName> <level>
- * ```
- *
- * To enable logcat echoing for a specific tag:
- * ```
- * $ adb shell settings put global systemui/tag/<tag> <level>
- * ```
- *
- * In either case, `level` can be any of `verbose`, `debug`, `info`, `warn`, `error`, `assert`, or
- * the first letter of any of the previous.
- *
- * In SystemUI, buffers are provided by LogModule. Instances should be created using a SysUI
- * LogBufferFactory.
- *
- * @param name The name of this buffer, printed when the buffer is dumped and in some other
- * situations.
- * @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
- * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
- * the maximum, it behaves like a ring buffer.
- */
-class LogBuffer
-@JvmOverloads
-constructor(
- private val name: String,
- private val maxSize: Int,
- private val logcatEchoTracker: LogcatEchoTracker,
- private val systrace: Boolean = true,
-) {
- private val buffer = RingBuffer(maxSize) { LogMessageImpl.create() }
-
- private val echoMessageQueue: BlockingQueue<LogMessage>? =
- if (logcatEchoTracker.logInBackgroundThread) ArrayBlockingQueue(10) else null
-
- init {
- if (logcatEchoTracker.logInBackgroundThread && echoMessageQueue != null) {
- thread(start = true, name = "LogBuffer-$name", priority = Thread.NORM_PRIORITY) {
- try {
- while (true) {
- echoToDesiredEndpoints(echoMessageQueue.take())
- }
- } catch (e: InterruptedException) {
- Thread.currentThread().interrupt()
- }
- }
- }
- }
-
- var frozen = false
- private set
-
- private val mutable
- get() = !frozen && maxSize > 0
-
- /**
- * Logs a message to the log buffer
- *
- * May also log the message to logcat if echoing is enabled for this buffer or tag.
- *
- * The actual string of the log message is not constructed until it is needed. To accomplish
- * this, logging a message is a two-step process. First, a fresh instance of [LogMessage] is
- * obtained and is passed to the [messageInitializer]. The initializer stores any relevant data
- * on the message's fields. The message is then inserted into the buffer where it waits until it
- * is either pushed out by newer messages or it needs to printed. If and when this latter moment
- * occurs, the [messagePrinter] function is called on the message. It reads whatever data the
- * initializer stored and converts it to a human-readable log message.
- *
- * @param tag A string of at most 23 characters, used for grouping logs into categories or
- * subjects. If this message is echoed to logcat, this will be the tag that is used.
- * @param level Which level to log the message at, both to the buffer and to logcat if it's
- * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
- * INFO level should be reserved for information that other parts of the system might care
- * about, leaving the specifics of code's day-to-day operations to DEBUG.
- * @param messageInitializer A function that will be called immediately to store relevant data
- * on the log message. The value of `this` will be the LogMessage to be initialized.
- * @param messagePrinter A function that will be called if and when the message needs to be
- * dumped to logcat or a bug report. It should read the data stored by the initializer and
- * convert it to a human-readable string. The value of `this` will be the LogMessage to be
- * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
- * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
- * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
- * allocation.
- * @param exception Provide any exception that need to be logged. This is saved as
- * [LogMessage.exception]
- */
- @JvmOverloads
- inline fun log(
- tag: String,
- level: LogLevel,
- messageInitializer: MessageInitializer,
- noinline messagePrinter: MessagePrinter,
- exception: Throwable? = null,
- ) {
- val message = obtain(tag, level, messagePrinter, exception)
- messageInitializer(message)
- commit(message)
- }
-
- /**
- * Logs a compile-time string constant [message] to the log buffer. Use sparingly.
- *
- * May also log the message to logcat if echoing is enabled for this buffer or tag. This is for
- * simpler use-cases where [message] is a compile time string constant. For use-cases where the
- * log message is built during runtime, use the [LogBuffer.log] overloaded method that takes in
- * an initializer and a message printer.
- *
- * Log buffers are limited by the number of entries, so logging more frequently will limit the
- * time window that the LogBuffer covers in a bug report. Richer logs, on the other hand, make a
- * bug report more actionable, so using the [log] with a messagePrinter to add more detail to
- * every log may do more to improve overall logging than adding more logs with this method.
- */
- @JvmOverloads
- fun log(
- tag: String,
- level: LogLevel,
- @CompileTimeConstant message: String,
- exception: Throwable? = null,
- ) = log(tag, level, { str1 = message }, { str1!! }, exception)
-
- /**
- * You should call [log] instead of this method.
- *
- * Obtains the next [LogMessage] from the ring buffer. If the buffer is not yet at max size,
- * grows the buffer by one.
- *
- * After calling [obtain], the message will now be at the end of the buffer. The caller must
- * store any relevant data on the message and then call [commit].
- */
- @Synchronized
- fun obtain(
- tag: String,
- level: LogLevel,
- messagePrinter: MessagePrinter,
- exception: Throwable? = null,
- ): LogMessage {
- if (!mutable) {
- return FROZEN_MESSAGE
- }
- val message = buffer.advance()
- message.reset(tag, level, System.currentTimeMillis(), messagePrinter, exception)
- return message
- }
-
- /**
- * You should call [log] instead of this method.
- *
- * After acquiring a message via [obtain], call this method to signal to the buffer that you
- * have finished filling in its data fields. The message will be echoed to logcat if necessary.
- */
- @Synchronized
- fun commit(message: LogMessage) {
- if (!mutable) {
- return
- }
- // 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: LogMessage) {
- val includeInLogcat =
- logcatEchoTracker.isBufferLoggable(name, message.level) ||
- logcatEchoTracker.isTagLoggable(message.tag, message.level)
- echo(message, toLogcat = includeInLogcat, toSystrace = systrace)
- }
-
- /** Converts the entire buffer to a newline-delimited string */
- @Synchronized
- fun dump(pw: PrintWriter, tailLength: Int) {
- val iterationStart =
- if (tailLength <= 0) {
- 0
- } else {
- max(0, buffer.size - tailLength)
- }
-
- for (i in iterationStart until buffer.size) {
- buffer[i].dump(pw)
- }
- }
-
- /**
- * "Freezes" the contents of the buffer, making it immutable until [unfreeze] is called. Calls
- * to [log], [obtain], and [commit] will not affect the buffer and will return dummy values if
- * necessary.
- */
- @Synchronized
- fun freeze() {
- if (!frozen) {
- log(TAG, LogLevel.DEBUG, { str1 = name }, { "$str1 frozen" })
- frozen = true
- }
- }
-
- /** Undoes the effects of calling [freeze]. */
- @Synchronized
- fun unfreeze() {
- if (frozen) {
- frozen = false
- log(TAG, LogLevel.DEBUG, { str1 = name }, { "$str1 unfrozen" })
- }
- }
-
- private fun echo(message: LogMessage, toLogcat: Boolean, toSystrace: Boolean) {
- if (toLogcat || toSystrace) {
- val strMessage = message.messagePrinter(message)
- if (toSystrace) {
- echoToSystrace(message, strMessage)
- }
- if (toLogcat) {
- echoToLogcat(message, strMessage)
- }
- }
- }
-
- private fun echoToSystrace(message: LogMessage, strMessage: String) {
- Trace.instantForTrack(
- Trace.TRACE_TAG_APP,
- "UI Events",
- "$name - ${message.level.shortString} ${message.tag}: $strMessage"
- )
- }
-
- private fun echoToLogcat(message: LogMessage, strMessage: String) {
- when (message.level) {
- LogLevel.VERBOSE -> Log.v(message.tag, strMessage, message.exception)
- LogLevel.DEBUG -> Log.d(message.tag, strMessage, message.exception)
- LogLevel.INFO -> Log.i(message.tag, strMessage, message.exception)
- LogLevel.WARNING -> Log.w(message.tag, strMessage, message.exception)
- LogLevel.ERROR -> Log.e(message.tag, strMessage, message.exception)
- LogLevel.WTF -> Log.wtf(message.tag, strMessage, message.exception)
- }
- }
-}
-
-/**
- * A function that will be called immediately to store relevant data on the log message. The value
- * of `this` will be the LogMessage to be initialized.
- */
-typealias MessageInitializer = LogMessage.() -> Unit
-
-private const val TAG = "LogBuffer"
-private val FROZEN_MESSAGE = LogMessageImpl.create()
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogLevel.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogLevel.kt
deleted file mode 100644
index b036cf0..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogLevel.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-import android.util.Log
-
-/** Enum version of @Log.Level */
-enum class LogLevel(@Log.Level val nativeLevel: Int, val shortString: String) {
- VERBOSE(Log.VERBOSE, "V"),
- DEBUG(Log.DEBUG, "D"),
- INFO(Log.INFO, "I"),
- WARNING(Log.WARN, "W"),
- ERROR(Log.ERROR, "E"),
- WTF(Log.ASSERT, "WTF")
-}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessage.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessage.kt
deleted file mode 100644
index 9468681..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessage.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-import java.io.PrintWriter
-import java.text.SimpleDateFormat
-import java.util.Locale
-
-/**
- * Generic data class for storing messages logged to a [LogBuffer]
- *
- * Each LogMessage has a few standard fields ([level], [tag], and [timestamp]). The rest are generic
- * data slots that may or may not be used, depending on the nature of the specific message being
- * logged.
- *
- * When a message is logged, the code doing the logging stores data in one or more of the generic
- * fields ([str1], [int1], etc). When it comes time to dump the message to logcat/bugreport/etc, the
- * [messagePrinter] function reads the data stored in the generic fields and converts that to a
- * human- readable string. Thus, for every log type there must be a specialized initializer function
- * that stores data specific to that log type and a specialized printer function that prints that
- * data.
- *
- * See [LogBuffer.log] for more information.
- */
-interface LogMessage {
- val level: LogLevel
- val tag: String
- val timestamp: Long
- val messagePrinter: MessagePrinter
- val exception: Throwable?
-
- var str1: String?
- var str2: String?
- var str3: String?
- var int1: Int
- var int2: Int
- var long1: Long
- var long2: Long
- var double1: Double
- var bool1: Boolean
- var bool2: Boolean
- var bool3: Boolean
- var bool4: Boolean
-
- /** Function that dumps the [LogMessage] to the provided [writer]. */
- fun dump(writer: PrintWriter) {
- val formattedTimestamp = DATE_FORMAT.format(timestamp)
- val shortLevel = level.shortString
- val messageToPrint = messagePrinter(this)
- printLikeLogcat(writer, formattedTimestamp, shortLevel, tag, messageToPrint)
- exception?.printStackTrace(writer)
- }
-}
-
-/**
- * A function that will be called if and when the message needs to be dumped to logcat or a bug
- * report. It should read the data stored by the initializer and convert it to a human-readable
- * string. The value of `this` will be the LogMessage to be printed. **IMPORTANT:** The printer
- * should ONLY ever reference fields on the LogMessage and NEVER any variables in its enclosing
- * scope. Otherwise, the runtime will need to allocate a new instance of the printer for each call,
- * thwarting our attempts at avoiding any sort of allocation.
- */
-typealias MessagePrinter = LogMessage.() -> String
-
-private fun printLikeLogcat(
- pw: PrintWriter,
- formattedTimestamp: String,
- shortLogLevel: String,
- tag: String,
- message: String
-) {
- pw.print(formattedTimestamp)
- pw.print(" ")
- pw.print(shortLogLevel)
- pw.print(" ")
- pw.print(tag)
- pw.print(": ")
- pw.println(message)
-}
-
-private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessageImpl.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessageImpl.kt
deleted file mode 100644
index f2a6a91..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessageImpl.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-/** Recyclable implementation of [LogMessage]. */
-data class LogMessageImpl(
- override var level: LogLevel,
- override var tag: String,
- override var timestamp: Long,
- override var messagePrinter: MessagePrinter,
- override var exception: Throwable?,
- override var str1: String?,
- override var str2: String?,
- override var str3: String?,
- override var int1: Int,
- override var int2: Int,
- override var long1: Long,
- override var long2: Long,
- override var double1: Double,
- override var bool1: Boolean,
- override var bool2: Boolean,
- override var bool3: Boolean,
- override var bool4: Boolean,
-) : LogMessage {
-
- fun reset(
- tag: String,
- level: LogLevel,
- timestamp: Long,
- renderer: MessagePrinter,
- exception: Throwable? = null,
- ) {
- this.level = level
- this.tag = tag
- this.timestamp = timestamp
- this.messagePrinter = renderer
- this.exception = exception
- str1 = null
- str2 = null
- str3 = null
- int1 = 0
- int2 = 0
- long1 = 0
- long2 = 0
- double1 = 0.0
- bool1 = false
- bool2 = false
- bool3 = false
- bool4 = false
- }
-
- companion object Factory {
- fun create(): LogMessageImpl {
- return LogMessageImpl(
- LogLevel.DEBUG,
- DEFAULT_TAG,
- 0,
- DEFAULT_PRINTER,
- null,
- null,
- null,
- null,
- 0,
- 0,
- 0,
- 0,
- 0.0,
- false,
- false,
- false,
- false
- )
- }
- }
-}
-
-private const val DEFAULT_TAG = "UnknownTag"
-private val DEFAULT_PRINTER: MessagePrinter = { "Unknown message: $this" }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTracker.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTracker.kt
deleted file mode 100644
index cfe894f..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTracker.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-/** Keeps track of which [LogBuffer] messages should also appear in logcat. */
-interface LogcatEchoTracker {
- /** Whether [bufferName] should echo messages of [level] or higher to logcat. */
- fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean
-
- /** 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/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
deleted file mode 100644
index 7a125ac..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.log
-
-import android.content.ContentResolver
-import android.database.ContentObserver
-import android.net.Uri
-import android.os.Handler
-import android.os.Looper
-import android.os.Trace
-import android.provider.Settings
-
-/**
- * Version of [LogcatEchoTracker] for debuggable builds
- *
- * The log level of individual buffers or tags can be controlled via global settings:
- * ```
- * # Echo any message to <bufferName> of <level> or higher
- * $ adb shell settings put global systemui/buffer/<bufferName> <level>
- *
- * # Echo any message of <tag> and of <level> or higher
- * $ adb shell settings put global systemui/tag/<tag> <level>
- * ```
- */
-class LogcatEchoTrackerDebug private constructor(private val contentResolver: ContentResolver) :
- LogcatEchoTracker {
- private val cachedBufferLevels: MutableMap<String, LogLevel> = mutableMapOf()
- private val cachedTagLevels: MutableMap<String, LogLevel> = mutableMapOf()
- override val logInBackgroundThread = true
-
- companion object Factory {
- @JvmStatic
- fun create(contentResolver: ContentResolver, mainLooper: Looper): LogcatEchoTrackerDebug {
- val tracker = LogcatEchoTrackerDebug(contentResolver)
- tracker.attach(mainLooper)
- return tracker
- }
- }
-
- private fun clearCache() {
- Trace.beginSection("LogcatEchoTrackerDebug#clearCache")
- cachedBufferLevels.clear()
- Trace.endSection()
- }
-
- private fun attach(mainLooper: Looper) {
- Trace.beginSection("LogcatEchoTrackerDebug#attach")
- contentResolver.registerContentObserver(
- Settings.Global.getUriFor(BUFFER_PATH),
- true,
- object : ContentObserver(Handler(mainLooper)) {
- override fun onChange(selfChange: Boolean, uri: Uri?) {
- super.onChange(selfChange, uri)
- clearCache()
- }
- }
- )
-
- contentResolver.registerContentObserver(
- Settings.Global.getUriFor(TAG_PATH),
- true,
- object : ContentObserver(Handler(mainLooper)) {
- override fun onChange(selfChange: Boolean, uri: Uri?) {
- super.onChange(selfChange, uri)
- clearCache()
- }
- }
- )
- Trace.endSection()
- }
-
- /** Whether [bufferName] should echo messages of [level] or higher to logcat. */
- @Synchronized
- override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean {
- return level.ordinal >= getLogLevel(bufferName, BUFFER_PATH, cachedBufferLevels).ordinal
- }
-
- /** Whether [tagName] should echo messages of [level] or higher to logcat. */
- @Synchronized
- override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
- return level >= getLogLevel(tagName, TAG_PATH, cachedTagLevels)
- }
-
- private fun getLogLevel(
- name: String,
- path: String,
- cache: MutableMap<String, LogLevel>
- ): LogLevel {
- return cache[name] ?: readSetting("$path/$name").also { cache[name] = it }
- }
-
- private fun readSetting(path: String): LogLevel {
- return try {
- Trace.beginSection("LogcatEchoTrackerDebug#readSetting")
- parseProp(Settings.Global.getString(contentResolver, path))
- } catch (_: Settings.SettingNotFoundException) {
- DEFAULT_LEVEL
- } finally {
- Trace.endSection()
- }
- }
-
- private fun parseProp(propValue: String?): LogLevel {
- return when (propValue?.lowercase()) {
- "verbose" -> LogLevel.VERBOSE
- "v" -> LogLevel.VERBOSE
- "debug" -> LogLevel.DEBUG
- "d" -> LogLevel.DEBUG
- "info" -> LogLevel.INFO
- "i" -> LogLevel.INFO
- "warning" -> LogLevel.WARNING
- "warn" -> LogLevel.WARNING
- "w" -> LogLevel.WARNING
- "error" -> LogLevel.ERROR
- "e" -> LogLevel.ERROR
- "assert" -> LogLevel.WTF
- "wtf" -> LogLevel.WTF
- else -> DEFAULT_LEVEL
- }
- }
-}
-
-private val DEFAULT_LEVEL = LogLevel.WARNING
-private const val BUFFER_PATH = "systemui/buffer"
-private const val TAG_PATH = "systemui/tag"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerProd.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerProd.kt
deleted file mode 100644
index 3c8bda4..0000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerProd.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.plugins.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
- }
-
- override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
- return level >= LogLevel.WARNING
- }
-}
diff --git a/packages/SystemUI/plugin/tests/log/LogBufferTest.kt b/packages/SystemUI/plugin/tests/log/LogBufferTest.kt
deleted file mode 100644
index a39b856..0000000
--- a/packages/SystemUI/plugin/tests/log/LogBufferTest.kt
+++ /dev/null
@@ -1,138 +0,0 @@
-package com.android.systemui.log
-
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.log.LogBuffer
-import com.google.common.truth.Truth.assertThat
-import java.io.PrintWriter
-import java.io.StringWriter
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.junit.MockitoJUnitRunner
-
-@SmallTest
-@RunWith(MockitoJUnitRunner::class)
-class LogBufferTest : SysuiTestCase() {
- private lateinit var buffer: LogBuffer
-
- private lateinit var outputWriter: StringWriter
-
- @Mock private lateinit var logcatEchoTracker: LogcatEchoTracker
-
- @Before
- fun setup() {
- outputWriter = StringWriter()
- buffer = createBuffer()
- }
-
- private fun createBuffer(): LogBuffer {
- return LogBuffer("TestBuffer", 1, logcatEchoTracker, false)
- }
-
- @Test
- fun log_shouldSaveLogToBuffer() {
- buffer.log("Test", LogLevel.INFO, "Some test message")
-
- val dumpedString = dumpBuffer()
-
- assertThat(dumpedString).contains("Some test message")
- }
-
- @Test
- fun log_shouldRotateIfLogBufferIsFull() {
- buffer.log("Test", LogLevel.INFO, "This should be rotated")
- buffer.log("Test", LogLevel.INFO, "New test message")
-
- val dumpedString = dumpBuffer()
-
- assertThat(dumpedString).contains("New test message")
- }
-
- @Test
- fun dump_writesExceptionAndStacktrace() {
- buffer = createBuffer()
- val exception = createTestException("Exception message", "TestClass")
- buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
-
- val dumpedString = dumpBuffer()
-
- assertThat(dumpedString).contains("Extra message")
- assertThat(dumpedString).contains("java.lang.RuntimeException: Exception message")
- assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:1)")
- assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:2)")
- }
-
- @Test
- fun dump_writesCauseAndStacktrace() {
- buffer = createBuffer()
- val exception =
- createTestException(
- "Exception message",
- "TestClass",
- cause = createTestException("The real cause!", "TestClass")
- )
- buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
-
- val dumpedString = dumpBuffer()
-
- assertThat(dumpedString).contains("Caused by: java.lang.RuntimeException: The real cause!")
- assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:1)")
- assertThat(dumpedString).contains("at TestClass.TestMethod(TestClass.java:2)")
- }
-
- @Test
- fun dump_writesSuppressedExceptionAndStacktrace() {
- buffer = createBuffer()
- val exception = RuntimeException("Root exception message")
- exception.addSuppressed(
- createTestException(
- "First suppressed exception",
- "FirstClass",
- createTestException("Cause of suppressed exp", "ThirdClass")
- )
- )
- exception.addSuppressed(createTestException("Second suppressed exception", "SecondClass"))
- buffer.log("Tag", LogLevel.ERROR, { str1 = "Extra message" }, { str1!! }, exception)
-
- val dumpedStr = dumpBuffer()
-
- // first suppressed exception
- assertThat(dumpedStr)
- .contains("Suppressed: " + "java.lang.RuntimeException: First suppressed exception")
- assertThat(dumpedStr).contains("at FirstClass.TestMethod(FirstClass.java:1)")
- assertThat(dumpedStr).contains("at FirstClass.TestMethod(FirstClass.java:2)")
-
- assertThat(dumpedStr)
- .contains("Caused by: java.lang.RuntimeException: Cause of suppressed exp")
- assertThat(dumpedStr).contains("at ThirdClass.TestMethod(ThirdClass.java:1)")
- assertThat(dumpedStr).contains("at ThirdClass.TestMethod(ThirdClass.java:2)")
-
- // second suppressed exception
- assertThat(dumpedStr)
- .contains("Suppressed: " + "java.lang.RuntimeException: Second suppressed exception")
- assertThat(dumpedStr).contains("at SecondClass.TestMethod(SecondClass.java:1)")
- assertThat(dumpedStr).contains("at SecondClass.TestMethod(SecondClass.java:2)")
- }
-
- private fun createTestException(
- message: String,
- errorClass: String,
- cause: Throwable? = null,
- ): Exception {
- val exception = RuntimeException(message, cause)
- exception.stackTrace =
- (1..5)
- .map { lineNumber ->
- StackTraceElement(errorClass, "TestMethod", "$errorClass.java", lineNumber)
- }
- .toTypedArray()
- return exception
- }
-
- private fun dumpBuffer(): String {
- buffer.dump(PrintWriter(outputWriter), tailLength = 100)
- return outputWriter.toString()
- }
-}