diff options
| author | Lorenzo Colitti <lorenzo@google.com> | 2014-08-22 03:07:27 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-08-22 03:07:28 +0000 |
| commit | e258de6f9e4eae028fd6c09d76ea440d4fc169e8 (patch) | |
| tree | 99baa3344c37eed6f0ed9c05b1caf22e0e8d649f /core/java/android | |
| parent | 1bfc75fc047d69968f0f5ec217270bf751293d7f (diff) | |
| parent | 9f1274b7e43d14c7e3a42148ebfda3905fec8b06 (diff) | |
Merge "Rework the per-network URL API." into lmp-dev
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/net/Network.java | 112 | ||||
| -rw-r--r-- | core/java/android/net/NetworkUtils.java | 3 |
2 files changed, 51 insertions, 64 deletions
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 0de3f2606bfc..d2a4728fb070 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -16,10 +16,10 @@ package android.net; -import android.net.NetworkBoundURLFactory; import android.net.NetworkUtils; import android.os.Parcelable; import android.os.Parcel; +import android.system.ErrnoException; import java.io.IOException; import java.net.InetAddress; @@ -30,6 +30,7 @@ import java.net.SocketAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.net.URL; +import java.net.URLConnection; import java.net.URLStreamHandler; import java.util.concurrent.atomic.AtomicReference; import javax.net.SocketFactory; @@ -54,7 +55,7 @@ public class Network implements Parcelable { public final int netId; // Objects used to perform per-network operations such as getSocketFactory - // and getBoundURL, and a lock to protect access to them. + // and openConnection, and a lock to protect access to them. private volatile NetworkBoundSocketFactory mNetworkBoundSocketFactory = null; private volatile OkHttpClient mOkHttpClient = null; private Object mLock = new Object(); @@ -157,12 +158,7 @@ public class Network implements Parcelable { @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(); - if (!NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), mNetId)) { - throw new SocketException("Failed to bind socket to network."); - } + bindSocket(socket); return socket; } } @@ -187,73 +183,63 @@ public class Network implements Parcelable { return mNetworkBoundSocketFactory; } - /** The default NetworkBoundURLFactory, used if setNetworkBoundURLFactory is never called. */ - private static final NetworkBoundURLFactory DEFAULT_URL_FACTORY = new NetworkBoundURLFactory() { - public URL getBoundURL(final Network network, URL url) throws MalformedURLException { - if (network.mOkHttpClient == null) { - synchronized (network.mLock) { - if (network.mOkHttpClient == null) { - HostResolver hostResolver = new HostResolver() { - @Override - public InetAddress[] getAllByName(String host) - throws UnknownHostException { - return network.getAllByName(host); - } - }; - network.mOkHttpClient = new OkHttpClient() - .setSocketFactory(network.getSocketFactory()) - .setHostResolver(hostResolver); - } + private void maybeInitHttpClient() { + if (mOkHttpClient == null) { + synchronized (mLock) { + if (mOkHttpClient == null) { + HostResolver hostResolver = new HostResolver() { + @Override + public InetAddress[] getAllByName(String host) throws UnknownHostException { + return Network.this.getAllByName(host); + } + }; + mOkHttpClient = new OkHttpClient() + .setSocketFactory(getSocketFactory()) + .setHostResolver(hostResolver); } } - - String protocol = url.getProtocol(); - URLStreamHandler handler = network.mOkHttpClient.createURLStreamHandler(protocol); - if (handler == null) { - // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if - // passed another protocol. - throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol); - } - return new URL(url, "", handler); } - }; - - private static AtomicReference<NetworkBoundURLFactory> sNetworkBoundURLFactory = - new AtomicReference <NetworkBoundURLFactory>(DEFAULT_URL_FACTORY); + } /** - * Returns a {@link URL} based on the given URL but bound to this {@code Network}, - * such that opening the URL will send all network traffic on this Network. + * Opens the specified {@link URL} on this {@code Network}, such that all traffic will be sent + * on this Network. The URL protocol must be {@code HTTP} or {@code HTTPS}. * - * Note that if this {@code Network} ever disconnects, any URL object generated by this method - * in the past or future will cease to work. - * - * The returned URL may have a {@link URLStreamHandler} explicitly set, which may not be the - * handler generated by the factory set with {@link java.net.URL#setURLStreamHandlerFactory}. To - * affect the {@code URLStreamHandler}s of URLs returned by this method, call - * {@link #setNetworkBoundURLFactory}. - * - * Because the returned URLs may have an explicit {@code URLStreamHandler} set, using them as a - * context when constructing other URLs and explicitly specifying a {@code URLStreamHandler} may - * result in URLs that are no longer bound to the same {@code Network}. - * - * The default implementation only supports {@code HTTP} and {@code HTTPS} URLs. - * - * @return a {@link URL} bound to this {@code Network}. + * @return a {@code URLConnection} to the resource referred to by this URL. + * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS. + * @throws IOException if an error occurs while opening the connection. + * @see java.net.URL#openConnection() */ - public URL getBoundURL(URL url) throws MalformedURLException { - return sNetworkBoundURLFactory.get().getBoundURL(this, url); + public URLConnection openConnection(URL url) throws IOException { + maybeInitHttpClient(); + String protocol = url.getProtocol(); + URLStreamHandler handler = mOkHttpClient.createURLStreamHandler(protocol); + if (handler == null) { + // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if + // passed another protocol. + throw new MalformedURLException("Invalid URL or unrecognized protocol " + protocol); + } + return new URL(url, "", handler).openConnection(); } /** - * Sets the {@link NetworkBoundURLFactory} to be used by future {@link #getBoundURL} calls. - * If {@code null}, clears any factory that was previously specified. + * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket + * will be sent on this {@code Network}, irrespective of any process-wide network binding set by + * {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be connected. */ - public static void setNetworkBoundURLFactory(NetworkBoundURLFactory factory) { - if (factory == null) { - factory = DEFAULT_URL_FACTORY; + public void bindSocket(Socket socket) throws IOException { + if (socket.isConnected()) { + throw new SocketException("Socket is connected"); + } + // 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(); + int err = NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), netId); + if (err != 0) { + // bindSocketToNetwork returns negative errno. + throw new ErrnoException("Binding socket to network " + netId, -err) + .rethrowAsSocketException(); } - sNetworkBoundURLFactory.set(factory); } // implement the Parcelable interface diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 54d8676be5a1..d2a29975c3e7 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -128,8 +128,9 @@ public class NetworkUtils { /** * Explicitly binds {@code socketfd} to the network designated by {@code netId}. This * overrides any binding via {@link #bindProcessToNetwork}. + * @return 0 on success or negative errno on failure. */ - public native static boolean bindSocketToNetwork(int socketfd, int netId); + public native static int bindSocketToNetwork(int socketfd, int netId); /** * Protect {@code socketfd} from VPN connections. After protecting, data sent through |
