Merge "Remove setsockoptGroupSourceReq and StructGroupSourceReq"
diff --git a/Android.bp b/Android.bp
index 30a9c59..6d3ab86 100644
--- a/Android.bp
+++ b/Android.bp
@@ -19,6 +19,12 @@
vendor_available: true,
}
+cc_library_headers {
+ name: "jni_platform_headers",
+ host_supported: true,
+ export_include_dirs: ["platform_include"],
+}
+
cc_library {
name: "libnativehelper",
host_supported: true,
@@ -40,13 +46,12 @@
},
},
- header_libs: ["jni_headers"],
+ header_libs: ["jni_headers", "jni_platform_headers"],
export_header_lib_headers: ["jni_headers"],
shared_libs: [
"liblog",
],
- clang: true,
cflags: [
"-Werror",
"-fvisibility=protected",
@@ -63,10 +68,12 @@
cc_library_shared {
name: "libnativehelper_compat_libc++",
- clang: true,
- local_include_dirs: ["include/nativehelper"],
- export_include_dirs: ["include/nativehelper"],
+ export_include_dirs: [
+ "include",
+ "include/nativehelper", // TODO(b/63762847): remove
+ ],
cflags: ["-Werror"],
+ include_dirs: ["libnativehelper/platform_include"],
srcs: [
"JNIHelp.cpp",
"JniConstants.cpp",
@@ -82,9 +89,9 @@
ndk_headers {
name: "ndk_jni.h",
- from: "include/nativehelper",
+ from: "include_jni",
to: "",
- srcs: ["include/nativehelper/jni.h"],
+ srcs: ["include_jni/jni.h"],
license: "NOTICE",
}
diff --git a/AsynchronousCloseMonitor.cpp b/AsynchronousCloseMonitor.cpp
index 1815580..95de317 100644
--- a/AsynchronousCloseMonitor.cpp
+++ b/AsynchronousCloseMonitor.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "AsynchronousCloseMonitor"
-#include "AsynchronousCloseMonitor.h"
+#include <nativehelper/AsynchronousCloseMonitor.h>
#include "cutils/log.h"
#include <errno.h>
diff --git a/JNIHelp-priv.h b/JNIHelp-priv.h
new file mode 100644
index 0000000..ce350a5
--- /dev/null
+++ b/JNIHelp-priv.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef NATIVEHELPER_JNIHELP_PRIV_H_
+#define NATIVEHELPER_JNIHELP_PRIV_H_
+
+namespace android {
+
+void ClearJNIHelpLocalCache();
+
+} // namespace android
+
+#endif // JNIHELP_PRIV
diff --git a/JNIHelp.cpp b/JNIHelp.cpp
index 54012b8..9c6cd74 100644
--- a/JNIHelp.cpp
+++ b/JNIHelp.cpp
@@ -23,8 +23,8 @@
#define LOG_TAG "JNIHelp"
-#include "JniConstants.h"
-#include "JNIHelp.h"
+#include <nativehelper/JniConstants.h>
+#include <nativehelper/JNIHelp.h>
#include "ALog-priv.h"
#include <stdio.h>
@@ -34,6 +34,55 @@
#include <string>
+namespace {
+
+// java.io.FileDescriptor.descriptor.
+jfieldID fileDescriptorDescriptorField = nullptr;
+
+// void java.io.FileDescriptor.<init>().
+jmethodID fileDescriptorInitMethod = nullptr;
+// Object java.lang.ref.Reference.get()
+jmethodID referenceGetMethod = nullptr;
+
+jfieldID FindField(JNIEnv* env, jclass klass, const char* name, const char* desc) {
+ jfieldID result = env->GetFieldID(klass, name, desc);
+ if (result == NULL) {
+ ALOGV("failed to find field '%s:%s'", name, desc);
+ abort();
+ }
+ return result;
+}
+
+jmethodID FindMethod(JNIEnv* env, jclass klass, const char* name, const char* signature) {
+ jmethodID result = env->GetMethodID(klass, name, signature);
+ if (result == NULL) {
+ ALOGV("failed to find method '%s%s'", name, signature);
+ abort();
+ }
+ return result;
+}
+
+void InitFieldsAndMethods(JNIEnv* env) {
+ JniConstants::init(env); // Ensure that classes are cached.
+ fileDescriptorDescriptorField = FindField(env, JniConstants::fileDescriptorClass, "descriptor",
+ "I");
+ fileDescriptorInitMethod = FindMethod(env, JniConstants::fileDescriptorClass, "<init>", "()V");
+ referenceGetMethod = FindMethod(env, JniConstants::referenceClass, "get",
+ "()Ljava/lang/Object;");
+}
+
+}
+
+namespace android {
+
+void ClearJNIHelpLocalCache() {
+ fileDescriptorDescriptorField = nullptr;
+ fileDescriptorInitMethod = nullptr;
+ referenceGetMethod = nullptr;
+}
+
+}
+
/**
* Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.)
*/
@@ -326,9 +375,11 @@
jobject jniCreateFileDescriptor(C_JNIEnv* env, int fd) {
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
- JniConstants::init(e);
- static jmethodID ctor = e->GetMethodID(JniConstants::fileDescriptorClass, "<init>", "()V");
- jobject fileDescriptor = (*env)->NewObject(e, JniConstants::fileDescriptorClass, ctor);
+ if (fileDescriptorInitMethod == nullptr) {
+ InitFieldsAndMethods(e);
+ }
+ jobject fileDescriptor = (*env)->NewObject(e, JniConstants::fileDescriptorClass,
+ fileDescriptorInitMethod);
// NOTE: NewObject ensures that an OutOfMemoryError will be seen by the Java
// caller if the alloc fails, so we just return NULL when that happens.
if (fileDescriptor != NULL) {
@@ -339,10 +390,12 @@
int jniGetFDFromFileDescriptor(C_JNIEnv* env, jobject fileDescriptor) {
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
- JniConstants::init(e);
- static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
+ if (fileDescriptorDescriptorField == nullptr) {
+ InitFieldsAndMethods(e);
+ }
if (fileDescriptor != NULL) {
- return (*env)->GetIntField(e, fileDescriptor, fid);
+ return (*env)->GetIntField(e, fileDescriptor,
+ fileDescriptorDescriptorField);
} else {
return -1;
}
@@ -350,16 +403,18 @@
void jniSetFileDescriptorOfFD(C_JNIEnv* env, jobject fileDescriptor, int value) {
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
- JniConstants::init(e);
- static jfieldID fid = e->GetFieldID(JniConstants::fileDescriptorClass, "descriptor", "I");
- (*env)->SetIntField(e, fileDescriptor, fid, value);
+ if (fileDescriptorDescriptorField == nullptr) {
+ InitFieldsAndMethods(e);
+ }
+ (*env)->SetIntField(e, fileDescriptor, fileDescriptorDescriptorField, value);
}
jobject jniGetReferent(C_JNIEnv* env, jobject ref) {
JNIEnv* e = reinterpret_cast<JNIEnv*>(env);
- JniConstants::init(e);
- static jmethodID get = e->GetMethodID(JniConstants::referenceClass, "get", "()Ljava/lang/Object;");
- return (*env)->CallObjectMethod(e, ref, get);
+ if (referenceGetMethod == nullptr) {
+ InitFieldsAndMethods(e);
+ }
+ return (*env)->CallObjectMethod(e, ref, referenceGetMethod);
}
jstring jniCreateString(C_JNIEnv* env, const jchar* unicodeChars, jsize len) {
diff --git a/JniConstants.cpp b/JniConstants.cpp
index c637d82..3ac554b 100644
--- a/JniConstants.cpp
+++ b/JniConstants.cpp
@@ -17,8 +17,10 @@
#define LOG_TAG "JniConstants"
#include "ALog-priv.h"
-#include "JniConstants.h"
-#include "ScopedLocalRef.h"
+#include "JNIHelp-priv.h"
+#include <nativehelper/JniConstants.h>
+#include <nativehelper/JniConstants-priv.h>
+#include <nativehelper/ScopedLocalRef.h>
#include <stdlib.h>
@@ -136,3 +138,12 @@
g_constants_initialized = true;
}
+
+namespace android {
+
+void ClearJniConstantsCache() {
+ g_constants_initialized = false;
+ ClearJNIHelpLocalCache();
+}
+
+}
diff --git a/JniInvocation.cpp b/JniInvocation.cpp
index b869914..031dcb3 100644
--- a/JniInvocation.cpp
+++ b/JniInvocation.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "JniInvocation.h"
+#include <nativehelper/JniInvocation.h>
#include <dlfcn.h>
#include <stdlib.h>
diff --git a/include/nativehelper/ScopedLocalRef.h b/include/nativehelper/ScopedLocalRef.h
index 6e30eb3..4018f20 100644
--- a/include/nativehelper/ScopedLocalRef.h
+++ b/include/nativehelper/ScopedLocalRef.h
@@ -17,9 +17,9 @@
#ifndef SCOPED_LOCAL_REF_H_included
#define SCOPED_LOCAL_REF_H_included
-#include "jni.h"
+#include <cstddef>
-#include <stddef.h>
+#include "jni.h"
#include "JNIHelp.h" // for DISALLOW_COPY_AND_ASSIGN.
// A smart pointer that deletes a JNI local reference when it goes out of scope.
@@ -52,8 +52,40 @@
return mLocalRef;
}
+// Some better C++11 support.
+#if __cplusplus >= 201103L
+ // Move constructor.
+ ScopedLocalRef(ScopedLocalRef&& s) : mEnv(s.mEnv), mLocalRef(s.release()) {
+ }
+
+ explicit ScopedLocalRef(JNIEnv* env) : mEnv(env), mLocalRef(nullptr) {
+ }
+
+ // We do not expose an empty constructor as it can easily lead to errors
+ // using common idioms, e.g.:
+ // ScopedLocalRef<...> ref;
+ // ref.reset(...);
+
+ // Move assignment operator.
+ ScopedLocalRef& operator=(ScopedLocalRef&& s) {
+ reset(s.release());
+ mEnv = s.mEnv;
+ return *this;
+ }
+
+ // Allows "if (scoped_ref == nullptr)"
+ bool operator==(std::nullptr_t) const {
+ return mLocalRef == nullptr;
+ }
+
+ // Allows "if (scoped_ref != nullptr)"
+ bool operator!=(std::nullptr_t) const {
+ return mLocalRef != nullptr;
+ }
+#endif
+
private:
- JNIEnv* const mEnv;
+ JNIEnv* mEnv;
T mLocalRef;
DISALLOW_COPY_AND_ASSIGN(ScopedLocalRef);
diff --git a/include/nativehelper/ScopedUtfChars.h b/include/nativehelper/ScopedUtfChars.h
index 9cfa9a0..aa8489d 100644
--- a/include/nativehelper/ScopedUtfChars.h
+++ b/include/nativehelper/ScopedUtfChars.h
@@ -22,30 +22,53 @@
// A smart pointer that provides read-only access to a Java string's UTF chars.
// Unlike GetStringUTFChars, we throw NullPointerException rather than abort if
-// passed a null jstring, and c_str will return NULL.
+// passed a null jstring, and c_str will return nullptr.
// This makes the correct idiom very simple:
//
// ScopedUtfChars name(env, java_name);
-// if (name.c_str() == NULL) {
-// return NULL;
+// if (name.c_str() == nullptr) {
+// return nullptr;
// }
class ScopedUtfChars {
public:
ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
- if (s == NULL) {
- utf_chars_ = NULL;
- jniThrowNullPointerException(env, NULL);
+ if (s == nullptr) {
+ utf_chars_ = nullptr;
+ jniThrowNullPointerException(env, nullptr);
} else {
- utf_chars_ = env->GetStringUTFChars(s, NULL);
+ utf_chars_ = env->GetStringUTFChars(s, nullptr);
}
}
+ ScopedUtfChars(ScopedUtfChars&& rhs) :
+ env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) {
+ rhs.env_ = nullptr;
+ rhs.string_ = nullptr;
+ rhs.utf_chars_ = nullptr;
+ }
+
~ScopedUtfChars() {
if (utf_chars_) {
env_->ReleaseStringUTFChars(string_, utf_chars_);
}
}
+ ScopedUtfChars& operator=(ScopedUtfChars&& rhs) {
+ if (this != &rhs) {
+ // Delete the currently owned UTF chars.
+ this->~ScopedUtfChars();
+
+ // Move the rhs ScopedUtfChars and zero it out.
+ env_ = rhs.env_;
+ string_ = rhs.string_;
+ utf_chars_ = rhs.utf_chars_;
+ rhs.env_ = nullptr;
+ rhs.string_ = nullptr;
+ rhs.utf_chars_ = nullptr;
+ }
+ return *this;
+ }
+
const char* c_str() const {
return utf_chars_;
}
@@ -59,8 +82,8 @@
}
private:
- JNIEnv* const env_;
- const jstring string_;
+ JNIEnv* env_;
+ jstring string_;
const char* utf_chars_;
DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
diff --git a/include_deprecated/JNIHelp.h b/include_deprecated/JNIHelp.h
new file mode 120000
index 0000000..d4cf162
--- /dev/null
+++ b/include_deprecated/JNIHelp.h
@@ -0,0 +1 @@
+../include/nativehelper/JNIHelp.h
\ No newline at end of file
diff --git a/include_deprecated/UniquePtr.h b/include_deprecated/UniquePtr.h
new file mode 120000
index 0000000..e47c2a2
--- /dev/null
+++ b/include_deprecated/UniquePtr.h
@@ -0,0 +1 @@
+../include/nativehelper/UniquePtr.h
\ No newline at end of file
diff --git a/include_deprecated/jni.h b/include_deprecated/jni.h
new file mode 120000
index 0000000..0f70e26
--- /dev/null
+++ b/include_deprecated/jni.h
@@ -0,0 +1 @@
+../include_jni/jni.h
\ No newline at end of file
diff --git a/include_jni/jni.h b/include_jni/jni.h
deleted file mode 120000
index 88d1a00..0000000
--- a/include_jni/jni.h
+++ /dev/null
@@ -1 +0,0 @@
-../include/nativehelper/jni.h
\ No newline at end of file
diff --git a/include/nativehelper/jni.h b/include_jni/jni.h
similarity index 100%
rename from include/nativehelper/jni.h
rename to include_jni/jni.h
diff --git a/platform_include/nativehelper/JniConstants-priv.h b/platform_include/nativehelper/JniConstants-priv.h
new file mode 100644
index 0000000..c4cba7c
--- /dev/null
+++ b/platform_include/nativehelper/JniConstants-priv.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef NATIVEHELPER_PLATFORM_INCLUDE_NATIVEHELPER_JNICONSTANTS_PRIV_H_
+#define NATIVEHELPER_PLATFORM_INCLUDE_NATIVEHELPER_JNICONSTANTS_PRIV_H_
+
+namespace android {
+
+void ClearJniConstantsCache();
+
+} // namespace android
+
+#endif // NATIVEHELPER_PLATFORM_INCLUDE_NATIVEHELPER_JNICONSTANTS_PRIV_H_
diff --git a/tests/Android.bp b/tests/Android.bp
index 523b419..21d4073 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -4,7 +4,6 @@
name: "JniInvocation_test",
test_suites: ["device-tests"],
host_supported: true,
- clang: true,
srcs: ["JniInvocation_test.cpp"],
shared_libs: ["libnativehelper"],
}
diff --git a/tests/JniInvocation_test.cpp b/tests/JniInvocation_test.cpp
index 7a73c70..1467cb3 100644
--- a/tests/JniInvocation_test.cpp
+++ b/tests/JniInvocation_test.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "NativeBridge_test"
-#include <JniInvocation.h>
+#include <nativehelper/JniInvocation.h>
#include <gtest/gtest.h>
diff --git a/toStringArray.cpp b/toStringArray.cpp
index f2b0add..3ccc053 100644
--- a/toStringArray.cpp
+++ b/toStringArray.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "JniConstants.h"
-#include "toStringArray.h"
+#include <nativehelper/JniConstants.h>
+#include <nativehelper/toStringArray.h>
jobjectArray newStringArray(JNIEnv* env, size_t count) {
return env->NewObjectArray(count, JniConstants::stringClass, NULL);