am 090df1dc: Merge "Delay connectivity change notifications." into honeycomb-LTE

* commit '090df1dc4188e5b9ef10a0aca5081a196085ff56':
  Delay connectivity change notifications.
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 2733fd3..557cf1f 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -216,6 +216,12 @@
     private static final int EVENT_SET_DEPENDENCY_MET =
             MAX_NETWORK_STATE_TRACKER_EVENT + 10;
 
+    /**
+     * used internally to send a sticky broadcast delayed.
+     */
+    private static final int EVENT_SEND_STICKY_BROADCAST_INTENT =
+            MAX_NETWORK_STATE_TRACKER_EVENT + 11;
+
     private Handler mHandler;
 
     // list of DeathRecipients used to make sure features are turned off when
@@ -511,6 +517,17 @@
         }
     }
 
+    private int getConnectivityChangeDelay() {
+        final ContentResolver cr = mContext.getContentResolver();
+
+        /** Check system properties for the default value then use secure settings value, if any. */
+        int defaultDelay = SystemProperties.getInt(
+                "conn." + Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
+                Settings.Secure.CONNECTIVITY_CHANGE_DELAY_DEFAULT);
+        return Settings.Secure.getInt(cr, Settings.Secure.CONNECTIVITY_CHANGE_DELAY,
+                defaultDelay);
+    }
+
     private int getPersistedNetworkPreference() {
         final ContentResolver cr = mContext.getContentResolver();
 
@@ -1243,13 +1260,14 @@
         // do this before we broadcast the change
         handleConnectivityChange(prevNetType, doReset);
 
-        sendStickyBroadcast(intent);
+        sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
         /*
          * If the failover network is already connected, then immediately send
          * out a followup broadcast indicating successful failover
          */
         if (mActiveDefaultNetwork != -1) {
-            sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo());
+            sendConnectedBroadcastDelayed(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(),
+                    getConnectivityChangeDelay());
         }
     }
 
@@ -1303,11 +1321,15 @@
         sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION);
     }
 
+    private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) {
+        sendGeneralBroadcastDelayed(info, ConnectivityManager.CONNECTIVITY_ACTION, delayMs);
+    }
+
     private void sendInetConditionBroadcast(NetworkInfo info) {
         sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION);
     }
 
-    private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
+    private Intent makeGeneralIntent(NetworkInfo info, String bcastType) {
         Intent intent = new Intent(bcastType);
         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
         if (info.isFailover()) {
@@ -1322,7 +1344,15 @@
                     info.getExtraInfo());
         }
         intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
-        sendStickyBroadcast(intent);
+        return intent;
+    }
+
+    private void sendGeneralBroadcast(NetworkInfo info, String bcastType) {
+        sendStickyBroadcast(makeGeneralIntent(info, bcastType));
+    }
+
+    private void sendGeneralBroadcastDelayed(NetworkInfo info, String bcastType, int delayMs) {
+        sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs);
     }
 
     /**
@@ -1387,10 +1417,25 @@
                 mInitialBroadcast = new Intent(intent);
             }
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+            if (DBG) {
+                log("sendStickyBroadcast: NetworkInfo=" +
+                    intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO));
+            }
+
             mContext.sendStickyBroadcast(intent);
         }
     }
 
+    private void sendStickyBroadcastDelayed(Intent intent, int delayMs) {
+        if (delayMs <= 0) {
+            sendStickyBroadcast(intent);
+        } else {
+            if (DBG) log("sendStickyBroadcastDelayed: delayMs=" + delayMs + " intent=" + intent);
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(
+                    EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs);
+        }
+    }
+
     void systemReady() {
         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
         mNetd = INetworkManagementService.Stub.asInterface(b);
@@ -1467,7 +1512,7 @@
         thisNet.setTeardownRequested(false);
         updateNetworkSettings(thisNet);
         handleConnectivityChange(type, false);
-        sendConnectedBroadcast(info);
+        sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
     }
 
     /**
@@ -2037,6 +2082,13 @@
                     handleSetDependencyMet(msg.arg2, met);
                     break;
                 }
+                case EVENT_SEND_STICKY_BROADCAST_INTENT:
+                {
+                    Intent intent = (Intent)msg.obj;
+                    log("EVENT_SEND_STICKY_BROADCAST_INTENT: sendStickyBroadcast intent=" + intent);
+                    sendStickyBroadcast(intent);
+                    break;
+                }
             }
         }
     }
@@ -2223,10 +2275,13 @@
             if (DBG) log("event hold for obsolete network - aborting");
             return;
         }
-        if (mDefaultInetConditionPublished == mDefaultInetCondition) {
-            if (DBG) log("no change in condition - aborting");
-            return;
-        }
+        // TODO: Figure out why this optimization sometimes causes a
+        //       change in mDefaultInetCondition to be missed and the
+        //       UI to not be updated.
+        //if (mDefaultInetConditionPublished == mDefaultInetCondition) {
+        //    if (DBG) log("no change in condition - aborting");
+        //    return;
+        //}
         NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
         if (networkInfo.isConnected() == false) {
             if (DBG) log("default network not connected - aborting");