Reduce the spinning while tethering.

Doing too much stuff - don't retry when we know we shouldn't.

bug:3293460
Change-Id: Ic7b0b6486b39377d74df7a35572059ac60d03fa0
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index e7e4302..feb7b63 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1574,11 +1574,18 @@
         }
     }
 
-    private void writePidDns(Collection <InetAddress> dnses, int pid) {
+    // 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) {
-            SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
+            String dnsString = dns.getHostAddress();
+            if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
+                changed = true;
+                SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
+            }
         }
+        return changed;
     }
 
     private void bumpDns() {
@@ -1609,26 +1616,40 @@
             LinkProperties p = nt.getLinkProperties();
             if (p == null) return;
             Collection<InetAddress> dnses = p.getDnses();
+            boolean changed = false;
             if (mNetAttributes[netType].isDefault()) {
                 int j = 1;
                 if (dnses.size() == 0 && mDefaultDns != null) {
-                    if (DBG) {
-                        log("no dns provided - using " + mDefaultDns.getHostAddress());
+                    String dnsString = mDefaultDns.getHostAddress();
+                    if (!dnsString.equals(SystemProperties.get("net.dns1"))) {
+                        if (DBG) {
+                            log("no dns provided - using " + dnsString);
+                        }
+                        changed = true;
+                        SystemProperties.set("net.dns1", dnsString);
                     }
-                    SystemProperties.set("net.dns1", mDefaultDns.getHostAddress());
                     j++;
                 } else {
                     for (InetAddress dns : dnses) {
+                        String dnsString = dns.getHostAddress();
+                        if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) {
+                            j++;
+                            continue;
+                        }
                         if (DBG) {
                             log("adding dns " + dns + " for " +
                                     nt.getNetworkInfo().getTypeName());
                         }
-                        SystemProperties.set("net.dns" + j++, dns.getHostAddress());
+                        changed = true;
+                        SystemProperties.set("net.dns" + j++, dnsString);
                     }
                 }
                 for (int k=j ; k<mNumDnsEntries; k++) {
-                    if (DBG) log("erasing net.dns" + k);
-                    SystemProperties.set("net.dns" + k, "");
+                    if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) {
+                        if (DBG) log("erasing net.dns" + k);
+                        changed = true;
+                        SystemProperties.set("net.dns" + k, "");
+                    }
                 }
                 mNumDnsEntries = j;
             } else {
@@ -1636,10 +1657,10 @@
                 List pids = mNetRequestersPids[netType];
                 for (int y=0; y< pids.size(); y++) {
                     Integer pid = (Integer)pids.get(y);
-                    writePidDns(dnses, pid.intValue());
+                    changed = writePidDns(dnses, pid.intValue());
                 }
             }
-            bumpDns();
+            if (changed) bumpDns();
         }
     }
 
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index a93d596..a562e1f 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -68,7 +68,7 @@
 
     private Context mContext;
     private final static String TAG = "Tethering";
-    private final static boolean DEBUG = false;
+    private final static boolean DEBUG = true;
 
     private boolean mBooted = false;
     //used to remember if we got connected before boot finished
@@ -942,7 +942,12 @@
                         String newUpstreamIfaceName = (String)(message.obj);
                         b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
                         service = INetworkManagementService.Stub.asInterface(b);
-
+                        if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
+                                (mMyUpstreamIfaceName != null &&
+                                mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
+                            if (DEBUG) Log.d(TAG, "Connection changed noop - dropping");
+                            break;
+                        }
                         if (mMyUpstreamIfaceName != null) {
                             try {
                                 service.disableNat(mIfaceName, mMyUpstreamIfaceName);
@@ -1085,7 +1090,8 @@
 
         private ArrayList mNotifyList;
 
-        private boolean mConnectionRequested = false;
+        private int mCurrentConnectionSequence;
+        private boolean mMobileReserved = false;
 
         private String mUpstreamIfaceName = null;
 
@@ -1124,32 +1130,36 @@
             public boolean processMessage(Message m) {
                 return false;
             }
-            protected int turnOnMobileConnection() {
+            protected boolean turnOnMobileConnection() {
+                boolean retValue = true;
+                if (mMobileReserved) return retValue;
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
-                int retValue = Phone.APN_REQUEST_FAILED;
+                int result = Phone.APN_REQUEST_FAILED;
                 try {
-                    retValue = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
+                    result = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                             (mDunRequired ? Phone.FEATURE_ENABLE_DUN : Phone.FEATURE_ENABLE_HIPRI),
                             new Binder());
                 } catch (Exception e) {
                 }
-                switch (retValue) {
+                switch (result) {
                 case Phone.APN_ALREADY_ACTIVE:
                 case Phone.APN_REQUEST_STARTED:
-                    sendMessageDelayed(CMD_CELL_CONNECTION_RENEW, CELL_CONNECTION_RENEW_MS);
-                    mConnectionRequested = true;
+                    mMobileReserved = true;
+                    Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
+                    m.arg1 = ++mCurrentConnectionSequence;
+                    sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
                     break;
                 case Phone.APN_REQUEST_FAILED:
                 default:
-                    mConnectionRequested = false;
+                    retValue = false;
                     break;
                 }
 
                 return retValue;
             }
             protected boolean turnOffMobileConnection() {
-                if (mConnectionRequested) {
+                if (mMobileReserved) {
                     IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                     IConnectivityManager service =
                             IConnectivityManager.Stub.asInterface(b);
@@ -1160,7 +1170,7 @@
                     } catch (Exception e) {
                         return false;
                     }
-                    mConnectionRequested = false;
+                    mMobileReserved = false;
                 }
                 return true;
             }
@@ -1240,13 +1250,14 @@
                 }
                 return null;
             }
+
             protected void chooseUpstreamType(boolean tryCell) {
                 // decide if the current upstream is good or not and if not
                 // do something about it (start up DUN if required or HiPri if not)
                 String iface = findActiveUpstreamIface();
                 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
-                mConnectionRequested = false;
+                mMobileReserved = false;
                 if (DEBUG) {
                     Log.d(TAG, "chooseUpstreamType(" + tryCell + "),  dunRequired ="
                             + mDunRequired + ", iface=" + iface);
@@ -1287,11 +1298,14 @@
                 }
                 // may have been set to null in the if above
                 if (iface == null ) {
+                    boolean success = false;
                     if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) {
-                        turnOnMobileConnection();
+                        success = turnOnMobileConnection();
                     }
-                    // wait for things to settle and retry
-                    sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
+                    if (!success) {
+                        // wait for things to settle and retry
+                        sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
+                    }
                 }
                 notifyTetheredOfNewUpstreamIface(iface);
             }
@@ -1309,7 +1323,7 @@
         class InitialState extends TetherMasterUtilState {
             @Override
             public void enter() {
-                mConnectionRequested = false;
+                mMobileReserved = false;
             }
             @Override
             public boolean processMessage(Message message) {
@@ -1382,11 +1396,12 @@
                     case CMD_CELL_CONNECTION_RENEW:
                         // make sure we're still using a requested connection - may have found
                         // wifi or something since then.
-                        if (mConnectionRequested) {
+                        if (mCurrentConnectionSequence == message.arg1) {
                             if (DEBUG) {
                                 Log.d(TAG, "renewing mobile connection - requeuing for another " +
                                         CELL_CONNECTION_RENEW_MS + "ms");
                             }
+                            mMobileReserved = false; // need to renew it
                             turnOnMobileConnection();
                         }
                         break;