aidl: All flattenable types now must also be parcelable.

This is more a limitation of the grammar than anything else triggering laziness on my part.

Change-Id: I73b21022388c54e516d7e1cddfd4895d351cd194
diff --git a/tools/aidl/Type.cpp b/tools/aidl/Type.cpp
index 8161ef3..b84b3c4 100755
--- a/tools/aidl/Type.cpp
+++ b/tools/aidl/Type.cpp
@@ -123,7 +123,7 @@
     RPC_DATA_TYPE = new RpcDataType();
     NAMES.Add(RPC_DATA_TYPE);
 
-    RPC_ERROR_TYPE = new ParcelableType("com.android.athome.rpc", "RpcError",
+    RPC_ERROR_TYPE = new UserDataType("com.android.athome.rpc", "RpcError",
                                     true, __FILE__, __LINE__);
     NAMES.Add(RPC_ERROR_TYPE);
 
@@ -896,29 +896,22 @@
 
 // ================================================================
 
-ParcelableType::ParcelableType(const string& package, const string& name,
-                        bool builtIn, const string& declFile, int declLine)
-    :Type(package, name, builtIn ? BUILT_IN : PARCELABLE, true, false, true,
-            declFile, declLine)
-{
-}
-
-ParcelableType::ParcelableType(const string& package, const string& name,
-                            bool builtIn, bool canWriteToRpcData,
-                            const string& declFile, int declLine)
-    :Type(package, name, builtIn ? BUILT_IN : PARCELABLE, true, canWriteToRpcData, true,
-            declFile, declLine)
+UserDataType::UserDataType(const string& package, const string& name,
+                        bool builtIn, bool canWriteToParcel, bool canWriteToRpcData,
+                        const string& declFile, int declLine)
+    :Type(package, name, builtIn ? BUILT_IN : USERDATA, canWriteToParcel, canWriteToRpcData,
+            true, declFile, declLine)
 {
 }
 
 string
-ParcelableType::CreatorName() const
+UserDataType::CreatorName() const
 {
     return QualifiedName() + ".CREATOR";
 }
 
 void
-ParcelableType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+UserDataType::WriteToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
 {
     // if (v != null) {
     //     parcel.writeInt(1);
@@ -941,7 +934,7 @@
 }
 
 void
-ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
+UserDataType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     // if (0 != parcel.readInt()) {
     //     v = CLASS.CREATOR.createFromParcel(parcel)
@@ -962,7 +955,7 @@
 }
 
 void
-ParcelableType::ReadFromParcel(StatementBlock* addTo, Variable* v,
+UserDataType::ReadFromParcel(StatementBlock* addTo, Variable* v,
                     Variable* parcel, Variable**)
 {
     // TODO: really, we don't need to have this extra check, but we
@@ -978,20 +971,20 @@
 }
 
 bool
-ParcelableType::CanBeArray() const
+UserDataType::CanBeArray() const
 {
     return true;
 }
 
 void
-ParcelableType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
+UserDataType::WriteArrayToParcel(StatementBlock* addTo, Variable* v, Variable* parcel, int flags)
 {
     addTo->Add(new MethodCall(parcel, "writeTypedArray", 2, v,
                 BuildWriteToParcelFlags(flags)));
 }
 
 void
-ParcelableType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
+UserDataType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
                             Variable* parcel, Variable**)
 {
     string creator = v->type->QualifiedName() + ".CREATOR";
@@ -1000,30 +993,15 @@
 }
 
 void
-ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
+UserDataType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     string creator = v->type->QualifiedName() + ".CREATOR";
     addTo->Add(new MethodCall(parcel, "readTypedArray", 2,
                     v, new LiteralExpression(creator)));
 }
 
-// ================================================================
-
-FlattenableType::FlattenableType(const string& package, const string& name,
-                        bool builtIn, const string& declFile, int declLine)
-    :Type(package, name, builtIn ? BUILT_IN : PARCELABLE, false, true, true,
-            declFile, declLine)
-{
-}
-
-string
-FlattenableType::CreatorName() const
-{
-    return QualifiedName() + ".CREATOR";
-}
-
 void
-FlattenableType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v,
+UserDataType::WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v,
                                     Variable* data, int flags)
 {
     // if (v != null) {
@@ -1042,7 +1020,7 @@
 }
 
 void
-FlattenableType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v,
+UserDataType::CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v,
                                     Variable* data, Variable** cl)
 {
     // RpcData _obj_XX = data.getRpcData(k);
@@ -1070,12 +1048,6 @@
     block->Add(ifpart);
 }
 
