OSDN Git Service

Query HTTP proxy for network via a new API to avoid permissions exceptions
authorPaul Jensen <pauljensen@google.com>
Wed, 6 May 2015 11:32:40 +0000 (07:32 -0400)
committerPaul Jensen <pauljensen@google.com>
Mon, 18 May 2015 17:05:51 +0000 (17:05 +0000)
Add @hidden ConnectivityManager.getProxyForNetwork() API.

Bug:20470604
Change-Id: I6a9bc4afc8273bc43b14cdeccfedbbf3ff66be40

core/java/android/app/ActivityThread.java
core/java/android/net/ConnectivityManager.java
core/java/android/net/IConnectivityManager.aidl
core/java/android/net/Network.java
core/java/android/net/NetworkUtils.java
core/jni/android_net_NetUtils.cpp
services/core/java/com/android/server/ConnectivityService.java

index da6d8c5..b81ddcb 100644 (file)
@@ -4552,7 +4552,7 @@ public final class ActivityThread {
             // crash if we can't get it.
             IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
             try {
-                final ProxyInfo proxyInfo = service.getDefaultProxy();
+                final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
                 Proxy.setHttpProxySystemProperty(proxyInfo);
             } catch (RemoteException e) {}
         }
index d8c3361..1c67f31 100644 (file)
@@ -1904,9 +1904,6 @@ public class ConnectivityManager {
      *
      * @return {@link ProxyInfo} for the current global HTTP proxy or {@code null}
      *        if no global HTTP proxy is set.
-     *
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
      * @hide
      */
     public ProxyInfo getGlobalProxy() {
@@ -1918,6 +1915,28 @@ public class ConnectivityManager {
     }
 
     /**
+     * Retrieve the global HTTP proxy, or if no global HTTP proxy is set, a
+     * network-specific HTTP proxy.  If {@code network} is null, the
+     * network-specific proxy returned is the proxy of the default active
+     * network.
+     *
+     * @return {@link ProxyInfo} for the current global HTTP proxy, or if no
+     *         global HTTP proxy is set, {@code ProxyInfo} for {@code network},
+     *         or when {@code network} is {@code null},
+     *         the {@code ProxyInfo} for the default active network.  Returns
+     *         {@code null} when no proxy applies or the caller doesn't have
+     *         permission to use {@code network}.
+     * @hide
+     */
+    public ProxyInfo getProxyForNetwork(Network network) {
+        try {
+            return mService.getProxyForNetwork(network);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
      * 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 #bindProcessToNetwork} then that {@code Network}'s proxy is returned, otherwise
@@ -1927,19 +1946,7 @@ public class ConnectivityManager {
      *        HTTP proxy is active.
      */
     public ProxyInfo getDefaultProxy() {
-        final Network network = getBoundNetworkForProcess();
-        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.getDefaultProxy();
-        } catch (RemoteException e) {
-            return null;
-        }
+        return getProxyForNetwork(getBoundNetworkForProcess());
     }
 
     /**
index 77200a5..397e47b 100644 (file)
@@ -104,7 +104,7 @@ interface IConnectivityManager
 
     void setGlobalProxy(in ProxyInfo p);
 
-    ProxyInfo getDefaultProxy();
+    ProxyInfo getProxyForNetwork(in Network nework);
 
     boolean prepareVpn(String oldPackage, String newPackage);
 
index 67ecb5d..754c6b3 100644 (file)
@@ -247,12 +247,7 @@ public class Network implements Parcelable {
             throw new IOException("No ConnectivityManager yet constructed, please construct one");
         }
         // 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();
-        }
+        final ProxyInfo proxyInfo = cm.getProxyForNetwork(this);
         java.net.Proxy proxy = null;
         if (proxyInfo != null) {
             proxy = proxyInfo.makeProxy();
index 29dd8ad..4487cab 100644 (file)
@@ -194,6 +194,12 @@ public class NetworkUtils {
     public native static boolean protectFromVpn(int socketfd);
 
     /**
+     * Determine if {@code uid} can access network designated by {@code netId}.
+     * @return {@code true} if {@code uid} can access network, {@code false} otherwise.
+     */
+    public native static boolean queryUserAccess(int uid, 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
      */
index 60e8ed0..fada7ac 100644 (file)
@@ -291,6 +291,11 @@ static jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint
     return (jboolean) !protectFromVpn(socket);
 }
 
+static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jint uid, jint netId)
+{
+    return (jboolean) !queryUserAccess(uid, netId);
+}
+
 
 // ----------------------------------------------------------------------------
 
@@ -311,6 +316,7 @@ static JNINativeMethod gNetworkUtilMethods[] = {
     { "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
     { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
     { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
+    { "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
     { "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
 };
 
index 8d1d124..eceac51 100644 (file)
@@ -2626,7 +2626,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
                 actionToken);
     }
 
-    public ProxyInfo getDefaultProxy() {
+    private ProxyInfo getDefaultProxy() {
         // this information is already available as a world read/writable jvm property
         // so this API change wouldn't have a benifit.  It also breaks the passing
         // of proxy info to all the JVMs.
@@ -2638,6 +2638,22 @@ public class ConnectivityService extends IConnectivityManager.Stub
         }
     }
 
+    public ProxyInfo getProxyForNetwork(Network network) {
+        if (network == null) return getDefaultProxy();
+        final ProxyInfo globalProxy = getGlobalProxy();
+        if (globalProxy != null) return globalProxy;
+        if (!NetworkUtils.queryUserAccess(Binder.getCallingUid(), network.netId)) return null;
+        // Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
+        // caller may not have.
+        final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+        if (nai == null) return null;
+        synchronized (nai) {
+            final ProxyInfo proxyInfo = nai.linkProperties.getHttpProxy();
+            if (proxyInfo == null) return null;
+            return new ProxyInfo(proxyInfo);
+        }
+    }
+
     // Convert empty ProxyInfo's to null as null-checks are used to determine if proxies are present
     // (e.g. if mGlobalProxy==null fall back to network-specific proxy, if network-specific
     // proxy is null then there is no proxy in place).