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