Home | History | Annotate | Download | only in profiler
      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 
     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 
     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 
     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 
     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   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
     71       << " __attribute__((__unused__)) = " << arg_name
     72       << "->add_vector_value();\n";
     73   GenerateProfilerForTypedVariable(out, val.vector_value(0),
     74                                    vector_element_name, arg_value + "[i]");
     75   out.unindent();
     76   out << "}\n";
     77 }
     78 
     79 void HalHidlProfilerCodeGen::GenerateProfilerForArrayVariable(
     80     Formatter& out, const VariableSpecificationMessage& val,
     81     const std::string& arg_name, const std::string& arg_value) {
     82   out << arg_name << "->set_type(TYPE_ARRAY);\n";
     83   out << arg_name << "->set_vector_size(" << val.vector_size() << ");\n";
     84   out << "for (int i = 0; i < " << val.vector_size() << "; i++) {\n";
     85   out.indent();
     86   std::string array_element_name = arg_name + "_array_i";
     87   out << "auto *" << array_element_name
     88       << " __attribute__((__unused__)) = " << arg_name
     89       << "->add_vector_value();\n";
     90   GenerateProfilerForTypedVariable(out, val.vector_value(0), array_element_name,
     91                                    arg_value + "[i]");
     92   out.unindent();
     93   out << "}\n";
     94 }
     95 
     96 void HalHidlProfilerCodeGen::GenerateProfilerForStructVariable(
     97     Formatter& out, const VariableSpecificationMessage& val,
     98     const std::string& arg_name, const std::string& arg_value) {
     99   out << arg_name << "->set_type(TYPE_STRUCT);\n";
    100   // For predefined type, call the corresponding profile method.
    101   if (val.struct_value().size() == 0 && val.has_predefined_type()) {
    102     std::string predefined_type = val.predefined_type();
    103     ReplaceSubString(predefined_type, "::", "__");
    104     out << "profile__" << predefined_type << "(" << arg_name << ", "
    105         << arg_value << ");\n";
    106   } else {
    107     for (const auto struct_field : val.struct_value()) {
    108       std::string struct_field_name = arg_name + "_" + struct_field.name();
    109       out << "auto *" << struct_field_name
    110           << " __attribute__((__unused__)) = " << arg_name
    111           << "->add_struct_value();\n";
    112       GenerateProfilerForTypedVariable(out, struct_field, struct_field_name,
    113                                        arg_value + "." + struct_field.name());
    114     }
    115   }
    116 }
    117 
    118 void HalHidlProfilerCodeGen::GenerateProfilerForUnionVariable(
    119     Formatter& out, const VariableSpecificationMessage& val,
    120     const std::string& arg_name, const std::string& arg_value) {
    121   out << arg_name << "->set_type(TYPE_UNION);\n";
    122   // For predefined type, call the corresponding profile method.
    123   if (val.union_value().size() == 0 && val.has_predefined_type()) {
    124     std::string predefined_type = val.predefined_type();
    125     ReplaceSubString(predefined_type, "::", "__");
    126     out << "profile__" << predefined_type << "(" << arg_name << ", "
    127         << arg_value << ");\n";
    128   } else {
    129     for (const auto union_field : val.union_value()) {
    130       std::string union_field_name = arg_name + "_" + union_field.name();
    131       out << "auto *" << union_field_name << " = " << arg_name
    132           << "->add_union_value();\n";
    133       GenerateProfilerForTypedVariable(out, union_field, union_field_name,
    134                                        arg_value + "." + union_field.name());
    135     }
    136   }
    137 }
    138 
    139 void HalHidlProfilerCodeGen::GenerateProfilerForHidlCallbackVariable(
    140     Formatter& out, const VariableSpecificationMessage& val,
    141     const std::string& arg_name, const std::string&) {
    142   out << arg_name << "->set_type(TYPE_HIDL_CALLBACK);\n";
    143   out << arg_name << "->set_predefined_type(\"" << val.predefined_type()
    144       << "\");\n";
    145 }
    146 
    147 void HalHidlProfilerCodeGen::GenerateProfilerForHidlInterfaceVariable(
    148     Formatter& out, const VariableSpecificationMessage& val,
    149     const std::string& arg_name, const std::string&) {
    150   out << arg_name << "->set_type(TYPE_HIDL_INTERFACE);\n";
    151   out << arg_name << "->set_predefined_type(\"" << val.predefined_type()
    152       << "\");\n";
    153 }
    154 
    155 void HalHidlProfilerCodeGen::GenerateProfilerForMaskVariable(
    156     Formatter& out, const VariableSpecificationMessage& val,
    157     const std::string& arg_name, const std::string& arg_value) {
    158   out << arg_name << "->set_type(TYPE_MASK);\n";
    159   out << arg_name << "->set_scalar_type(\"" << val.scalar_type() << "\");\n";
    160   out << arg_name << "->mutable_scalar_value()->set_" << val.scalar_type()
    161       << "(" << arg_value << ");\n";
    162 }
    163 
    164 void HalHidlProfilerCodeGen::GenerateProfilerForHandleVariable(
    165     Formatter& out, const VariableSpecificationMessage&,
    166     const std::string& arg_name, const std::string& arg_value) {
    167   out << arg_name << "->set_type(TYPE_HANDLE);\n";
    168   std::string handle_name = arg_name + "_h";
    169   out << "auto " << handle_name << " = " << arg_value
    170       << ".getNativeHandle();\n";
    171   out << "if (!" << handle_name << ") {\n";
    172   out.indent();
    173   out << "LOG(WARNING) << \"null handle\";\n";
    174   out << "return;\n";
    175   out.unindent();
    176   out << "}\n";
    177   out << arg_name << "->mutable_handle_value()->set_version(" << handle_name
    178       << "->version);\n";
    179   out << arg_name << "->mutable_handle_value()->set_num_ints(" << handle_name
    180       << "->numInts);\n";
    181   out << arg_name << "->mutable_handle_value()->set_num_fds(" << handle_name
    182       << "->numFds);\n";
    183   out << "for (int i = 0; i < " << handle_name << "->numInts + " << handle_name
    184       << "->numFds; i++) {\n";
    185   out.indent();
    186   out << "if(i < " << handle_name << "->numFds) {\n";
    187   out.indent();
    188   out << "auto* fd_val_i = " << arg_name
    189       << "->mutable_handle_value()->add_fd_val();\n";
    190   out << "char filePath[PATH_MAX];\n";
    191   out << "string procPath = \"/proc/self/fd/\" + to_string(" << handle_name
    192       << "->data[i]);\n";
    193   out << "ssize_t r = readlink(procPath.c_str(), filePath, "
    194          "sizeof(filePath));\n";
    195   out << "if (r == -1) {\n";
    196   out.indent();
    197   out << "LOG(ERROR) << \"Unable to get file path\";\n";
    198   out << "continue;\n";
    199   out.unindent();
    200   out << "}\n";
    201   out << "filePath[r] = '\\0';\n";
    202   out << "fd_val_i->set_file_name(filePath);\n";
    203   out << "struct stat statbuf;\n";
    204   out << "fstat(" << handle_name << "->data[i], &statbuf);\n";
    205   out << "fd_val_i->set_mode(statbuf.st_mode);\n";
    206   out << "if(S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)){\n";
    207   out.indent();
    208   out << "fd_val_i->set_type(S_ISREG(statbuf.st_mode)? FILE_TYPE: DIR_TYPE);\n";
    209   out << "int flags = fcntl(" << handle_name << "->data[i], F_GETFL);\n";
    210   out << "fd_val_i->set_flags(flags);\n";
    211   out.unindent();
    212   out << "}\n";
    213   out << "else if(S_ISCHR(statbuf.st_mode) || S_ISBLK(statbuf.st_mode)){\n";
    214   out.indent();
    215   out << "fd_val_i->set_type(DEV_TYPE);\n";
    216   out << "if(strcmp(filePath, \"/dev/ashmem\") == 0) {\n";
    217   out.indent();
    218   out << "int size = ashmem_get_size_region(" << handle_name << "->data[i]);\n";
    219   out << "fd_val_i->mutable_memory()->set_size(size);\n";
    220   out.unindent();
    221   out << "}\n";
    222   out.unindent();
    223   out << "}\n";
    224   out << "else if(S_ISFIFO(statbuf.st_mode)){\n";
    225   out.indent();
    226   out << "fd_val_i->set_type(PIPE_TYPE);\n";
    227   out.unindent();
    228   out << "}\n";
    229   out << "else if(S_ISSOCK(statbuf.st_mode)){\n";
    230   out.indent();
    231   out << "fd_val_i->set_type(SOCKET_TYPE);\n";
    232   out.unindent();
    233   out << "}\n";
    234   out << "else {\n";
    235   out.indent();
    236   out << "fd_val_i->set_type(LINK_TYPE);\n";
    237   out.unindent();
    238   out << "}\n";
    239   out.unindent();
    240   out << "} else {\n";
    241   out.indent();
    242   out << arg_name << "->mutable_handle_value()->add_int_val(" << handle_name
    243       << "->data[i]);\n";
    244   out.unindent();
    245   out << "}\n";
    246   out.unindent();
    247   out << "}\n";
    248 }
    249 
    250 void HalHidlProfilerCodeGen::GenerateProfilerForHidlMemoryVariable(
    251     Formatter& out, const VariableSpecificationMessage&,
    252     const std::string& arg_name, const std::string& arg_value) {
    253   out << arg_name << "->set_type(TYPE_HIDL_MEMORY);\n";
    254   out << arg_name << "->mutable_hidl_memory_value()->set_size"
    255       << "(" << arg_value << ".size());\n";
    256   // TODO(zhuoyao): dump the memory contents as well.
    257 }
    258 
    259 void HalHidlProfilerCodeGen::GenerateProfilerForPointerVariable(
    260     Formatter& out, const VariableSpecificationMessage&,
    261     const std::string& arg_name, const std::string&) {
    262   out << arg_name << "->set_type(TYPE_POINTER);\n";
    263   // TODO(zhuoyao): figure the right way to profile pointer type.
    264 }
    265 
    266 void HalHidlProfilerCodeGen::GenerateProfilerForFMQSyncVariable(
    267     Formatter& out, const VariableSpecificationMessage& val,
    268     const std::string& arg_name, const std::string& arg_value) {
    269   out << arg_name << "->set_type(TYPE_FMQ_SYNC);\n";
    270   string element_type = GetCppVariableType(val.fmq_value(0), nullptr);
    271   std::string queue_name = arg_name + "_q";
    272   std::string temp_result_name = arg_name + "_result";
    273   out << "MessageQueue<" << element_type << ", kSynchronizedReadWrite> "
    274       << queue_name << "(" << arg_value << ", false);\n";
    275   out << "for (int i = 0; i < (int)" << queue_name
    276       << ".availableToRead(); i++) {\n";
    277   out.indent();
    278   std::string fmq_item_name = arg_name + "_item_i";
    279   out << "auto *" << fmq_item_name << " = " << arg_name
    280       << "->add_fmq_value();\n";
    281   out << element_type << " " << temp_result_name << ";\n";
    282   out << queue_name << ".read(&" << temp_result_name << ");\n";
    283   out << queue_name << ".write(&" << temp_result_name << ");\n";
    284   GenerateProfilerForTypedVariable(out, val.fmq_value(0), fmq_item_name,
    285                                    temp_result_name);
    286   out.unindent();
    287   out << "}\n";
    288 }
    289 
    290 void HalHidlProfilerCodeGen::GenerateProfilerForFMQUnsyncVariable(
    291     Formatter& out, const VariableSpecificationMessage& val,
    292     const std::string& arg_name, const std::string& arg_value) {
    293   out << arg_name << "->set_type(TYPE_FMQ_UNSYNC);\n";
    294   string element_type = GetCppVariableType(val.fmq_value(0), nullptr);
    295   std::string queue_name = arg_name + "_q";
    296   std::string temp_result_name = arg_name + "_result";
    297   out << "MessageQueue<" << element_type << ", kUnsynchronizedWrite> "
    298       << queue_name << "(" << arg_value << ");\n";
    299   out << "for (int i = 0; i < (int)" << queue_name
    300       << ".availableToRead(); i++) {\n";
    301   out.indent();
    302   std::string fmq_item_name = arg_name + "_item_i";
    303   out << "auto *" << fmq_item_name << " = " << arg_name
    304       << "->add_fmq_value();\n";
    305   out << element_type << " " << temp_result_name << ";\n";
    306   out << queue_name << ".read(&" << temp_result_name << ");\n";
    307   GenerateProfilerForTypedVariable(out, val.fmq_value(0), fmq_item_name,
    308                                    temp_result_name);
    309   out.unindent();
    310   out << "}\n";
    311 }
    312 
    313 void HalHidlProfilerCodeGen::GenerateProfilerForMethod(
    314     Formatter& out, const FunctionSpecificationMessage& method) {
    315   out << "FunctionSpecificationMessage msg;\n";
    316   out << "msg.set_name(\"" << method.name() << "\");\n";
    317   out << "if (!args) {\n";
    318   out.indent();
    319   out << "LOG(WARNING) << \"no argument passed\";\n";
    320   out.unindent();
    321   out << "} else {\n";
    322   out.indent();
    323   out << "switch (event) {\n";
    324   out.indent();
    325   // TODO(b/32141398): Support profiling in passthrough mode.
    326   out << "case details::HidlInstrumentor::CLIENT_API_ENTRY:\n";
    327   out << "case details::HidlInstrumentor::SERVER_API_ENTRY:\n";
    328   out << "case details::HidlInstrumentor::PASSTHROUGH_ENTRY:\n";
    329   out << "{\n";
    330   out.indent();
    331   ComponentSpecificationMessage message;
    332   out << "if ((*args).size() != " << method.arg().size() << ") {\n";
    333   out.indent();
    334   out << "LOG(ERROR) << \"Number of arguments does not match. expect: "
    335       << method.arg().size()
    336       << ", actual: \" << (*args).size() << \", method name: " << method.name()
    337       << ", event type: \" << event;\n";
    338   out << "break;\n";
    339   out.unindent();
    340   out << "}\n";
    341   for (int i = 0; i < method.arg().size(); i++) {
    342     const VariableSpecificationMessage arg = method.arg(i);
    343     std::string arg_name = "arg_" + std::to_string(i);
    344     std::string arg_value = "arg_val_" + std::to_string(i);
    345     out << "auto *" << arg_name
    346         << " __attribute__((__unused__)) = msg.add_arg();\n";
    347     out << GetCppVariableType(arg, &message) << " *" << arg_value
    348         << " __attribute__((__unused__)) = reinterpret_cast<"
    349         << GetCppVariableType(arg, &message) << "*> ((*args)[" << i << "]);\n";
    350     GenerateProfilerForTypedVariable(out, arg, arg_name,
    351                                      "(*" + arg_value + ")");
    352   }
    353   out << "break;\n";
    354   out.unindent();
    355   out << "}\n";
    356 
    357   out << "case details::HidlInstrumentor::CLIENT_API_EXIT:\n";
    358   out << "case details::HidlInstrumentor::SERVER_API_EXIT:\n";
    359   out << "case details::HidlInstrumentor::PASSTHROUGH_EXIT:\n";
    360   out << "{\n";
    361   out.indent();
    362   out << "if ((*args).size() != " << method.return_type_hidl().size()
    363       << ") {\n";
    364   out.indent();
    365   out << "LOG(ERROR) << \"Number of return values does not match. expect: "
    366       << method.return_type_hidl().size()
    367       << ", actual: \" << (*args).size() << \", method name: " << method.name()
    368       << ", event type: \" << event;\n";
    369   out << "break;\n";
    370   out.unindent();
    371   out << "}\n";
    372   for (int i = 0; i < method.return_type_hidl().size(); i++) {
    373     const VariableSpecificationMessage arg = method.return_type_hidl(i);
    374     std::string result_name = "result_" + std::to_string(i);
    375     std::string result_value = "result_val_" + std::to_string(i);
    376     out << "auto *" << result_name
    377         << " __attribute__((__unused__)) = msg.add_return_type_hidl();\n";
    378     out << GetCppVariableType(arg, &message) << " *" << result_value
    379         << " __attribute__((__unused__)) = reinterpret_cast<"
    380         << GetCppVariableType(arg, &message) << "*> ((*args)[" << i << "]);\n";
    381     GenerateProfilerForTypedVariable(out, arg, result_name,
    382                                      "(*" + result_value + ")");
    383   }
    384   out << "break;\n";
    385   out.unindent();
    386   out << "}\n";
    387   out << "default:\n";
    388   out << "{\n";
    389   out.indent();
    390   out << "LOG(WARNING) << \"not supported. \";\n";
    391   out << "break;\n";
    392   out.unindent();
    393   out << "}\n";
    394   out.unindent();
    395   out << "}\n";
    396   out.unindent();
    397   out << "}\n";
    398   out << "profiler.AddTraceEvent(event, package, version, interface, msg);\n";
    399 }
    400 
    401 void HalHidlProfilerCodeGen::GenerateHeaderIncludeFiles(
    402     Formatter& out, const ComponentSpecificationMessage& message) {
    403   // Basic includes.
    404   out << "#include <android-base/logging.h>\n";
    405   out << "#include <hidl/HidlSupport.h>\n";
    406   out << "#include <linux/limits.h>\n";
    407   out << "#include <test/vts/proto/ComponentSpecificationMessage.pb.h>\n";
    408   out << "#include \"VtsProfilingInterface.h\"\n";
    409   out << "\n";
    410 
    411   // Include generated hal classes.
    412   out << "#include <" << GetPackagePath(message) << "/" << GetVersion(message)
    413       << "/" << GetComponentName(message) << ".h>\n";
    414 
    415   // Include imported classes.
    416   for (const auto& import : message.import()) {
    417     FQName import_name = FQName(import);
    418     string imported_package_name = import_name.package();
    419     string imported_package_version = import_name.version();
    420     string imported_component_name = import_name.name();
    421     string imported_package_path = imported_package_name;
    422     ReplaceSubString(imported_package_path, ".", "/");
    423     out << "#include <" << imported_package_path << "/"
    424         << imported_package_version << "/" << imported_component_name
    425         << ".h>\n";
    426     if (imported_package_name.find("android.hardware") != std::string::npos) {
    427       if (imported_component_name[0] == 'I') {
    428         imported_component_name = imported_component_name.substr(1);
    429       }
    430       out << "#include <" << imported_package_path << "/"
    431           << imported_package_version << "/" << imported_component_name
    432           << ".vts.h>\n";
    433     }
    434   }
    435   out << "\n\n";
    436 }
    437 
    438 void HalHidlProfilerCodeGen::GenerateSourceIncludeFiles(
    439     Formatter& out, const ComponentSpecificationMessage& message) {
    440   // Include the corresponding profiler header file.
    441   out << "#include \"" << GetPackagePath(message) << "/" << GetVersion(message)
    442       << "/" << GetComponentBaseName(message) << ".vts.h\"\n";
    443   out << "#include <cutils/ashmem.h>\n";
    444   out << "#include <fcntl.h>\n";
    445   out << "#include <fmq/MessageQueue.h>\n";
    446   out << "#include <sys/stat.h>\n";
    447   out << "\n";
    448 }
    449 
    450 void HalHidlProfilerCodeGen::GenerateUsingDeclaration(
    451     Formatter& out, const ComponentSpecificationMessage& message) {
    452   out << "using namespace ";
    453   out << GetPackageNamespaceToken(message) << "::" << GetVersion(message, true)
    454       << ";\n";
    455   out << "using namespace android::hardware;\n";
    456   out << "\n";
    457 }
    458 
    459 void HalHidlProfilerCodeGen::GenerateMacros(
    460     Formatter& out, const ComponentSpecificationMessage&) {
    461   out << "#define TRACEFILEPREFIX \"/data/local/tmp\"\n";
    462   out << "\n";
    463 }
    464 
    465 void HalHidlProfilerCodeGen::GenerateProfilerSanityCheck(
    466     Formatter& out, const ComponentSpecificationMessage& message) {
    467   out << "if (strcmp(package, \"" << GetPackageName(message) << "\") != 0) {\n";
    468   out.indent();
    469   out << "LOG(WARNING) << \"incorrect package.\";\n";
    470   out << "return;\n";
    471   out.unindent();
    472   out << "}\n";
    473 
    474   out << "if (strcmp(version, \"" << GetVersion(message) << "\") != 0) {\n";
    475   out.indent();
    476   out << "LOG(WARNING) << \"incorrect version.\";\n";
    477   out << "return;\n";
    478   out.unindent();
    479   out << "}\n";
    480 
    481   out << "if (strcmp(interface, \"" << GetComponentName(message)
    482       << "\") != 0) {\n";
    483   out.indent();
    484   out << "LOG(WARNING) << \"incorrect interface.\";\n";
    485   out << "return;\n";
    486   out.unindent();
    487   out << "}\n";
    488   out << "\n";
    489 }
    490 
    491 void HalHidlProfilerCodeGen::GenerateLocalVariableDefinition(
    492     Formatter& out, const ComponentSpecificationMessage&) {
    493   // generate the name of file to store the trace.
    494   out << "char trace_file[PATH_MAX];\n";
    495   out << "sprintf(trace_file, \"%s/%s_%s\", TRACEFILEPREFIX, package, version);"
    496       << "\n";
    497 
    498   // create and initialize the VTS profiler interface.
    499   out << "VtsProfilingInterface& profiler = "
    500       << "VtsProfilingInterface::getInstance(trace_file);\n";
    501   out << "profiler.Init();\n";
    502   out << "\n";
    503 }
    504 
    505 }  // namespace vts
    506 }  // namespace android
    507