am 0f5cfd9f: am c9baf342: Merge "CTS: Add test for JNI class-loading" into lollipop-cts-dev automerge: d5716c8

* commit '0f5cfd9fdfebf2225d843c80ffb18b17b968dfd6':
  CTS: Add test for JNI class-loading
diff --git a/tests/tests/jni/libjnitest/Android.mk b/tests/tests/jni/libjnitest/Android.mk
index d7d1bad..396e161 100644
--- a/tests/tests/jni/libjnitest/Android.mk
+++ b/tests/tests/jni/libjnitest/Android.mk
@@ -29,6 +29,7 @@
 	android_jni_cts_InstanceNonce.c \
 	android_jni_cts_JniCTest.c \
 	android_jni_cts_JniCppTest.cpp \
+	android_jni_cts_JniStaticTest.cpp \
 	android_jni_cts_StaticNonce.c \
 	helper.c \
 	register.c
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_JniStaticTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_JniStaticTest.cpp
new file mode 100644
index 0000000..5e8bea0
--- /dev/null
+++ b/tests/tests/jni/libjnitest/android_jni_cts_JniStaticTest.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/*
+ * Native implementation for the JniStaticTest parts.
+ */
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+extern "C" JNIEXPORT jint JNICALL Java_android_jni_cts_ClassLoaderHelper_nativeGetHashCode(
+        JNIEnv* env,
+        jobject obj __attribute__((unused)),
+        jobject appLoader,
+        jclass appLoaderClass) {
+  jmethodID midFindClass = env->GetMethodID(appLoaderClass, "findClass",
+          "(Ljava/lang/String;)Ljava/lang/Class;");
+  jstring coreClsName = env->NewStringUTF("android.jni.cts.ClassLoaderStaticNonce");
+  jobject coreClass = env->CallObjectMethod(appLoader, midFindClass, coreClsName);
+  jmethodID midHashCode = env->GetMethodID((jclass)coreClass, "hashCode", "()I");
+  jint hash = env->CallIntMethod(coreClass, midHashCode);
+
+  return hash;
+}
diff --git a/tests/tests/jni/src/android/jni/cts/ClassLoaderHelper.java b/tests/tests/jni/src/android/jni/cts/ClassLoaderHelper.java
new file mode 100644
index 0000000..c4fe0f0
--- /dev/null
+++ b/tests/tests/jni/src/android/jni/cts/ClassLoaderHelper.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package android.jni.cts;
+
+class ClassLoaderHelper {
+
+    // Note: To not hava a dependency on other classes, assume that if we do initialize then
+    // it's OK to load the library.
+    static {
+        System.loadLibrary("jnitest");
+    }
+
+    public static boolean run() {
+        ClassLoaderHelper clh = new ClassLoaderHelper();
+
+        int firstHashCode = clh.getHashCodeDirect();
+
+        Runtime.getRuntime().gc();
+
+        int secondHashCode = clh.getHashCodeNative();
+
+        return (firstHashCode == secondHashCode);
+    }
+
+    // Simple helpers to avoid keeping references alive because of dex registers.
+    private int getHashCodeDirect() {
+        return ClassLoaderStaticNonce.class.hashCode();
+    }
+    private int getHashCodeNative() {
+        ClassLoader loader = getClass().getClassLoader();
+        return nativeGetHashCode(loader, loader.getClass());
+    }
+
+    private native int nativeGetHashCode(ClassLoader loader, Class<?> classLoaderClass);
+}
\ No newline at end of file
diff --git a/tests/tests/jni/src/android/jni/cts/ClassLoaderStaticNonce.java b/tests/tests/jni/src/android/jni/cts/ClassLoaderStaticNonce.java
new file mode 100644
index 0000000..d425c77
--- /dev/null
+++ b/tests/tests/jni/src/android/jni/cts/ClassLoaderStaticNonce.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+package android.jni.cts;
+
+import android.util.Log;
+
+/**
+ * Class to help with class-loader check..
+ */
+public class ClassLoaderStaticNonce {
+
+    static Object ctx;
+
+    // Have a static initializer block.
+    static {
+        ctx = new Object();
+        log("Initializing ClassLoaderStaticNonce");
+    }
+
+    private final static A a = new A();
+
+    public static void log(String s) {
+        Log.i("ClassLoaderStaticNone", s);
+    }
+
+    public static class A {
+        // Have a finalizer. This will make the outer class not finalizable when we allocate for
+        // a static field.
+        public void finalize() throws Throwable {
+            super.finalize();
+
+            // Do something so that the finalizer can't be recognized as empty.
+            toNull = null;
+        }
+
+        private Object toNull = new Object();
+    }
+
+
+    public static void setCtx(Object in) {
+        ctx = in;
+    }
+
+    public static Object getCtx() {
+        return ctx;
+    }
+}
diff --git a/tests/tests/jni/src/android/jni/cts/JniStaticTest.java b/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
index 3036c71..d4b51b9 100644
--- a/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
+++ b/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
@@ -24,6 +24,20 @@
  */
 public class JniStaticTest extends JniTestCase {
 
+    static {
+        if (!JniTestCase.isCpuAbiNone()) {
+            System.loadLibrary("jnitest");
+        }
+    }
+
+    /**
+     * Test that accessing classes true JNI works as expected. b/19382130
+     */
+    public void test_classload() {
+        // Use an independent class to do this.
+        assertEquals(true, ClassLoaderHelper.run());
+    }
+
     /**
      * Test a simple no-op and void-returning method call.
      */