am dc7b3e3b: am 012e650e: Merge "KeyStore: stop using state()"

# Via Android Git Automerger (1) and others
* commit 'dc7b3e3b6e1aa3f347c7d843ee453688c4d90e29':
  KeyStore: stop using state()
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 6ff1a33..000c56c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -228,6 +228,21 @@
     public static final String EXTRA_ERRORED_TETHER = "erroredArray";
 
     /**
+     * Broadcast Action: The captive portal tracker has finished its test.
+     * Sent only while running Setup Wizard, in lieu of showing a user
+     * notification.
+     * @hide
+     */
+    public static final String ACTION_CAPTIVE_PORTAL_TEST_COMPLETED =
+            "android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED";
+    /**
+     * The lookup key for a boolean that indicates whether a captive portal was detected.
+     * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+     * @hide
+     */
+    public static final String EXTRA_IS_CAPTIVE_PORTAL = "captivePortal";
+
+    /**
      * The absence of APN..
      * @hide
      */
@@ -328,6 +343,18 @@
     /** {@hide} */
     public static final int MAX_NETWORK_TYPE = TYPE_WIFI_P2P;
 
+    /**
+     * If you want to set the default network preference,you can directly
+     * change the networkAttributes array in framework's config.xml.
+     *
+     * @deprecated Since we support so many more networks now, the single
+     *             network default network preference can't really express
+     *             the heirarchy.  Instead, the default is defined by the
+     *             networkAttributes in config.xml.  You can determine
+     *             the current value by calling {@link #getNetworkPreference()}
+     *             from an App.
+     */
+    @Deprecated
     public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
 
     /**
diff --git a/core/java/android/net/DhcpInfo.java b/core/java/android/net/DhcpInfo.java
index e2660e4..2b359eb 100644
--- a/core/java/android/net/DhcpInfo.java
+++ b/core/java/android/net/DhcpInfo.java
@@ -22,16 +22,17 @@
 
 /**
  * A simple object for retrieving the results of a DHCP request.
+ * @deprecated - use LinkProperties - To be removed 11/2013
+ * STOPSHIP - make sure we expose LinkProperties through ConnectivityManager
  */
 public class DhcpInfo implements Parcelable {
     public int ipAddress;
     public int gateway;
     public int netmask;
-
     public int dns1;
     public int dns2;
-
     public int serverAddress;
+
     public int leaseDuration;
 
     public DhcpInfo() {
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 75646fd..b9362da 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -51,9 +51,10 @@
  */
 public class LinkProperties implements Parcelable {
 
-    String mIfaceName;
+    private String mIfaceName;
     private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
     private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
+    private String mDomains;
     private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
     private ProxyProperties mHttpProxy;
 
@@ -82,9 +83,10 @@
             mIfaceName = source.getInterfaceName();
             for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
             for (InetAddress i : source.getDnses()) mDnses.add(i);
+            mDomains = source.getDomains();
             for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
             mHttpProxy = (source.getHttpProxy() == null)  ?
-                null : new ProxyProperties(source.getHttpProxy());
+                    null : new ProxyProperties(source.getHttpProxy());
         }
     }
 
@@ -120,6 +122,14 @@
         return Collections.unmodifiableCollection(mDnses);
     }
 
+    public String getDomains() {
+        return mDomains;
+    }
+
+    public void setDomains(String domains) {
+        mDomains = domains;
+    }
+
     public void addRoute(RouteInfo route) {
         if (route != null) mRoutes.add(route);
     }
@@ -138,6 +148,7 @@
         mIfaceName = null;
         mLinkAddresses.clear();
         mDnses.clear();
+        mDomains = null;
         mRoutes.clear();
         mHttpProxy = null;
     }
@@ -162,12 +173,14 @@
         for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
         dns += "] ";
 
-        String routes = "Routes: [";
+        String domainName = "Domains: " + mDomains;
+
+        String routes = " Routes: [";
         for (RouteInfo route : mRoutes) routes += route.toString() + ",";
         routes += "] ";
         String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
 
