Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0bef716 authored by Paul Jensen's avatar Paul Jensen
Browse files

Fix several HTTP proxy issues with multinetworking.

1. Send PROXY_CHANGE_ACTION broadcast when any network's proxy changes,
   not just the default network.
2. When a process is bound to a particular Network, update the proxy
   system properties to those for the bound Network, and keep them
   updated when PROXY_CHANGE_ACTION broadcasts are received.
3. Make Network.openConnection() use the proxy for the Network.

bug:17905627
bug:17420465
bug:18144582

(cherry-pick of https://android-review.googlesource.com/#/c/115170)

Change-Id: Ia2819985e6108a8c121e74c683a5646becfd0a97
parent 8b33cf4d
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -44,7 +44,10 @@ import android.database.sqlite.SQLiteDebug.DbStats;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.hardware.display.DisplayManagerGlobal;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.Proxy;
import android.net.ProxyInfo;
import android.net.Uri;
@@ -839,8 +842,14 @@ public final class ActivityThread {
        }

        public void setHttpProxy(String host, String port, String exclList, Uri pacFileUrl) {
            final Network network = ConnectivityManager.getProcessDefaultNetwork();
            if (network != null) {
                Proxy.setHttpProxySystemProperty(
                        ConnectivityManager.from(getSystemContext()).getDefaultProxy());
            } else {
                Proxy.setHttpProxySystemProperty(host, port, exclList, pacFileUrl);
            }
        }

        public void processInBackground() {
            mH.removeMessages(H.GC_WHEN_IDLE);
@@ -4430,7 +4439,7 @@ public final class ActivityThread {
            // crash if we can't get it.
            IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
            try {
                ProxyInfo proxyInfo = service.getProxy();
                final ProxyInfo proxyInfo = service.getDefaultProxy();
                Proxy.setHttpProxySystemProperty(proxyInfo);
            } catch (RemoteException e) {}
        }
+38 −9
Original line number Diff line number Diff line
@@ -452,6 +452,13 @@ public class ConnectivityManager {
    public static final int NETID_UNSET = 0;

    private final IConnectivityManager mService;
    /**
     * A kludge to facilitate static access where a Context pointer isn't available, like in the
     * case of the static set/getProcessDefaultNetwork methods and from the Network class.
     * TODO: Remove this after deprecating the static methods in favor of non-static methods or
     * methods that take a Context argument.
     */
    private static ConnectivityManager sInstance;

    private INetworkManagementService mNMService;

@@ -1397,6 +1404,7 @@ public class ConnectivityManager {
     */
    public ConnectivityManager(IConnectivityManager service) {
        mService = checkNotNull(service, "missing IConnectivityManager");
        sInstance = this;
    }

    /** {@hide} */
@@ -1418,6 +1426,18 @@ public class ConnectivityManager {
        }
    }

    /**
     * @deprecated - use getSystemService. This is a kludge to support static access in certain
     *               situations where a Context pointer is unavailable.
     * @hide
     */
    public static ConnectivityManager getInstance() {
        if (sInstance == null) {
            throw new IllegalStateException("No ConnectivityManager yet constructed");
        }
        return sInstance;
    }

    /**
     * Get the set of tetherable, available interfaces.  This list is limited by
     * device configuration and current interface existence.
@@ -1749,20 +1769,26 @@ public class ConnectivityManager {
    }

    /**
     * Get the HTTP proxy settings for the current default network.  Note that
     * if a global proxy is set, it will override any per-network setting.
     * Get the current default HTTP proxy settings.  If a global proxy is set it will be returned,
     * otherwise if this process is bound to a {@link Network} using
     * {@link #setProcessDefaultNetwork} then that {@code Network}'s proxy is returned, otherwise
     * the default network's proxy is returned.
     *
     * @return the {@link ProxyInfo} for the current HTTP proxy, or {@code null} if no
     *        HTTP proxy is active.
     *
     * <p>This method requires the call to hold the permission
     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
     * {@hide}
     * @deprecated Deprecated in favor of {@link #getLinkProperties}
     * @hide
     */
    public ProxyInfo getProxy() {
    public ProxyInfo getDefaultProxy() {
        final Network network = getProcessDefaultNetwork();
        if (network != null) {
            final ProxyInfo globalProxy = getGlobalProxy();
            if (globalProxy != null) return globalProxy;
            final LinkProperties lp = getLinkProperties(network);
            if (lp != null) return lp.getHttpProxy();
            return null;
        }
        try {
            return mService.getProxy();
            return mService.getDefaultProxy();
        } catch (RemoteException e) {
            return null;
        }
@@ -2475,6 +2501,9 @@ public class ConnectivityManager {
            return true;
        }
        if (NetworkUtils.bindProcessToNetwork(netId)) {
            // Set HTTP proxy system properties to match network.
            // TODO: Deprecate this static method and replace it with a non-static version.
            Proxy.setHttpProxySystemProperty(getInstance().getDefaultProxy());
            // Must flush DNS cache as new network may have different DNS resolutions.
            InetAddress.clearDnsCache();
            // Must flush socket pool as idle sockets will be bound to previous network and may
+1 −1
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ interface IConnectivityManager

    void setGlobalProxy(in ProxyInfo p);

    ProxyInfo getProxy();
    ProxyInfo getDefaultProxy();

    void setDataDependency(int networkType, boolean met);

+34 −3
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.ProxySelector;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
@@ -244,16 +245,46 @@ public class Network implements Parcelable {
     * @see java.net.URL#openConnection()
     */
    public URLConnection openConnection(URL url) throws IOException {
        final ConnectivityManager cm = ConnectivityManager.getInstance();
        // TODO: Should this be optimized to avoid fetching the global proxy for every request?
        ProxyInfo proxyInfo = cm.getGlobalProxy();
        if (proxyInfo == null) {
            // TODO: Should this be optimized to avoid fetching LinkProperties for every request?
            final LinkProperties lp = cm.getLinkProperties(this);
            if (lp != null) proxyInfo = lp.getHttpProxy();
        }
        java.net.Proxy proxy = null;
        if (proxyInfo != null) {
            proxy = proxyInfo.makeProxy();
        } else {
            proxy = java.net.Proxy.NO_PROXY;
        }
        return openConnection(url, proxy);
    }

    /**
     * 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}.
     *
     * @param proxy the proxy through which the connection will be established.
     * @return a {@code URLConnection} to the resource referred to by this URL.
     * @throws MalformedURLException if the URL protocol is not HTTP or HTTPS.
     * @throws IllegalArgumentException if the argument proxy is null.
     * @throws IOException if an error occurs while opening the connection.
     * @see java.net.URL#openConnection()
     * @hide
     */
    public URLConnection openConnection(URL url, java.net.Proxy proxy) throws IOException {
        if (proxy == null) throw new IllegalArgumentException("proxy is null");
        maybeInitHttpClient();
        String protocol = url.getProtocol();
        OkHttpClient client;
        // TODO: HttpHandler creates OkHttpClients that share the default ResponseCache.
        // Could this cause unexpected behavior?
        // TODO: Should the network's proxy be specified?
        if (protocol.equals("http")) {
            client = HttpHandler.createHttpOkHttpClient(null /* proxy */);
            client = HttpHandler.createHttpOkHttpClient(proxy);
        } else if (protocol.equals("https")) {
            client = HttpsHandler.createHttpsOkHttpClient(null /* proxy */);
            client = HttpsHandler.createHttpsOkHttpClient(proxy);
        } else {
            // OkHttpClient only supports HTTP and HTTPS and returns a null URLStreamHandler if
            // passed another protocol.
+2 −1
Original line number Diff line number Diff line
@@ -260,7 +260,8 @@ public class ProxyInfo implements Parcelable {
        if (!Uri.EMPTY.equals(mPacFileUrl)) {
            sb.append("PAC Script: ");
            sb.append(mPacFileUrl);
        } else if (mHost != null) {
        }
        if (mHost != null) {
            sb.append("[");
            sb.append(mHost);
            sb.append("] ");
Loading