summaryrefslogtreecommitdiff
path: root/src/com/android/launcher3/util/EventLogArray.kt
blob: a17d6509e370d8c81df3ce7c10fdf2bbfd10e276 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
 * Copyright (C) 2023 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.launcher3.util

import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
 * A utility class to record and log events. Events are stored in a fixed size array and old logs
 * are purged as new events come.
 */
class EventLogArray(private val name: String, size: Int) {

    companion object {
        private const val TYPE_ONE_OFF = 0
        private const val TYPE_FLOAT = 1
        private const val TYPE_INTEGER = 2
        private const val TYPE_BOOL_TRUE = 3
        private const val TYPE_BOOL_FALSE = 4
        private fun isEntrySame(entry: EventEntry?, type: Int, event: String): Boolean {
            return entry != null && entry.type == type && entry.event == event
        }
    }

    private val logs: Array<EventEntry?>
    private var nextIndex = 0

    init {
        logs = arrayOfNulls(size)
    }

    fun addLog(event: String) {
        addLog(TYPE_ONE_OFF, event, 0f)
    }

    fun addLog(event: String, extras: Int) {
        addLog(TYPE_INTEGER, event, extras.toFloat())
    }

    fun addLog(event: String, extras: Float) {
        addLog(TYPE_FLOAT, event, extras)
    }

    fun addLog(event: String, extras: Boolean) {
        addLog(if (extras) TYPE_BOOL_TRUE else TYPE_BOOL_FALSE, event, 0f)
    }

    private fun addLog(type: Int, event: String, extras: Float) {
        // Merge the logs if it's a duplicate
        val last = (nextIndex + logs.size - 1) % logs.size
        val secondLast = (nextIndex + logs.size - 2) % logs.size
        if (isEntrySame(logs[last], type, event) && isEntrySame(logs[secondLast], type, event)) {
            logs[last]!!.update(type, event, extras)
            logs[secondLast]!!.duplicateCount++
            return
        }
        if (logs[nextIndex] == null) {
            logs[nextIndex] = EventEntry()
        }
        logs[nextIndex]!!.update(type, event, extras)
        nextIndex = (nextIndex + 1) % logs.size
    }

    fun dump(prefix: String, writer: PrintWriter) {
        writer.println("$prefix$name event history:")
        val sdf = SimpleDateFormat("  HH:mm:ss.SSSZ  ", Locale.US)
        val date = Date()
        for (i in logs.indices) {
            val log = logs[(nextIndex + logs.size - i - 1) % logs.size] ?: continue
            date.time = log.time
            val msg = StringBuilder(prefix).append(sdf.format(date)).append(log.event)
            when (log.type) {
                TYPE_BOOL_FALSE -> msg.append(": false")
                TYPE_BOOL_TRUE -> msg.append(": true")
                TYPE_FLOAT -> msg.append(": ").append(log.extras)
                TYPE_INTEGER -> msg.append(": ").append(log.extras.toInt())
                else -> {}
            }
            if (log.duplicateCount > 0) {
                msg.append(" & ").append(log.duplicateCount).append(" similar events")
            }
            writer.println(msg)
        }
    }

    /** A single event entry. */
    private class EventEntry {
        var type = 0
        var event: String? = null
        var extras = 0f
        var time: Long = 0
        var duplicateCount = 0
        fun update(type: Int, event: String, extras: Float) {
            this.type = type
            this.event = event
            this.extras = extras
            time = System.currentTimeMillis()
            duplicateCount = 0
        }
    }
}