-        return ifaceName + linkAddresses + routes + dns + proxy;
+        return ifaceName + linkAddresses + routes + dns + domainName + proxy;
     }
 
     /**
@@ -181,7 +194,7 @@
     }
 
     /**
-     * Compares this {@code LinkProperties} interface name against the target
+     * Compares this {@code LinkProperties} interface addresses against the target
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
@@ -201,6 +214,12 @@
      */
     public boolean isIdenticalDnses(LinkProperties target) {
         Collection<InetAddress> targetDnses = target.getDnses();
+        String targetDomains = target.getDomains();
+        if (mDomains == null) {
+            if (targetDomains != null) return false;
+        } else {
+            if (mDomains.equals(targetDomains) == false) return false;
+        }
         return (mDnses.size() == targetDnses.size()) ?
                     mDnses.containsAll(targetDnses) : false;
     }
@@ -359,13 +378,13 @@
         return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
                 + mLinkAddresses.size() * 31
                 + mDnses.size() * 37
+                + ((null == mDomains) ? 0 : mDomains.hashCode())
                 + mRoutes.size() * 41
                 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
     }
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(getInterfaceName());
@@ -378,6 +397,7 @@
         for(InetAddress d : mDnses) {
             dest.writeByteArray(d.getAddress());
         }
+        dest.writeString(mDomains);
 
         dest.writeInt(mRoutes.size());
         for(RouteInfo route : mRoutes) {
@@ -394,19 +414,15 @@
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public static final Creator<LinkProperties> CREATOR =
         new Creator<LinkProperties>() {
             public LinkProperties createFromParcel(Parcel in) {
                 LinkProperties netProp = new LinkProperties();
+
                 String iface = in.readString();
                 if (iface != null) {
-                    try {
-                        netProp.setInterfaceName(iface);
-                    } catch (Exception e) {
-                        return null;
-                    }
+                    netProp.setInterfaceName(iface);
                 }
                 int addressCount = in.readInt();
                 for (int i=0; i<addressCount; i++) {
@@ -418,6 +434,7 @@
                         netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
                     } catch (UnknownHostException e) { }
                 }
+                netProp.setDomains(in.readString());
                 addressCount = in.readInt();
                 for (int i=0; i<addressCount; i++) {
                     netProp.addRoute((RouteInfo)in.readParcelable(null));
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 0b23cb7..689dae5 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -19,6 +19,8 @@
 import android.os.Parcelable;
 import android.os.Parcel;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.EnumMap;
 
 /**
@@ -312,7 +314,9 @@
         }
     }
 
-    void setRoaming(boolean isRoaming) {
+    /** {@hide} */
+    @VisibleForTesting
+    public void setRoaming(boolean isRoaming) {
         synchronized (this) {
             mIsRoaming = isRoaming;
         }
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d39e741..4ab479e 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -62,21 +62,21 @@
      * addresses. This call blocks until it obtains a result (either success
      * or failure) from the daemon.
      * @param interfaceName the name of the interface to configure
-     * @param ipInfo if the request succeeds, this object is filled in with
+     * @param dhcpResults if the request succeeds, this object is filled in with
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo);
+    public native static boolean runDhcp(String interfaceName, DhcpResults dhcpResults);
 
     /**
      * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
      * a result (either success or failure) from the daemon.
      * @param interfaceName the name of the interface to configure
-     * @param ipInfo if the request succeeds, this object is filled in with
+     * @param dhcpResults if the request succeeds, this object is filled in with
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo);
+    public native static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults);
 
     /**
      * Shut down the DHCP client daemon.
@@ -124,12 +124,9 @@
      * @param inetAddr is an InetAddress corresponding to the IPv4 address
      * @return the IP address as an integer in network byte order
      */
-    public static int inetAddressToInt(InetAddress inetAddr)
+    public static int inetAddressToInt(Inet4Address inetAddr)
             throws IllegalArgumentException {
         byte [] addr = inetAddr.getAddress();
-        if (addr.length != 4) {
-            throw new IllegalArgumentException("Not an IPv4 address");
-        }
         return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
                 ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
     }
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 275f32a..112e143 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -76,6 +76,10 @@
         this(null, gateway);
     }
 
+    public RouteInfo(LinkAddress host) {
+        this(host, null);
+    }
+
     public static RouteInfo makeHostRoute(InetAddress host) {
         return makeHostRoute(host, null);
     }
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 1f2b1ae..f5f22b2 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -28,25 +28,25 @@
 int ifc_disable(const char *ifname);
 int ifc_reset_connections(const char *ifname, int reset_mask);
 
-int dhcp_do_request(const char *ifname,
+int dhcp_do_request(const char * const ifname,
                     const char *ipaddr,
                     const char *gateway,
                     uint32_t *prefixLength,
-                    const char *dns1,
-                    const char *dns2,
+                    const char *dns[],
                     const char *server,
                     uint32_t *lease,
-                    const char *vendorInfo);
+                    const char *vendorInfo,
+                    const char *domains);
 
-int dhcp_do_request_renew(const char *ifname,
+int dhcp_do_request_renew(const char * const ifname,
                     const char *ipaddr,
                     const char *gateway,
                     uint32_t *prefixLength,
-                    const char *dns1,
-                    const char *dns2,
+                    const char *dns[],
                     const char *server,
                     uint32_t *lease,
-                    const char *vendorInfo);
+                    const char *vendorInfo,
+                    const char *domains);
 
 int dhcp_stop(const char *ifname);
 int dhcp_release_lease(const char *ifname);
@@ -63,15 +63,16 @@
  * to look them up every time.
  */
 static struct fieldIds {
-    jmethodID constructorId;
-    jfieldID ipaddress;
-    jfieldID prefixLength;
-    jfieldID dns1;
-    jfieldID dns2;
-    jfieldID serverAddress;
-    jfieldID leaseDuration;
-    jfieldID vendorInfo;
-} dhcpInfoInternalFieldIds;
+    jmethodID clear;
+    jmethodID setInterfaceName;
+    jmethodID addLinkAddress;
+    jmethodID addGateway;
+    jmethodID addDns;
+    jmethodID setDomains;
+    jmethodID setServerAddress;
+    jmethodID setLeaseDuration;
+    jmethodID setVendorInfo;
+} dhcpResultsFieldIds;
 
 static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
 {
@@ -109,7 +110,7 @@
 }
 
 static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
-        jobject info, bool renew)
+        jobject dhcpResults, bool renew)
 {
     int result;
     char  ipaddr[PROPERTY_VALUE_MAX];
@@ -117,59 +118,87 @@
     char gateway[PROPERTY_VALUE_MAX];
     char    dns1[PROPERTY_VALUE_MAX];
     char    dns2[PROPERTY_VALUE_MAX];
+    char    dns3[PROPERTY_VALUE_MAX];
+    char    dns4[PROPERTY_VALUE_MAX];
+    const char *dns[5] = {dns1, dns2, dns3, dns4, NULL};
     char  server[PROPERTY_VALUE_MAX];
     uint32_t lease;
     char vendorInfo[PROPERTY_VALUE_MAX];
+    char domains[PROPERTY_VALUE_MAX];
 
     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
     if (nameStr == NULL) return (jboolean)false;
 
     if (renew) {
         result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
-                dns1, dns2, server, &lease, vendorInfo);
+                dns, server, &lease, vendorInfo, domains);
     } else {
         result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
-                dns1, dns2, server, &lease, vendorInfo);
+                dns, server, &lease, vendorInfo, domains);
     }
