Fix function mangling of rs_quaternion* arguments in stubs white list.

Fix the generator of the RenderScript header files to allow functions
that take rs_quaternion arguments. Previously they were wrongly mangled
in the RenderScript stubs white list (float* instead of float4*). Factor
out the calculation of vector length from the runtime header generator,
and call it after expanding a typedef to update the vector length. This
way it can calculate the right mangling for a function taking a pointer
to rs_quaternion (which is not itself a vector but the mangling does
need to output a vector length, i.e. Dv4_f). This fix is required by a
following change list, which moves the bodies of the quaternion builtins
to libclcore, so their mangled names are then added to the white list.

(cherry picked from commit 1f08801f894a04d3f9221e7a85a93de1e3215def)

Change-Id: If90d402830631e144afa91d6004f710fead89036
diff --git a/api/GenerateStubsWhiteList.cpp b/api/GenerateStubsWhiteList.cpp
index 5846c0c..5b202a5 100644
--- a/api/GenerateStubsWhiteList.cpp
+++ b/api/GenerateStubsWhiteList.cpp
@@ -93,7 +93,7 @@
  * the resulting list.  'apiLevel' and 'intSize' specifies the API level and bitness
  * we are currently processing.
  */
-list<string> expandTypedefs(const string type, unsigned int apiLevel, int intSize) {
+list<string> expandTypedefs(const string type, unsigned int apiLevel, int intSize, string& vectorSize) {
     // Split the string in tokens.
     istringstream stream(type);
     list<string> tokens{istream_iterator<string>{stream}, istream_iterator<string>{}};
@@ -106,6 +106,26 @@
         } else {
             // Split the replacement string in tokens.
             istringstream stream(substitute);
+
+            /* Get the new vector size. This is for the case of the type being for example
+             * rs_quaternion* == float4*, where we need the vector size to be 4 for the
+             * purposes of mangling, although the parameter itself is not determined to be
+             * a vector. */
+            string unused;
+            string newVectorSize;
+            getVectorSizeAndBaseType(*i, newVectorSize, unused);
+
+            istringstream vectorSizeBuf(vectorSize);
+            int vectorSizeVal;
+            vectorSizeBuf >> vectorSizeVal;
+
+            istringstream newVectorSizeBuf(newVectorSize);
+            int newVectorSizeVal;
+            newVectorSizeBuf >> newVectorSizeVal;
+
+            if (newVectorSizeVal > vectorSizeVal)
+                vectorSize = newVectorSize;
+
             list<string> newTokens{istream_iterator<string>{stream}, istream_iterator<string>{}};
             // Replace the token with the substitution. Don't advance, as the new substitution
             // might itself be replaced.
@@ -283,12 +303,14 @@
     vector<string> previousManglings;
     for (ParameterDefinition* p : params) {
         // Expand the typedefs and create a tokenized list.
-        list<string> tokens = expandTypedefs(p->rsType, apiLevel, intSize);
+        string vectorSize = p->mVectorSize;
+        list<string> tokens = expandTypedefs(p->rsType, apiLevel, intSize, vectorSize);
         if (p->isOutParameter) {
             tokens.push_back("*");
         }
         string mangling, compressedMangling;
-        if (!mangleType(p->mVectorSize, &tokens, &previousManglings, &mangling,
+
+        if (!mangleType(vectorSize, &tokens, &previousManglings, &mangling,
                         &compressedMangling)) {
             return false;
         }
diff --git a/api/Specification.cpp b/api/Specification.cpp
index 785f358..7afeea4 100644
--- a/api/Specification.cpp
+++ b/api/Specification.cpp
@@ -115,6 +115,27 @@
     return true;
 }
 
+void getVectorSizeAndBaseType(const string& type, string& vectorSize, string& baseType) {
+    vectorSize = "1";
+    baseType = type;
+
+    /* If it's a vector type, we need to split the base type from the size.
+     * We know that's it's a vector type if the last character is a digit and
+     * the rest is an actual base type.   We used to only verify the first part,
+     * which created a problem with rs_matrix2x2.
+     */
+    const int last = type.size() - 1;
+    const char lastChar = type[last];
+    if (lastChar >= '0' && lastChar <= '9') {
+        const string trimmed = type.substr(0, last);
+        int i = findCType(trimmed);
+        if (i >= 0) {
+            baseType = trimmed;
+            vectorSize = lastChar;
+        }
+    }
+}
+
 void ParameterDefinition::parseParameterDefinition(const string& type, const string& name,
                                                    const string& testOption, int lineNumber,
                                                    bool isReturn, Scanner* scanner) {
@@ -124,23 +145,7 @@
     // Determine if this is an output.
     isOutParameter = isReturn || charRemoved('*', &rsType);
 
-    rsBaseType = rsType;
-    mVectorSize = "1";
-    /* If it's a vector type, we need to split the base type from the size.
-     * We know that's it's a vector type if the last character is a digit and
-     * the rest is an actual base type.   We used to only verify the first part,
-     * which created a problem with rs_matrix2x2.
-     */
-    const int last = rsType.size() - 1;
-    const char lastChar = rsType[last];
-    if (lastChar >= '0' && lastChar <= '9') {
-        const string trimmed = rsType.substr(0, last);
-        int i = findCType(trimmed);
-        if (i >= 0) {
-            rsBaseType = trimmed;
-            mVectorSize = lastChar;
-        }
-    }
+    getVectorSizeAndBaseType(rsType, mVectorSize, rsBaseType);
     typeIndex = findCType(rsBaseType);
 
     if (mVectorSize == "3") {
diff --git a/api/Specification.h b/api/Specification.h
index 959935b..c467c5c 100644
--- a/api/Specification.h
+++ b/api/Specification.h
@@ -612,4 +612,10 @@
 extern const NumericalType TYPES[];
 extern const int NUM_TYPES;
 
+/* Given a renderscript type (string) calculate the vector size and base type. If the type
+ * is not a vector the vector size is 1 and baseType is just the type itself.
+ */
+void getVectorSizeAndBaseType(const std::string& type, std::string& vectorSize,
+                              std::string& baseType);
+
 #endif  // ANDROID_RS_API_GENERATOR_SPECIFICATION_H