Delay connectivity change notifications.
Because changes to the route tables take time to propagate
we add a delay when sending out change notifications. This allows
applications, such as GTalk, to create sockets without encountering
a 3 minute timeout.
Bug: 5008488
Change-Id: I0eefb03a5d6358a58ea6ae5b4f697ff302b5511d
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index eb9eb03..ec7d440 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3023,6 +3023,18 @@
public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
/**
+ * The number of milliseconds to delay before sending out Connectivyt Change broadcasts
+ * @hide
+ */
+ public static final String CONNECTIVITY_CHANGE_DELAY = "connectivity_change_delay";
+
+ /**
+ * Default value for CONNECTIVITY_CHANGE_DELAY in milliseconds.
+ * @hide
+ */
+ public static final int CONNECTIVITY_CHANGE_DELAY_DEFAULT = 3000;
+
+ /**
* Controls whether settings backup is enabled.
* Type: int ( 0 = disabled, 1 = enabled )
* @hide
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c9ab806..eeb5290 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);
@@ -1466,7 +1511,7 @@
thisNet.setTeardownRequested(false);
updateNetworkSettings(thisNet);
handleConnectivityChange(type, false);
- sendConnectedBroadcast(info);
+ sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
}
/**
@@ -2036,6 +2081,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;
+ }
}
}
}
@@ -2222,10 +2274,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");