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.device.traces.parsers.wm 18 19 import android.tools.common.Timestamp 20 import android.tools.common.Timestamps 21 import android.tools.common.parsers.AbstractTraceParser 22 import android.tools.common.traces.wm.ShellTransitionData 23 import android.tools.common.traces.wm.Transition 24 import android.tools.common.traces.wm.TransitionsTrace 25 import com.android.wm.shell.nano.WmShellTransitionTraceProto 26 27 /** Parser for [TransitionsTrace] objects */ 28 class ShellTransitionTraceParser : 29 AbstractTraceParser< 30 WmShellTransitionTraceProto, 31 com.android.wm.shell.nano.Transition, 32 Transition, 33 TransitionsTrace 34 >() { 35 override val traceName: String = "Transition trace (shell)" 36 createTracenull37 override fun createTrace(entries: List<Transition>): TransitionsTrace { 38 return TransitionsTrace(entries.toTypedArray()) 39 } 40 doDecodeByteArraynull41 override fun doDecodeByteArray(bytes: ByteArray): WmShellTransitionTraceProto = 42 WmShellTransitionTraceProto.parseFrom(bytes) 43 44 override fun shouldParseEntry(entry: com.android.wm.shell.nano.Transition): Boolean { 45 return true 46 } 47 getEntriesnull48 override fun getEntries( 49 input: WmShellTransitionTraceProto 50 ): List<com.android.wm.shell.nano.Transition> = input.transitions.toList() 51 52 override fun getTimestamp(entry: com.android.wm.shell.nano.Transition): Timestamp { 53 requireValidTimestamp(entry) 54 55 if (entry.dispatchTimeNs != 0L) { 56 return Timestamps.from(elapsedNanos = entry.dispatchTimeNs) 57 } 58 if (entry.mergeRequestTimeNs != 0L) { 59 return Timestamps.from(elapsedNanos = entry.mergeRequestTimeNs) 60 } 61 if (entry.mergeTimeNs != 0L) { 62 return Timestamps.from(elapsedNanos = entry.mergeTimeNs) 63 } 64 if (entry.abortTimeNs != 0L) { 65 return Timestamps.from(elapsedNanos = entry.abortTimeNs) 66 } 67 68 error("No valid timestamp for entry") 69 } 70 71 private val handlerMapping = mutableMapOf<Int, String>() 72 onBeforeParsenull73 override fun onBeforeParse(input: WmShellTransitionTraceProto) { 74 handlerMapping.clear() 75 for (mapping in input.handlerMappings) { 76 handlerMapping[mapping.id] = mapping.name 77 } 78 } 79 doParsenull80 override fun doParse( 81 input: WmShellTransitionTraceProto, 82 from: Timestamp, 83 to: Timestamp, 84 addInitialEntry: Boolean 85 ): TransitionsTrace { 86 val uncompressedTransitionsTrace = super.doParse(input, from, to, addInitialEntry) 87 return uncompressedTransitionsTrace.asCompressed() 88 } 89 doParseEntrynull90 override fun doParseEntry(entry: com.android.wm.shell.nano.Transition): Transition { 91 require(entry.id != 0) { "Entry needs a non null id" } 92 requireValidTimestamp(entry) 93 94 return Transition( 95 entry.id, 96 shellData = 97 ShellTransitionData( 98 dispatchTime = 99 if (entry.dispatchTimeNs == 0L) null 100 else Timestamps.from(elapsedNanos = entry.dispatchTimeNs), 101 mergeRequestTime = 102 if (entry.mergeRequestTimeNs == 0L) null 103 else Timestamps.from(elapsedNanos = entry.mergeRequestTimeNs), 104 mergeTime = 105 if (entry.mergeTimeNs == 0L) null 106 else Timestamps.from(elapsedNanos = entry.mergeTimeNs), 107 abortTime = 108 if (entry.abortTimeNs == 0L) null 109 else Timestamps.from(elapsedNanos = entry.abortTimeNs), 110 handler = handlerMapping[entry.handler], 111 mergedInto = if (entry.mergedInto == 0) null else entry.mergedInto 112 ) 113 ) 114 } 115 116 companion object { requireValidTimestampnull117 private fun requireValidTimestamp(entry: com.android.wm.shell.nano.Transition) { 118 require( 119 entry.dispatchTimeNs != 0L || 120 entry.mergeRequestTimeNs != 0L || 121 entry.mergeTimeNs != 0L || 122 entry.abortTimeNs != 0L 123 ) { 124 "Requires at least one non-null timestamp" 125 } 126 } 127 } 128 } 129