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.tracing.perfetto;
18 
19 import android.util.proto.ProtoOutputStream;
20 
21 import java.util.ArrayList;
22 import java.util.List;
23 
24 /**
25  * Argument passed to the lambda function passed to Trace().
26  *
27  * @param <DataSourceInstanceType> The type of the datasource this tracing context is for.
28  * @param <TlsStateType> The type of the custom TLS state, if any is used.
29  * @param <IncrementalStateType> The type of the custom incremental state, if any is used.
30  *
31  * @hide
32  */
33 public class TracingContext<DataSourceInstanceType extends DataSourceInstance, TlsStateType,
34         IncrementalStateType> {
35 
36     private final DataSource<DataSourceInstanceType, TlsStateType, IncrementalStateType>
37             mDataSource;
38     private final int mInstanceIndex;
39     private final List<ProtoOutputStream> mTracePackets = new ArrayList<>();
40 
TracingContext(DataSource<DataSourceInstanceType, TlsStateType, IncrementalStateType> dataSource, int instanceIndex)41     TracingContext(DataSource<DataSourceInstanceType, TlsStateType, IncrementalStateType>
42             dataSource,
43             int instanceIndex) {
44         this.mDataSource = dataSource;
45         this.mInstanceIndex = instanceIndex;
46     }
47 
48     /**
49      * Creates a new output stream to be used to write a trace packet to. The output stream will be
50      * encoded to the proto binary representation when the callback trace function finishes and
51      * send over to the native side to be included in the proto buffer.
52      *
53      * @return A proto output stream to write a trace packet proto to
54      */
newTracePacket()55     public ProtoOutputStream newTracePacket() {
56         final ProtoOutputStream os = new ProtoOutputStream(0);
57         mTracePackets.add(os);
58         return os;
59     }
60 
61     /**
62      * Can optionally be used to store custom per-sequence
63      * session data, which is not reset when incremental state is cleared
64      * (e.g. configuration options).
65      *h
66      * @return The TlsState instance for the tracing thread and instance.
67      */
getCustomTlsState()68     public TlsStateType getCustomTlsState() {
69         TlsStateType tlsState = (TlsStateType) nativeGetCustomTls(mDataSource.mNativeObj);
70         if (tlsState == null) {
71             final CreateTlsStateArgs<DataSourceInstanceType> args =
72                     new CreateTlsStateArgs<>(mDataSource, mInstanceIndex);
73             tlsState = mDataSource.createTlsState(args);
74             nativeSetCustomTls(mDataSource.mNativeObj, tlsState);
75         }
76 
77         return tlsState;
78     }
79 
80     /**
81      * Can optionally be used store custom per-sequence
82      * incremental data (e.g., interning tables).
83      *
84      * @return The current IncrementalState object instance.
85      */
getIncrementalState()86     public IncrementalStateType getIncrementalState() {
87         IncrementalStateType incrementalState =
88                 (IncrementalStateType) nativeGetIncrementalState(mDataSource.mNativeObj);
89         if (incrementalState == null) {
90             final CreateIncrementalStateArgs<DataSourceInstanceType> args =
91                     new CreateIncrementalStateArgs<>(mDataSource, mInstanceIndex);
92             incrementalState = mDataSource.createIncrementalState(args);
93             nativeSetIncrementalState(mDataSource.mNativeObj, incrementalState);
94         }
95 
96         return incrementalState;
97     }
98 
getAndClearAllPendingTracePackets()99     protected byte[][] getAndClearAllPendingTracePackets() {
100         byte[][] res = new byte[mTracePackets.size()][];
101         for (int i = 0; i < mTracePackets.size(); i++) {
102             ProtoOutputStream tracePacket = mTracePackets.get(i);
103             res[i] = tracePacket.getBytes();
104         }
105 
106         mTracePackets.clear();
107         return res;
108     }
109 
nativeGetCustomTls(long nativeDsPtr)110     private static native Object nativeGetCustomTls(long nativeDsPtr);
nativeSetCustomTls(long nativeDsPtr, Object tlsState)111     private static native void nativeSetCustomTls(long nativeDsPtr, Object tlsState);
112 
nativeGetIncrementalState(long nativeDsPtr)113     private static native Object nativeGetIncrementalState(long nativeDsPtr);
nativeSetIncrementalState(long nativeDsPtr, Object incrementalState)114     private static native void nativeSetIncrementalState(long nativeDsPtr, Object incrementalState);
115 }
116