Merge "Implement bind-to-network functionality of android.net.Network." into lmp-preview-dev
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index e0d69e3..e489e05 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -16,10 +16,13 @@
package android.net;
+import android.net.NetworkUtils;
import android.os.Parcelable;
import android.os.Parcel;
+import java.io.IOException;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.SocketFactory;
@@ -38,6 +41,8 @@
*/
public final int netId;
+ private NetworkBoundSocketFactory mNetworkBoundSocketFactory = null;
+
/**
* @hide
*/
@@ -79,6 +84,59 @@
}
/**
+ * A {@code SocketFactory} that produces {@code Socket}'s bound to this network.
+ */
+ private class NetworkBoundSocketFactory extends SocketFactory {
+ private final int mNetId;
+
+ public NetworkBoundSocketFactory(int netId) {
+ super();
+ mNetId = netId;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
+ Socket socket = createSocket();
+ socket.bind(new InetSocketAddress(localHost, localPort));
+ socket.connect(new InetSocketAddress(host, port));
+ return socket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
+ int localPort) throws IOException {
+ Socket socket = createSocket();
+ socket.bind(new InetSocketAddress(localAddress, localPort));
+ socket.connect(new InetSocketAddress(address, port));
+ return socket;
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ Socket socket = createSocket();
+ socket.connect(new InetSocketAddress(host, port));
+ return socket;
+ }
+
+ @Override
+ public Socket createSocket(String host, int port) throws IOException {
+ Socket socket = createSocket();
+ socket.connect(new InetSocketAddress(host, port));
+ return socket;
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ Socket socket = new Socket();
+ // Query a property of the underlying socket to ensure the underlying
+ // socket exists so a file descriptor is available to bind to a network.
+ socket.getReuseAddress();
+ NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), mNetId);
+ return socket;
+ }
+ }
+
+ /**
* Returns a {@link SocketFactory} bound to this network. Any {@link Socket} created by
* this factory will have its traffic sent over this {@code Network}. Note that if this
* {@code Network} ever disconnects, this factory and any {@link Socket} it produced in the
@@ -88,7 +146,10 @@
* {@code Network}.
*/
public SocketFactory socketFactory() {
- return null;
+ if (mNetworkBoundSocketFactory == null) {
+ mNetworkBoundSocketFactory = new NetworkBoundSocketFactory(netId);
+ }
+ return mNetworkBoundSocketFactory;
}
/**
@@ -99,6 +160,29 @@
* doesn't accidentally use sockets it thinks are still bound to a particular {@code Network}.
*/
public void bindProcess() {
+ NetworkUtils.bindProcessToNetwork(netId);
+ }
+
+ /**
+ * Binds host resolutions performed by this process to this network. {@link #bindProcess}
+ * takes precedence over this setting.
+ *
+ * @hide
+ * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
+ */
+ public void bindProcessForHostResolution() {
+ NetworkUtils.bindProcessToNetworkForHostResolution(netId);
+ }
+
+ /**
+ * Clears any process specific {@link Network} binding for host resolution. This does
+ * not clear bindings enacted via {@link #bindProcess}.
+ *
+ * @hide
+ * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
+ */
+ public void unbindProcessForHostResolution() {
+ NetworkUtils.unbindProcessToNetworkForHostResolution();
}
/**
@@ -107,7 +191,7 @@
* @return {@code Network} to which this process is bound.
*/
public static Network getProcessBoundNetwork() {
- return null;
+ return new Network(NetworkUtils.getNetworkBoundToProcess());
}
/**
@@ -115,6 +199,7 @@
* {@link Network#bindProcess}.
*/
public static void unbindProcess() {
+ NetworkUtils.unbindProcessToNetwork();
}
// implement the Parcelable interface
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index b24d396..edb3286 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -109,6 +109,50 @@
public native static void markSocket(int socketfd, int mark);
/**
+ * Binds the current process to the network designated by {@code netId}. All sockets created
+ * in the future (and not explicitly bound via a bound {@link SocketFactory} (see
+ * {@link Network#socketFactory}) will be bound to this network. Note that if this
+ * {@code Network} ever disconnects all sockets created in this way will cease to work. This
+ * is by design so an application doesn't accidentally use sockets it thinks are still bound to
+ * a particular {@code Network}.
+ */
+ public native static void bindProcessToNetwork(int netId);
+
+ /**
+ * Clear any process specific {@code Network} binding. This reverts a call to
+ * {@link #bindProcessToNetwork}.
+ */
+ public native static void unbindProcessToNetwork();
+
+ /**
+ * Return the netId last passed to {@link #bindProcessToNetwork}, or NETID_UNSET if
+ * {@link #unbindProcessToNetwork} has been called since {@link #bindProcessToNetwork}.
+ */
+ public native static int getNetworkBoundToProcess();
+
+ /**
+ * Binds host resolutions performed by this process to the network designated by {@code netId}.
+ * {@link #bindProcessToNetwork} takes precedence over this setting.
+ *
+ * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
+ */
+ public native static void bindProcessToNetworkForHostResolution(int netId);
+
+ /**
+ * Clears any process specific {@link Network} binding for host resolution. This does
+ * not clear bindings enacted via {@link #bindProcessToNetwork}.
+ *
+ * @deprecated This is strictly for legacy usage to support startUsingNetworkFeature().
+ */
+ public native static void unbindProcessToNetworkForHostResolution();
+
+ /**
+ * Explicitly binds {@code socketfd} to the network designated by {@code netId}. This
+ * overrides any binding via {@link #bindProcessToNetwork}.
+ */
+ public native static void bindSocketToNetwork(int socketfd, int netId);
+
+ /**
* Convert a IPv4 address from an integer to an InetAddress.
* @param hostAddress an int corresponding to the IPv4 address in network byte order
*/
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index a159715..f446c3a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -173,8 +173,10 @@
$(call include-path-for, bluedroid) \
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
+ $(TOP)/bionic/libc/dns/include \
$(TOP)/frameworks/av/include \
$(TOP)/system/media/camera/include \
+ $(TOP)/system/netd/include \
external/pdfium/core/include/fpdfapi \
external/pdfium/core/include/fpdfdoc \
external/pdfium/fpdfsdk/include \
@@ -233,6 +235,7 @@
libaudioutils \
libpdfium \
libimg_utils \
+ libnetd_client \
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 6d23c32..bc5e1b3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -18,6 +18,8 @@
#include "jni.h"
#include "JNIHelp.h"
+#include "NetdClient.h"
+#include "resolv_netid.h"
#include <utils/misc.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
@@ -250,6 +252,36 @@
}
}
+static void android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
+{
+ setNetworkForProcess(netId);
+}
+
+static void android_net_utils_unbindProcessToNetwork(JNIEnv *env, jobject thiz)
+{
+ setNetworkForProcess(NETID_UNSET);
+}
+
+static jint android_net_utils_getNetworkBoundToProcess(JNIEnv *env, jobject thiz)
+{
+ return getNetworkForProcess();
+}
+
+static void android_net_utils_bindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz, jint netId)
+{
+ setNetworkForResolv(netId);
+}
+
+static void android_net_utils_unbindProcessToNetworkForHostResolution(JNIEnv *env, jobject thiz)
+{
+ setNetworkForResolv(NETID_UNSET);
+}
+
+static void android_net_utils_bindSocketToNetwork(JNIEnv *env, jobject thiz, jint socket, jint netId)
+{
+ setNetworkForSocket(netId, socket);
+}
+
// ----------------------------------------------------------------------------
/*
@@ -267,6 +299,12 @@
{ "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease },
{ "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
{ "markSocket", "(II)V", (void*) android_net_utils_markSocket },
+ { "bindProcessToNetwork", "(I)V", (void*) android_net_utils_bindProcessToNetwork },
+ { "getNetworkBoundToProcess", "()I", (void*) android_net_utils_getNetworkBoundToProcess },
+ { "unbindProcessToNetwork", "()V", (void*) android_net_utils_unbindProcessToNetwork },
+ { "bindProcessToNetworkForHostResolution", "(I)V", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
+ { "unbindProcessToNetworkForHostResolution", "()V", (void*) android_net_utils_unbindProcessToNetworkForHostResolution },
+ { "bindSocketToNetwork", "(II)V", (void*) android_net_utils_bindSocketToNetwork },
};
int register_android_net_NetworkUtils(JNIEnv* env)