Home | History | Annotate | Download | only in hidl
      1 /*
      2  * Copyright (C) 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 "AST.h"
     18 
     19 #include "Coordinator.h"
     20 #include "EnumType.h"
     21 #include "Interface.h"
     22 #include "Method.h"
     23 #include "ScalarType.h"
     24 #include "Scope.h"
     25 
     26 #include <algorithm>
     27 #include <hidl-util/Formatter.h>
     28 #include <android-base/logging.h>
     29 #include <string>
     30 #include <vector>
     31 #include <set>
     32 
     33 namespace android {
     34 
     35 status_t AST::generateCppImpl(const std::string &outputPath) const {
     36     status_t err = generateStubImplHeader(outputPath);
     37 
     38     if (err == OK) {
     39         err = generateStubImplSource(outputPath);
     40     }
     41 
     42     return err;
     43 }
     44 
     45 void AST::generateFetchSymbol(Formatter &out, const std::string& ifaceName) const {
     46     out << "HIDL_FETCH_" << ifaceName;
     47 }
     48 
     49 status_t AST::generateStubImplMethod(Formatter &out,
     50                                      const std::string &className,
     51                                      const Method *method) const {
     52 
     53     // ignore HIDL reserved methods -- implemented in IFoo already.
     54     if (method->isHidlReserved()) {
     55         return OK;
     56     }
     57 
     58     method->generateCppSignature(out, className, false /* specifyNamespaces */);
     59 
     60     out << " {\n";
     61 
     62     out.indent();
     63     out << "// TODO implement\n";
     64 
     65     const TypedVar *elidedReturn = method->canElideCallback();
     66 
     67     if (elidedReturn == nullptr) {
     68         out << "return Void();\n";
     69     } else {
     70         out << "return "
     71             << elidedReturn->type().getCppResultType()
     72             << " {};\n";
     73     }
     74 
     75     out.unindent();
     76 
     77     out << "}\n\n";
     78 
     79     return OK;
     80 }
     81 
     82 status_t AST::generateStubImplHeader(const std::string &outputPath) const {
     83     if (!AST::isInterface()) {
     84         // types.hal does not get a stub header.
     85         return OK;
     86     }
     87 
     88     const Interface* iface = mRootScope.getInterface();
     89     const std::string baseName = iface->getBaseName();
     90 
     91     std::string path = outputPath;
     92     path.append(baseName);
     93     path.append(".h");
     94 
     95     CHECK(Coordinator::MakeParentHierarchy(path));
     96     FILE *file = fopen(path.c_str(), "w");
     97 
     98     if (file == NULL) {
     99         return -errno;
    100     }
    101 
    102     Formatter out(file);
    103 
    104     const std::string guard = makeHeaderGuard(baseName, false /* indicateGenerated */);
    105 
    106     out << "#ifndef " << guard << "\n";
    107     out << "#define " << guard << "\n\n";
    108 
    109     generateCppPackageInclude(out, mPackage, iface->localName());
    110 
    111     out << "#include <hidl/MQDescriptor.h>\n";
    112     out << "#include <hidl/Status.h>\n\n";
    113 
    114     enterLeaveNamespace(out, true /* enter */);
    115     out << "namespace implementation {\n\n";
    116 
    117     out << "using ::android::hardware::hidl_array;\n";
    118     out << "using ::android::hardware::hidl_memory;\n";
    119     out << "using ::android::hardware::hidl_string;\n";
    120     out << "using ::android::hardware::hidl_vec;\n";
    121     out << "using ::android::hardware::Return;\n";
    122     out << "using ::android::hardware::Void;\n";
    123     out << "using ::android::sp;\n";
    124 
    125     out << "\n";
    126 
    127     out << "struct "
    128         << baseName
    129         << " : public "
    130         << iface->localName()
    131         << " {\n";
    132 
    133     out.indent();
    134 
    135     status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
    136         // ignore HIDL reserved methods -- implemented in IFoo already.
    137         if (method->isHidlReserved()) {
    138             return OK;
    139         }
    140         method->generateCppSignature(out, "" /* className */,
    141                 false /* specifyNamespaces */);
    142         out << " override;\n";
    143         return OK;
    144     });
    145 
    146     if (err != OK) {
    147         return err;
    148     }
    149 
    150     out.unindent();
    151 
    152     out << "};\n\n";
    153 
    154     out << "// FIXME: most likely delete, this is only for passthrough implementations\n"
    155         << "// extern \"C\" "
    156         << iface->localName()
    157         << "* ";
    158     generateFetchSymbol(out, iface->localName());
    159     out << "(const char* name);\n\n";
    160 
    161     out << "}  // namespace implementation\n";
    162     enterLeaveNamespace(out, false /* leave */);
    163 
    164     out << "\n#endif  // " << guard << "\n";
    165 
    166     return OK;
    167 }
    168 
    169 status_t AST::generateStubImplSource(const std::string &outputPath) const {
    170     if (!AST::isInterface()) {
    171         // types.hal does not get a stub header.
    172         return OK;
    173     }
    174 
    175     const Interface* iface = mRootScope.getInterface();
    176     const std::string baseName = iface->getBaseName();
    177 
    178     std::string path = outputPath;
    179     path.append(baseName);
    180     path.append(".cpp");
    181 
    182     CHECK(Coordinator::MakeParentHierarchy(path));
    183     FILE *file = fopen(path.c_str(), "w");
    184 
    185     if (file == NULL) {
    186         return -errno;
    187     }
    188 
    189     Formatter out(file);
    190 
    191     out << "#include \"" << baseName << ".h\"\n\n";
    192 
    193     enterLeaveNamespace(out, true /* enter */);
    194     out << "namespace implementation {\n\n";
    195 
    196     status_t err = generateMethods(out, [&](const Method *method, const Interface *) {
    197         return generateStubImplMethod(out, baseName, method);
    198     });
    199 
    200     if (err != OK) {
    201         return err;
    202     }
    203 
    204     out.setLinePrefix("//");
    205     out << iface->localName()
    206         << "* ";
    207     generateFetchSymbol(out, iface->localName());
    208     out << "(const char* /* name */) {\n";
    209     out.indent();
    210     out << "return new " << baseName << "();\n";
    211     out.unindent();
    212     out << "}\n\n";
    213     out.unsetLinePrefix();
    214 
    215     out << "}  // namespace implementation\n";
    216     enterLeaveNamespace(out, false /* leave */);
    217 
    218     return OK;
    219 }
    220 
    221 }  // namespace android
    222