1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.tools.traces.io
18 
19 import android.tools.Timestamp
20 import android.tools.io.FLICKER_IO_TAG
21 import android.tools.io.Reader
22 import android.tools.io.ResultArtifactDescriptor
23 import android.tools.io.TraceType
24 import android.tools.io.TransitionTimeRange
25 import android.tools.traces.TraceConfigs
26 import android.tools.traces.events.EventLog
27 import android.tools.traces.surfaceflinger.LayersTrace
28 import android.tools.traces.wm.WindowManagerTrace
29 import android.tools.withTracing
30 import android.util.Log
31 import android.util.LruCache
32 import java.io.IOException
33 
34 /**
35  * Helper class to read results from a flicker artifact using a LRU
36  *
37  * @param result to read from
38  * @param traceConfig
39  */
40 open class ResultReaderWithLru(
41     result: IResultData,
42     traceConfig: TraceConfigs,
43     private val reader: ResultReader = ResultReader(result, traceConfig)
44 ) : Reader by reader {
45     /** {@inheritDoc} */
46     @Throws(IOException::class)
readWmTracenull47     override fun readWmTrace(): WindowManagerTrace? {
48         val descriptor = ResultArtifactDescriptor(TraceType.WM)
49         val key = CacheKey(reader.artifact.stableId, descriptor, reader.transitionTimeRange)
50         return wmTraceCache.logAndReadTrace(key) { reader.readWmTrace() }
51     }
52 
53     /** {@inheritDoc} */
54     @Throws(IOException::class)
readLayersTracenull55     override fun readLayersTrace(): LayersTrace? {
56         val descriptor = ResultArtifactDescriptor(TraceType.SF)
57         val key = CacheKey(reader.artifact.stableId, descriptor, reader.transitionTimeRange)
58         return layersTraceCache.logAndReadTrace(key) { reader.readLayersTrace() }
59     }
60 
61     /** {@inheritDoc} */
62     @Throws(IOException::class)
readEventLogTracenull63     override fun readEventLogTrace(): EventLog? {
64         val descriptor = ResultArtifactDescriptor(TraceType.EVENT_LOG)
65         val key = CacheKey(reader.artifact.stableId, descriptor, reader.transitionTimeRange)
66         return eventLogCache.logAndReadTrace(key) { reader.readEventLogTrace() }
67     }
68 
69     /** {@inheritDoc} */
slicenull70     override fun slice(startTimestamp: Timestamp, endTimestamp: Timestamp): ResultReaderWithLru {
71         val slicedReader = reader.slice(startTimestamp, endTimestamp)
72         return ResultReaderWithLru(slicedReader.result, slicedReader.traceConfig, slicedReader)
73     }
74 
logAndReadTracenull75     private fun <TraceType> LruCache<CacheKey, TraceType>.logAndReadTrace(
76         key: CacheKey,
77         predicate: () -> TraceType?
78     ): TraceType? {
79         return withTracing("logAndReadTrace") {
80             var value = this[key]
81             if (value == null) {
82                 value =
83                     withTracing("cache miss") {
84                         Log.d(FLICKER_IO_TAG, "Cache miss $key, $reader")
85                         predicate()
86                     }
87             }
88 
89             if (value != null) {
90                 this.put(key, value)
91                 Log.d(FLICKER_IO_TAG, "Add to cache $key, $reader")
92             }
93             value
94         }
95     }
96 
97     companion object {
98         data class CacheKey(
99             private val artifact: String,
100             internal val descriptor: ResultArtifactDescriptor,
101             private val transitionTimeRange: TransitionTimeRange
102         )
103 
104         private val wmTraceCache = LruCache<CacheKey, WindowManagerTrace>(5)
105         private val layersTraceCache = LruCache<CacheKey, LayersTrace>(5)
106         private val eventLogCache = LruCache<CacheKey, EventLog>(5)
107     }
108 }
109