1 /*
2  * Copyright 2025 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 androidx.tracing.driver
18 
19 internal const val TRACE_EVENT_TYPE_UNDEFINED: Int = 0
20 internal const val TRACE_EVENT_TYPE_BEGIN: Int = 1
21 internal const val TRACE_EVENT_TYPE_END: Int = 2
22 internal const val TRACE_EVENT_TYPE_INSTANT: Int = 3
23 internal const val TRACE_EVENT_TYPE_COUNTER: Int = 4
24 
25 /**
26  * Mutable in-memory only representation a trace event, such as a slice start, slice end, or counter
27  * update.
28  *
29  * This structure is optimized for performance, with the expectation that these are created by a
30  * trace event, and passed to a background thread to be serialized. Mutability (and thus reuse) is
31  * an important component of this.
32  *
33  * Code outside of tracing-driver implementation should only ever consume these objects, not produce
34  * them.
35  */
36 @Suppress("NOTHING_TO_INLINE")
37 public class TraceEvent
38 internal constructor(
39     /**
40      * Must be one of [TRACE_EVENT_TYPE_UNDEFINED], [TRACE_EVENT_TYPE_INSTANT],
41      * [TRACE_EVENT_TYPE_BEGIN], [TRACE_EVENT_TYPE_END], [TRACE_EVENT_TYPE_COUNTER]
42      */
43     @field:Suppress("MutableBareField") // public / mutable to minimize overhead
44     @JvmField
45     public var type: Int,
46     /** Set to the value of the containing [Track]'s [Track.uuid]. */
47     @field:Suppress("MutableBareField") // public / mutable to minimize overhead
48     @JvmField
49     public var trackUuid: Long,
50 
51     /** Timestamp in nanoseconds of the trace event. */
52     @field:Suppress("MutableBareField") // public / mutable to minimize overhead
53     @JvmField
54     public var timestamp: Long,
55 
56     /** Name of the trace event - null if the event [type] is [TRACE_EVENT_TYPE_COUNTER]. */
57     @field:Suppress("MutableBareField") // public / mutable to minimize overhead
58     @JvmField
59     public var name: String?,
60     @field:Suppress(
61         "MutableBareField", // public / mutable to minimize overhead
62         "AutoBoxing", // temporary
63     )
64 
65     /**
66      * Value of the trace event if the event [type] is [TRACE_EVENT_TYPE_COUNTER].
67      *
68      * Note that only one of [counterDoubleValue] and [counterLongValue] may be set.
69      */
70     @JvmField
71     public var counterDoubleValue: Double?,
72 
73     /**
74      * Value of the trace event if the event [type] is [TRACE_EVENT_TYPE_COUNTER].
75      *
76      * Note that only one of [counterDoubleValue] and [counterLongValue] may be set.
77      */
78     @field:Suppress(
79         "MutableBareField", // public / mutable to minimize overhead
80         "AutoBoxing", // temporary
81     )
82     @JvmField
83     public var counterLongValue: Long?,
84 
85     /** List of trace flows associated with this event. */
86     // ideally this would be a array to avoid boxing, but proto libs consume longs anyway :|
87     @field:Suppress("MutableBareField") // public / mutable to minimize overhead
88     @JvmField
89     public var flowIds: List<Long>,
90 
91     /**
92      * If not null, this TraceEvent initializes a track, and the [TrackDescriptor] defines its
93      * properties.
94      */
95     @field:Suppress("MutableBareField") // public / mutable to minimize overhead
96     @JvmField
97     public var trackDescriptor: TrackDescriptor?,
98 ) {
99     public constructor() :
100         this(
101             type = INVALID_INT,
102             trackUuid = INVALID_LONG,
103             timestamp = INVALID_LONG,
104             name = null,
105             counterDoubleValue = null,
106             counterLongValue = null,
107             flowIds = emptyList(),
108             trackDescriptor = null
109         )
110 
setPreamblenull111     internal inline fun setPreamble(trackDescriptor: TrackDescriptor) {
112         this.trackDescriptor = trackDescriptor
113         this.timestamp = nanoTime()
114     }
115 
setBeginSectionnull116     internal inline fun setBeginSection(trackUuid: Long, name: String) {
117         type = TRACE_EVENT_TYPE_BEGIN
118         this.trackUuid = trackUuid
119         timestamp = nanoTime()
120         this.name = name
121     }
122 
setBeginSectionWithFlowsnull123     internal inline fun setBeginSectionWithFlows(
124         trackUuid: Long,
125         name: String,
126         flowIds: List<Long>
127     ) {
128         type = TRACE_EVENT_TYPE_BEGIN
129         this.trackUuid = trackUuid
130         timestamp = nanoTime()
131         this.flowIds = flowIds
132         this.name = name
133     }
134 
setEndSectionnull135     internal inline fun setEndSection(trackUuid: Long) {
136         type = TRACE_EVENT_TYPE_END
137         this.trackUuid = trackUuid
138         timestamp = nanoTime()
139     }
140 
setInstantnull141     internal inline fun setInstant(
142         trackUuid: Long,
143         name: String,
144     ) {
145         type = TRACE_EVENT_TYPE_END
146         this.trackUuid = trackUuid
147         timestamp = nanoTime()
148         this.name = name
149     }
150 
setCounterLongnull151     internal inline fun setCounterLong(trackUuid: Long, value: Long) {
152         type = TRACE_EVENT_TYPE_COUNTER
153         this.trackUuid = trackUuid
154         timestamp = nanoTime()
155         counterLongValue = value
156     }
157 
setCounterDoublenull158     internal inline fun setCounterDouble(trackUuid: Long, value: Double) {
159         type = TRACE_EVENT_TYPE_COUNTER
160         this.trackUuid = trackUuid
161         timestamp = nanoTime()
162         counterDoubleValue = value
163     }
164 
resetnull165     public fun reset() {
166         type = INVALID_INT
167         trackUuid = INVALID_LONG
168         timestamp = INVALID_LONG
169         name = null
170         counterDoubleValue = null
171         counterLongValue = null
172         flowIds = emptyList()
173         trackDescriptor = null
174     }
175 }
176