-bool
-FlattenableType::CanBeArray() const
-{
-    return true;
-}
-
 // ================================================================
 
 InterfaceType::InterfaceType(const string& package, const string& name,
@@ -1266,7 +1238,7 @@
 // ================================================================
 
 RpcDataType::RpcDataType()
-    :ParcelableType("com.android.athome.rpc", "RpcData", true, true)
+    :UserDataType("com.android.athome.rpc", "RpcData", true, true, true)
 {
 }
 
diff --git a/tools/aidl/Type.h b/tools/aidl/Type.h
index a144448..f2f3f21 100755
--- a/tools/aidl/Type.h
+++ b/tools/aidl/Type.h
@@ -13,7 +13,7 @@
     // kinds
     enum {
         BUILT_IN,
-        PARCELABLE,
+        USERDATA,
         INTERFACE,
         GENERATED
     };
@@ -350,13 +350,11 @@
                                     Variable* data, Variable** cl);
 };
 
-class ParcelableType : public Type
+class UserDataType : public Type
 {
 public:
-                    ParcelableType(const string& package, const string& name,
-                            bool builtIn, const string& declFile, int declLine);
-                    ParcelableType(const string& package, const string& name,
-                            bool builtIn, bool canWriteToRpcData,
+                    UserDataType(const string& package, const string& name,
+                            bool builtIn, bool canWriteToParcel, bool canWriteToRpcData,
                             const string& declFile = "", int declLine = -1);
 
     virtual string  CreatorName() const;
@@ -376,22 +374,11 @@
                                     Variable* parcel, Variable** cl);
     virtual void    ReadArrayFromParcel(StatementBlock* addTo, Variable* v,
                                     Variable* parcel, Variable** cl);
-};
-
-class FlattenableType : public Type
-{
-public:
-                    FlattenableType(const string& package, const string& name,
-                            bool builtIn, const string& declFile, int declLine);
-
-    virtual string  CreatorName() const;
 
     virtual void    WriteToRpcData(StatementBlock* addTo, Expression* k, Variable* v,
                                     Variable* data, int flags);
     virtual void    CreateFromRpcData(StatementBlock* addTo, Expression* k, Variable* v,
                                     Variable* data, Variable** cl);
-
-    virtual bool    CanBeArray() const;
 };
 
 class InterfaceType : public Type
@@ -437,7 +424,7 @@
     vector<Type*> m_args;
 };
 
-class RpcDataType : public ParcelableType
+class RpcDataType : public UserDataType
 {
 public:
                     RpcDataType();
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index ab9a245..e5689b9 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -50,13 +50,14 @@
             }
             printf("}\n");
         }
