Move to dynamic dispatch. Add support for IoAllocation* in rs.spec.

Change-Id: I013409cbb758ce5aae78347acb39c43d07aeb9bf
diff --git a/cpp/Android.mk b/cpp/Android.mk
index 689b2fa..75a8ae7 100644
--- a/cpp/Android.mk
+++ b/cpp/Android.mk
@@ -24,7 +24,6 @@
 	ScriptIntrinsics.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libRS \
 	libz \
 	libcutils \
 	libutils \
diff --git a/cpp/BaseObj.cpp b/cpp/BaseObj.cpp
index fa7d73c..814e552 100644
--- a/cpp/BaseObj.cpp
+++ b/cpp/BaseObj.cpp
@@ -51,7 +51,7 @@
 
 void BaseObj::updateFromNative() {
     const char *name = NULL;
-    rsaGetName(mRS->getContext(), mID, &name);
+    RS::dispatch->GetName(mRS->getContext(), mID, &name);
     mName = name;
 }
 
diff --git a/cpp/RenderScript.cpp b/cpp/RenderScript.cpp
index b542ad6..6acfc9e 100644
--- a/cpp/RenderScript.cpp
+++ b/cpp/RenderScript.cpp
@@ -23,6 +23,10 @@
 
 #include <dlfcn.h>
 
+#if !defined(RS_SERVER) && defined(HAVE_ANDROID_OS)
+#include <cutils/properties.h>
+#endif
+
 #define LOG_NDEBUG 0
 #define LOG_TAG "rsC++"
 
@@ -30,10 +34,9 @@
 using namespace RSC;
 
 bool RS::gInitialized = false;
+bool RS::usingNative = false;
 pthread_mutex_t RS::gInitMutex = PTHREAD_MUTEX_INITIALIZER;
-void* RS::librs = NULL;
 dispatchTable* RS::dispatch = NULL;
-
 static int gInitError = 0;
 
 RS::RS() {
@@ -109,6 +112,11 @@
         ALOGE("Couldn't initialize RS::dispatch->ContextCreate");
         return false;
     }
+    RS::dispatch->GetName = (GetNameFnPtr)dlsym(handle, "rsaGetName");;
+    if (RS::dispatch->GetName == NULL) {
+        ALOGE("Couldn't initialize RS::dispatch->GetName");
+        return false;
+    }
     RS::dispatch->ContextDestroy = (ContextDestroyFnPtr)dlsym(handle, "rsContextDestroy");
     if (RS::dispatch->ContextDestroy == NULL) {
         ALOGE("Couldn't initialize RS::dispatch->ContextDestroy");
@@ -393,25 +401,51 @@
     return true;
 }
 
-bool RS::initDispatch(int targetApi) {
+static bool loadSO(const char* filename) {
+    void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+    if (handle == NULL) {
+        ALOGE("couldn't dlopen %s, %s", filename, dlerror());
+        return false;
+    }
 
+    if (loadSymbols(handle) == false) {
+        ALOGE("%s init failed!", filename);
+        return false;
+    }
+    ALOGE("Successfully loaded %s", filename);
+    return true;
+}
+
+static uint32_t getProp(const char *str) {
+#if !defined(RS_SERVER) && defined(HAVE_ANDROID_OS)
+    char buf[256];
+    property_get(str, buf, "0");
+    return atoi(buf);
+#else
+    return 0;
+#endif
+}
+
+bool RS::initDispatch(int targetApi) {
     pthread_mutex_lock(&gInitMutex);
     if (gInitError) {
         goto error;
     } else if (gInitialized) {
         return true;
     }
-    // pick appropriate lib at some point
-    RS::librs = dlopen("libRS.so", RTLD_LAZY | RTLD_LOCAL);
-    if (RS::librs == 0) {
-        ALOGE("couldn't dlopen libRS, %s", dlerror());
-        goto error;
-    }
-    ALOGE("libRS initialized successfully");
 
     RS::dispatch = new dispatchTable;
-    if (loadSymbols(RS::librs) == false) {
-        goto error;
+
+    // attempt to load libRS, load libRSSupport on failure
+    // if property is set, proceed directly to libRSSupport
+    if (getProp("debug.rs.forcecompat") == 0) {
+        usingNative = loadSO("libRS.so");
+    }
+    if (usingNative == false) {
+        if (loadSO("libRSSupport.so") == false) {
+            ALOGE("Failed to load libRS.so and libRSSupport.so");
+            goto error;
+        }
     }
 
     gInitialized = true;
diff --git a/cpp/rsCppStructs.h b/cpp/rsCppStructs.h
index fcc5fc5..7a876b3 100644
--- a/cpp/rsCppStructs.h
+++ b/cpp/rsCppStructs.h
@@ -67,8 +67,7 @@
     static dispatchTable* dispatch;
 
  private:
-    static void* librs;
-
+    static bool usingNative;
     static bool initDispatch(int targetApi);
 
     bool init(int targetApi, bool forceCpu, bool synchronous);
diff --git a/cpp/rsDispatch.h b/cpp/rsDispatch.h
index 133572e..139ef52 100644
--- a/cpp/rsDispatch.h
+++ b/cpp/rsDispatch.h
@@ -27,6 +27,8 @@
 typedef void (*DeviceDestroyFnPtr) (RsDevice dev);
 typedef void (*DeviceSetConfigFnPtr) (RsDevice dev, RsDeviceParam p, int32_t value);
 typedef RsContext (*ContextCreateFnPtr)(RsDevice vdev, uint32_t version, uint32_t sdkVersion, RsContextType ct, bool forceCpu, bool synchronous);
+typedef void (*GetNameFnPtr)(RsContext, void * obj, const char **name);
+
 typedef void (*ContextDestroyFnPtr) (RsContext);
 typedef RsMessageToClientType (*ContextGetMessageFnPtr) (RsContext, void*, size_t, size_t*, size_t, uint32_t*, size_t);
 typedef RsMessageToClientType (*ContextPeekMessageFnPtr) (RsContext, size_t*, size_t, uint32_t*, size_t);
@@ -91,11 +93,11 @@
     ElementGetNativeDataFnPtr ElementGetNativeData;
     ElementGetSubElementsFnPtr ElementGetSubElements;
 
-
     DeviceCreateFnPtr DeviceCreate;
     DeviceDestroyFnPtr DeviceDestroy;
     DeviceSetConfigFnPtr DeviceSetConfig;
     ContextCreateFnPtr ContextCreate;
+    GetNameFnPtr GetName;
 
     // generated from rs.spec
     ContextDestroyFnPtr ContextDestroy;