• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "HalHidlProfilerCodeGen.h"
18 #include "utils/InterfaceSpecUtil.h"
19 #include "utils/StringUtil.h"
20 #include "VtsCompilerUtils.h"
21 
22 namespace android {
23 namespace vts {
24 
GenerateProfilerForScalarVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)25 void HalHidlProfilerCodeGen::GenerateProfilerForScalarVariable(Formatter& out,
26   const VariableSpecificationMessage& val, const std::string& arg_name,
27   const std::string& arg_value) {
28   out << arg_name << "->set_type(TYPE_SCALAR);\n";
29   out << arg_name << "->mutable_scalar_value()->set_" << val.scalar_type()
30       << "(" << arg_value << ");\n";
31 }
32 
GenerateProfilerForStringVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string & arg_value)33 void HalHidlProfilerCodeGen::GenerateProfilerForStringVariable(Formatter& out,
34   const VariableSpecificationMessage&, const std::string& arg_name,
35   const std::string& arg_value) {
36   out << arg_name << "->set_type(TYPE_STRING);\n";
37   out << arg_name << "->mutable_string_value()->set_message" << "(" << arg_value
38       << ".c_str());\n";
39   out << arg_name << "->mutable_string_value()->set_length" << "(" << arg_value
40       << ".size());\n";
41 }
42 
GenerateProfilerForEnumVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)43 void HalHidlProfilerCodeGen::GenerateProfilerForEnumVariable(Formatter& out,
44   const VariableSpecificationMessage& val, const std::string& arg_name,
45   const std::string& arg_value) {
46   out << arg_name << "->set_type(TYPE_ENUM);\n";
47 
48   // For predefined type, call the corresponding profile method.
49   if (val.has_predefined_type()) {
50     std::string predefined_type = val.predefined_type();
51     ReplaceSubString(predefined_type, "::", "__");
52     out << "profile__" << predefined_type << "(" << arg_name << ", "
53         << arg_value << ");\n";
54   } else {
55     const std::string scalar_type = val.enum_value().scalar_type();
56     out << arg_name << "->mutable_scalar_value()->set_" << scalar_type
57         << "(static_cast<" << scalar_type << ">(" << arg_value << "));\n";
58     out << arg_name << "->set_scalar_type(\"" << scalar_type << "\");\n";
59   }
60 }
61 
GenerateProfilerForVectorVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)62 void HalHidlProfilerCodeGen::GenerateProfilerForVectorVariable(Formatter& out,
63   const VariableSpecificationMessage& val, const std::string& arg_name,
64   const std::string& arg_value) {
65   out << arg_name << "->set_type(TYPE_VECTOR);\n";
66   out << arg_name << "->set_vector_size(" << arg_value << ".size());\n";
67   out << "for (int i = 0; i < (int)" << arg_value << ".size(); i++) {\n";
68   out.indent();
69   std::string vector_element_name = arg_name + "_vector_i";
70   out << "auto *" << vector_element_name << " = " << arg_name
71       << "->add_vector_value();\n";
72   GenerateProfilerForTypedVariable(out, val.vector_value(0),
73                                    vector_element_name, arg_value + "[i]");
74   out.unindent();
75   out << "}\n";
76 }
77 
GenerateProfilerForArrayVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)78 void HalHidlProfilerCodeGen::GenerateProfilerForArrayVariable(Formatter& out,
79   const VariableSpecificationMessage& val, const std::string& arg_name,
80   const std::string& arg_value) {
81   out << arg_name << "->set_type(TYPE_ARRAY);\n";
82   out << arg_name << "->set_vector_size(" << val.vector_size() << ");\n";
83   out << "for (int i = 0; i < " << val.vector_size() << "; i++) {\n";
84   out.indent();
85   std::string array_element_name = arg_name + "_array_i";
86   out << "auto *" << array_element_name << " = " << arg_name
87       << "->add_vector_value();\n";
88   GenerateProfilerForTypedVariable(out, val.vector_value(0), array_element_name,
89                                    arg_value + "[i]");
90   out.unindent();
91   out << "}\n";
92 }
93 
GenerateProfilerForStructVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)94 void HalHidlProfilerCodeGen::GenerateProfilerForStructVariable(Formatter& out,
95   const VariableSpecificationMessage& val, const std::string& arg_name,
96   const std::string& arg_value) {
97   out << arg_name << "->set_type(TYPE_STRUCT);\n";
98   // For predefined type, call the corresponding profile method.
99   if (val.struct_value().size() == 0 && val.has_predefined_type()) {
100     std::string predefined_type = val.predefined_type();
101     ReplaceSubString(predefined_type, "::", "__");
102     out << "profile__" << predefined_type << "(" << arg_name << ", "
103         << arg_value << ");\n";
104   } else {
105     for (const auto struct_field : val.struct_value()) {
106       std::string struct_field_name = arg_name + "_" + struct_field.name();
107       out << "auto *" << struct_field_name << " = " << arg_name
108           << "->add_struct_value();\n";
109       GenerateProfilerForTypedVariable(out, struct_field, struct_field_name,
110                                        arg_value + "." + struct_field.name());
111     }
112   }
113 }
114 
GenerateProfilerForUnionVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)115 void HalHidlProfilerCodeGen::GenerateProfilerForUnionVariable(Formatter& out,
116   const VariableSpecificationMessage& val, const std::string& arg_name,
117   const std::string& arg_value) {
118   out << arg_name << "->set_type(TYPE_UNION);\n";
119   // For predefined type, call the corresponding profile method.
120   if (val.union_value().size() == 0 && val.has_predefined_type()) {
121     std::string predefined_type = val.predefined_type();
122     ReplaceSubString(predefined_type, "::", "__");
123     out << "profile__" << predefined_type << "(" << arg_name << ", "
124         << arg_value << ");\n";
125   } else {
126     for (const auto union_field : val.union_value()) {
127       std::string union_field_name = arg_name + "_" + union_field.name();
128       out << "auto *" << union_field_name << " = " << arg_name
129           << "->add_union_value();\n";
130       GenerateProfilerForTypedVariable(out, union_field, union_field_name,
131                                        arg_value + "." + union_field.name());
132     }
133   }
134 }
135 
GenerateProfilerForHidlCallbackVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)136 void HalHidlProfilerCodeGen::GenerateProfilerForHidlCallbackVariable(
137   Formatter& out, const VariableSpecificationMessage&,
138   const std::string& arg_name, const std::string&) {
139   out << arg_name << "->set_type(TYPE_HIDL_CALLBACK);\n";
140   // TODO(zhuoyao): figure the right way to profile hidl callback type.
141 }
142 
GenerateProfilerForHidlInterfaceVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)143 void HalHidlProfilerCodeGen::GenerateProfilerForHidlInterfaceVariable(
144   Formatter& out, const VariableSpecificationMessage&,
145   const std::string& arg_name, const std::string&) {
146   out << arg_name << "->set_type(TYPE_HIDL_INTERFACE);\n";
147   // TODO(zhuoyao): figure the right way to profile hidl interface type.
148 }
149 
GenerateProfilerForMaskVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)150 void HalHidlProfilerCodeGen::GenerateProfilerForMaskVariable(Formatter& out,
151     const VariableSpecificationMessage&, const std::string& arg_name,
152     const std::string&) {
153   out << arg_name << "->set_type(TYPE_MASK);\n";
154   // TODO(zhuoyao): figure the right way to profile mask type.
155 }
156 
GenerateProfilerForHidlMemoryVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)157 void HalHidlProfilerCodeGen::GenerateProfilerForHidlMemoryVariable(
158     Formatter& out, const VariableSpecificationMessage&,
159     const std::string& arg_name, const std::string&) {
160   out << arg_name << "->set_type(TYPE_HIDL_MEMORY);\n";
161   // TODO(zhuoyao): figure the right way to profile hidl memory type.
162 }
163 
GenerateProfilerForPointerVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)164 void HalHidlProfilerCodeGen::GenerateProfilerForPointerVariable(Formatter& out,
165     const VariableSpecificationMessage&, const std::string& arg_name,
166     const std::string&) {
167   out << arg_name << "->set_type(TYPE_POINTER);\n";
168   // TODO(zhuoyao): figure the right way to profile pointer type.
169 }
170 
GenerateProfilerForFMQSyncVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)171 void HalHidlProfilerCodeGen::GenerateProfilerForFMQSyncVariable(Formatter& out,
172     const VariableSpecificationMessage&, const std::string& arg_name,
173     const std::string&) {
174   out << arg_name << "->set_type(TYPE_FMQ_SYNC);\n";
175   // TODO(zhuoyao): figure the right way to profile fmq sync type.
176 }
177 
GenerateProfilerForFMQUnsyncVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)178 void HalHidlProfilerCodeGen::GenerateProfilerForFMQUnsyncVariable(
179     Formatter& out, const VariableSpecificationMessage&,
180     const std::string& arg_name, const std::string&) {
181   out << arg_name << "->set_type(TYPE_FMQ_UNSYNC);\n";
182   // TODO(zhuoyao): figure the right way to profile fmq unsync type.
183 }
184 
GenerateProfilerForMethod(Formatter & out,const FunctionSpecificationMessage & method)185 void HalHidlProfilerCodeGen::GenerateProfilerForMethod(Formatter& out,
186   const FunctionSpecificationMessage& method) {
187   out << "FunctionSpecificationMessage msg;\n";
188   out << "msg.set_name(\"" << method.name() << "\");\n";
189   out << "if (!args) {\n";
190   out.indent();
191   out << "LOG(WARNING) << \"no argument passed\";\n";
192   out.unindent();
193   out << "} else {\n";
194   out.indent();
195   out << "switch (event) {\n";
196   out.indent();
197   // TODO(b/32141398): Support profiling in passthrough mode.
198   out << "case details::HidlInstrumentor::CLIENT_API_ENTRY:\n";
199   out << "case details::HidlInstrumentor::SERVER_API_ENTRY:\n";
200   out << "case details::HidlInstrumentor::PASSTHROUGH_ENTRY:\n";
201   out << "{\n";
202   out.indent();
203   ComponentSpecificationMessage message;
204   out << "if ((*args).size() != " <<  method.arg().size() << ") {\n";
205   out.indent();
206   out << "LOG(ERROR) << \"Number of arguments does not match. expect: "
207       << method.arg().size()
208       << ", actual: \" << (*args).size() << \", method name: "
209       << method.name()
210       << ", event type: \" << event;\n";
211   out << "break;\n";
212   out.unindent();
213   out << "}\n";
214   for (int i = 0; i < method.arg().size(); i++) {
215     const VariableSpecificationMessage arg = method.arg(i);
216     std::string arg_name = "arg_" + std::to_string(i);
217     std::string arg_value = "arg_val_" + std::to_string(i);
218     out << "auto *" << arg_name << " = msg.add_arg();\n";
219     // TODO(zhuoyao): GetCppVariableType does not support array type for now.
220     out << GetCppVariableType(arg, &message) << " *" << arg_value
221         << " = reinterpret_cast<" << GetCppVariableType(arg, &message)
222         << "*> ((*args)[" << i << "]);\n";
223     GenerateProfilerForTypedVariable(out, arg, arg_name,
224                                      "(*" + arg_value + ")");
225   }
226   out << "break;\n";
227   out.unindent();
228   out << "}\n";
229 
230   // TODO(b/32141398): Support profiling in passthrough mode.
231   out << "case details::HidlInstrumentor::CLIENT_API_EXIT:\n";
232   out << "case details::HidlInstrumentor::SERVER_API_EXIT:\n";
233   out << "case details::HidlInstrumentor::PASSTHROUGH_EXIT:\n";
234   out << "{\n";
235   out.indent();
236   out << "if ((*args).size() != " <<  method.return_type_hidl().size() << ") {\n";
237   out.indent();
238   out << "LOG(ERROR) << \"Number of return values does not match. expect: "
239       << method.return_type_hidl().size()
240       << ", actual: \" << (*args).size() << \", method name: "
241       << method.name()
242       << ", event type: \" << event;\n";
243   out << "break;\n";
244   out.unindent();
245   out << "}\n";
246   for (int i = 0; i < method.return_type_hidl().size(); i++) {
247     const VariableSpecificationMessage arg = method.return_type_hidl(i);
248     std::string result_name = "result_" + std::to_string(i);
249     std::string result_value = "result_val_" + std::to_string(i);
250     out << "auto *" << result_name << " = msg.add_return_type_hidl();\n";
251     out << GetCppVariableType(arg, &message) << " *" << result_value
252         << " = reinterpret_cast<" << GetCppVariableType(arg, &message)
253         << "*> ((*args)[" << i << "]);\n";
254     GenerateProfilerForTypedVariable(out, arg, result_name,
255                                      "(*" + result_value + ")");
256   }
257   out << "break;\n";
258   out.unindent();
259   out << "}\n";
260   out << "default:\n";
261   out << "{\n";
262   out.indent();
263   out << "LOG(WARNING) << \"not supported. \";\n";
264   out << "break;\n";
265   out.unindent();
266   out << "}\n";
267   out.unindent();
268   out << "}\n";
269   out.unindent();
270   out << "}\n";
271   out << "profiler.AddTraceEvent(event, package, version, interface, msg);\n";
272 }
273 
GenerateHeaderIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message)274 void HalHidlProfilerCodeGen::GenerateHeaderIncludeFiles(Formatter& out,
275     const ComponentSpecificationMessage& message) {
276   // Basic includes.
277   out << "#include <android-base/logging.h>\n";
278   out << "#include <hidl/HidlSupport.h>\n";
279   out << "#include <linux/limits.h>\n";
280   out << "#include <test/vts/proto/ComponentSpecificationMessage.pb.h>\n";
281   out << "#include \"VtsProfilingInterface.h\"\n";
282   out << "\n";
283 
284   std::string package_path = GetPackage(message);
285   ReplaceSubString(package_path, ".", "/");
286 
287   // Include generated hal classes.
288   out << "#include <" << package_path << "/" << GetPackageVersion(message)
289       << "/" << GetComponentName(message) << ".h>\n";
290 
291   // Include imported classes.
292   for (const auto& import : message.import()) {
293     FQName import_name = FQName(import);
294     string imported_package_name = import_name.package();
295     string imported_package_version = import_name.version();
296     string imported_component_name = import_name.name();
297     string imported_package_path = imported_package_name;
298     ReplaceSubString(imported_package_path, ".", "/");
299     out << "#include <" << imported_package_path << "/"
300         << imported_package_version << "/" << imported_component_name
301         << ".h>\n";
302     if (imported_package_name.find("android.hardware") != std::string::npos) {
303       if (imported_component_name[0] == 'I') {
304         imported_component_name = imported_component_name.substr(1);
305       }
306       out << "#include <" << imported_package_path << "/"
307           << imported_package_version << "/" << imported_component_name
308           << ".vts.h>\n";
309     }
310   }
311   out << "\n\n";
312 }
313 
GenerateSourceIncludeFiles(Formatter & out,const ComponentSpecificationMessage &)314 void HalHidlProfilerCodeGen::GenerateSourceIncludeFiles(Formatter& out,
315     const ComponentSpecificationMessage& /*message*/) {
316   // Include the corresponding profiler header file.
317   out << "#include \"" << input_vts_file_path_ << ".h\"\n";
318   out << "\n";
319 }
320 
GenerateUsingDeclaration(Formatter & out,const ComponentSpecificationMessage & message)321 void HalHidlProfilerCodeGen::GenerateUsingDeclaration(Formatter& out,
322   const ComponentSpecificationMessage& message) {
323   std::string package_path = GetPackage(message);
324   ReplaceSubString(package_path, ".", "::");
325 
326   out << "using namespace ";
327   out << package_path << "::"
328       << GetVersionString(message.component_type_version(), true) << ";\n";
329   out << "using namespace android::hardware;\n";
330   out << "\n";
331 }
332 
GenerateMacros(Formatter & out,const ComponentSpecificationMessage &)333 void HalHidlProfilerCodeGen::GenerateMacros(Formatter& out,
334     const ComponentSpecificationMessage&) {
335   out << "#define TRACEFILEPREFIX \"/data/local/tmp\"\n";
336   out << "\n";
337 }
338 
GenerateProfierSanityCheck(Formatter & out,const ComponentSpecificationMessage & message)339 void HalHidlProfilerCodeGen::GenerateProfierSanityCheck(Formatter& out,
340   const ComponentSpecificationMessage& message) {
341   out << "if (strcmp(package, \"" << GetPackage(message) << "\") != 0) {\n";
342   out.indent();
343   out << "LOG(WARNING) << \"incorrect package.\";\n";
344   out << "return;\n";
345   out.unindent();
346   out << "}\n";
347 
348   out << "if (strcmp(version, \"" << GetPackageVersion(message)
349       << "\") != 0) {\n";
350   out.indent();
351   out << "LOG(WARNING) << \"incorrect version.\";\n";
352   out << "return;\n";
353   out.unindent();
354   out << "}\n";
355 
356   out << "if (strcmp(interface, \"" << GetComponentName(message)
357       << "\") != 0) {\n";
358   out.indent();
359   out << "LOG(WARNING) << \"incorrect interface.\";\n";
360   out << "return;\n";
361   out.unindent();
362   out << "}\n";
363   out << "\n";
364 }
365 
GenerateLocalVariableDefinition(Formatter & out,const ComponentSpecificationMessage &)366 void HalHidlProfilerCodeGen::GenerateLocalVariableDefinition(Formatter& out,
367   const ComponentSpecificationMessage&) {
368   // generate the name of file to store the trace.
369   out << "char trace_file[PATH_MAX];\n";
370   out << "sprintf(trace_file, \"%s/%s_%s\", TRACEFILEPREFIX, package, version);"
371       << "\n";
372 
373   // create and initialize the VTS profiler interface.
374   out << "VtsProfilingInterface& profiler = "
375       << "VtsProfilingInterface::getInstance(trace_file);\n";
376   out << "profiler.Init();\n";
377   out << "\n";
378 }
379 
380 }  // namespace vts
381 }  // namespace android
382