-        else if (d->item_type == PARCELABLE_TYPE) {
-            parcelable_type* b = (parcelable_type*)d;
-            printf("parcelable %s %s;\n", b->package, b->name.data);
-        }
-        else if (d->item_type == FLATTENABLE_TYPE) {
-            parcelable_type* b = (parcelable_type*)d;
-            printf("flattenable %s %s;\n", b->package, b->name.data);
+        else if (d->item_type == USER_DATA_TYPE) {
+            user_data_type* b = (user_data_type*)d;
+            if ((b->flattening_methods & PARCELABLE_DATA) != 0) {
+                printf("parcelable %s %s;\n", b->package, b->name.data);
+            }
+            if ((b->flattening_methods & RPC_DATA) != 0) {
+                printf("flattenable %s %s;\n", b->package, b->name.data);
+            }
         }
         else {
             printf("UNKNOWN d=0x%08lx d->item_type=%d\n", (long)d, d->item_type);
@@ -242,9 +243,8 @@
 {
     int err = 0;
     while (items) {
-        if (items->item_type == PARCELABLE_TYPE
-                || items->item_type == FLATTENABLE_TYPE) {
-            parcelable_type* p = (parcelable_type*)items;
+        if (items->item_type == USER_DATA_TYPE) {
+            user_data_type* p = (user_data_type*)items;
             err |= check_filename(filename, p->package, &p->name);
         }
         else if (items->item_type == INTERFACE_TYPE_BINDER
@@ -270,8 +270,8 @@
     {
         case Type::INTERFACE:
             return "an interface";
-        case Type::PARCELABLE:
-            return "a parcelable";
+        case Type::USERDATA:
+            return "a user data";
         default:
             return "ERROR";
     }
@@ -296,15 +296,11 @@
     int err = 0;
     while (items) {
         Type* type;
-        if (items->item_type == PARCELABLE_TYPE) {
-            parcelable_type* p = (parcelable_type*)items;
-            type = new ParcelableType(p->package ? p->package : "",
-                            p->name.data, false, filename, p->name.lineno);
-        }
-        else if (items->item_type == FLATTENABLE_TYPE) {
-            parcelable_type* p = (parcelable_type*)items;
-            type = new FlattenableType(p->package ? p->package : "",
-                            p->name.data, false, filename, p->name.lineno);
+        if (items->item_type == USER_DATA_TYPE) {
+            user_data_type* p = (user_data_type*)items;
+            type = new UserDataType(p->package ? p->package : "", p->name.data,
+                    false, ((p->flattening_methods & PARCELABLE_DATA) != 0),
+                    ((p->flattening_methods & RPC_DATA) != 0), filename, p->name.lineno);
         }
         else if (items->item_type == INTERFACE_TYPE_BINDER
                 || items->item_type == INTERFACE_TYPE_RPC) {
@@ -539,7 +535,7 @@
 {
     int err = 0;
     while (items) {
-        // (nothing to check for PARCELABLE_TYPE or FLATTENABLE_TYPE)
+        // (nothing to check for USER_DATA_TYPE)
         if (items->item_type == INTERFACE_TYPE_BINDER
                 || items->item_type == INTERFACE_TYPE_RPC) {
             map<string,method_type*> methodNames;
@@ -593,26 +589,23 @@
         else if (next->item_type == INTERFACE_TYPE_RPC) {
             lineno = ((interface_type*)next)->interface_token.lineno;
         }
-        else if (next->item_type == PARCELABLE_TYPE) {
-            lineno = ((parcelable_type*)next)->parcelable_token.lineno;
-        }
-        else if (next->item_type == FLATTENABLE_TYPE) {
-            lineno = ((parcelable_type*)next)->parcelable_token.lineno;
+        else if (next->item_type == USER_DATA_TYPE) {
+            lineno = ((user_data_type*)next)->keyword_token.lineno;
         }
         fprintf(stderr, "%s:%d aidl can only handle one interface per file\n",
                             filename, lineno);
         return 1;
     }
 
-    if (items->item_type == PARCELABLE_TYPE || items->item_type == FLATTENABLE_TYPE) {
+    if (items->item_type == USER_DATA_TYPE) {
         *onlyParcelable = true;
         if (options.failOnParcelable) {
             fprintf(stderr, "%s:%d aidl can only generate code for interfaces, not"
                             " parcelables or flattenables,\n", filename,
-                            ((parcelable_type*)items)->parcelable_token.lineno);
+                            ((user_data_type*)items)->keyword_token.lineno);
             fprintf(stderr, "%s:%d .aidl files that only declare parcelables or flattenables"
                             "may not go in the Makefile.\n", filename,
-                            ((parcelable_type*)items)->parcelable_token.lineno);
+                            ((user_data_type*)items)->keyword_token.lineno);
             return 1;
         }
     } else {
@@ -711,8 +704,8 @@
         interface_type* type = (interface_type*)items;
 
         return generate_outputFileName2(options, type->name, type->package);
-    } else if (items->item_type == PARCELABLE_TYPE || items->item_type == FLATTENABLE_TYPE) {
-        parcelable_type* type = (parcelable_type*)items;
+    } else if (items->item_type == USER_DATA_TYPE) {
+        user_data_type* type = (user_data_type*)items;
         return generate_outputFileName2(options, type->name, type->package);
     }
 
@@ -783,31 +776,33 @@
         document_item_type* doc;
         
         if (0 == strcmp("parcelable", type)) {
-            parcelable_type* parcl = (parcelable_type*)malloc(
-                    sizeof(parcelable_type));
-            memset(parcl, 0, sizeof(parcelable_type));
-            parcl->document_item.item_type = PARCELABLE_TYPE;
-            parcl->parcelable_token.lineno = lineno;
-            parcl->parcelable_token.data = strdup(type);
+            user_data_type* parcl = (user_data_type*)malloc(
+                    sizeof(user_data_type));
+            memset(parcl, 0, sizeof(user_data_type));
+            parcl->document_item.item_type = USER_DATA_TYPE;
+            parcl->keyword_token.lineno = lineno;
+            parcl->keyword_token.data = strdup(type);
             parcl->package = packagename ? strdup(packagename) : NULL;
             parcl->name.lineno = lineno;
             parcl->name.data = strdup(classname);
             parcl->semicolon_token.lineno = lineno;
             parcl->semicolon_token.data = strdup(";");
+            parcl->flattening_methods = PARCELABLE_DATA;
             doc = (document_item_type*)parcl;
         }
         else if (0 == strcmp("flattenable", type)) {
-            parcelable_type* parcl = (parcelable_type*)malloc(
-                    sizeof(parcelable_type));
-            memset(parcl, 0, sizeof(parcelable_type));
-            parcl->document_item.item_type = FLATTENABLE_TYPE;
-            parcl->parcelable_token.lineno = lineno;
-            parcl->parcelable_token.data = strdup(type);
+            user_data_type* parcl = (user_data_type*)malloc(
+                    sizeof(user_data_type));
+            memset(parcl, 0, sizeof(user_data_type));
+            parcl->document_item.item_type = USER_DATA_TYPE;
+            parcl->keyword_token.lineno = lineno;
+            parcl->keyword_token.data = strdup(type);
             parcl->package = packagename ? strdup(packagename) : NULL;
             parcl->name.lineno = lineno;
             parcl->name.data = strdup(classname);
             parcl->semicolon_token.lineno = lineno;
             parcl->semicolon_token.data = strdup(";");
+            parcl->flattening_methods = RPC_DATA;
             doc = (document_item_type*)parcl;
         }
         else if (0 == strcmp("interface", type)) {
@@ -986,18 +981,14 @@
         }
         document_item_type* doc = g_document;
         string line;
-        if (doc->item_type == PARCELABLE_TYPE) {
-            line = "parcelable ";
-            parcelable_type* parcelable = (parcelable_type*)doc;
-            if (parcelable->package) {
-                line += parcelable->package;
-                line += '.';
+        if (doc->item_type == USER_DATA_TYPE) {
+            user_data_type* parcelable = (user_data_type*)doc;
+            if ((parcelable->flattening_methods & PARCELABLE_DATA) != 0) {
+                line = "parcelable ";
             }
-            line += parcelable->name.data;
-        }
-        else if (doc->item_type == FLATTENABLE_TYPE) {
-            line = "parcelable ";
-            parcelable_type* parcelable = (parcelable_type*)doc;
+            if ((parcelable->flattening_methods & RPC_DATA) != 0) {
+                line = "flattenable ";
+            }
             if (parcelable->package) {
                 line += parcelable->package;
                 line += '.';
diff --git a/tools/aidl/aidl_language.h b/tools/aidl/aidl_language.h
index b490a59..f203dbb0 100644
--- a/tools/aidl/aidl_language.h
+++ b/tools/aidl/aidl_language.h
@@ -63,8 +63,7 @@
 } method_type;
 
 enum {
-    PARCELABLE_TYPE = 12,
-    FLATTENABLE_TYPE,
+    USER_DATA_TYPE = 12,
     INTERFACE_TYPE_BINDER,
     INTERFACE_TYPE_RPC
 };
@@ -74,13 +73,21 @@
     struct document_item_type* next;
 } document_item_type;
 
-typedef struct parcelable_type {
+
+// for user_data_type.flattening_methods
+enum {
+    PARCELABLE_DATA = 0x1,
+    RPC_DATA = 0x2
+};
+
+typedef struct user_data_type {
     document_item_type document_item;
-    buffer_type parcelable_token;
+    buffer_type keyword_token; // only the first one
     char* package;
     buffer_type name;
     buffer_type semicolon_token;
-} parcelable_type;
+    int flattening_methods;
+} user_data_type;
 
 typedef struct interface_type {
     document_item_type document_item;
@@ -102,7 +109,7 @@
     method_type* method;
     interface_item_type* interface_item;
     interface_type* interface_obj;
-    parcelable_type* parcelable;
+    user_data_type* user_data;
     document_item_type* document_item;
 } lexer_type;
 
diff --git a/tools/aidl/aidl_language_y.y b/tools/aidl/aidl_language_y.y
index 12bb3d7..cc04d15 100644
--- a/tools/aidl/aidl_language_y.y
+++ b/tools/aidl/aidl_language_y.y
@@ -74,50 +74,52 @@
     ;
 
 declaration:
-        parcelable_decl                            { $$.document_item = (document_item_type*)$1.parcelable; }
+        parcelable_decl                            { $$.document_item = (document_item_type*)$1.user_data; }
     |   interface_decl                             { $$.document_item = (document_item_type*)$1.interface_item; }
     ;
 
 parcelable_decl:
         PARCELABLE IDENTIFIER ';'                   {
-                                                        parcelable_type* b = (parcelable_type*)malloc(sizeof(parcelable_type));
-                                                        b->document_item.item_type = PARCELABLE_TYPE;
+                                                        user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type));
+                                                        b->document_item.item_type = USER_DATA_TYPE;
                                                         b->document_item.next = NULL;
-                                                        b->parcelable_token = $1.buffer;
+                                                        b->keyword_token = $1.buffer;
                                                         b->name = $2.buffer;
                                                         b->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
                                                         b->semicolon_token = $3.buffer;
-                                                        $$.parcelable = b;
+                                                        b->flattening_methods = PARCELABLE_DATA;
+                                                        $$.user_data = b;
                                                     }
     |   PARCELABLE ';'                              {
                                                         fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n",
                                                                      g_currentFilename, $1.buffer.lineno);
-                                                        $$.parcelable = NULL;
+                                                        $$.user_data = NULL;
                                                     }
     |   PARCELABLE error ';'                        {
                                                         fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name, saw \"%s\".\n",
                                                                      g_currentFilename, $2.buffer.lineno, $2.buffer.data);
-                                                        $$.parcelable = NULL;
+                                                        $$.user_data = NULL;
                                                     }
     |   FLATTENABLE IDENTIFIER ';'                  {
-                                                        parcelable_type* b = (parcelable_type*)malloc(sizeof(parcelable_type));
-                                                        b->document_item.item_type = FLATTENABLE_TYPE;
+                                                        user_data_type* b = (user_data_type*)malloc(sizeof(user_data_type));
+                                                        b->document_item.item_type = USER_DATA_TYPE;
                                                         b->document_item.next = NULL;
-                                                        b->parcelable_token = $1.buffer;
+                                                        b->keyword_token = $1.buffer;
                                                         b->name = $2.buffer;
                                                         b->package = g_currentPackage ? strdup(g_currentPackage) : NULL;
                                                         b->semicolon_token = $3.buffer;
-                                                        $$.parcelable = b;
+                                                        b->flattening_methods = PARCELABLE_DATA | RPC_DATA;
+                                                        $$.user_data = b;
                                                     }
     |   FLATTENABLE ';'                             {
                                                         fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name.\n",
                                                                      g_currentFilename, $1.buffer.lineno);
-                                                        $$.parcelable = NULL;
+                                                        $$.user_data = NULL;
                                                     }
     |   FLATTENABLE error ';'                       {
                                                         fprintf(stderr, "%s:%d syntax error in flattenable declaration. Expected type name, saw \"%s\".\n",
                                                                      g_currentFilename, $2.buffer.lineno, $2.buffer.data);
-                                                        $$.parcelable = NULL;
+                                                        $$.user_data = NULL;
                                                     }
 
     ;
diff --git a/tools/aidl/generate_java_rpc.cpp b/tools/aidl/generate_java_rpc.cpp
index a770380..937fed6 100644
--- a/tools/aidl/generate_java_rpc.cpp
+++ b/tools/aidl/generate_java_rpc.cpp
@@ -18,13 +18,13 @@
 // TODO: Just use Endpoint, so this works for all endpoints.
 Type* RPC_CONNECTOR_TYPE = new Type("com.android.athome.connector", "Connector",
         Type::BUILT_IN, false, false, false);
-Type* RPC_ENDPOINT_INFO_TYPE = new ParcelableType("com.android.athome.rpc",
+Type* RPC_ENDPOINT_INFO_TYPE = new UserDataType("com.android.athome.rpc",
         "EndpointInfo", true, __FILE__, __LINE__);
-Type* RPC_RESULT_HANDLER_TYPE = new ParcelableType("com.android.athome.rpc", "RpcResultHandler",
+Type* RPC_RESULT_HANDLER_TYPE = new UserDataType("com.android.athome.rpc", "RpcResultHandler",
         true, __FILE__, __LINE__);
 Type* RPC_ERROR_LISTENER_TYPE = new Type("com.android.athome.rpc", "RpcErrorHandler",
         Type::BUILT_IN, false, false, false);
-Type* RPC_CONTEXT_TYPE = new ParcelableType("com.android.athome.rpc", "RpcContext", true,
+Type* RPC_CONTEXT_TYPE = new UserDataType("com.android.athome.rpc", "RpcContext", true,
         __FILE__, __LINE__);
 
 static void generate_create_from_data(Type* t, StatementBlock* addTo, const string& key,