Mark scripts as threadable or not

bug 19095896

Read embedded flag in .rs.info and use it to mark Scripts as threadable.
In compat lib path, scripts are always threadable.

Change-Id: I85a3753ffae788dbdec5fd130c20581790c4ee07
diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp
index a4e3059..3190d79 100644
--- a/cpu_ref/rsCpuScript.cpp
+++ b/cpu_ref/rsCpuScript.cpp
@@ -436,6 +436,7 @@
 #define EXPORT_FOREACH_STR "exportForEachCount: "
 #define OBJECT_SLOT_STR "objectSlotCount: "
 #define PRAGMA_STR "pragmaCount: "
+#define THREADABLE_STR "isThreadable: "
 
 // Copy up to a newline or size chars from str -> s, updating str
 // Returns s when successful and nullptr when '\0' is finally reached.
@@ -515,6 +516,9 @@
         memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
     }
 
+    mIsThreadable = mScriptExec->getThreadable();
+    //ALOGE("Script isThreadable? %d", mIsThreadable);
+
     return true;
 }
 
@@ -527,6 +531,7 @@
     size_t forEachCount = 0;
     size_t objectSlotCount = 0;
     size_t pragmaCount = 0;
+    bool isThreadable = true;
 
     const char *rsInfo = (const char *) dlsym(sharedObj, ".rs.info");
 
@@ -649,10 +654,13 @@
     }
 
 #ifdef RS_COMPATIBILITY_LIB
-    // Do not attempt to read pragmas in compat lib path
+    // Do not attempt to read pragmas or isThreadable flag in compat lib path.
+    // Neither is applicable for compat lib
     std::vector<const char *> pragmaKeys(pragmaCount);
     std::vector<const char *> pragmaValues(pragmaCount);
 
+    isThreadable = true;
+
 #else
     if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
         return nullptr;
@@ -700,11 +708,31 @@
         pragmaValues[i] = pValue;
         //ALOGE("Pragma %zu: Key: '%s' Value: '%s'", i, pKey, pValue);
     }
+
+    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+        return nullptr;
+    }
+
+    char tmpFlag[4];
+    if (sscanf(line, THREADABLE_STR "%4s", tmpFlag) != 1) {
+        ALOGE("Invalid threadable flag!: %s", line);
+        return nullptr;
+    }
+    if (strcmp(tmpFlag, "yes") == 0)
+        isThreadable = true;
+    else if (strcmp(tmpFlag, "no") == 0)
+        isThreadable = false;
+    else {
+        ALOGE("Invalid threadable flag!: %s", tmpFlag);
+        return nullptr;
+    }
+
 #endif
 
     return new ScriptExecutable(
         RSContext, fieldAddress, fieldIsObject, invokeFunctions,
-        forEachFunctions, forEachSignatures, pragmaKeys, pragmaValues);
+        forEachFunctions, forEachSignatures, pragmaKeys, pragmaValues,
+        isThreadable);
 }
 
 bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
diff --git a/cpu_ref/rsCpuScript.h b/cpu_ref/rsCpuScript.h
index b84abb3..873a79a 100644
--- a/cpu_ref/rsCpuScript.h
+++ b/cpu_ref/rsCpuScript.h
@@ -73,7 +73,9 @@
                    std::vector<ForEachFunc_t>& forEachFunctions,
                    std::vector<uint32_t>& forEachSignatures,
                    std::vector<const char *> &pragmaKeys,
-                   std::vector<const char *> &pragmaValues) : mRS(RSContext) {
+                   std::vector<const char *> &pragmaValues,
+                   bool isThreadable)
+                   : mIsThreadable(isThreadable), mRS(RSContext) {
       mFieldAddress.swap(fieldAddress);
       mFieldIsObject.swap(fieldIsObject);
       mInvokeFunctions.swap(invokeFunctions);
@@ -114,8 +116,10 @@
   ForEachFunc_t getForEachFunction(int slot) const { return mForEachFunctions[slot]; }
   uint32_t getForEachSignature(int slot) const { return mForEachSignatures[slot]; }
 
-  std::vector<const char *> & getPragmaKeys() { return mPragmaKeys; }
-  std::vector<const char *> & getPragmaValues() { return mPragmaValues; }
+  const std::vector<const char *> & getPragmaKeys() const { return mPragmaKeys; }
+  const std::vector<const char *> & getPragmaValues() const { return mPragmaValues; }
+
+  bool getThreadable() const { return mIsThreadable; }
 
  private:
   std::vector<void*> mFieldAddress;
@@ -126,6 +130,8 @@
   std::vector<const char *> mPragmaKeys;
   std::vector<const char *> mPragmaValues;
 
+  bool mIsThreadable;
+
   Context* mRS;
 };