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

Commit 9c353347 authored by Ned Burns's avatar Ned Burns Committed by Automerger Merge Worker
Browse files

Merge changes from topic "log-buffer" into tm-dev am: ff1b7dc5

parents e768a02a ff1b7dc5
Loading
Loading
Loading
Loading
+39 −60
Original line number Original line Diff line number Diff line
@@ -19,13 +19,14 @@ package com.android.systemui.log
import android.os.Trace
import android.os.Trace
import android.util.Log
import android.util.Log
import com.android.systemui.log.dagger.LogModule
import com.android.systemui.log.dagger.LogModule
import com.android.systemui.util.collection.RingBuffer
import java.io.PrintWriter
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.text.SimpleDateFormat
import java.util.ArrayDeque
import java.util.Locale
import java.util.Locale
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.BlockingQueue
import java.util.concurrent.BlockingQueue
import kotlin.concurrent.thread
import kotlin.concurrent.thread
import kotlin.math.max


/**
/**
 * A simple ring buffer of recyclable log messages
 * A simple ring buffer of recyclable log messages
@@ -63,29 +64,22 @@ import kotlin.concurrent.thread
 *
 *
 * Buffers are provided by [LogModule]. Instances should be created using a [LogBufferFactory].
 * Buffers are provided by [LogModule]. Instances should be created using a [LogBufferFactory].
 *
 *
 * @param name The name of this buffer
 * @param name The name of this buffer, printed when the buffer is dumped and in some other
 * @param maxLogs The maximum number of messages to keep in memory at any one time, including the
 * situations.
 * unused pool. Must be >= [poolSize].
 * @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
 * @param poolSize The maximum amount that the size of the buffer is allowed to flex in response to
 * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
 * sequential calls to [document] that aren't immediately followed by a matching call to [push].
 * the maximum, it behaves like a ring buffer.
 */
 */
