From 4f0de1e2853d7f9a30f335e0f170f35fbd48f3c3 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Thu, 4 Aug 2011 15:01:58 -0700 Subject: [PATCH] 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 --- .../android/server/ConnectivityService.java | 73 ++++++++++++++++--- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index c9ab806dfb..eeb5290b34 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -216,6 +216,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } + 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { // 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { thisNet.setTeardownRequested(false); updateNetworkSettings(thisNet); handleConnectivityChange(type, false); - sendConnectedBroadcast(info); + sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay()); } /** @@ -2036,6 +2081,13 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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 @@ public class ConnectivityService extends IConnectivityManager.Stub { 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");