Move queryCacheDir to a separate shared object.

Bug: 37272603

  - Under Treble, a vendor process cannot load libandroid_runtime.so.
  - The queryCacheDir function should NOT be used in a vendor process,
    as it depends on libandroid_runtime.so.
  - It is moved out from libRS.so to a separate shared object,
    libRSCacheDir.so. libRS.so will only load libRSCacheDir.so when the
    calling process is found to be a non-vendor process.

Test: mm
Test: Made sure libRS won't load libRSCacheDir for /vendor processes
      on Angler and Marlin.
Test: Made sure other processes able to query the cache dir on Angler
      and Marlin.

Change-Id: Iebc4505dc629dac1578fc806b60cec3adaf5ea64
diff --git a/rsCacheDir.cpp b/rsCacheDir.cpp
new file mode 100644
index 0000000..00e1a83
--- /dev/null
+++ b/rsCacheDir.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android_runtime/AndroidRuntime.h>
+#include <log/log.h>
+
+#include <string>
+
+// Use reflection to query the default cache dir.
+// The function is NOT thread-safe. It is expected to be called
+// at most once per process.
+extern "C" const char* rsQueryCacheDir() {
+    static std::string cacheDir;
+    // First check if we have JavaVM running in this process.
+    if (android::AndroidRuntime::getJavaVM()) {
+        JNIEnv* env = android::AndroidRuntime::getJNIEnv();
+        if (env) {
+            jclass cacheDirClass = env->FindClass("android/renderscript/RenderScriptCacheDir");
+            jfieldID cacheDirID = env->GetStaticFieldID(cacheDirClass, "mCacheDir", "Ljava/io/File;");
+            jobject cache_dir = env->GetStaticObjectField(cacheDirClass, cacheDirID);
+
+            if (cache_dir) {
+                jclass fileClass = env->FindClass("java/io/File");
+                jmethodID getPath = env->GetMethodID(fileClass, "getPath", "()Ljava/lang/String;");
+                jstring path_string = (jstring)env->CallObjectMethod(cache_dir, getPath);
+                const char *path_chars = env->GetStringUTFChars(path_string, NULL);
+
+                ALOGD("Successfully queried cache dir: %s", path_chars);
+                cacheDir = std::string(path_chars);
+                env->ReleaseStringUTFChars(path_string, path_chars);
+            } else {
+                ALOGD("Cache dir not initialized");
+            }
+        } else {
+            ALOGD("Failed to query the default cache dir.");
+        }
+    }
+
+    return cacheDir.c_str();
+}
+