-
     env->ReleaseStringUTFChars(ifname, nameStr);
     if (result == 0) {
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
 
+        // set mIfaceName
+        // dhcpResults->setInterfaceName(ifname)
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname);
+
+        // set the linkAddress
+        // dhcpResults->addLinkAddress(inetAddress, prefixLength)
+        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress,
+                env->NewStringUTF(ipaddr), prefixLength);
+    }
+
+    if (result == 0) {
         // set the gateway
-        jclass cls = env->FindClass("java/net/InetAddress");
-        jmethodID method = env->GetStaticMethodID(cls, "getByName",
-                "(Ljava/lang/String;)Ljava/net/InetAddress;");
-        jvalue args[1];
-        args[0].l = env->NewStringUTF(gateway);
-        jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args);
+        // dhcpResults->addGateway(gateway)
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway));
+    }
 
-        if (!env->ExceptionOccurred()) {
-            cls = env->FindClass("android/net/RouteInfo");
-            method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V");
-            args[0].l = inetAddressObject;
-            jobject routeInfoObject = env->NewObjectA(cls, method, args);
+    if (result == 0) {
+        // dhcpResults->addDns(new InetAddress(dns1))
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1));
+    }
 
-            cls = env->FindClass("android/net/DhcpInfoInternal");
-            method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V");
-            args[0].l = routeInfoObject;
-            env->CallVoidMethodA(info, method, args);
-        } else {
-            // if we have an exception (host not found perhaps), just don't add the route
-            env->ExceptionClear();
+    if (result == 0) {
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setDomains,
+                env->NewStringUTF(domains));
+
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2));
+
+        if (result == 0) {
+            result = env->CallBooleanMethod(dhcpResults,
+                    dhcpResultsFieldIds.addDns, env->NewStringUTF(dns3));
+            if (result == 0) {
+                result = env->CallBooleanMethod(dhcpResults,
+                        dhcpResultsFieldIds.addDns, env->NewStringUTF(dns4));
+            }
         }
