hidl-gen: accept oneway methods

b/30843534: oneway methods seem broken

Change-Id: I122fc26b4054eb0952d209e6b8c18d3a2ea446df
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/Method.cpp b/Method.cpp
index 37c71ea..0cf9bd4 100644
--- a/Method.cpp
+++ b/Method.cpp
@@ -9,10 +9,12 @@
 Method::Method(const char *name,
        std::vector<TypedVar *> *args,
        std::vector<TypedVar *> *results,
+       bool oneway,
        AnnotationVector *annotations)
     : mName(name),
       mArgs(args),
       mResults(results),
+      mOneway(oneway),
       mAnnotationsByName(annotations) {
 }
 
diff --git a/Method.h b/Method.h
index c0bfc6c..11caf3e 100644
--- a/Method.h
+++ b/Method.h
@@ -21,11 +21,13 @@
     Method(const char *name,
            std::vector<TypedVar *> *args,
            std::vector<TypedVar *> *results,
+           bool oneway,
            AnnotationVector *annotations);
 
     std::string name() const;
     const std::vector<TypedVar *> &args() const;
     const std::vector<TypedVar *> &results() const;
+    bool isOneway() const { return mOneway; }
     const AnnotationVector &annotations() const;
 
     static std::string GetSignature(const std::vector<TypedVar *> &args);
@@ -37,6 +39,7 @@
     std::string mName;
     std::vector<TypedVar *> *mArgs;
     std::vector<TypedVar *> *mResults;
+    bool mOneway;
     AnnotationVector *mAnnotationsByName;
 
     DISALLOW_COPY_AND_ASSIGN(Method);
diff --git a/generateCpp.cpp b/generateCpp.cpp
index 51e8143..1fc98bf 100644
--- a/generateCpp.cpp
+++ b/generateCpp.cpp
@@ -637,47 +637,53 @@
                       << baseName
                       << "::"
                       << upcase(method->name())
-                      << ", _hidl_data, &_hidl_reply);\n";
-
-            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
-            out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
-            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
-
-            out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
-
-            for (const auto &arg : method->results()) {
-                emitCppReaderWriter(
-                        out,
-                        "_hidl_reply",
-                        false /* parcelObjIsPointer */,
-                        arg,
-                        true /* reader */,
-                        Type::ErrorMode_Goto);
+                      << ", _hidl_data, &_hidl_reply";
+            if (method->isOneway()) {
+                out << ", ::android::hardware::IBinder::FLAG_ONEWAY";
             }
+            out << ");\n";
 
-            if (returnsValue) {
-                out << "if (_hidl_cb != nullptr) {\n";
-                out.indent();
-                out << "_hidl_cb(";
+            out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
 
-                bool first = true;
+            if (!method->isOneway()) {
+                out << "_hidl_err = _hidl_status.readFromParcel(_hidl_reply);\n";
+                out << "if (_hidl_err != ::android::OK) { goto _hidl_error; }\n\n";
+
+                out << "if (!_hidl_status.isOk()) { return _hidl_status; }\n\n";
+
                 for (const auto &arg : method->results()) {
-                    if (!first) {
-                        out << ", ";
-                    }
-
-                    if (arg->type().resultNeedsDeref()) {
-                        out << "*";
-                    }
-                    out << arg->name();
-
-                    first = false;
+                    emitCppReaderWriter(
+                            out,
+                            "_hidl_reply",
+                            false /* parcelObjIsPointer */,
+                            arg,
+                            true /* reader */,
+                            Type::ErrorMode_Goto);
                 }
 
-                out << ");\n";
-                out.unindent();
-                out << "}\n\n";
+                if (returnsValue) {
+                    out << "if (_hidl_cb != nullptr) {\n";
+                    out.indent();
+                    out << "_hidl_cb(";
+
+                    bool first = true;
+                    for (const auto &arg : method->results()) {
+                        if (!first) {
+                            out << ", ";
+                        }
+
+                        if (arg->type().resultNeedsDeref()) {
+                            out << "*";
+                        }
+                        out << arg->name();
+
+                        first = false;
+                    }
+
+                    out << ");\n";
+                    out.unindent();
+                    out << "}\n\n";
+                }
             }
 
             out.unindent();
diff --git a/hidl-gen_l.ll b/hidl-gen_l.ll
index 359c351..d2066a9 100644
--- a/hidl-gen_l.ll
+++ b/hidl-gen_l.ll
@@ -61,6 +61,7 @@
 "typedef"		{ count(yyg); return(TYPEDEF); }
 "union"			{ count(yyg); return(UNION); }
 "vec"			{ count(yyg); return(VEC); }
+"oneway"		{ count(yyg); return(ONEWAY); }
 
 "char"			{ SCALAR_TYPE(KIND_CHAR); }
 "bool"			{ SCALAR_TYPE(KIND_BOOL); }
diff --git a/hidl-gen_y.yy b/hidl-gen_y.yy
index 09bd4c7..6e1957f 100644
--- a/hidl-gen_y.yy
+++ b/hidl-gen_y.yy
@@ -52,6 +52,7 @@
 %token<str> TYPEDEF
 %token<str> UNION
 %token<str> VEC
+%token<void> ONEWAY
 
 %type<str> optIdentifier package
 %type<str> const_value
@@ -310,11 +311,15 @@
 method_declaration
     : opt_annotations IDENTIFIER '(' typed_vars ')' ';'
       {
-          $$ = new Method($2, $4, new std::vector<TypedVar *>, $1);
+          $$ = new Method($2, $4, new std::vector<TypedVar *>, false, $1);
+      }
+    | opt_annotations ONEWAY IDENTIFIER '(' typed_vars ')' ';'
+      {
+          $$ = new Method($3, $5, new std::vector<TypedVar *>, true, $1);
       }
     | opt_annotations IDENTIFIER '(' typed_vars ')' GENERATES '(' typed_vars ')' ';'
       {
-          $$ = new Method($2, $4, $8, $1);
+          $$ = new Method($2, $4, $8, false, $1);
       }
     ;