Initial OpenJDK compatibility for Conscrypt
To allow use of Conscrypt on OpenJDK, add another directory. Works
currently, but no Makefile.
Change-Id: If93d2241282c7ac72881e8c9fbee0969ef66b32a
diff --git a/src/openjdk/java/dalvik/system/BlockGuard.java b/src/openjdk/java/dalvik/system/BlockGuard.java
new file mode 100644
index 0000000..6fd6001
--- /dev/null
+++ b/src/openjdk/java/dalvik/system/BlockGuard.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 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 dalvik.system;
+
+/**
+ * Blank class since OpenJDK does not implement something equivalent.
+ */
+public class BlockGuard {
+ private BlockGuard() {
+ }
+
+ public static Policy getThreadPolicy() {
+ return new PolicyWrapper();
+ }
+
+ public interface Policy {
+ void onNetwork();
+ }
+
+ public static class PolicyWrapper implements Policy {
+ private PolicyWrapper() {
+ }
+
+ public void onNetwork() {
+ }
+ }
+}
diff --git a/src/openjdk/java/dalvik/system/CloseGuard.java b/src/openjdk/java/dalvik/system/CloseGuard.java
new file mode 100644
index 0000000..70aa05e
--- /dev/null
+++ b/src/openjdk/java/dalvik/system/CloseGuard.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2014 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 dalvik.system;
+
+import java.lang.reflect.Method;
+
+/**
+ * Basically empty class since OpenJDK doesn't have the equivalent.
+ */
+public class CloseGuard {
+ private CloseGuard() {
+ }
+
+ public static CloseGuard get() {
+ return new CloseGuard();
+ }
+
+ public void open(String message) {
+ }
+
+ public void close() {
+ }
+
+ public void warnIfOpen() {
+ }
+}
diff --git a/src/openjdk/java/org/apache/harmony/security/utils/AlgNameMapper.java b/src/openjdk/java/org/apache/harmony/security/utils/AlgNameMapper.java
new file mode 100644
index 0000000..6ab1e72
--- /dev/null
+++ b/src/openjdk/java/org/apache/harmony/security/utils/AlgNameMapper.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2014 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 org.apache.harmony.security.utils;
+
+import java.security.NoSuchAlgorithmException;
+import org.conscrypt.NativeCrypto;
+import sun.security.x509.AlgorithmId;
+
+public class AlgNameMapper {
+ private AlgNameMapper() {
+ }
+
+ public static String map2AlgName(String oid) {
+ try {
+ // This gives us the common name in the Java language.
+ AlgorithmId algId = AlgorithmId.get(oid);
+ if (algId != null) {
+ return algId.getName();
+ }
+ } catch (NoSuchAlgorithmException ignored) {
+ }
+
+ // Otherwise fall back to OpenSSL or BoringSSL's name for it.
+ return NativeCrypto.OBJ_txt2nid_longName(oid);
+ }
+
+ public static void setSource(Object o) {
+ }
+}
diff --git a/src/openjdk/java/org/apache/harmony/security/utils/AlgNameMapperSource.java b/src/openjdk/java/org/apache/harmony/security/utils/AlgNameMapperSource.java
new file mode 100644
index 0000000..abca36c
--- /dev/null
+++ b/src/openjdk/java/org/apache/harmony/security/utils/AlgNameMapperSource.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 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 org.apache.harmony.security.utils;
+
+/**
+ * Provides a mapping source that the {@link AlgNameMapper} can query for
+ * mapping between algorithm names and OIDs.
+ */
+public interface AlgNameMapperSource {
+ public String mapNameToOid(String algName);
+
+ public String mapOidToName(String oid);
+}
diff --git a/src/openjdk/java/org/conscrypt/Platform.java b/src/openjdk/java/org/conscrypt/Platform.java
new file mode 100644
index 0000000..140ca46
--- /dev/null
+++ b/src/openjdk/java/org/conscrypt/Platform.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2014 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 org.conscrypt;
+
+import org.conscrypt.GCMParameters;
+import java.io.FileDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.security.InvalidKeyException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECParameterSpec;
+import javax.crypto.spec.GCMParameterSpec;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.X509TrustManager;
+
+/**
+ *
+ */
+public class Platform {
+ private static final String TAG = "Conscrypt";
+
+ private static Method m_getCurveName;
+ static {
+ try {
+ m_getCurveName = ECParameterSpec.class.getDeclaredMethod("getCurveName");
+ m_getCurveName.setAccessible(true);
+ } catch (Exception ignored) {
+ }
+ }
+
+ public static void setup() {
+ }
+
+ public static FileDescriptor getFileDescriptor(Socket s) {
+ try {
+ Field f_impl = Socket.class.getDeclaredField("impl");
+ f_impl.setAccessible(true);
+ Object socketImpl = f_impl.get(s);
+ Class<?> c_socketImpl = Class.forName("java.net.SocketImpl");
+ Field f_fd = c_socketImpl.getDeclaredField("fd");
+ f_fd.setAccessible(true);
+ return (FileDescriptor) f_fd.get(socketImpl);
+ } catch (Exception e) {
+ throw new RuntimeException("Can't get FileDescriptor from socket", e);
+ }
+ }
+
+ public static FileDescriptor getFileDescriptorFromSSLSocket(OpenSSLSocketImpl openSSLSocketImpl) {
+ return getFileDescriptor(openSSLSocketImpl);
+ }
+
+ public static String getCurveName(ECParameterSpec spec) {
+ if (m_getCurveName == null) {
+ return null;
+ }
+ try {
+ return (String) m_getCurveName.invoke(spec);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public static void setCurveName(ECParameterSpec spec, String curveName) {
+ // This doesn't appear to be needed.
+ }
+
+ /*
+ * Call Os.setsockoptTimeval via reflection.
+ */
+ public static void setSocketWriteTimeout(Socket s, long timeoutMillis) throws SocketException {
+ // TODO: figure this out on the RI
+ }
+
+ /**
+ * Tries to return a Class reference of one of the supplied class names.
+ */
+ private static Class<?> getClass(String... klasses) {
+ for (String klass : klasses) {
+ try {
+ return Class.forName(klass);
+ } catch (Exception ignored) {
+ }
+ }
+ return null;
+ }
+
+ public static void setEndpointIdentificationAlgorithm(SSLParameters params,
+ String endpointIdentificationAlgorithm) {
+ // TODO: implement this for RI
+ }
+
+ public static String getEndpointIdentificationAlgorithm(SSLParameters params) {
+ // TODO: implement this for RI
+ return null;
+ }
+
+ public static void checkServerTrusted(X509TrustManager x509tm, X509Certificate[] chain,
+ String authType, String host) throws CertificateException {
+ // TODO: use the host parameter somehow in RI
+ x509tm.checkServerTrusted(chain, authType);
+ }
+
+ /**
+ * Wraps an old AndroidOpenSSL key instance. This is not needed on RI.
+ */
+ public static OpenSSLKey wrapRsaKey(PrivateKey javaKey) {
+ return null;
+ }
+
+ /**
+ * Logs to the system EventLog system.
+ */
+ public static void logEvent(String message) {
+ }
+
+ /**
+ * Returns true if the supplied hostname is an literal IP address.
+ */
+ public static boolean isLiteralIpAddress(String hostname) {
+ // TODO: any RI API to make this better?
+ return AddressUtils.isLiteralIpAddress(hostname);
+ }
+
+ /**
+ * For unbundled versions, SNI is always enabled by default.
+ */
+ public static boolean isSniEnabledByDefault() {
+ return true;
+ }
+
+ /**
+ * Currently we don't wrap anything from the RI.
+ */
+ public static SSLSocketFactory wrapSocketFactoryIfNeeded(OpenSSLSocketFactoryImpl factory) {
+ return factory;
+ }
+
+ /**
+ * Convert from platform's GCMParameterSpec to our internal version.
+ */
+ public static GCMParameters fromGCMParameterSpec(AlgorithmParameterSpec params) {
+ if (params instanceof GCMParameterSpec) {
+ GCMParameterSpec gcmParams = (GCMParameterSpec) params;
+ return new GCMParameters(gcmParams.getTLen(), gcmParams.getIV());
+ }
+ return null;
+ }
+
+ /**
+ * Creates a platform version of {@code GCMParameterSpec}.
+ */
+ public static AlgorithmParameterSpec toGCMParameterSpec(int tagLenInBits, byte[] iv) {
+ return new GCMParameterSpec(tagLenInBits, iv);
+ }
+
+ /*
+ * CloseGuard functions.
+ */
+
+ public static Object closeGuardGet() {
+ return null;
+ }
+
+ public static void closeGuardOpen(Object guardObj, String message) {
+ }
+
+ public static void closeGuardClose(Object guardObj) {
+ }
+
+ public static void closeGuardWarnIfOpen(Object guardObj) {
+ }
+
+ /*
+ * BlockGuard functions.
+ */
+
+ public static void blockGuardOnNetwork() {
+ }
+}
diff --git a/src/openjdk/native/JNIHelp.cpp b/src/openjdk/native/JNIHelp.cpp
new file mode 100644
index 0000000..24639f4
--- /dev/null
+++ b/src/openjdk/native/JNIHelp.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2006 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.
+ */
+
+#define LOG_TAG "JNIHelp"
+
+#include "JNIHelp.h"
+
+#include "log_compat.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+/**
+ * Equivalent to ScopedLocalRef, but for C_JNIEnv instead. (And slightly more powerful.)
+ */
+template<typename T>
+class scoped_local_ref {
+public:
+ scoped_local_ref(JNIEnv* env, T localRef = NULL)
+ : mEnv(env), mLocalRef(localRef)
+ {
+ }
+
+ ~scoped_local_ref() {
+ reset();
+ }
+
+ void reset(T localRef = NULL) {
+ if (mLocalRef != NULL) {
+ mEnv->DeleteLocalRef(mLocalRef);
+ mLocalRef = localRef;
+ }
+ }
+
+ T get() const {
+ return mLocalRef;
+ }
+
+private:
+ JNIEnv* mEnv;
+ T mLocalRef;
+
+ // Disallow copy and assignment.
+ scoped_local_ref(const scoped_local_ref&);
+ void operator=(const scoped_local_ref&);
+};
+
+static jclass findClass(JNIEnv* env, const char* className) {
+ return env->FindClass(className);
+}
+
+extern "C" int jniRegisterNativeMethods(JNIEnv* env, const char* className,
+ const JNINativeMethod* gMethods, int numMethods)
+{
+ ALOGV("Registering %s's %d native methods...", className, numMethods);
+
+ scoped_local_ref<jclass> c(env, findClass(env, className));
+ if (c.get() == NULL) {
+ char* msg;
+ asprintf(&msg, "Native registration unable to find class '%s'; aborting...", className);
+ env->FatalError(msg);
+ }
+
+ if (env->RegisterNatives(c.get(), gMethods, numMethods) < 0) {
+ char* msg;
+ asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className);
+ env->FatalError(msg);
+ }
+
+ return 0;
+}
+
+#ifdef __cplusplus
+extern "C"
+#endif
+int jniThrowException(JNIEnv* env, const char* className, const char* msg) {
+ jclass exceptionClass = env->FindClass(className);
+
+ if (exceptionClass == NULL) {
+ ALOGD("Unable to find exception class %s", className);
+ /* ClassNotFoundException now pending */
+ return -1;
+ }
+
+ if (env->ThrowNew(exceptionClass, msg) != JNI_OK) {
+ ALOGD("Failed throwing '%s' '%s'", className, msg);
+ /* an exception, most likely OOM, will now be pending */
+ return -1;
+ }
+
+ env->DeleteLocalRef(exceptionClass);
+ return 0;
+}
+
+int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt, va_list args) {
+ char msgBuf[512];
+ vsnprintf(msgBuf, sizeof(msgBuf), fmt, args);
+ return jniThrowException(env, className, msgBuf);
+}
+
+int jniThrowNullPointerException(JNIEnv* env, const char* msg) {
+ return jniThrowException(env, "java/lang/NullPointerException", msg);
+}
+
+int jniThrowRuntimeException(JNIEnv* env, const char* msg) {
+ return jniThrowException(env, "java/lang/RuntimeException", msg);
+}
+
+int jniThrowIOException(JNIEnv* env, int errnum) {
+ char buffer[80];
+ const char* message = jniStrError(errnum, buffer, sizeof(buffer));
+ return jniThrowException(env, "java/io/IOException", message);
+}
+
+const char* jniStrError(int errnum, char* buf, size_t buflen) {
+#if __GLIBC__
+ // Note: glibc has a nonstandard strerror_r that returns char* rather than POSIX's int.
+ // char *strerror_r(int errnum, char *buf, size_t n);
+ return strerror_r(errnum, buf, buflen);
+#else
+ int rc = strerror_r(errnum, buf, buflen);
+ if (rc != 0) {
+ // (POSIX only guarantees a value other than 0. The safest
+ // way to implement this function is to use C++ and overload on the
+ // type of strerror_r to accurately distinguish GNU from POSIX.)
+ snprintf(buf, buflen, "errno %d", errnum);
+ }
+ return buf;
+#endif
+}
+
+int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor) {
+ scoped_local_ref<jclass> localClass(env, env->FindClass("java/io/FileDescriptor"));
+ static jfieldID fid = env->GetFieldID(localClass.get(), "descriptor", "I");
+ if (fileDescriptor != NULL) {
+ return env->GetIntField(fileDescriptor, fid);
+ } else {
+ return -1;
+ }
+}
diff --git a/src/openjdk/native/JNIHelp.h b/src/openjdk/native/JNIHelp.h
new file mode 100644
index 0000000..83c7d49
--- /dev/null
+++ b/src/openjdk/native/JNIHelp.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+/*
+ * JNI helper functions.
+ *
+ * This file may be included by C or C++ code, which is trouble because jni.h
+ * uses different typedefs for JNIEnv in each language.
+ *
+ * TODO: remove C support.
+ */
+#ifndef NATIVEHELPER_JNIHELP_H_
+#define NATIVEHELPER_JNIHELP_H_
+
+#include <jni.h>
+#include <errno.h>
+#include <unistd.h>
+
+#ifndef NELEM
+# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Register one or more native methods with a particular class.
+ * "className" looks like "java/lang/String". Aborts on failure.
+ * TODO: fix all callers and change the return type to void.
+ */
+int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods);
+
+/*
+ * Throw an exception with the specified class and an optional message.
+ *
+ * The "className" argument will be passed directly to FindClass, which
+ * takes strings with slashes (e.g. "java/lang/Object").
+ *
+ * If an exception is currently pending, we log a warning message and
+ * clear it.
+ *
+ * Returns 0 on success, nonzero if something failed (e.g. the exception
+ * class couldn't be found, so *an* exception will still be pending).
+ *
+ * Currently aborts the VM if it can't throw the exception.
+ */
+int jniThrowException(JNIEnv* env, const char* className, const char* msg);
+
+/*
+ * Throw a java.lang.NullPointerException, with an optional message.
+ */
+int jniThrowNullPointerException(JNIEnv* env, const char* msg);
+
+/*
+ * Throw a java.lang.RuntimeException, with an optional message.
+ */
+int jniThrowRuntimeException(JNIEnv* env, const char* msg);
+
+/*
+ * Throw a java.io.IOException, generating the message from errno.
+ */
+int jniThrowIOException(JNIEnv* env, int errnum);
+
+/*
+ * Return a pointer to a locale-dependent error string explaining errno
+ * value 'errnum'. The returned pointer may or may not be equal to 'buf'.
+ * This function is thread-safe (unlike strerror) and portable (unlike
+ * strerror_r).
+ */
+const char* jniStrError(int errnum, char* buf, size_t buflen);
+
+/*
+ * Returns a new java.io.FileDescriptor for the given int fd.
+ */
+jobject jniCreateFileDescriptor(JNIEnv* env, int fd);
+
+/*
+ * Returns the int fd from a java.io.FileDescriptor.
+ */
+int jniGetFDFromFileDescriptor(JNIEnv* env, jobject fileDescriptor);
+
+/*
+ * Sets the int fd in a java.io.FileDescriptor.
+ */
+void jniSetFileDescriptorOfFD(JNIEnv* env, jobject fileDescriptor, int value);
+
+/*
+ * Returns the reference from a java.lang.ref.Reference.
+ */
+jobject jniGetReferent(JNIEnv* env, jobject ref);
+
+/*
+ * Log a message and an exception.
+ * If exception is NULL, logs the current exception in the JNI environment.
+ */
+void jniLogException(JNIEnv* env, int priority, const char* tag, jthrowable exception);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#if defined(__cplusplus)
+extern "C" int jniThrowExceptionFmt(JNIEnv* env, const char* className, const char* fmt, va_list args);
+#endif
+
+/*
+ * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
+ * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
+ * not already defined, then define it here.
+ */
+#ifndef TEMP_FAILURE_RETRY
+/* Used to retry syscalls that can return EINTR. */
+#define TEMP_FAILURE_RETRY(exp) ({ \
+ typeof (exp) _rc; \
+ do { \
+ _rc = (exp); \
+ } while (_rc == -1 && errno == EINTR); \
+ _rc; })
+#endif
+
+#endif /* NATIVEHELPER_JNIHELP_H_ */
diff --git a/src/openjdk/native/NetFd.h b/src/openjdk/native/NetFd.h
new file mode 100644
index 0000000..235b057
--- /dev/null
+++ b/src/openjdk/native/NetFd.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 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 NET_FD_H_included
+#define NET_FD_H_included
+
+/**
+ * Wraps access to the int inside a java.io.FileDescriptor, taking care of throwing exceptions.
+ */
+class NetFd {
+public:
+ NetFd(JNIEnv* env, jobject fileDescriptor)
+ : mEnv(env), mFileDescriptor(fileDescriptor), mFd(-1)
+ {
+ }
+
+ bool isClosed() {
+ mFd = jniGetFDFromFileDescriptor(mEnv, mFileDescriptor);
+ bool closed = (mFd == -1);
+ if (closed) {
+ jniThrowException(mEnv, "java/net/SocketException", "Socket closed");
+ }
+ return closed;
+ }
+
+ int get() const {
+ return mFd;
+ }
+
+private:
+ JNIEnv* mEnv;
+ jobject mFileDescriptor;
+ int mFd;
+
+ // Disallow copy and assignment.
+ NetFd(const NetFd&);
+ void operator=(const NetFd&);
+};
+
+/**
+ * Used to retry syscalls that can return EINTR. This differs from TEMP_FAILURE_RETRY in that
+ * it also considers the case where the reason for failure is that another thread called
+ * Socket.close.
+ */
+#define NET_FAILURE_RETRY(fd, exp) ({ \
+ typeof (exp) _rc; \
+ do { \
+ _rc = (exp); \
+ if (_rc == -1) { \
+ if (fd.isClosed() || errno != EINTR) { \
+ break; \
+ } \
+ } \
+ } while (_rc == -1); \
+ _rc; })
+
+#endif // NET_FD_H_included
diff --git a/src/openjdk/native/ScopedLocalRef.h b/src/openjdk/native/ScopedLocalRef.h
new file mode 100644
index 0000000..71d5776
--- /dev/null
+++ b/src/openjdk/native/ScopedLocalRef.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 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 SCOPED_LOCAL_REF_H_included
+#define SCOPED_LOCAL_REF_H_included
+
+#include "jni.h"
+
+#include <stddef.h>
+
+// A smart pointer that deletes a JNI local reference when it goes out of scope.
+template<typename T>
+class ScopedLocalRef {
+public:
+ ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) {
+ }
+
+ ~ScopedLocalRef() {
+ reset();
+ }
+
+ void reset(T ptr = NULL) {
+ if (ptr != mLocalRef) {
+ if (mLocalRef != NULL) {
+ mEnv->DeleteLocalRef(mLocalRef);
+ }
+ mLocalRef = ptr;
+ }
+ }
+
+ T release() __attribute__((warn_unused_result)) {
+ T localRef = mLocalRef;
+ mLocalRef = NULL;
+ return localRef;
+ }
+
+ T get() const {
+ return mLocalRef;
+ }
+
+private:
+ JNIEnv* mEnv;
+ T mLocalRef;
+
+ // Disallow copy and assignment.
+ ScopedLocalRef(const ScopedLocalRef&);
+ void operator=(const ScopedLocalRef&);
+};
+
+#endif // SCOPED_LOCAL_REF_H_included
diff --git a/src/openjdk/native/ScopedPrimitiveArray.h b/src/openjdk/native/ScopedPrimitiveArray.h
new file mode 100644
index 0000000..d797b9d
--- /dev/null
+++ b/src/openjdk/native/ScopedPrimitiveArray.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 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 SCOPED_PRIMITIVE_ARRAY_H_included
+#define SCOPED_PRIMITIVE_ARRAY_H_included
+
+#include "JNIHelp.h"
+
+// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO,
+// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide
+// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write
+// access and should be used by default.
+#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \
+ class Scoped ## NAME ## ArrayRO { \
+ public: \
+ explicit Scoped ## NAME ## ArrayRO(JNIEnv* env) \
+ : mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \
+ Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
+ : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
+ if (mJavaArray == NULL) { \
+ jniThrowNullPointerException(mEnv, NULL); \
+ } else { \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ } \
+ ~Scoped ## NAME ## ArrayRO() { \
+ if (mRawArray) { \
+ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \
+ } \
+ } \
+ void reset(PRIMITIVE_TYPE ## Array javaArray) { \
+ mJavaArray = javaArray; \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ const PRIMITIVE_TYPE* get() const { return mRawArray; } \
+ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
+ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
+ size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
+ private: \
+ JNIEnv* mEnv; \
+ PRIMITIVE_TYPE ## Array mJavaArray; \
+ PRIMITIVE_TYPE* mRawArray; \
+ Scoped ## NAME ## ArrayRO(const Scoped ## NAME ## ArrayRO&); \
+ void operator=(const Scoped ## NAME ## ArrayRO&); \
+ }
+
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
+
+#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO
+
+// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW,
+// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide
+// convenient read-write access to Java arrays from JNI code. These are more expensive,
+// since they entail a copy back onto the Java heap, and should only be used when necessary.
+#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \
+ class Scoped ## NAME ## ArrayRW { \
+ public: \
+ explicit Scoped ## NAME ## ArrayRW(JNIEnv* env) \
+ : mEnv(env), mJavaArray(NULL), mRawArray(NULL) {} \
+ Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
+ : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
+ if (mJavaArray == NULL) { \
+ jniThrowNullPointerException(mEnv, NULL); \
+ } else { \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ } \
+ ~Scoped ## NAME ## ArrayRW() { \
+ if (mRawArray) { \
+ mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \
+ } \
+ } \
+ void reset(PRIMITIVE_TYPE ## Array javaArray) { \
+ mJavaArray = javaArray; \
+ mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
+ } \
+ const PRIMITIVE_TYPE* get() const { return mRawArray; } \
+ PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
+ const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
+ PRIMITIVE_TYPE* get() { return mRawArray; } \
+ PRIMITIVE_TYPE& operator[](size_t n) { return mRawArray[n]; } \
+ size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
+ private: \
+ JNIEnv* mEnv; \
+ PRIMITIVE_TYPE ## Array mJavaArray; \
+ PRIMITIVE_TYPE* mRawArray; \
+ Scoped ## NAME ## ArrayRW(const Scoped ## NAME ## ArrayRW&); \
+ void operator=(const Scoped ## NAME ## ArrayRW&); \
+ }
+
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long);
+INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short);
+
+#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW
+
+#endif // SCOPED_PRIMITIVE_ARRAY_H_included
diff --git a/src/openjdk/native/ScopedUtfChars.h b/src/openjdk/native/ScopedUtfChars.h
new file mode 100644
index 0000000..7761450
--- /dev/null
+++ b/src/openjdk/native/ScopedUtfChars.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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 SCOPED_UTF_CHARS_H_included
+#define SCOPED_UTF_CHARS_H_included
+
+#include "JNIHelp.h"
+#include <string.h>
+
+// 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.
+// This makes the correct idiom very simple:
+//
+// ScopedUtfChars name(env, java_name);
+// if (name.c_str() == NULL) {
+// return NULL;
+// }
+class ScopedUtfChars {
+ public:
+ ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
+ if (s == NULL) {
+ utf_chars_ = NULL;
+ jniThrowNullPointerException(env, NULL);
+ } else {
+ utf_chars_ = env->GetStringUTFChars(s, NULL);
+ }
+ }
+
+ ~ScopedUtfChars() {
+ if (utf_chars_) {
+ env_->ReleaseStringUTFChars(string_, utf_chars_);
+ }
+ }
+
+ const char* c_str() const {
+ return utf_chars_;
+ }
+
+ size_t size() const {
+ return strlen(utf_chars_);
+ }
+
+ const char& operator[](size_t n) const {
+ return utf_chars_[n];
+ }
+
+ private:
+ JNIEnv* env_;
+ jstring string_;
+ const char* utf_chars_;
+
+ // Disallow copy and assignment.
+ ScopedUtfChars(const ScopedUtfChars&);
+ void operator=(const ScopedUtfChars&);
+};
+
+#endif // SCOPED_UTF_CHARS_H_included
diff --git a/src/openjdk/native/UniquePtr.h b/src/openjdk/native/UniquePtr.h
new file mode 100644
index 0000000..50f75b2
--- /dev/null
+++ b/src/openjdk/native/UniquePtr.h
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2010 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 UNIQUE_PTR_H_included
+#define UNIQUE_PTR_H_included
+
+#include <cstdlib> // For NULL.
+
+// This is a fake declaration of std::swap to avoid including <algorithm>
+namespace std {
+template <class T> void swap(T&, T&);
+}
+
+// Default deleter for pointer types.
+template <typename T>
+struct DefaultDelete {
+ enum { type_must_be_complete = sizeof(T) };
+ DefaultDelete() {}
+ void operator()(T* p) const {
+ delete p;
+ }
+};
+
+// Default deleter for array types.
+template <typename T>
+struct DefaultDelete<T[]> {
+ enum { type_must_be_complete = sizeof(T) };
+ void operator()(T* p) const {
+ delete[] p;
+ }
+};
+
+// A smart pointer that deletes the given pointer on destruction.
+// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
+// and boost::scoped_array).
+// Named to be in keeping with Android style but also to avoid
+// collision with any other implementation, until we can switch over
+// to unique_ptr.
+// Use thus:
+// UniquePtr<C> c(new C);
+template <typename T, typename D = DefaultDelete<T> >
+class UniquePtr {
+public:
+ // Construct a new UniquePtr, taking ownership of the given raw pointer.
+ explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
+ }
+
+ ~UniquePtr() {
+ reset();
+ }
+
+ // Accessors.
+ T& operator*() const { return *mPtr; }
+ T* operator->() const { return mPtr; }
+ T* get() const { return mPtr; }
+
+ // Returns the raw pointer and hands over ownership to the caller.
+ // The pointer will not be deleted by UniquePtr.
+ T* release() __attribute__((warn_unused_result)) {
+ T* result = mPtr;
+ mPtr = NULL;
+ return result;
+ }
+
+ // Takes ownership of the given raw pointer.
+ // If this smart pointer previously owned a different raw pointer, that
+ // raw pointer will be freed.
+ void reset(T* ptr = NULL) {
+ if (ptr != mPtr) {
+ D()(mPtr);
+ mPtr = ptr;
+ }
+ }
+
+ // Swap with another unique pointer.
+ void swap(UniquePtr<T>& other) {
+ std::swap(mPtr, other.mPtr);
+ }
+
+private:
+ // The raw pointer.
+ T* mPtr;
+
+ // Comparing unique pointers is probably a mistake, since they're unique.
+ template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
+ template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
+
+ // Disallow copy and assignment.
+ UniquePtr(const UniquePtr&);
+ void operator=(const UniquePtr&);
+};
+
+// Partial specialization for array types. Like std::unique_ptr, this removes
+// operator* and operator-> but adds operator[].
+template <typename T, typename D>
+class UniquePtr<T[], D> {
+public:
+ explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
+ }
+
+ ~UniquePtr() {
+ reset();
+ }
+
+ T& operator[](size_t i) const {
+ return mPtr[i];
+ }
+ T* get() const { return mPtr; }
+
+ T* release() __attribute__((warn_unused_result)) {
+ T* result = mPtr;
+ mPtr = NULL;
+ return result;
+ }
+
+ void reset(T* ptr = NULL) {
+ if (ptr != mPtr) {
+ D()(mPtr);
+ mPtr = ptr;
+ }
+ }
+
+private:
+ T* mPtr;
+
+ // Disallow copy and assignment.
+ UniquePtr(const UniquePtr&);
+ void operator=(const UniquePtr&);
+};
+
+#if UNIQUE_PTR_TESTS
+
+// Run these tests with:
+// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
+
+#include <stdio.h>
+
+static void assert(bool b) {
+ if (!b) {
+ fprintf(stderr, "FAIL\n");
+ abort();
+ }
+ fprintf(stderr, "OK\n");
+}
+static int cCount = 0;
+struct C {
+ C() { ++cCount; }
+ ~C() { --cCount; }
+};
+static bool freed = false;
+struct Freer {
+ void operator()(int* p) {
+ assert(*p == 123);
+ free(p);
+ freed = true;
+ }
+};
+
+int main(int argc, char* argv[]) {
+ //
+ // UniquePtr<T> tests...
+ //
+
+ // Can we free a single object?
+ {
+ UniquePtr<C> c(new C);
+ assert(cCount == 1);
+ }
+ assert(cCount == 0);
+ // Does release work?
+ C* rawC;
+ {
+ UniquePtr<C> c(new C);
+ assert(cCount == 1);
+ rawC = c.release();
+ }
+ assert(cCount == 1);
+ delete rawC;
+ // Does reset work?
+ {
+ UniquePtr<C> c(new C);
+ assert(cCount == 1);
+ c.reset(new C);
+ assert(cCount == 1);
+ }
+ assert(cCount == 0);
+
+ //
+ // UniquePtr<T[]> tests...
+ //
+
+ // Can we free an array?
+ {
+ UniquePtr<C[]> cs(new C[4]);
+ assert(cCount == 4);
+ }
+ assert(cCount == 0);
+ // Does release work?
+ {
+ UniquePtr<C[]> c(new C[4]);
+ assert(cCount == 4);
+ rawC = c.release();
+ }
+ assert(cCount == 4);
+ delete[] rawC;
+ // Does reset work?
+ {
+ UniquePtr<C[]> c(new C[4]);
+ assert(cCount == 4);
+ c.reset(new C[2]);
+ assert(cCount == 2);
+ }
+ assert(cCount == 0);
+
+ //
+ // Custom deleter tests...
+ //
+ assert(!freed);
+ {
+ UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
+ *i = 123;
+ }
+ assert(freed);
+ return 0;
+}
+#endif
+
+#endif // UNIQUE_PTR_H_included
diff --git a/src/openjdk/native/log_compat.h b/src/openjdk/native/log_compat.h
new file mode 100644
index 0000000..0495ffe
--- /dev/null
+++ b/src/openjdk/native/log_compat.h
@@ -0,0 +1,6 @@
+#define ALOGD(...) \
+ /* __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) */
+#define ALOGE(...) \
+ /* __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) */
+#define ALOGV(...) \
+ /* __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) */