1 /* 2 * Copyright (C) 2023 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.common.traces.events 18 19 import android.tools.common.ITrace 20 import android.tools.common.Timestamp 21 import android.tools.common.Timestamps 22 import kotlin.js.JsExport 23 24 @JsExport 25 class CujTrace(override val entries: Array<Cuj>) : ITrace<Cuj> { 26 slicenull27 override fun slice(startTimestamp: Timestamp, endTimestamp: Timestamp): CujTrace { 28 return CujTrace( 29 entries 30 .dropWhile { it.endTimestamp < startTimestamp } 31 .dropLastWhile { it.startTimestamp > endTimestamp } 32 .toTypedArray() 33 ) 34 } 35 36 companion object { fromnull37 fun from(cujEvents: Array<CujEvent>): CujTrace { 38 val cujs = mutableListOf<Cuj>() 39 40 val sortedCujEvents = cujEvents.sortedBy { it.timestamp.unixNanos } 41 val startEvents = sortedCujEvents.filter { it.type == CujEvent.Companion.Type.START } 42 val endEvents = sortedCujEvents.filter { it.type == CujEvent.Companion.Type.END } 43 val canceledEvents = 44 sortedCujEvents.filter { it.type == CujEvent.Companion.Type.CANCEL } 45 46 for (startEvent in startEvents) { 47 val matchingEndEvent = 48 endEvents.firstOrNull { 49 it.cuj == startEvent.cuj && it.timestamp >= startEvent.timestamp 50 } 51 val matchingCancelEvent = 52 canceledEvents.firstOrNull { 53 it.cuj == startEvent.cuj && it.timestamp >= startEvent.timestamp 54 } 55 56 if (matchingCancelEvent == null && matchingEndEvent == null) { 57 // CUJ started but not ended within the trace 58 continue 59 } 60 61 val closingEvent = 62 listOf(matchingCancelEvent, matchingEndEvent).minBy { 63 it?.timestamp ?: Timestamps.max() 64 } 65 ?: error("Should have found one matching closing event") 66 val canceled = closingEvent.type == CujEvent.Companion.Type.CANCEL 67 68 cujs.add( 69 Cuj(startEvent.cuj, startEvent.timestamp, closingEvent.timestamp, canceled) 70 ) 71 } 72 73 return CujTrace(cujs.toTypedArray()) 74 } 75 } 76 } 77