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