1 /*
2 * Copyright 2016 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 #include "ProfilerCodeGenBase.h"
18 #include "utils/InterfaceSpecUtil.h"
19 #include "utils/StringUtil.h"
20 #include "VtsCompilerUtils.h"
21
22 namespace android {
23 namespace vts {
24
GenerateAll(Formatter & header_out,Formatter & source_out,const ComponentSpecificationMessage & message)25 void ProfilerCodeGenBase::GenerateAll(
26 Formatter& header_out, Formatter& source_out,
27 const ComponentSpecificationMessage& message) {
28 GenerateHeaderFile(header_out, message);
29 GenerateSourceFile(source_out, message);
30 }
31
GenerateHeaderFile(Formatter & out,const ComponentSpecificationMessage & message)32 void ProfilerCodeGenBase::GenerateHeaderFile(
33 Formatter& out, const ComponentSpecificationMessage& message) {
34 FQName component_fq_name = GetFQName(message);
35 out << "#ifndef __VTS_PROFILER_" << component_fq_name.tokenName()
36 << "__\n";
37 out << "#define __VTS_PROFILER_" << component_fq_name.tokenName()
38 << "__\n";
39 out << "\n\n";
40 GenerateHeaderIncludeFiles(out, message);
41 GenerateUsingDeclaration(out, message);
42 GenerateOpenNameSpaces(out, message);
43
44 if (message.has_interface()) {
45 InterfaceSpecificationMessage interface = message.interface();
46 // First generate the declaration of profiler functions for all user
47 // defined types within the interface.
48 for (const auto& attribute : interface.attribute()) {
49 GenerateProfilerMethodDeclForAttribute(out, attribute);
50 }
51
52 out << "extern \"C\" {\n";
53 out.indent();
54
55 // Generate the declaration of main profiler function.
56 FQName component_fq_name = GetFQName(message);
57 out << "\nvoid HIDL_INSTRUMENTATION_FUNCTION_" << component_fq_name.tokenName()
58 << "(\n";
59 out.indent();
60 out.indent();
61 out << "details::HidlInstrumentor::InstrumentationEvent event,\n";
62 out << "const char* package,\n";
63 out << "const char* version,\n";
64 out << "const char* interface,\n";
65 out << "const char* method,\n";
66 out << "std::vector<void *> *args);\n";
67 out.unindent();
68 out.unindent();
69
70 out.unindent();
71 out << "}\n\n";
72 } else {
73 // For types.vts, just generate the declaration of profiler functions
74 // for all user defined types.
75 for (const auto& attribute : message.attribute()) {
76 GenerateProfilerMethodDeclForAttribute(out, attribute);
77 }
78 }
79
80 GenerateCloseNameSpaces(out, message);
81 out << "#endif\n";
82 }
83
GenerateSourceFile(Formatter & out,const ComponentSpecificationMessage & message)84 void ProfilerCodeGenBase::GenerateSourceFile(
85 Formatter& out, const ComponentSpecificationMessage& message) {
86 GenerateSourceIncludeFiles(out, message);
87 GenerateUsingDeclaration(out, message);
88 GenerateMacros(out, message);
89 GenerateOpenNameSpaces(out, message);
90
91 if (message.has_interface()) {
92 InterfaceSpecificationMessage interface = message.interface();
93 // First generate profiler functions for all user defined types within
94 // the interface.
95 for (const auto& attribute : interface.attribute()) {
96 GenerateProfilerMethodImplForAttribute(out, attribute);
97 }
98 // Generate the main profiler function.
99 FQName component_fq_name = GetFQName(message);
100 out << "\nvoid HIDL_INSTRUMENTATION_FUNCTION_" << component_fq_name.tokenName()
101 << "(\n";
102 out.indent();
103 out.indent();
104 out << "details::HidlInstrumentor::InstrumentationEvent event "
105 "__attribute__((__unused__)),\n";
106 out << "const char* package,\n";
107 out << "const char* version,\n";
108 out << "const char* interface,\n";
109 out << "const char* method __attribute__((__unused__)),\n";
110 out << "std::vector<void *> *args __attribute__((__unused__))) {\n";
111 out.unindent();
112
113 // Generate code for sanity check.
114 GenerateProfilerSanityCheck(out, message);
115
116 if (interface.api_size() > 0) {
117 // Generate code to define local variables.
118 GenerateLocalVariableDefinition(out, message);
119
120 // Generate the profiler code for each method.
121 for (const FunctionSpecificationMessage& api : interface.api()) {
122 out << "if (strcmp(method, \"" << api.name() << "\") == 0) {\n";
123 out.indent();
124 GenerateProfilerForMethod(out, api);
125 out.unindent();
126 out << "}\n";
127 }
128 }
129
130 out.unindent();
131 out << "}\n\n";
132 } else {
133 // For types.vts, just generate profiler functions for the user defined
134 // types.
135 for (const auto& attribute : message.attribute()) {
136 GenerateProfilerMethodImplForAttribute(out, attribute);
137 }
138 }
139
140 GenerateCloseNameSpaces(out, message);
141 }
142
GenerateProfilerForTypedVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)143 void ProfilerCodeGenBase::GenerateProfilerForTypedVariable(Formatter& out,
144 const VariableSpecificationMessage& val, const std::string& arg_name,
145 const std::string& arg_value) {
146 switch (val.type()) {
147 case TYPE_SCALAR:
148 {
149 GenerateProfilerForScalarVariable(out, val, arg_name, arg_value);
150 break;
151 }
152 case TYPE_STRING:
153 {
154 GenerateProfilerForStringVariable(out, val, arg_name, arg_value);
155 break;
156 }
157 case TYPE_ENUM:
158 {
159 GenerateProfilerForEnumVariable(out, val, arg_name, arg_value);
160 break;
161 }
162 case TYPE_VECTOR:
163 {
164 GenerateProfilerForVectorVariable(out, val, arg_name, arg_value);
165 break;
166 }
167 case TYPE_ARRAY:
168 {
169 GenerateProfilerForArrayVariable(out, val, arg_name, arg_value);
170 break;
171 }
172 case TYPE_STRUCT:
173 {
174 GenerateProfilerForStructVariable(out, val, arg_name, arg_value);
175 break;
176 }
177 case TYPE_UNION: {
178 GenerateProfilerForUnionVariable(out, val, arg_name, arg_value);
179 break;
180 }
181 case TYPE_HIDL_CALLBACK:
182 {
183 GenerateProfilerForHidlCallbackVariable(out, val, arg_name, arg_value);
184 break;
185 }
186 case TYPE_HIDL_INTERFACE:
187 {
188 GenerateProfilerForHidlInterfaceVariable(out, val, arg_name, arg_value);
189 break;
190 }
191 case TYPE_MASK:
192 {
193 GenerateProfilerForMaskVariable(out, val, arg_name, arg_value);
194 break;
195 }
196 case TYPE_HANDLE: {
197 GenerateProfilerForHandleVariable(out, val, arg_name, arg_value);
198 break;
199 }
200 case TYPE_HIDL_MEMORY:
201 {
202 GenerateProfilerForHidlMemoryVariable(out, val, arg_name, arg_value);
203 break;
204 }
205 case TYPE_POINTER:
206 {
207 GenerateProfilerForPointerVariable(out, val, arg_name, arg_value);
208 break;
209 }
210 case TYPE_FMQ_SYNC:
211 {
212 GenerateProfilerForFMQSyncVariable(out, val, arg_name, arg_value);
213 break;
214 }
215 case TYPE_FMQ_UNSYNC:
216 {
217 GenerateProfilerForFMQUnsyncVariable(out, val, arg_name, arg_value);
218 break;
219 }
220 case TYPE_SAFE_UNION: {
221 GenerateProfilerForSafeUnionVariable(out, val, arg_name, arg_value);
222 break;
223 }
224 default: {
225 out << "LOG(ERROR) << \"Type " << val.type()
226 << "is not supported yet. \";\n";
227 }
228 }
229 }
230
GenerateProfilerMethodDeclForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)231 void ProfilerCodeGenBase::GenerateProfilerMethodDeclForAttribute(Formatter& out,
232 const VariableSpecificationMessage& attribute) {
233 if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION ||
234 attribute.type() == TYPE_SAFE_UNION) {
235 // Recursively generate profiler method declaration for all sub_types.
236 for (const auto& sub_struct : attribute.sub_struct()) {
237 GenerateProfilerMethodDeclForAttribute(out, sub_struct);
238 }
239 for (const auto& sub_union : attribute.sub_union()) {
240 GenerateProfilerMethodDeclForAttribute(out, sub_union);
241 }
242 for (const auto& sub_safe_union : attribute.sub_safe_union()) {
243 GenerateProfilerMethodDeclForAttribute(out, sub_safe_union);
244 }
245 }
246 std::string attribute_name = attribute.name();
247 ReplaceSubString(attribute_name, "::", "__");
248 out << "void profile__" << attribute_name
249 << "(VariableSpecificationMessage* arg_name,\n" << attribute.name()
250 << " arg_val_name);\n";
251 }
252
GenerateProfilerMethodImplForAttribute(Formatter & out,const VariableSpecificationMessage & attribute)253 void ProfilerCodeGenBase::GenerateProfilerMethodImplForAttribute(
254 Formatter& out, const VariableSpecificationMessage& attribute) {
255 if (attribute.type() == TYPE_STRUCT || attribute.type() == TYPE_UNION ||
256 attribute.type() == TYPE_SAFE_UNION) {
257 // Recursively generate profiler method implementation for all sub_types.
258 for (const auto& sub_struct : attribute.sub_struct()) {
259 GenerateProfilerMethodImplForAttribute(out, sub_struct);
260 }
261 for (const auto& sub_union : attribute.sub_union()) {
262 GenerateProfilerMethodImplForAttribute(out, sub_union);
263 }
264 for (const auto& sub_safe_union : attribute.sub_safe_union()) {
265 GenerateProfilerMethodImplForAttribute(out, sub_safe_union);
266 }
267 }
268 std::string attribute_name = attribute.name();
269 ReplaceSubString(attribute_name, "::", "__");
270 out << "void profile__" << attribute_name
271 << "(VariableSpecificationMessage* arg_name,\n"
272 << attribute.name() << " arg_val_name __attribute__((__unused__))) {\n";
273 out.indent();
274 GenerateProfilerForTypedVariable(out, attribute, "arg_name", "arg_val_name");
275 out.unindent();
276 out << "}\n\n";
277 }
278
GenerateOpenNameSpaces(Formatter & out,const ComponentSpecificationMessage &)279 void ProfilerCodeGenBase::GenerateOpenNameSpaces(Formatter& out,
280 const ComponentSpecificationMessage& /*message*/) {
281 out << "namespace android {\n";
282 out << "namespace vts {\n";
283 }
284
GenerateCloseNameSpaces(Formatter & out,const ComponentSpecificationMessage &)285 void ProfilerCodeGenBase::GenerateCloseNameSpaces(Formatter& out,
286 const ComponentSpecificationMessage& /*message*/) {
287 out << "} // namespace vts\n";
288 out << "} // namespace android\n";
289 }
290
IncludeHidlNativeType(const ComponentSpecificationMessage & message,const VariableType & type)291 bool ProfilerCodeGenBase::IncludeHidlNativeType(
292 const ComponentSpecificationMessage& message, const VariableType& type) {
293 if (message.has_interface()) {
294 InterfaceSpecificationMessage interface = message.interface();
295 for (const VariableSpecificationMessage& attribute :
296 interface.attribute()) {
297 if (IncludeHidlNativeType(attribute, type)) {
298 return true;
299 }
300 }
301 for (const FunctionSpecificationMessage& api : interface.api()) {
302 for (const VariableSpecificationMessage& arg : api.arg()) {
303 if (IncludeHidlNativeType(arg, type)) {
304 return true;
305 }
306 }
307 for (const VariableSpecificationMessage& result :
308 api.return_type_hidl()) {
309 if (IncludeHidlNativeType(result, type)) {
310 return true;
311 }
312 }
313 }
314 } else {
315 for (const VariableSpecificationMessage& attribute : message.attribute()) {
316 if (IncludeHidlNativeType(attribute, type)) {
317 return true;
318 }
319 }
320 }
321 return false;
322 }
323
IncludeHidlNativeType(const VariableSpecificationMessage & val,const VariableType & type)324 bool ProfilerCodeGenBase::IncludeHidlNativeType(
325 const VariableSpecificationMessage& val, const VariableType& type) {
326 if (val.type() == type) {
327 return true;
328 }
329 if (val.type() == TYPE_VECTOR || val.type() == TYPE_ARRAY) {
330 if (IncludeHidlNativeType(val.vector_value(0), type)) return true;
331 }
332 if (val.type() == TYPE_STRUCT) {
333 if (!val.has_predefined_type()) {
334 for (const auto& sub_struct : val.sub_struct()) {
335 if (IncludeHidlNativeType(sub_struct, type)) return true;
336 }
337 for (const auto& struct_field : val.struct_value()) {
338 if (IncludeHidlNativeType(struct_field, type)) return true;
339 }
340 }
341 }
342 if (val.type() == TYPE_UNION) {
343 if (!val.has_predefined_type()) {
344 for (const auto& sub_union : val.sub_union()) {
345 if (IncludeHidlNativeType(sub_union, type)) return true;
346 }
347 for (const auto& union_field : val.union_value()) {
348 if (IncludeHidlNativeType(union_field, type)) return true;
349 }
350 }
351 }
352 return false;
353 }
354
355 } // namespace vts
356 } // namespace android
357