+    }
 
-        env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress,
+    if (result == 0) {
+        // dhcpResults->setServerAddress(new InetAddress(server))
+        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress,
                 env->NewStringUTF(server));
-        env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease);
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.vendorInfo, env->NewStringUTF(vendorInfo));
+    }
+
+    if (result == 0) {
+        // dhcpResults->setLeaseDuration(lease)
+        env->CallVoidMethod(dhcpResults,
+                dhcpResultsFieldIds.setLeaseDuration, lease);
+
+        // dhcpResults->setVendorInfo(vendorInfo)
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo,
+                env->NewStringUTF(vendorInfo));
     }
     return (jboolean)(result == 0);
 }
 
+
 static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
 {
     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
@@ -217,8 +246,8 @@
     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
     { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
     { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
-    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
-    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
+    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
+    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
     { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
@@ -226,16 +255,26 @@
 
 int register_android_net_NetworkUtils(JNIEnv* env)
 {
-    jclass dhcpInfoInternalClass = env->FindClass("android/net/DhcpInfoInternal");
-    LOG_FATAL_IF(dhcpInfoInternalClass == NULL, "Unable to find class android/net/DhcpInfoInternal");
-    dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalClass, "<init>", "()V");
-    dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalClass, "prefixLength", "I");
-    dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.serverAddress = env->GetFieldID(dhcpInfoInternalClass, "serverAddress", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.leaseDuration = env->GetFieldID(dhcpInfoInternalClass, "leaseDuration", "I");
-    dhcpInfoInternalFieldIds.vendorInfo = env->GetFieldID(dhcpInfoInternalClass, "vendorInfo", "Ljava/lang/String;");
+    jclass dhcpResultsClass = env->FindClass("android/net/DhcpResults");
+    LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults");
+    dhcpResultsFieldIds.clear =
+            env->GetMethodID(dhcpResultsClass, "clear", "()V");
+    dhcpResultsFieldIds.setInterfaceName =
+            env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V");
+    dhcpResultsFieldIds.addLinkAddress =
+            env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z");
+    dhcpResultsFieldIds.addGateway =
+            env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.addDns =
+            env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.setDomains =
+            env->GetMethodID(dhcpResultsClass, "setDomains", "(Ljava/lang/String;)V");
+    dhcpResultsFieldIds.setServerAddress =
+            env->GetMethodID(dhcpResultsClass, "setServerAddress", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.setLeaseDuration =
+            env->GetMethodID(dhcpResultsClass, "setLeaseDuration", "(I)V");
+    dhcpResultsFieldIds.setVendorInfo =
+            env->GetMethodID(dhcpResultsClass, "setVendorInfo", "(Ljava/lang/String;)V");
 
     return AndroidRuntime::registerNativeMethods(env,
             NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index e5cfdf6..c31cde7 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -183,7 +183,7 @@
      * A per Net list of the PID's that requested access to the net
      * used both as a refcount and for per-PID DNS selection
      */
-    private List mNetRequestersPids[];
+    private List<Integer> mNetRequestersPids[];
 
     // priority order of the nettrackers
     // (excluding dynamically set mNetworkPreference)
@@ -412,8 +412,6 @@
                 ConnectivityManager.MAX_NETWORK_TYPE+1];
         mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
 
-        mNetworkPreference = getPersistedNetworkPreference();
-
         mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
         mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
 
@@ -495,15 +493,29 @@
             }
         }
 
-        mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
+        // Update mNetworkPreference according to user mannually first then overlay config.xml
+        mNetworkPreference = getPersistedNetworkPreference();
+        if (mNetworkPreference == -1) {
+            for (int n : mPriorityList) {
+                if (mNetConfigs[n].isDefault() && ConnectivityManager.isNetworkTypeValid(n)) {
+                    mNetworkPreference = n;
+                    break;
+                }
+            }
+            if (mNetworkPreference == -1) {
+                throw new IllegalStateException(
+                        "You should set at least one default Network in config.xml!");
+            }
+        }
+
+        mNetRequestersPids =
+                (List<Integer> [])new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
         for (int i : mPriorityList) {
-            mNetRequestersPids[i] = new ArrayList();
+            mNetRequestersPids[i] = new ArrayList<Integer>();
         }
 
         mFeatureUsers = new ArrayList<FeatureUser>();
 
-        mNumDnsEntries = 0;
-
         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
                 && SystemProperties.get("ro.build.type").equals("eng");
 
@@ -726,11 +738,8 @@
 
         final int networkPrefSetting = Settings.Global
                 .getInt(cr, Settings.Global.NETWORK_PREFERENCE, -1);
-        if (networkPrefSetting != -1) {
-            return networkPrefSetting;
-        }
 
-        return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE;
+        return networkPrefSetting;
     }
 
     /**
@@ -1306,7 +1315,14 @@
             if (usedNetworkType != networkType) {
                 Integer currentPid = new Integer(pid);
                 mNetRequestersPids[usedNetworkType].remove(currentPid);
-                reassessPidDns(pid, true);
+
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    reassessPidDns(pid, true);
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+                flushVmDnsCache();
                 if (mNetRequestersPids[usedNetworkType].size() != 0) {
                     if (VDBG) {
                         log("stopUsingNetworkFeature: net " + networkType + ": " + feature +
@@ -1688,9 +1704,8 @@
          * in accordance with network preference policies.
          */
         if (!mNetConfigs[prevNetType].isDefault()) {
-            List pids = mNetRequestersPids[prevNetType];
-            for (int i = 0; i<pids.size(); i++) {
-                Integer pid = (Integer)pids.get(i);
+            List<Integer> pids = mNetRequestersPids[prevNetType];
+            for (Integer pid : pids) {
                 // will remove them because the net's no longer connected
                 // need to do this now as only now do we know the pids and
                 // can properly null things that are no longer referenced.
@@ -2240,6 +2255,7 @@
                         }
                     }
                     if (resetDns) {
+                        flushVmDnsCache();
                         if (VDBG) log("resetting DNS cache for " + iface);
                         try {
                             mNetd.flushInterfaceDnsCache(iface);
@@ -2406,9 +2422,10 @@
      * on the highest priority active net which this process requested.
      * If there aren't any, clear it out
      */
-    private void reassessPidDns(int myPid, boolean doBump)
+    private void reassessPidDns(int pid, boolean doBump)
     {
-        if (VDBG) log("reassessPidDns for pid " + myPid);
+        if (VDBG) log("reassessPidDns for pid " + pid);
+        Integer myPid = new Integer(pid);
         for(int i : mPriorityList) {
             if (mNetConfigs[i].isDefault()) {
                 continue;
@@ -2418,61 +2435,25 @@
                     !nt.isTeardownRequested()) {
                 LinkProperties p = nt.getLinkProperties();
                 if (p == null) continue;
-                List pids = mNetRequestersPids[i];
-                for (int j=0; j<pids.size(); j++) {
-                    Integer pid = (Integer)pids.get(j);
-                    if (pid.intValue() == myPid) {
-                        Collection<InetAddress> dnses = p.getDnses();
-                        writePidDns(dnses, myPid);
-                        if (doBump) {
-                            bumpDns();
-                        }
-                        return;
+                if (mNetRequestersPids[i].contains(myPid)) {
+                    try {
+                        mNetd.setDnsInterfaceForPid(p.getInterfaceName(), pid);
+                    } catch (Exception e) {
+                        Slog.e(TAG, "exception reasseses pid dns: " + e);
                     }
+                    return;
                 }
            }
         }
         // nothing found - delete
-        for (int i = 1; ; i++) {
-            String prop = "net.dns" + i + "." + myPid;
-            if (SystemProperties.get(prop).length() == 0) {
-                if (doBump) {
-                    bumpDns();
-                }
-                return;
-            }
-            SystemProperties.set(prop, "");
+        try {
+            mNetd.clearDnsInterfaceForPid(pid);
+        } catch (Exception e) {
+            Slog.e(TAG, "exception clear interface from pid: " + e);
         }
     }
 
-    // return true if results in a change
-    private boolean writePidDns(Collection <InetAddress> dnses, int pid) {
-        int j = 1;
-        boolean changed = false;
-        for (InetAddress dns : dnses) {
-            String dnsString = dns.getHostAddress();
-            if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
-                changed = true;
-                SystemProperties.set("net.dns" + j + "." + pid, dns.getHostAddress());
-            }
-            j++;
-        }
-        return changed;
-    }
-
-    private void bumpDns() {
-        /*
-         * Bump the property that tells the name resolver library to reread
-         * the DNS server list from the properties.
-         */
-        String propVal = SystemProperties.get("net.dnschange");
-        int n = 0;
-        if (propVal.length() != 0) {
-            try {
-                n = Integer.parseInt(propVal);
-            } catch (NumberFormatException e) {}
-        }
-        SystemProperties.set("net.dnschange", "" + (n+1));
+    private void flushVmDnsCache() {
         /*
          * Tell the VMs to toss their DNS caches
          */
@@ -2491,56 +2472,34 @@
     }
 
     // Caller must grab mDnsLock.
-    private boolean updateDns(String network, String iface,
+    private void updateDnsLocked(String network, String iface,
             Collection<InetAddress> dnses, String domains) {
-        boolean changed = false;
         int last = 0;
         if (dnses.size() == 0 && mDefaultDns != null) {
-            ++last;
-            String value = mDefaultDns.getHostAddress();
-            if (!value.equals(SystemProperties.get("net.dns1"))) {
-                if (DBG) {
-                    loge("no dns provided for " + network + " - using " + value);
-                }
-                changed = true;
-                SystemProperties.set("net.dns1", value);
+            dnses = new ArrayList();
+            dnses.add(mDefaultDns);
+            if (DBG) {
+                loge("no dns provided for " + network + " - using " + mDefaultDns.getHostAddress());
             }
-        } else {
+        }
+
+        try {
+            mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
+            mNetd.setDefaultInterfaceForDns(iface);
             for (InetAddress dns : dnses) {
                 ++last;
                 String key = "net.dns" + last;
                 String value = dns.getHostAddress();
-                if (!changed && value.equals(SystemProperties.get(key))) {
-                    continue;
-                }
-                if (VDBG) {
-                    log("adding dns " + value + " for " + network);
-                }
-                changed = true;
                 SystemProperties.set(key, value);
             }
-        }
-        for (int i = last + 1; i <= mNumDnsEntries; ++i) {
-            String key = "net.dns" + i;
-            if (VDBG) log("erasing " + key);
-            changed = true;
-            SystemProperties.set(key, "");
-        }
-        mNumDnsEntries = last;
-
-        if (changed) {
-            try {
-                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
-                mNetd.setDefaultInterfaceForDns(iface);
-            } catch (Exception e) {
-                if (DBG) loge("exception setting default dns interface: " + e);
+            for (int i = last + 1; i <= mNumDnsEntries; ++i) {
+                String key = "net.dns" + i;
+                SystemProperties.set(key, "");
             }
+            mNumDnsEntries = last;
+        } catch (Exception e) {
+            if (DBG) loge("exception setting default dns interface: " + e);
         }
-        if (!domains.equals(SystemProperties.get("net.dns.search"))) {
-            SystemProperties.set("net.dns.search", domains);
-            changed = true;
-        }
-        return changed;
     }
 
     private void handleDnsConfigurationChange(int netType) {
@@ -2550,29 +2509,31 @@
             LinkProperties p = nt.getLinkProperties();
             if (p == null) return;
             Collection<InetAddress> dnses = p.getDnses();
-            boolean changed = false;
             if (mNetConfigs[netType].isDefault()) {
                 String network = nt.getNetworkInfo().getTypeName();
                 synchronized (mDnsLock) {
                     if (!mDnsOverridden) {
-                        changed = updateDns(network, p.getInterfaceName(), dnses, "");
+                        updateDnsLocked(network, p.getInterfaceName(), dnses, p.getDomains());
                     }
                 }
             } else {
                 try {
                     mNetd.setDnsServersForInterface(p.getInterfaceName(),
-                            NetworkUtils.makeStrings(dnses));
+                            NetworkUtils.makeStrings(dnses), p.getDomains());
                 } catch (Exception e) {
                     if (DBG) loge("exception setting dns servers: " + e);
                 }
                 // set per-pid dns for attached secondary nets
-                List pids = mNetRequestersPids[netType];
-                for (int y=0; y< pids.size(); y++) {
-                    Integer pid = (Integer)pids.get(y);
-                    changed = writePidDns(dnses, pid.intValue());
+                List<Integer> pids = mNetRequestersPids[netType];
+                for (Integer pid : pids) {
+                    try {
+                        mNetd.setDnsInterfaceForPid(p.getInterfaceName(), pid);
+                    } catch (Exception e) {
+                        Slog.e(TAG, "exception setting interface for pid: " + e);
+                    }
                 }
             }
-            if (changed) bumpDns();
+            flushVmDnsCache();
         }
     }
 
@@ -2631,7 +2592,7 @@
         pw.increaseIndent();
         for (int net : mPriorityList) {
             String pidString = net + ": ";
-            for (Object pid : mNetRequestersPids[net]) {
+            for (Integer pid : mNetRequestersPids[net]) {
                 pidString = pidString + pid.toString() + ", ";
             }
             pw.println(pidString);
@@ -3341,14 +3302,10 @@
             String domains = buffer.toString().trim();
 
             // Apply DNS changes.
-            boolean changed = false;
             synchronized (mDnsLock) {
-                changed = updateDns("VPN", "VPN", addresses, domains);
+                updateDnsLocked("VPN", "VPN", addresses, domains);
                 mDnsOverridden = true;
             }
-            if (changed) {
-                bumpDns();
-            }
 
             // Temporarily disable the default proxy.
             synchronized (mDefaultProxyLock) {