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 "VtsCompilerUtils.h"
19 #include "utils/InterfaceSpecUtil.h"
20 #include "utils/StringUtil.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(
26     Formatter& out, const VariableSpecificationMessage& val,
27     const std::string& arg_name, 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(
34     Formatter& out, const VariableSpecificationMessage&,
35     const std::string& arg_name, const std::string& arg_value) {
36   out << arg_name << "->set_type(TYPE_STRING);\n";
37   out << arg_name << "->mutable_string_value()->set_message"
38       << "(" << arg_value << ".c_str());\n";
39   out << arg_name << "->mutable_string_value()->set_length"
40       << "(" << arg_value << ".size());\n";
41 }
42 
GenerateProfilerForEnumVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)43 void HalHidlProfilerCodeGen::GenerateProfilerForEnumVariable(
44     Formatter& out, const VariableSpecificationMessage& val,
45     const std::string& arg_name, 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(
63     Formatter& out, const VariableSpecificationMessage& val,
64     const std::string& arg_name, 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   std::string index_name = GetVarString(arg_name) + "_index";
68   out << "for (int " << index_name << " = 0; " << index_name << " < (int)"
69       << arg_value << ".size(); " << index_name << "++) {\n";
70   out.indent();
71   std::string vector_element_name =
72       GetVarString(arg_name) + "_vector_" + index_name;
73   out << "auto *" << vector_element_name
74       << " __attribute__((__unused__)) = " << arg_name
75       << "->add_vector_value();\n";
76   GenerateProfilerForTypedVariable(out, val.vector_value(0),
77                                    vector_element_name,
78                                    arg_value + "[" + index_name + "]");
79   out.unindent();
80   out << "}\n";
81 }
82 
GenerateProfilerForArrayVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)83 void HalHidlProfilerCodeGen::GenerateProfilerForArrayVariable(
84     Formatter& out, const VariableSpecificationMessage& val,
85     const std::string& arg_name, const std::string& arg_value) {
86   out << arg_name << "->set_type(TYPE_ARRAY);\n";
87   out << arg_name << "->set_vector_size(" << val.vector_size() << ");\n";
88   std::string index_name = GetVarString(arg_name) + "_index";
89   out << "for (int " << index_name << " = 0; " << index_name << " < "
90       << val.vector_size() << "; " << index_name << "++) {\n";
91   out.indent();
92   std::string array_element_name =
93       GetVarString(arg_name) + "_array_" + index_name;
94   out << "auto *" << array_element_name
95       << " __attribute__((__unused__)) = " << arg_name
96       << "->add_vector_value();\n";
97   GenerateProfilerForTypedVariable(out, val.vector_value(0), array_element_name,
98                                    arg_value + "[" + index_name + "]");
99   out.unindent();
100   out << "}\n";
101 }
102 
GenerateProfilerForStructVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)103 void HalHidlProfilerCodeGen::GenerateProfilerForStructVariable(
104     Formatter& out, const VariableSpecificationMessage& val,
105     const std::string& arg_name, const std::string& arg_value) {
106   out << arg_name << "->set_type(TYPE_STRUCT);\n";
107   // For predefined type, call the corresponding profile method.
108   if (val.struct_value().size() == 0 && val.has_predefined_type()) {
109     std::string predefined_type = val.predefined_type();
110     ReplaceSubString(predefined_type, "::", "__");
111     out << "profile__" << predefined_type << "(" << arg_name << ", "
112         << arg_value << ");\n";
113   } else {
114     for (const auto& struct_field : val.struct_value()) {
115       std::string struct_field_name = arg_name + "_" + struct_field.name();
116       out << "auto *" << struct_field_name
117           << " __attribute__((__unused__)) = " << arg_name
118           << "->add_struct_value();\n";
119       GenerateProfilerForTypedVariable(out, struct_field, struct_field_name,
120                                        arg_value + "." + struct_field.name());
121     }
122   }
123 }
124 
GenerateProfilerForUnionVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)125 void HalHidlProfilerCodeGen::GenerateProfilerForUnionVariable(
126     Formatter& out, const VariableSpecificationMessage& val,
127     const std::string& arg_name, const std::string& arg_value) {
128   out << arg_name << "->set_type(TYPE_UNION);\n";
129   // For predefined type, call the corresponding profile method.
130   if (val.union_value().size() == 0 && val.has_predefined_type()) {
131     std::string predefined_type = val.predefined_type();
132     ReplaceSubString(predefined_type, "::", "__");
133     out << "profile__" << predefined_type << "(" << arg_name << ", "
134         << arg_value << ");\n";
135   } else {
136     for (const auto& union_field : val.union_value()) {
137       std::string union_field_name = arg_name + "_" + union_field.name();
138       out << "auto *" << union_field_name << " = " << arg_name
139           << "->add_union_value();\n";
140       GenerateProfilerForTypedVariable(out, union_field, union_field_name,
141                                        arg_value + "." + union_field.name());
142     }
143   }
144 }
145 
GenerateProfilerForHidlCallbackVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string &)146 void HalHidlProfilerCodeGen::GenerateProfilerForHidlCallbackVariable(
147     Formatter& out, const VariableSpecificationMessage& val,
148     const std::string& arg_name, const std::string&) {
149   out << arg_name << "->set_type(TYPE_HIDL_CALLBACK);\n";
150   out << arg_name << "->set_predefined_type(\"" << val.predefined_type()
151       << "\");\n";
152 }
153 
GenerateProfilerForHidlInterfaceVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string &)154 void HalHidlProfilerCodeGen::GenerateProfilerForHidlInterfaceVariable(
155     Formatter& out, const VariableSpecificationMessage& val,
156     const std::string& arg_name, const std::string&) {
157   out << arg_name << "->set_type(TYPE_HIDL_INTERFACE);\n";
158   out << arg_name << "->set_predefined_type(\"" << val.predefined_type()
159       << "\");\n";
160 }
161 
GenerateProfilerForMaskVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)162 void HalHidlProfilerCodeGen::GenerateProfilerForMaskVariable(
163     Formatter& out, const VariableSpecificationMessage& val,
164     const std::string& arg_name, const std::string& arg_value) {
165   out << arg_name << "->set_type(TYPE_MASK);\n";
166   out << arg_name << "->set_scalar_type(\"" << val.scalar_type() << "\");\n";
167   out << arg_name << "->mutable_scalar_value()->set_" << val.scalar_type()
168       << "(" << arg_value << ");\n";
169 }
170 
GenerateProfilerForHandleVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string & arg_value)171 void HalHidlProfilerCodeGen::GenerateProfilerForHandleVariable(
172     Formatter& out, const VariableSpecificationMessage&,
173     const std::string& arg_name, const std::string& arg_value) {
174   out << arg_name << "->set_type(TYPE_HANDLE);\n";
175   std::string handle_name = arg_name + "_h";
176   out << "auto " << handle_name << " = " << arg_value
177       << ".getNativeHandle();\n";
178   out << "if (" << handle_name << ") {\n";
179   out.indent();
180   out << arg_name << "->mutable_handle_value()->set_version(" << handle_name
181       << "->version);\n";
182   out << arg_name << "->mutable_handle_value()->set_num_ints(" << handle_name
183       << "->numInts);\n";
184   out << arg_name << "->mutable_handle_value()->set_num_fds(" << handle_name
185       << "->numFds);\n";
186   out << "for (int i = 0; i < " << handle_name << "->numInts + " << handle_name
187       << "->numFds; i++) {\n";
188   out.indent();
189   out << "if(i < " << handle_name << "->numFds) {\n";
190   out.indent();
191   out << "auto* fd_val_i = " << arg_name
192       << "->mutable_handle_value()->add_fd_val();\n";
193   out << "char filePath[PATH_MAX];\n";
194   out << "string procPath = \"/proc/self/fd/\" + to_string(" << handle_name
195       << "->data[i]);\n";
196   out << "ssize_t r = readlink(procPath.c_str(), filePath, "
197          "sizeof(filePath));\n";
198   out << "if (r == -1) {\n";
199   out.indent();
200   out << "LOG(ERROR) << \"Unable to get file path\";\n";
201   out << "continue;\n";
202   out.unindent();
203   out << "}\n";
204   out << "filePath[r] = '\\0';\n";
205   out << "fd_val_i->set_file_name(filePath);\n";
206   out << "struct stat statbuf;\n";
207   out << "fstat(" << handle_name << "->data[i], &statbuf);\n";
208   out << "fd_val_i->set_mode(statbuf.st_mode);\n";
209   out << "if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) {\n";
210   out.indent();
211   out << "fd_val_i->set_type(S_ISREG(statbuf.st_mode)? FILE_TYPE: DIR_TYPE);\n";
212   out << "int flags = fcntl(" << handle_name << "->data[i], F_GETFL);\n";
213   out << "fd_val_i->set_flags(flags);\n";
214   out.unindent();
215   out << "}\n";
216   out << "else if (S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)) {\n";
217   out.indent();
218   out << "fd_val_i->set_type(DEV_TYPE);\n";
219   out << "if (strcmp(filePath, \"/dev/ashmem\") == 0) {\n";
220   out.indent();
221   out << "int size = ashmem_get_size_region(" << handle_name << "->data[i]);\n";
222   out << "fd_val_i->mutable_memory()->set_size(size);\n";
223   out.unindent();
224   out << "}\n";
225   out.unindent();
226   out << "}\n";
227   out << "else if (S_ISFIFO(statbuf.st_mode)){\n";
228   out.indent();
229   out << "fd_val_i->set_type(PIPE_TYPE);\n";
230   out.unindent();
231   out << "}\n";
232   out << "else if (S_ISSOCK(statbuf.st_mode)) {\n";
233   out.indent();
234   out << "fd_val_i->set_type(SOCKET_TYPE);\n";
235   out.unindent();
236   out << "}\n";
237   out << "else {\n";
238   out.indent();
239   out << "fd_val_i->set_type(LINK_TYPE);\n";
240   out.unindent();
241   out << "}\n";
242   out.unindent();
243   out << "} else {\n";
244   out.indent();
245   out << arg_name << "->mutable_handle_value()->add_int_val(" << handle_name
246       << "->data[i]);\n";
247   out.unindent();
248   out << "}\n";
249   out.unindent();
250   out << "}\n";
251   out.unindent();
252   out << "} else {\n";
253   out.indent();
254   out << "LOG(WARNING) << \"null handle\";\n";
255   out << arg_name << "->mutable_handle_value()->set_hidl_handle_address(0);\n";
256   out.unindent();
257   out << "}\n";
258 }
259 
GenerateProfilerForHidlMemoryVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string & arg_value)260 void HalHidlProfilerCodeGen::GenerateProfilerForHidlMemoryVariable(
261     Formatter& out, const VariableSpecificationMessage&,
262     const std::string& arg_name, const std::string& arg_value) {
263   out << arg_name << "->set_type(TYPE_HIDL_MEMORY);\n";
264   out << arg_name << "->mutable_hidl_memory_value()->set_size"
265       << "(" << arg_value << ".size());\n";
266   // Dump the memory contents if specified in system property.
267   out << "if (property_get_bool(\"hal.instrumentation.dump.memory\", "
268          "false)){\n";
269   out.indent();
270   string mem_name = arg_name + "_mem";
271   string mem_content_name = arg_name + "_mem_char";
272   out << "sp<android::hidl::memory::V1_0::IMemory> " << mem_name
273       << " = mapMemory(" << arg_value << ");\n";
274   out << "if (" << mem_name << " == nullptr) {\n";
275   out.indent();
276   out << "LOG(WARNING) << \"Unable to map hidl_memory to IMemory object.\";\n";
277   out.unindent();
278   out << "} else {\n";
279   out.indent();
280   out << mem_name << "->read();\n";
281   out << "char* " << mem_content_name
282       << " = static_cast<char*>(static_cast<void*>(" << mem_name
283       << "->getPointer()));\n";
284   out << arg_name << "->mutable_hidl_memory_value()->set_contents(string("
285       << mem_content_name << ", " << arg_value << ".size()));\n";
286   out << mem_name << "->commit();\n";
287   out.unindent();
288   out << "}\n";
289   out.unindent();
290   out << "}\n";
291 }
292 
GenerateProfilerForPointerVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)293 void HalHidlProfilerCodeGen::GenerateProfilerForPointerVariable(
294     Formatter& out, const VariableSpecificationMessage&,
295     const std::string& arg_name, const std::string&) {
296   out << arg_name << "->set_type(TYPE_POINTER);\n";
297   // TODO(zhuoyao): figure the right way to profile pointer type.
298 }
299 
GenerateProfilerForFMQSyncVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)300 void HalHidlProfilerCodeGen::GenerateProfilerForFMQSyncVariable(
301     Formatter& out, const VariableSpecificationMessage& val,
302     const std::string& arg_name, const std::string& arg_value) {
303   out << arg_name << "->set_type(TYPE_FMQ_SYNC);\n";
304   string element_type = GetCppVariableType(val.fmq_value(0));
305   std::string queue_name = arg_name + "_q";
306   std::string temp_result_name = arg_name + "_result";
307   out << "MessageQueue<" << element_type << ", kSynchronizedReadWrite> "
308       << queue_name << "(" << arg_value << ", false);\n";
309   out << "if (" << queue_name << ".isValid()) {\n";
310   out.indent();
311   out << "for (int i = 0; i < (int)" << queue_name
312       << ".availableToRead(); i++) {\n";
313   out.indent();
314   std::string fmq_item_name = arg_name + "_item_i";
315   out << "auto *" << fmq_item_name << " = " << arg_name
316       << "->add_fmq_value();\n";
317   out << element_type << " " << temp_result_name << ";\n";
318   out << queue_name << ".read(&" << temp_result_name << ");\n";
319   out << queue_name << ".write(&" << temp_result_name << ");\n";
320   GenerateProfilerForTypedVariable(out, val.fmq_value(0), fmq_item_name,
321                                    temp_result_name);
322   out.unindent();
323   out << "}\n";
324   out.unindent();
325   out << "}\n";
326 }
327 
GenerateProfilerForFMQUnsyncVariable(Formatter & out,const VariableSpecificationMessage & val,const std::string & arg_name,const std::string & arg_value)328 void HalHidlProfilerCodeGen::GenerateProfilerForFMQUnsyncVariable(
329     Formatter& out, const VariableSpecificationMessage& val,
330     const std::string& arg_name, const std::string& arg_value) {
331   out << arg_name << "->set_type(TYPE_FMQ_UNSYNC);\n";
332   string element_type = GetCppVariableType(val.fmq_value(0));
333   std::string queue_name = arg_name + "_q";
334   std::string temp_result_name = arg_name + "_result";
335   out << "MessageQueue<" << element_type << ", kUnsynchronizedWrite> "
336       << queue_name << "(" << arg_value << ");\n";
337   out << "if (" << queue_name << ".isValid()) {\n";
338   out.indent();
339   out << "for (int i = 0; i < (int)" << queue_name
340       << ".availableToRead(); i++) {\n";
341   out.indent();
342   std::string fmq_item_name = arg_name + "_item_i";
343   out << "auto *" << fmq_item_name << " = " << arg_name
344       << "->add_fmq_value();\n";
345   out << element_type << " " << temp_result_name << ";\n";
346   out << queue_name << ".read(&" << temp_result_name << ");\n";
347   GenerateProfilerForTypedVariable(out, val.fmq_value(0), fmq_item_name,
348                                    temp_result_name);
349   out.unindent();
350   out << "}\n";
351   out.unindent();
352   out << "}\n";
353 }
354 
GenerateProfilerForSafeUnionVariable(Formatter & out,const VariableSpecificationMessage &,const std::string & arg_name,const std::string &)355 void HalHidlProfilerCodeGen::GenerateProfilerForSafeUnionVariable(
356     Formatter& out, const VariableSpecificationMessage&,
357     const std::string& arg_name, const std::string&) {
358   out << arg_name << "->set_type(TYPE_SAFE_UNION);\n";
359   out << "LOG(ERROR) << \"TYPE_SAFE_UNION is not supported yet. \";\n";
360 }
361 
GenerateProfilerForMethod(Formatter & out,const FunctionSpecificationMessage & method)362 void HalHidlProfilerCodeGen::GenerateProfilerForMethod(
363     Formatter& out, const FunctionSpecificationMessage& method) {
364   out << "FunctionSpecificationMessage msg;\n";
365   out << "msg.set_name(\"" << method.name() << "\");\n";
366   out << "if (profiling_for_args) {\n";
367   out.indent();
368   out << "if (!args) {\n";
369   out.indent();
370   out << "LOG(WARNING) << \"no argument passed\";\n";
371   out.unindent();
372   out << "} else {\n";
373   out.indent();
374   out << "switch (event) {\n";
375   out.indent();
376   out << "case details::HidlInstrumentor::CLIENT_API_ENTRY:\n";
377   out << "case details::HidlInstrumentor::SERVER_API_ENTRY:\n";
378   out << "case details::HidlInstrumentor::PASSTHROUGH_ENTRY:\n";
379   out << "{\n";
380   out.indent();
381   ComponentSpecificationMessage message;
382   out << "if ((*args).size() != " << method.arg().size() << ") {\n";
383   out.indent();
384   out << "LOG(ERROR) << \"Number of arguments does not match. expect: "
385       << method.arg().size()
386       << ", actual: \" << (*args).size() << \", method name: " << method.name()
387       << ", event type: \" << event;\n";
388   out << "break;\n";
389   out.unindent();
390   out << "}\n";
391   for (int i = 0; i < method.arg().size(); i++) {
392     const VariableSpecificationMessage arg = method.arg(i);
393     std::string arg_name = "arg_" + std::to_string(i);
394     std::string arg_value = "arg_val_" + std::to_string(i);
395     out << "auto *" << arg_name
396         << " __attribute__((__unused__)) = msg.add_arg();\n";
397     out << GetCppVariableType(arg) << " *" << arg_value
398         << " __attribute__((__unused__)) = reinterpret_cast<"
399         << GetCppVariableType(arg) << "*> ((*args)[" << i << "]);\n";
400     out << "if (" << arg_value << " != nullptr) {\n";
401     out.indent();
402     GenerateProfilerForTypedVariable(out, arg, arg_name,
403                                      "(*" + arg_value + ")");
404     out.unindent();
405     out << "} else {\n";
406     out.indent();
407     out << "LOG(WARNING) << \"argument " << i << " is null.\";\n";
408     out.unindent();
409     out << "}\n";
410   }
411   out << "break;\n";
412   out.unindent();
413   out << "}\n";
414 
415   out << "case details::HidlInstrumentor::CLIENT_API_EXIT:\n";
416   out << "case details::HidlInstrumentor::SERVER_API_EXIT:\n";
417   out << "case details::HidlInstrumentor::PASSTHROUGH_EXIT:\n";
418   out << "{\n";
419   out.indent();
420   out << "if ((*args).size() != " << method.return_type_hidl().size()
421       << ") {\n";
422   out.indent();
423   out << "LOG(ERROR) << \"Number of return values does not match. expect: "
424       << method.return_type_hidl().size()
425       << ", actual: \" << (*args).size() << \", method name: " << method.name()
426       << ", event type: \" << event;\n";
427   out << "break;\n";
428   out.unindent();
429   out << "}\n";
430   for (int i = 0; i < method.return_type_hidl().size(); i++) {
431     const VariableSpecificationMessage arg = method.return_type_hidl(i);
432     std::string result_name = "result_" + std::to_string(i);
433     std::string result_value = "result_val_" + std::to_string(i);
434     out << "auto *" << result_name
435         << " __attribute__((__unused__)) = msg.add_return_type_hidl();\n";
436     out << GetCppVariableType(arg) << " *" << result_value
437         << " __attribute__((__unused__)) = reinterpret_cast<"
438         << GetCppVariableType(arg) << "*> ((*args)[" << i << "]);\n";
439     out << "if (" << result_value << " != nullptr) {\n";
440     out.indent();
441     GenerateProfilerForTypedVariable(out, arg, result_name,
442                                      "(*" + result_value + ")");
443     out.unindent();
444     out << "} else {\n";
445     out.indent();
446     out << "LOG(WARNING) << \"return value " << i << " is null.\";\n";
447     out.unindent();
448     out << "}\n";
449   }
450   out << "break;\n";
451   out.unindent();
452   out << "}\n";
453   out << "default:\n";
454   out << "{\n";
455   out.indent();
456   out << "LOG(WARNING) << \"not supported. \";\n";
457   out << "break;\n";
458   out.unindent();
459   out << "}\n";
460   out.unindent();
461   out << "}\n";
462   out.unindent();
463   out << "}\n";
464   out.unindent();
465   out << "}\n";
466   out << "profiler.AddTraceEvent(event, package, version, interface, msg);\n";
467 }
468 
GenerateHeaderIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message)469 void HalHidlProfilerCodeGen::GenerateHeaderIncludeFiles(
470     Formatter& out, const ComponentSpecificationMessage& message) {
471   // Basic includes.
472   out << "#include <android-base/logging.h>\n";
473   out << "#include <hidl/HidlSupport.h>\n";
474   out << "#include <linux/limits.h>\n";
475   out << "#include <test/vts/proto/ComponentSpecificationMessage.pb.h>\n";
476 
477   out << "#include \"VtsProfilingInterface.h\"\n";
478   out << "\n";
479 
480   out << "// HACK: NAN is #defined by math.h which gets included by\n";
481   out << "// ComponentSpecificationMessage.pb.h, but some HALs use\n";
482   out << "// enums called NAN.  Undefine NAN to work around it.\n";
483   out << "#undef NAN\n";
484   out << "\n";
485 
486   // Include generated hal classes.
487   out << "#include <" << GetPackagePath(message) << "/" << GetVersion(message)
488       << "/" << GetComponentName(message) << ".h>\n";
489 
490   // Include imported classes.
491   for (const auto& import : message.import()) {
492     FQName import_name;
493     if (!FQName::parse(import, &import_name)) {
494       abort();
495     }
496 
497     string imported_package_name = import_name.package();
498     string imported_package_version = import_name.version();
499     string imported_component_name = import_name.name();
500     string imported_package_path = imported_package_name;
501     ReplaceSubString(imported_package_path, ".", "/");
502     out << "#include <" << imported_package_path << "/"
503         << imported_package_version << "/" << imported_component_name
504         << ".h>\n";
505     // Exclude the base hal in include list.
506     if (imported_package_name.find("android.hidl.base") == std::string::npos) {
507       if (imported_component_name[0] == 'I') {
508         imported_component_name = imported_component_name.substr(1);
509       }
510       out << "#include <" << imported_package_path << "/"
511           << imported_package_version << "/" << imported_component_name
512           << ".vts.h>\n";
513     }
514   }
515   out << "\n\n";
516 }
517 
GenerateSourceIncludeFiles(Formatter & out,const ComponentSpecificationMessage & message)518 void HalHidlProfilerCodeGen::GenerateSourceIncludeFiles(
519     Formatter& out, const ComponentSpecificationMessage& message) {
520   // Include the corresponding profiler header file.
521   out << "#include \"" << GetPackagePath(message) << "/" << GetVersion(message)
522       << "/" << GetComponentBaseName(message) << ".vts.h\"\n";
523   out << "#include <cutils/properties.h>\n";
524   if (IncludeHidlNativeType(message, TYPE_HANDLE)) {
525     out << "#include <cutils/ashmem.h>\n";
526     out << "#include <fcntl.h>\n";
527     out << "#include <sys/stat.h>\n";
528   }
529   if (IncludeHidlNativeType(message, TYPE_FMQ_SYNC) ||
530       IncludeHidlNativeType(message, TYPE_FMQ_UNSYNC)) {
531     out << "#include <fmq/MessageQueue.h>\n";
532   }
533   if (IncludeHidlNativeType(message, TYPE_HIDL_MEMORY)) {
534     out << "#include <cutils/properties.h>\n";
535     out << "#include <android/hidl/memory/1.0/IMemory.h>\n";
536     out << "#include <hidlmemory/mapping.h>\n";
537   }
538   out << "\n";
539 }
540 
GenerateUsingDeclaration(Formatter & out,const ComponentSpecificationMessage & message)541 void HalHidlProfilerCodeGen::GenerateUsingDeclaration(
542     Formatter& out, const ComponentSpecificationMessage& message) {
543   out << "using namespace ";
544   out << GetPackageNamespaceToken(message) << "::" << GetVersion(message, true)
545       << ";\n";
546   out << "using namespace android::hardware;\n";
547   out << "\n";
548 }
549 
GenerateMacros(Formatter & out,const ComponentSpecificationMessage &)550 void HalHidlProfilerCodeGen::GenerateMacros(
551     Formatter& out, const ComponentSpecificationMessage&) {
552   out << "#define TRACEFILEPREFIX \"/data/local/tmp/\"\n";
553   out << "\n";
554 }
555 
GenerateProfilerSanityCheck(Formatter & out,const ComponentSpecificationMessage & message)556 void HalHidlProfilerCodeGen::GenerateProfilerSanityCheck(
557     Formatter& out, const ComponentSpecificationMessage& message) {
558   out << "if (strcmp(package, \"" << GetPackageName(message) << "\") != 0) {\n";
559   out.indent();
560   out << "LOG(WARNING) << \"incorrect package. Expect: "
561       << GetPackageName(message) << " actual: \" << package;\n";
562   out.unindent();
563   out << "}\n";
564   out << "std::string version_str = std::string(version);\n";
565   out << "int major_version = stoi(version_str.substr(0, "
566          "version_str.find('.')));\n";
567   out << "int minor_version = stoi(version_str.substr(version_str.find('.') + "
568          "1));\n";
569   out << "if (major_version != " << GetMajorVersion(message)
570       << " || minor_version > " << GetMinorVersion(message) << ") {\n";
571   out.indent();
572   out << "LOG(WARNING) << \"incorrect version. Expect: " << GetVersion(message)
573       << " or lower (if version != x.0), actual: \" << version;\n";
574   out.unindent();
575   out << "}\n";
576 
577   out << "if (strcmp(interface, \"" << GetComponentName(message)
578       << "\") != 0) {\n";
579   out.indent();
580   out << "LOG(WARNING) << \"incorrect interface. Expect: "
581       << GetComponentName(message) << " actual: \" << interface;\n";
582   out.unindent();
583   out << "}\n";
584   out << "\n";
585 }
586 
GenerateLocalVariableDefinition(Formatter & out,const ComponentSpecificationMessage &)587 void HalHidlProfilerCodeGen::GenerateLocalVariableDefinition(
588     Formatter& out, const ComponentSpecificationMessage&) {
589   // create and initialize the VTS profiler interface.
590   out << "VtsProfilingInterface& profiler = "
591       << "VtsProfilingInterface::getInstance(TRACEFILEPREFIX);\n\n";
592   out << "bool profiling_for_args = "
593          "property_get_bool(\"hal.instrumentation.profile.args\", true);\n";
594 }
595 
596 }  // namespace vts
597 }  // namespace android
598