Convert Vpn from NetworkStateTracker to NetworkAgent.

This eliminates the need for the ConnectivityService.VpnCallback class.
This requires shifting VPNs to the new "network" netd API.
VpnService.protect() is modified to no longer go through ConnectivityService.
NetworkCapabilities is extended to add a transport type for VPNs and a
capability requiring a non-VPN (so the default NetworkRequest isn't satisfied
by a VPN).

bug:15409918
Change-Id: Ic4498f1961582208add6f375ad16ce376ee9eb95
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b76fc38..b9c6491 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -115,8 +115,6 @@
 
     void setDataDependency(int networkType, boolean met);
 
-    boolean protectVpn(in ParcelFileDescriptor socket);
-
     boolean prepareVpn(String oldPackage, String newPackage);
 
     ParcelFileDescriptor establishVpn(in VpnConfig config);
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 3d0874b..41eab02 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -92,6 +92,20 @@
      */
     public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
 
+    /**
+     * Sent by the NetworkAgent to ConnectivityService to add new UID ranges
+     * to be forced into this Network.  For VPNs only.
+     * obj = UidRange[] to forward
+     */
+    public static final int EVENT_UID_RANGES_ADDED = BASE + 5;
+
+    /**
+     * Sent by the NetworkAgent to ConnectivityService to remove UID ranges
+     * from being forced into this Network.  For VPNs only.
+     * obj = UidRange[] to stop forwarding
+     */
+    public static final int EVENT_UID_RANGES_REMOVED = BASE + 6;
+
     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
             NetworkCapabilities nc, LinkProperties lp, int score) {
         super(looper);
@@ -194,6 +208,22 @@
     }
 
     /**
+     * Called by the VPN code when it wants to add ranges of UIDs to be routed
+     * through the VPN network.
+     */
+    public void addUidRanges(UidRange[] ranges) {
+        queueOrSendMessage(EVENT_UID_RANGES_ADDED, ranges);
+    }
+
+    /**
+     * Called by the VPN code when it wants to remove ranges of UIDs from being routed
+     * through the VPN network.
+     */
+    public void removeUidRanges(UidRange[] ranges) {
+        queueOrSendMessage(EVENT_UID_RANGES_REMOVED, ranges);
+    }
+
+    /**
      * Called when ConnectivityService has indicated they no longer want this network.
      * The parent factory should (previously) have received indication of the change
      * as well, either canceling NetworkRequests or altering their score such that this
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 00200d0..239db86 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -64,7 +64,7 @@
      * by any Network that matches all of them.
      */
     private long mNetworkCapabilities = (1 << NET_CAPABILITY_NOT_RESTRICTED) |
-            (1 << NET_CAPABILITY_TRUSTED);
+            (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_NOT_VPN);
 
     /**
      * Indicates this is a network that has the ability to reach the
@@ -158,9 +158,15 @@
      */
     public static final int NET_CAPABILITY_TRUSTED        = 14;
 
+    /*
+     * Indicates that this network is not a VPN.  This capability is set by default and should be
+     * explicitly cleared when creating VPN networks.
+     */
+    public static final int NET_CAPABILITY_NOT_VPN        = 15;
+
 
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_TRUSTED;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VPN;
 
     /**
      * Adds the given capability to this {@code NetworkCapability} instance.
@@ -271,8 +277,13 @@
      */
     public static final int TRANSPORT_ETHERNET = 3;
 
+    /**
+     * Indicates this network uses a VPN transport.
+     */
+    public static final int TRANSPORT_VPN = 4;
+
     private static final int MIN_TRANSPORT = TRANSPORT_CELLULAR;
