Merge "Background data notification, API clean up."
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 68e80ff..9c96883 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -261,11 +261,18 @@
      */
     public static final int TYPE_MOBILE_CBS  = 12;
 
-    /** {@hide} */
-    public static final int MAX_RADIO_TYPE   = TYPE_MOBILE_CBS;
+    /**
+     * A Wi-Fi p2p connection. Only requesting processes will have access to
+     * the peers connected.
+     * {@hide}
+     */
+    public static final int TYPE_WIFI_P2P    = 13;
 
     /** {@hide} */
-    public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_CBS;
+    public static final int MAX_RADIO_TYPE   = TYPE_WIFI_P2P;
+
+    /** {@hide} */
+    public static final int MAX_NETWORK_TYPE = TYPE_WIFI_P2P;
 
     public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
 
@@ -304,6 +311,8 @@
                 return "MOBILE_IMS";
             case TYPE_MOBILE_CBS:
                 return "MOBILE_CBS";
+            case TYPE_WIFI_P2P:
+                return "WIFI_P2P";
             default:
                 return Integer.toString(type);
         }
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 2bb952e..1341dd4 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -456,14 +456,10 @@
         for (int netType : mPriorityList) {
             switch (mNetConfigs[netType].radio) {
             case ConnectivityManager.TYPE_WIFI:
-                if (DBG) log("Starting Wifi Service.");
-                WifiStateTracker wst = new WifiStateTracker();
-                WifiService wifiService = new WifiService(context);
-                ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
-                wifiService.checkAndStartWifi();
-                mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
-                wst.startMonitoring(context, mHandler);
-                break;
+                mNetTrackers[netType] = new WifiStateTracker(netType,
+                        mNetConfigs[netType].name);
+                mNetTrackers[netType].startMonitoring(context, mHandler);
+               break;
             case ConnectivityManager.TYPE_MOBILE:
                 mNetTrackers[netType] = new MobileDataStateTracker(netType,
                         mNetConfigs[netType].name);
@@ -870,15 +866,8 @@
 
         FeatureUser f = new FeatureUser(networkType, feature, binder);
 
-        // TODO - move this into the MobileDataStateTracker
-        int usedNetworkType = networkType;
-        if(networkType == ConnectivityManager.TYPE_MOBILE) {
-            usedNetworkType = convertFeatureToNetworkType(feature);
-            if (usedNetworkType < 0) {
-                loge("Can't match any netTracker!");
-                usedNetworkType = networkType;
-            }
-        }
+        // TODO - move this into individual networktrackers
+        int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
 
         if (mProtectedNetworks.contains(usedNetworkType)) {
             enforceConnectivityInternalPermission();
@@ -888,7 +877,6 @@
         if (network != null) {
             Integer currentPid = new Integer(getCallingPid());
             if (usedNetworkType != networkType) {
-                NetworkStateTracker radio = mNetTrackers[networkType];
                 NetworkInfo ni = network.getNetworkInfo();
 
                 if (ni.isAvailable() == false) {
@@ -1034,14 +1022,9 @@
                 }
             }
 
-            // TODO - move to MobileDataStateTracker
-            int usedNetworkType = networkType;
-            if (networkType == ConnectivityManager.TYPE_MOBILE) {
-                usedNetworkType = convertFeatureToNetworkType(feature);
-                if (usedNetworkType < 0) {
-                    usedNetworkType = networkType;
-                }
-            }
+            // TODO - move to individual network trackers
+            int usedNetworkType = convertFeatureToNetworkType(networkType, feature);
+
             tracker =  mNetTrackers[usedNetworkType];
             if (tracker == null) {
                 if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType);
@@ -1737,15 +1720,32 @@
             }
         }
         mCurrentLinkProperties[netType] = newLp;
-        updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
+        boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
 
-        if (doReset || resetMask != 0) {
+        if (resetMask != 0 || resetDns) {
             LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
             if (linkProperties != null) {
                 String iface = linkProperties.getInterfaceName();
                 if (TextUtils.isEmpty(iface) == false) {
-                    if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
-                    NetworkUtils.resetConnections(iface, resetMask);
+                    if (resetMask != 0) {
+                        if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
+                        NetworkUtils.resetConnections(iface, resetMask);
+
+                        // Tell VPN the interface is down. It is a temporary
+                        // but effective fix to make VPN aware of the change.
+                        if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
+                            mVpn.interfaceStatusChanged(iface, false);
+                        }
+                    }
+                    if (resetDns) {
+                        if (DBG) log("resetting DNS cache for " + iface);
+                        try {
+                            mNetd.flushInterfaceDnsCache(iface);
+                        } catch (Exception e) {
+                            // never crash - catch them all
+                            loge("Exception resetting dns cache: " + e);
+                        }
+                    }
                 }
             }
         }
@@ -1767,8 +1767,10 @@
      * is a noop.
      * Uses isLinkDefault to determine if default routes should be set or conversely if
      * host routes should be set to the dns servers
+     * returns a boolean indicating the routes changed
      */
-    private void updateRoutes(LinkProperties newLp, LinkProperties curLp, boolean isLinkDefault) {
+    private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp,
+            boolean isLinkDefault) {
         Collection<RouteInfo> routesToAdd = null;
         CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>();
         CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>();
@@ -1781,6 +1783,8 @@
             dnsDiff.added = newLp.getDnses();
         }
 
+        boolean routesChanged = (routeDiff.removed.size() != 0 || routeDiff.added.size() != 0);
+
         for (RouteInfo r : routeDiff.removed) {
             if (isLinkDefault || ! r.isDefaultRoute()) {
                 removeRoute(curLp, r);
@@ -1808,15 +1812,7 @@
 
         if (!isLinkDefault) {
             // handle DNS routes
-            if (routeDiff.removed.size() == 0 && routeDiff.added.size() == 0) {
-                // no change in routes, check for change in dns themselves
-                for (InetAddress oldDns : dnsDiff.removed) {
-                    removeRouteToAddress(curLp, oldDns);
-                }
-                for (InetAddress newDns : dnsDiff.added) {
-                    addRouteToAddress(newLp, newDns);
-                }
-            } else {
+            if (routesChanged) {
                 // routes changed - remove all old dns entries and add new
                 if (curLp != null) {
                     for (InetAddress oldDns : curLp.getDnses()) {
@@ -1828,8 +1824,17 @@
                         addRouteToAddress(newLp, newDns);
                     }
                 }
+            } else {
+                // no change in routes, check for change in dns themselves
+                for (InetAddress oldDns : dnsDiff.removed) {
+                    removeRouteToAddress(curLp, oldDns);
+                }
+                for (InetAddress newDns : dnsDiff.added) {
+                    addRouteToAddress(newLp, newDns);
+                }
             }
         }
+        return routesChanged;
     }
 
 
@@ -2603,25 +2608,38 @@
         Slog.e(TAG, s);
     }
 
-    int convertFeatureToNetworkType(String feature){
-        int networkType = -1;
-        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
-            networkType = ConnectivityManager.TYPE_MOBILE_MMS;
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
-            networkType = ConnectivityManager.TYPE_MOBILE_SUPL;
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
-                TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
-            networkType = ConnectivityManager.TYPE_MOBILE_DUN;
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
-            networkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
-            networkType = ConnectivityManager.TYPE_MOBILE_FOTA;
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
-            networkType = ConnectivityManager.TYPE_MOBILE_IMS;
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
-            networkType = ConnectivityManager.TYPE_MOBILE_CBS;
+    int convertFeatureToNetworkType(int networkType, String feature) {
+        int usedNetworkType = networkType;
+
+        if(networkType == ConnectivityManager.TYPE_MOBILE) {
+            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) ||
+                    TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS;
+            } else {
+                Slog.e(TAG, "Can't match any mobile netTracker!");
+            }
+        } else if (networkType == ConnectivityManager.TYPE_WIFI) {
+            if (TextUtils.equals(feature, "p2p")) {
+                usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P;
+            } else {
+                Slog.e(TAG, "Can't match any wifi netTracker!");
+            }
+        } else {
+            Slog.e(TAG, "Unexpected network type");
         }
-        return networkType;
+        return usedNetworkType;
     }
 
     private static <T> T checkNotNull(T value, String message) {