Fix aidl to cope with multiple collection types per method.

Bug: http://code.google.com/p/android/issues/detail?id=18497
Change-Id: I152416022524d2860cb16b46c4812c5be6bdcbad
diff --git a/Type.cpp b/Type.cpp
index a44072d..6b69864 100755
--- a/Type.cpp
+++ b/Type.cpp
@@ -198,7 +198,7 @@
 }
 
 void
-Type::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+Type::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -207,7 +207,7 @@
 }
 
 void
-Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+Type::ReadFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -226,7 +226,7 @@
 
 void
 Type::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -235,7 +235,7 @@
 }
 
 void
-Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+Type::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d qualifiedName=%s\n",
             __FILE__, __LINE__, m_qualifiedName.c_str());
@@ -284,7 +284,7 @@
 }
 
 void
-BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BasicType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, m_unmarshallMethod)));
 }
@@ -303,13 +303,13 @@
 
 void
 BasicType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, m_createArrayMethod)));
 }
 
 void
-BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BasicType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, m_readArrayMethod, 1, v));
 }
@@ -331,7 +331,7 @@
 }
 
 void
-BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BooleanType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new Comparison(new LiteralExpression("0"),
                     "!=", new MethodCall(parcel, "readInt"))));
@@ -351,13 +351,13 @@
 
 void
 BooleanType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createBooleanArray")));
 }
 
 void
-BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+BooleanType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readBooleanArray", 1, v));
 }
@@ -378,7 +378,7 @@
 }
 
 void
-CharType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+CharType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "readInt"), this));
 }
@@ -397,13 +397,13 @@
 
 void
 CharType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createCharArray")));
 }
 
 void
-CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+CharType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readCharArray", 1, v));
 }
@@ -428,7 +428,7 @@
 }
 
 void
-StringType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+StringType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "readString")));
 }
@@ -447,13 +447,13 @@
 
 void
 StringType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createStringArray")));
 }
 
 void
-StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+StringType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readStringArray", 1, v));
 }
@@ -496,7 +496,7 @@
 
 void
 CharSequenceType::CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                Variable* parcel)
+                                Variable* parcel, Variable**)
 {
     // if (0 != parcel.readInt()) {
     //     v = TextUtils.createFromParcel(parcel)
@@ -532,7 +532,7 @@
 }
 
 void
-RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+RemoteExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -551,7 +551,7 @@
 }
 
 void
-RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+RuntimeExceptionType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -571,7 +571,7 @@
 }
 
 void
-IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+IBinderType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "readStrongBinder")));
 }
@@ -584,13 +584,13 @@
 
 void
 IBinderType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     addTo->Add(new Assignment(v, new MethodCall(parcel, "createBinderArray")));
 }
 
 void
-IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+IBinderType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     addTo->Add(new MethodCall(parcel, "readBinderArray", 1, v));
 }
@@ -610,7 +610,7 @@
 }
 
 void
-IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+IInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -631,7 +631,7 @@
 
 void
 BinderType::CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel)
+                                    Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -652,7 +652,7 @@
 
 void
 BinderProxyType::CreateFromParcel(StatementBlock* addTo, Variable* v,
-                                    Variable* parcel)
+                                    Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -672,7 +672,7 @@
 }
 
 void
-ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -691,7 +691,7 @@
 }
 
 void
-ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelableInterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "aidl:internal error %s:%d\n", __FILE__, __LINE__);
 }
@@ -709,25 +709,31 @@
     addTo->Add(new MethodCall(parcel, "writeMap", 1, v));
 }
 
-void
-MapType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+static void EnsureClassLoader(StatementBlock* addTo, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl,
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, cl)));
+    // We don't want to look up the class loader once for every
+    // collection argument, so ensure we do it at most once per method.
+    if (*cl == NULL) {
+        *cl = new Variable(CLASSLOADER_TYPE, "cl");
+        addTo->Add(new VariableDeclaration(*cl,
+                new LiteralExpression("this.getClass().getClassLoader()"),
+                CLASSLOADER_TYPE));
+    }
+}
+
+void
+MapType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable** cl)
+{
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new Assignment(v, new MethodCall(parcel, "readHashMap", 1, *cl)));
 }
 
 void
 MapType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                    Variable* parcel)
+                    Variable* parcel, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl, 
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new MethodCall(parcel, "readMap", 2, v, cl));
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new MethodCall(parcel, "readMap", 2, v, *cl));
 }
 
 
@@ -751,24 +757,18 @@
 }
 
 void
-ListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl, 
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new Assignment(v, new MethodCall(parcel, "readArrayList", 1, cl)));
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new Assignment(v, new MethodCall(parcel, "readArrayList", 1, *cl)));
 }
 
 void
 ListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                    Variable* parcel)
+                    Variable* parcel, Variable** cl)
 {
-    Variable *cl = new Variable(CLASSLOADER_TYPE, "cl");
-    addTo->Add(new VariableDeclaration(cl, 
-        new LiteralExpression("this.getClass().getClassLoader()"),
-        CLASSLOADER_TYPE));
-    addTo->Add(new MethodCall(parcel, "readList", 2, v, cl));
+    EnsureClassLoader(addTo, cl);
+    addTo->Add(new MethodCall(parcel, "readList", 2, v, *cl));
 }
 
 
@@ -811,7 +811,7 @@
 }
 
 void
-ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelableType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     // if (0 != parcel.readInt()) {
     //     v = CLASS.CREATOR.createFromParcel(parcel)
@@ -833,7 +833,7 @@
 
 void
 ParcelableType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                    Variable* parcel)
+                    Variable* parcel, Variable**)
 {
     // TODO: really, we don't need to have this extra check, but we
     // don't have two separate marshalling code paths
@@ -862,7 +862,7 @@
 
 void
 ParcelableType::CreateArrayFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     string creator = v->type->QualifiedName() + ".CREATOR";
     addTo->Add(new Assignment(v, new MethodCall(parcel,
@@ -870,7 +870,7 @@
 }
 
 void
-ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+ParcelableType::ReadArrayFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     string creator = v->type->QualifiedName() + ".CREATOR";
     addTo->Add(new MethodCall(parcel, "readTypedArray", 2,
@@ -907,7 +907,7 @@
 }
 
 void
-InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+InterfaceType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     // v = Interface.asInterface(parcel.readStrongBinder());
     string type = v->type->QualifiedName();
@@ -961,14 +961,14 @@
 }
 
 void
-GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+GenericType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     fprintf(stderr, "implement GenericType::CreateFromParcel\n");
 }
 
 void
 GenericType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     fprintf(stderr, "implement GenericType::ReadFromParcel\n");
 }
@@ -1009,7 +1009,7 @@
 }
 
 void
-GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel)
+GenericListType::CreateFromParcel(StatementBlock* addTo, Variable* v, Variable* parcel, Variable**)
 {
     if (m_creator == STRING_TYPE->CreatorName()) {
         addTo->Add(new Assignment(v,
@@ -1027,7 +1027,7 @@
 
 void
 GenericListType::ReadFromParcel(StatementBlock* addTo, Variable* v,
-                            Variable* parcel)
+                            Variable* parcel, Variable**)
 {
     if (m_creator == STRING_TYPE->CreatorName()) {
         addTo->Add(new MethodCall(parcel, "readStringList", 1, v));