-    private static final int MAX_TRANSPORT = TRANSPORT_ETHERNET;
+    private static final int MAX_TRANSPORT = TRANSPORT_VPN;
 
     /**
      * Adds the given transport type to this {@code NetworkCapability} instance.
@@ -500,6 +511,7 @@
                 case TRANSPORT_WIFI:        transports += "WIFI"; break;
                 case TRANSPORT_BLUETOOTH:   transports += "BLUETOOTH"; break;
                 case TRANSPORT_ETHERNET:    transports += "ETHERNET"; break;
+                case TRANSPORT_VPN:         transports += "VPN"; break;
             }
             if (++i < types.length) transports += "|";
         }
@@ -523,6 +535,7 @@
                 case NET_CAPABILITY_INTERNET:       capabilities += "INTERNET"; break;
                 case NET_CAPABILITY_NOT_RESTRICTED: capabilities += "NOT_RESTRICTED"; break;
                 case NET_CAPABILITY_TRUSTED:        capabilities += "TRUSTED"; break;
+                case NET_CAPABILITY_NOT_VPN:        capabilities += "NOT_VPN"; break;
             }
             if (++i < types.length) capabilities += "&";
         }
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index c4b17b6..aa1e123 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -155,6 +155,13 @@
     public native static boolean bindSocketToNetwork(int socketfd, int netId);
 
     /**
+     * Protect {@code socketfd} from VPN connections.  After protecting, data sent through
+     * this socket will go directly to the underlying network, so its traffic will not be
+     * forwarded through the VPN.
+     */
+    public native static boolean protectFromVpn(int socketfd);
+
+    /**
      * 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/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl
new file mode 100644
index 0000000..f9be628
--- /dev/null
+++ b/core/java/android/net/UidRange.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 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 android.net;
+
+/**
+ * An inclusive range of UIDs.
+ *
+ * {@hide}
+ */
+parcelable UidRange;
diff --git a/core/java/android/net/UidRange.java b/core/java/android/net/UidRange.java
new file mode 100644
index 0000000..2e586b3
--- /dev/null
+++ b/core/java/android/net/UidRange.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 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 android.net;
+
+import static android.os.UserHandle.PER_USER_RANGE;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.IllegalArgumentException;
+
+/**
+ * An inclusive range of UIDs.
+ *
+ * @hide
+ */
+public final class UidRange implements Parcelable {
+    public final int start;
+    public final int stop;
+
+    public UidRange(int startUid, int stopUid) {
+        if (startUid < 0) throw new IllegalArgumentException("Invalid start UID.");
+        if (stopUid < 0) throw new IllegalArgumentException("Invalid stop UID.");
+        if (startUid > stopUid) throw new IllegalArgumentException("Invalid UID range.");
+        start = startUid;
+        stop  = stopUid;
+    }
+
+    public static UidRange createForUser(int userId) {
+        return new UidRange(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
+    }
+
+    public int getStartUser() {
+        return start / PER_USER_RANGE;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + start;
+        result = 31 * result + stop;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o instanceof UidRange) {
+            UidRange other = (UidRange) o;
+            return start == other.start && stop == other.stop;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return start + "-" + stop;
+    }
+
+    // implement the Parcelable interface
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(start);
+        dest.writeInt(stop);
+    }
+
+    public static final Creator<UidRange> CREATOR =
+        new Creator<UidRange>() {
+            @Override
+            public UidRange createFromParcel(Parcel in) {
+                int start = in.readInt();
+                int stop = in.readInt();
+
+                return new UidRange(start, stop);
+            }
+            @Override
+            public UidRange[] newArray(int size) {
+                return new UidRange[size];
+            }
+    };
+}
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 7c62bf6..1d89eae 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -24,6 +24,7 @@
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
+import android.net.NetworkUtils;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -168,19 +169,7 @@
      * @return {@code true} on success.
      */
     public boolean protect(int socket) {
-        ParcelFileDescriptor dup = null;
-        try {
-            dup = ParcelFileDescriptor.fromFd(socket);
-            return getService().protectVpn(dup);
-        } catch (Exception e) {
-            return false;
-        } finally {
-            try {
-                dup.close();
-            } catch (Exception e) {
-                // ignore
-            }
-        }
+        return NetworkUtils.protectFromVpn(socket);
     }
 
     /**
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index eb9ba13..d997e44 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -22,6 +22,7 @@
 import android.net.LinkAddress;
 import android.net.NetworkStats;
 import android.net.RouteInfo;
+import android.net.UidRange;
 import android.net.wifi.WifiConfiguration;
 import android.os.INetworkActivityListener;
 
@@ -325,28 +326,14 @@
     void setFirewallUidRule(int uid, boolean allow);
 
     /**
-     * Set all packets from users [uid_start,uid_end] to go through interface iface
-     * iface must already be set for marked forwarding by {@link setMarkedForwarding}
+     * Set all packets from users in ranges to go through VPN specified by netId.
      */
-    void setUidRangeRoute(String iface, int uid_start, int uid_end, boolean forward_dns);
+    void addVpnUidRanges(int netId, in UidRange[] ranges);
 
     /**
-     * Clears the special routing rules for users [uid_start,uid_end]
+     * Clears the special VPN rules for users in ranges and VPN specified by netId.
      */
-    void clearUidRangeRoute(String iface, int uid_start, int uid_end);
-
-    /**
-     * Setup an interface for routing packets marked by {@link setUidRangeRoute}
-     *
-     * This sets up a dedicated routing table for packets marked for {@code iface} and adds
-     * source-NAT rules so that the marked packets have the correct source address.
-     */
-    void setMarkedForwarding(String iface);
-
-    /**
-     * Removes marked forwarding for an interface
-     */
-    void clearMarkedForwarding(String iface);
+    void removeVpnUidRanges(int netId, in UidRange[] ranges);
 
     /**
      * Get the SO_MARK associated with routing packets for user {@code uid}
@@ -410,9 +397,14 @@
     boolean isNetworkActive();
 
     /**
-     * Setup a new network.
+     * Setup a new physical network.
      */
-    void createNetwork(int netId);
+    void createPhysicalNetwork(int netId);
+
+    /**
+     * Setup a new VPN.
+     */
+    void createVirtualNetwork(int netId, boolean hasDNS);
 
     /**
      * Remove a network.
@@ -437,4 +429,14 @@
 
     void setPermission(boolean internal, boolean changeNetState, in int[] uids);
     void clearPermission(in int[] uids);
+
+    /**
+     * Allow UID to call protect().
+     */
+    void allowProtect(int uid);
+
+    /**
+     * Deny UID from calling protect().
+     */
+    void denyProtect(int uid);
 }