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