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__) */