class LogBuffer @JvmOverloads constructor(
class LogBuffer @JvmOverloads constructor(
    private val name: String,
    private val name: String,
    private val maxLogs: Int,
    private val maxSize: Int,
    private val poolSize: Int,
    private val logcatEchoTracker: LogcatEchoTracker,
    private val logcatEchoTracker: LogcatEchoTracker,
    private val systrace: Boolean = true
    private val systrace: Boolean = true
) {
) {
    init {
    private val buffer = RingBuffer(maxSize) { LogMessageImpl.create() }
        if (maxLogs < poolSize) {
            throw IllegalArgumentException("maxLogs must be greater than or equal to poolSize, " +
                    "but maxLogs=$maxLogs < $poolSize=poolSize")
        }
    }


    private val buffer: ArrayDeque<LogMessageImpl> = ArrayDeque()
    private val echoMessageQueue: BlockingQueue<LogMessage>? =
    private val echoMessageQueue: BlockingQueue<LogMessageImpl>? =
            if (logcatEchoTracker.logInBackgroundThread) ArrayBlockingQueue(10) else null
            if (logcatEchoTracker.logInBackgroundThread) ArrayBlockingQueue(poolSize) else null


    init {
    init {
        if (logcatEchoTracker.logInBackgroundThread && echoMessageQueue != null) {
        if (logcatEchoTracker.logInBackgroundThread && echoMessageQueue != null) {
@@ -104,6 +98,9 @@ class LogBuffer @JvmOverloads constructor(
    var frozen = false
    var frozen = false
        private set
        private set


    private val mutable
        get() = !frozen && maxSize > 0

    /**
    /**
     * Logs a message to the log buffer
     * Logs a message to the log buffer
     *
     *
@@ -138,34 +135,19 @@ class LogBuffer @JvmOverloads constructor(
        initializer: LogMessage.() -> Unit,
        initializer: LogMessage.() -> Unit,
        noinline printer: LogMessage.() -> String
        noinline printer: LogMessage.() -> String
    ) {
    ) {
        if (!frozen) {
            val message = obtain(tag, level, printer)
            initializer(message)
            push(message)
        }
    }

    /**
     * Same as [log], but doesn't push the message to the buffer. Useful if you need to supply a
     * "reason" for doing something (the thing you supply the reason to will presumably call [push]
     * on that message at some point).
     */
    inline fun document(
        tag: String,
        level: LogLevel,
        initializer: LogMessage.() -> Unit,
        noinline printer: LogMessage.() -> String
    ): LogMessage {
        val message = obtain(tag, level, printer)
        val message = obtain(tag, level, printer)
        initializer(message)
        initializer(message)
        return message
        commit(message)
    }
    }


    /**
    /**
     * Obtains an instance of [LogMessageImpl], usually from the object pool. If the pool has been
     * You should call [log] instead of this method.
     * exhausted, creates a new instance.
     *
     *
     * In general, you should call [log] or [document] 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
    @Synchronized
    fun obtain(
    fun obtain(
@@ -173,28 +155,26 @@ class LogBuffer @JvmOverloads constructor(
        level: LogLevel,
        level: LogLevel,
        printer: (LogMessage) -> String
        printer: (LogMessage) -> String
    ): LogMessageImpl {
    ): LogMessageImpl {
        val message = when {
        if (!mutable) {
            frozen -> LogMessageImpl.create()
            return FROZEN_MESSAGE
            buffer.size > maxLogs - poolSize -> buffer.removeFirst()
            else -> LogMessageImpl.create()
        }
        }
        val message = buffer.advance()
        message.reset(tag, level, System.currentTimeMillis(), printer)
        message.reset(tag, level, System.currentTimeMillis(), printer)
        return message
        return message
    }
    }


    /**
    /**
     * Pushes a message into buffer, possibly evicting an older message if the buffer is full.
     * 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
    @Synchronized
    fun push(message: LogMessage) {
    fun commit(message: LogMessage) {
        if (frozen) {
        if (!mutable) {
            return
            return
        }
        }
        if (buffer.size == maxLogs) {
            Log.e(TAG, "LogBuffer $name has exceeded its pool size")
            buffer.removeFirst()
        }
        buffer.add(message as LogMessageImpl)
        // Log in the background thread only if echoMessageQueue exists and has capacity (checking
        // Log in the background thread only if echoMessageQueue exists and has capacity (checking
        // capacity avoids the possibility of blocking this thread)
        // capacity avoids the possibility of blocking this thread)
        if (echoMessageQueue != null && echoMessageQueue.remainingCapacity() > 0) {
        if (echoMessageQueue != null && echoMessageQueue.remainingCapacity() > 0) {
@@ -210,7 +190,7 @@ class LogBuffer @JvmOverloads constructor(
    }
    }


    /** Sends message to echo after determining whether to use Logcat and/or systrace. */
    /** Sends message to echo after determining whether to use Logcat and/or systrace. */
    private fun echoToDesiredEndpoints(message: LogMessageImpl) {
    private fun echoToDesiredEndpoints(message: LogMessage) {
        val includeInLogcat = logcatEchoTracker.isBufferLoggable(name, message.level) ||
        val includeInLogcat = logcatEchoTracker.isBufferLoggable(name, message.level) ||
                logcatEchoTracker.isTagLoggable(message.tag, message.level)
                logcatEchoTracker.isTagLoggable(message.tag, message.level)
        echo(message, toLogcat = includeInLogcat, toSystrace = systrace)
        echo(message, toLogcat = includeInLogcat, toSystrace = systrace)
@@ -219,19 +199,17 @@ class LogBuffer @JvmOverloads constructor(
    /** Converts the entire buffer to a newline-delimited string */
    /** Converts the entire buffer to a newline-delimited string */
    @Synchronized
    @Synchronized
    fun dump(pw: PrintWriter, tailLength: Int) {
    fun dump(pw: PrintWriter, tailLength: Int) {
        val start = if (tailLength <= 0) { 0 } else { buffer.size - tailLength }
        val iterationStart = if (tailLength <= 0) { 0 } else { max(0, buffer.size - tailLength) }


        for ((i, message) in buffer.withIndex()) {
        for (i in iterationStart until buffer.size) {
            if (i >= start) {
            dumpMessage(buffer[i], pw)
                dumpMessage(message, pw)
            }
        }
        }
    }
    }


    /**
    /**
     * "Freezes" the contents of the buffer, making them immutable until [unfreeze] is called.
     * "Freezes" the contents of the buffer, making it immutable until [unfreeze] is called.
     * Calls to [log], [document], [obtain], and [push] will not affect the buffer and will return
     * Calls to [log], [obtain], and [commit] will not affect the buffer and will return dummy
     * dummy values if necessary.
     * values if necessary.
     */
     */
    @Synchronized
    @Synchronized
    fun freeze() {
    fun freeze() {
@@ -293,3 +271,4 @@ class LogBuffer @JvmOverloads constructor(


private const val TAG = "LogBuffer"
private const val TAG = "LogBuffer"
private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
private val FROZEN_MESSAGE = LogMessageImpl.create()
 No newline at end of file
+6 −7
Original line number Original line Diff line number Diff line
@@ -27,22 +27,21 @@ class LogBufferFactory @Inject constructor(
    private val logcatEchoTracker: LogcatEchoTracker
    private val logcatEchoTracker: LogcatEchoTracker
) {
) {
    /* limit the size of maxPoolSize for low ram (Go) devices */
    /* limit the size of maxPoolSize for low ram (Go) devices */
    private fun poolLimit(maxPoolSize_requested: Int): Int {
    private fun adjustMaxSize(requestedMaxSize: Int): Int {
        if (ActivityManager.isLowRamDeviceStatic()) {
        return if (ActivityManager.isLowRamDeviceStatic()) {
            return minOf(maxPoolSize_requested, 20) /* low ram max log size*/
            minOf(requestedMaxSize, 20) /* low ram max log size*/
        } else {
        } else {
            return maxPoolSize_requested
            requestedMaxSize
        }
        }
    }
    }


    @JvmOverloads
    @JvmOverloads
    fun create(
    fun create(
        name: String,
        name: String,
        maxPoolSize: Int,
        maxSize: Int,
        flexSize: Int = 10,
        systrace: Boolean = true
        systrace: Boolean = true
    ): LogBuffer {
    ): LogBuffer {
        val buffer = LogBuffer(name, poolLimit(maxPoolSize), flexSize, logcatEchoTracker, systrace)
        val buffer = LogBuffer(name, adjustMaxSize(maxSize), logcatEchoTracker, systrace)
        dumpManager.registerBuffer(name, buffer)
        dumpManager.registerBuffer(name, buffer)
        return buffer
        return buffer
    }
    }
+3 −3
Original line number Original line Diff line number Diff line
@@ -60,7 +60,7 @@ class LogcatEchoTrackerDebug private constructor(
                Settings.Global.getUriFor(BUFFER_PATH),
                Settings.Global.getUriFor(BUFFER_PATH),
                true,
                true,
                object : ContentObserver(Handler(mainLooper)) {
                object : ContentObserver(Handler(mainLooper)) {
                    override fun onChange(selfChange: Boolean, uri: Uri) {
                    override fun onChange(selfChange: Boolean, uri: Uri?) {
                        super.onChange(selfChange, uri)
                        super.onChange(selfChange, uri)
                        cachedBufferLevels.clear()
                        cachedBufferLevels.clear()
                    }
                    }
@@ -70,7 +70,7 @@ class LogcatEchoTrackerDebug private constructor(
                Settings.Global.getUriFor(TAG_PATH),
                Settings.Global.getUriFor(TAG_PATH),
                true,
                true,
                object : ContentObserver(Handler(mainLooper)) {
                object : ContentObserver(Handler(mainLooper)) {
                    override fun onChange(selfChange: Boolean, uri: Uri) {
                    override fun onChange(selfChange: Boolean, uri: Uri?) {
                        super.onChange(selfChange, uri)
                        super.onChange(selfChange, uri)
                        cachedTagLevels.clear()
                        cachedTagLevels.clear()
                    }
                    }
@@ -110,7 +110,7 @@ class LogcatEchoTrackerDebug private constructor(
    }
    }


    private fun parseProp(propValue: String?): LogLevel {
    private fun parseProp(propValue: String?): LogLevel {
        return when (propValue?.toLowerCase()) {
        return when (propValue?.lowercase()) {
            "verbose" -> LogLevel.VERBOSE
            "verbose" -> LogLevel.VERBOSE
            "v" -> LogLevel.VERBOSE
            "v" -> LogLevel.VERBOSE
            "debug" -> LogLevel.DEBUG
            "debug" -> LogLevel.DEBUG
+7 −10
Original line number Original line Diff line number Diff line
@@ -49,8 +49,7 @@ public class LogModule {
    @SysUISingleton
    @SysUISingleton
    @NotificationLog
    @NotificationLog
    public static LogBuffer provideNotificationsLogBuffer(LogBufferFactory factory) {
    public static LogBuffer provideNotificationsLogBuffer(LogBufferFactory factory) {
        return factory.create("NotifLog", 1000 /* maxPoolSize */,
        return factory.create("NotifLog", 1000 /* maxSize */, false /* systrace */);
                10 /* flexSize */, false /* systrace */);
    }
    }


    /** Provides a logging buffer for all logs related to the data layer of notifications. */
    /** Provides a logging buffer for all logs related to the data layer of notifications. */
@@ -74,8 +73,7 @@ public class LogModule {
    @SysUISingleton
    @SysUISingleton
    @NotificationSectionLog
    @NotificationSectionLog
    public static LogBuffer provideNotificationSectionLogBuffer(LogBufferFactory factory) {
    public static LogBuffer provideNotificationSectionLogBuffer(LogBufferFactory factory) {
        return factory.create("NotifSectionLog", 1000 /* maxPoolSize */,
        return factory.create("NotifSectionLog", 1000 /* maxSize */, false /* systrace */);
                10 /* flexSize */, false /* systrace */);
    }
    }


    /** Provides a logging buffer for all logs related to the data layer of notifications. */
    /** Provides a logging buffer for all logs related to the data layer of notifications. */
@@ -91,8 +89,7 @@ public class LogModule {
    @SysUISingleton
    @SysUISingleton
    @QSLog
    @QSLog
    public static LogBuffer provideQuickSettingsLogBuffer(LogBufferFactory factory) {
    public static LogBuffer provideQuickSettingsLogBuffer(LogBufferFactory factory) {
        return factory.create("QSLog", 500 /* maxPoolSize */,
        return factory.create("QSLog", 500 /* maxSize */, false /* systrace */);
                10 /* flexSize */, false /* systrace */);
    }
    }


    /** Provides a logging buffer for {@link com.android.systemui.broadcast.BroadcastDispatcher} */
    /** Provides a logging buffer for {@link com.android.systemui.broadcast.BroadcastDispatcher} */
@@ -100,8 +97,8 @@ public class LogModule {
    @SysUISingleton
    @SysUISingleton
    @BroadcastDispatcherLog
    @BroadcastDispatcherLog
    public static LogBuffer provideBroadcastDispatcherLogBuffer(LogBufferFactory factory) {
    public static LogBuffer provideBroadcastDispatcherLogBuffer(LogBufferFactory factory) {
        return factory.create("BroadcastDispatcherLog", 500 /* maxPoolSize */,
        return factory.create("BroadcastDispatcherLog", 500 /* maxSize */,
                10 /* flexSize */, false /* systrace */);
                false /* systrace */);
    }
    }


    /** Provides a logging buffer for all logs related to Toasts shown by SystemUI. */
    /** Provides a logging buffer for all logs related to Toasts shown by SystemUI. */
@@ -139,8 +136,8 @@ public class LogModule {
    @SysUISingleton
    @SysUISingleton
    @QSFragmentDisableLog
    @QSFragmentDisableLog
    public static LogBuffer provideQSFragmentDisableLogBuffer(LogBufferFactory factory) {
    public static LogBuffer provideQSFragmentDisableLogBuffer(LogBufferFactory factory) {
        return factory.create("QSFragmentDisableFlagsLog", 10 /* maxPoolSize */,
        return factory.create("QSFragmentDisableFlagsLog", 10 /* maxSize */,
                10 /* flexSize */, false /* systrace */);
                false /* systrace */);
    }
    }


    /**
    /**
+5 −12
Original line number Original line Diff line number Diff line
@@ -14,9 +14,9 @@
package com.android.systemui.statusbar.phone
package com.android.systemui.statusbar.phone


import android.view.MotionEvent
import android.view.MotionEvent
import com.android.internal.util.RingBuffer
import com.android.systemui.dump.DumpsysTableLogger
import com.android.systemui.dump.DumpsysTableLogger
import com.android.systemui.dump.Row
import com.android.systemui.dump.Row
import com.android.systemui.util.collection.RingBuffer
import java.text.SimpleDateFormat
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.Locale


@@ -67,16 +67,9 @@ class NPVCDownEventState private constructor(
     * Do not use [append] to add new elements. Instead use [insert], as it will recycle if
     * Do not use [append] to add new elements. Instead use [insert], as it will recycle if
     * necessary.
     * necessary.
     */
     */
    class Buffer(
    class Buffer(capacity: Int) {
        capacity: Int
    ) : RingBuffer<NPVCDownEventState>(NPVCDownEventState::class.java, capacity) {
        override fun append(t: NPVCDownEventState?) {
            throw UnsupportedOperationException("Not supported, use insert instead")
        }


        override fun createNewItem(): NPVCDownEventState {
        private val buffer = RingBuffer(capacity) { NPVCDownEventState() }
            return NPVCDownEventState()
        }


        /**
        /**
         * Insert a new element in the buffer.
         * Insert a new element in the buffer.
@@ -94,7 +87,7 @@ class NPVCDownEventState private constructor(
            touchSlopExceededBeforeDown: Boolean,
            touchSlopExceededBeforeDown: Boolean,
            lastEventSynthesized: Boolean
            lastEventSynthesized: Boolean
        ) {
        ) {
            nextSlot.apply {
            buffer.advance().apply {
                this.timeStamp = timeStamp
                this.timeStamp = timeStamp
                this.x = x
                this.x = x
                this.y = y
                this.y = y
@@ -115,7 +108,7 @@ class NPVCDownEventState private constructor(
         * @see NPVCDownEventState.asStringList
         * @see NPVCDownEventState.asStringList
         */
         */
        fun toList(): List<Row> {
        fun toList(): List<Row> {
            return toArray().map { it.asStringList }
            return buffer.asSequence().map { it.asStringList }.toList()
        }
        }
    }
    }


Loading