Merge "Fix shared library location in build_rs.py"
diff --git a/rsApiStubs.cpp b/rsApiStubs.cpp
index e0753b0..28f1b1e 100644
--- a/rsApiStubs.cpp
+++ b/rsApiStubs.cpp
@@ -57,6 +57,28 @@
 // supported on Android are built on top of pthread, std::mutex is safe for them.
 static std::mutex contextMapMutex;
 
+// globalObjAlive is a global flag indicating whether the global objects,
+// contextMap & contextMapMutex, are still alive.
+// For the protected functions during application teardown, this
+// flag will be checked before accessing the global objects.
+static bool globalObjAlive;
+
+// GlobalObjGuard manipulates the globalObjAlive flag during construction and
+// destruction. If the guard object is destroyed, globalObjAlive will be set
+// to false, which will make the protected functions NO-OP.
+// https://goto.google.com/rs-static-destructor
+class GlobalObjGuard {
+  public:
+    GlobalObjGuard() {
+        globalObjAlive = true;
+    }
+
+    ~GlobalObjGuard() {
+        globalObjAlive = false;
+    }
+};
+static GlobalObjGuard guard;
+
 // API to find high-level context (RsContextWrapper) given a low level context.
 // This API is only intended to be used by RenderScript debugger.
 extern "C" RsContext rsDebugGetHighLevelContext(RsContext context) {
@@ -96,6 +118,11 @@
 extern "C" RsContext rsContextCreate(RsDevice vdev, uint32_t version, uint32_t sdkVersion,
                                      RsContextType ct, uint32_t flags)
 {
+    if (!globalObjAlive) {
+        ALOGE("rsContextCreate is not allowed during process teardown.");
+        return nullptr;
+    }
+
     RsHidlAdaptation& instance = RsHidlAdaptation::GetInstance();
     RsContext context = instance.GetEntryFuncs()->ContextCreate(vdev, version, sdkVersion, ct, flags);
     // Wait for debugger to attach if RS_CONTEXT_WAIT_FOR_ATTACH flag set.
@@ -155,6 +182,10 @@
 
 extern "C" void rsContextDestroy (RsContext ctxWrapper)
 {
+    if (!globalObjAlive) {
+        return;
+    }
+
     RS_DISPATCH(ctxWrapper, ContextDestroy);
 
     // Lock contextMap when deleting an existing entry.
@@ -683,6 +714,11 @@
 RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, uint32_t sdkVersion,
                             RsSurfaceConfig sc, uint32_t dpi)
 {
+    if (!globalObjAlive) {
+        ALOGE("rsContextCreateGL is not allowed during process teardown.");
+        return nullptr;
+    }
+
     RsFallbackAdaptation& instance = RsFallbackAdaptation::GetInstance();
     RsContext context = instance.GetEntryFuncs()->ContextCreateGL(vdev, version, sdkVersion, sc, dpi);
 
diff --git a/rsHidlAdaptation.h b/rsHidlAdaptation.h
index 48c4b6a..372a298 100644
--- a/rsHidlAdaptation.h
+++ b/rsHidlAdaptation.h
@@ -32,6 +32,10 @@
  * 1. Load the dispatch table with HIDL implementation or CPU fallback.
  * 2. Convert input paramters to HIDL types, when using HIDL path.
  * 3. Convert output parameters from HIDL types to RS types, when using HIDL path.
+ *
+ * Access of static member objects is protected by global teardown flag.
+ * https://goto.google.com/rs-static-destructor
+ *
  */
 class RsHidlAdaptation
 {
diff --git a/tests/cpp_api/cpp-globalguard/Android.mk b/tests/cpp_api/cpp-globalguard/Android.mk
new file mode 100644
index 0000000..118c9fb
--- /dev/null
+++ b/tests/cpp_api/cpp-globalguard/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= rstest-cpp-globalguard
+
+LOCAL_SDK_VERSION := 21
+LOCAL_NDK_STL_VARIANT := stlport_static
+
+LOCAL_SRC_FILES:= \
+	multiply.rs \
+	compute.cpp
+
+LOCAL_STATIC_LIBRARIES := \
+	libRScpp_static
+
+LOCAL_LDFLAGS += -llog
+
+include frameworks/rs/tests/cpp_api/common.mk
+include $(BUILD_EXECUTABLE)
diff --git a/tests/cpp_api/cpp-globalguard/compute.cpp b/tests/cpp_api/cpp-globalguard/compute.cpp
new file mode 100644
index 0000000..8b9789c
--- /dev/null
+++ b/tests/cpp_api/cpp-globalguard/compute.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+// This file is based on frameworks/rs/tests/cpp_api/cppallocation/compute.cpp.
+
+#include "RenderScript.h"
+
+#include "ScriptC_multiply.h"
+
+sp<RS> rs;
+sp<const Element> e;
+sp<const Type> t;
+sp<Allocation> ain;
+sp<Allocation> aout;
+sp<ScriptC_multiply> sc;
+
+int main(int argc, char** argv)
+{
+    uint32_t numElems = 1024;
+
+    if (argc >= 2) {
+        int tempNumElems = atoi(argv[1]);
+        if (tempNumElems < 1) {
+            printf("numElems must be greater than 0\n");
+            return 1;
+        }
+        numElems = (uint32_t) tempNumElems;
+    }
+
+    rs = new RS();
+
+    if (!rs->init("/system/bin")) {
+        printf("Could not initialize RenderScript\n");
+        return 1;
+    }
+
+    e = Element::U32(rs);
+
+    Type::Builder tb(rs, e);
+    tb.setX(numElems);
+    t = tb.create();
+
+    ain = Allocation::createTyped(rs, t);
+    aout = Allocation::createTyped(rs, t);
+
+    sc = new ScriptC_multiply(rs);
+
+    uint32_t* buf = new uint32_t[numElems];
+    for (uint32_t ct=0; ct < numElems; ct++) {
+        buf[ct] = (uint32_t)ct;
+    }
+
+    ain->copy1DRangeFrom(0, numElems, buf);
+
+    sc->forEach_multiply(ain, aout);
+
+    aout->copy1DRangeTo(0, numElems, buf);
+
+    for (uint32_t ct=0; ct < numElems; ct++) {
+        if (buf[ct] !=  ct * 2) {
+            printf("Mismatch at location %d: %u\n", ct, buf[ct]);
+            return 1;
+        }
+    }
+
+    printf("Test successful with %u elems!\n", numElems);
+}
diff --git a/tests/cpp_api/cpp-globalguard/multiply.rs b/tests/cpp_api/cpp-globalguard/multiply.rs
new file mode 100644
index 0000000..6ee7fb5
--- /dev/null
+++ b/tests/cpp_api/cpp-globalguard/multiply.rs
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(unused)
+#pragma rs_fp_relaxed
+
+uint32_t RS_KERNEL multiply(uint32_t in) {
+    return in * 2;
+}
+
+