diff options
6 files changed, 258 insertions, 73 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 5b0f60f..d127ca8 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -105,6 +105,14 @@ public class ConnectivityManager * it with {@link android.content.Intent#getStringExtra(String)}. */ public static final String EXTRA_EXTRA_INFO = "extraInfo"; + /** + * The lookup key for an int that provides information about + * our connection to the internet at large. 0 indicates no connection, + * 100 indicates a great connection. Retrieve it with + * {@link android.content.Intent@getIntExtra(String)}. + * {@hide} + */ + public static final String EXTRA_INET_CONDITION = "inetCondition"; /** * Broadcast Action: The setting for background data usage has changed @@ -548,5 +556,17 @@ public class ConnectivityManager } catch (RemoteException e) { return TETHER_ERROR_SERVICE_UNAVAIL; } - } + } + + /** + * @param networkType The type of network you want to report on + * @param percentage The quality of the connection 0 is bad, 100 is good + * {@hide} + */ + public void reportInetCondition(int networkType, int percentage) { + try { + mService.reportInetCondition(networkType, percentage); + } catch (RemoteException e) { + } + } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 0eb3afd..afccdd9 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -74,4 +74,6 @@ interface IConnectivityManager String[] getTetherableUsbRegexs(); String[] getTetherableWifiRegexs(); + + void reportInetCondition(int networkType, int percentage); } diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java index 838696d..0707df3 100644 --- a/core/java/android/net/NetworkStateTracker.java +++ b/core/java/android/net/NetworkStateTracker.java @@ -63,6 +63,15 @@ public abstract class NetworkStateTracker extends Handler { public static final int EVENT_ROAMING_CHANGED = 5; public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 6; public static final int EVENT_RESTORE_DEFAULT_NETWORK = 7; + /** + * arg1: network type + * arg2: condition (0 bad, 100 good) + */ + public static final int EVENT_INET_CONDITION_CHANGE = 8; + /** + * arg1: network type + */ + public static final int EVENT_INET_CONDITION_HOLD_END = 9; public NetworkStateTracker(Context context, Handler target, diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7fbae6d..dd83006 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3427,6 +3427,21 @@ public final class Settings { public static final String DOWNLOAD_MAX_BYTES_OVER_MOBILE = "download_manager_max_bytes_over_mobile"; + /** + * ms during which to consume extra events related to Inet connection condition + * after a transtion to fully-connected + * @hide + */ + public static final String INET_CONDITION_DEBOUNCE_UP_DELAY = + "inet_condition_debounce_up_delay"; + + /** + * ms during which to consume extra events related to Inet connection condtion + * after a transtion to partly-connected + * @hide + */ + public static final String INET_CONDITION_DEBOUNCE_DOWN_DELAY = + "inet_condition_debounce_down_delay"; /** * @hide diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java index e828f68..c5688e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java @@ -36,6 +36,7 @@ import android.location.LocationManager; import android.media.AudioManager; import android.media.Ringtone; import android.media.RingtoneManager; +import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.net.wifi.WifiManager; @@ -91,6 +92,8 @@ public class StatusBarPolicy { private static final int AM_PM_STYLE = AM_PM_STYLE_GONE; + private static final int INET_CONDITION_THRESHOLD = 50; + private final Context mContext; private final StatusBarManager mService; private final Handler mHandler = new StatusBarHandler(); @@ -232,42 +235,62 @@ public class StatusBarPolicy { }; //***** Data connection icons - private int[] mDataIconList = sDataNetType_g; + private int[] mDataIconList = sDataNetType_g[0]; //GSM/UMTS - private static final int[] sDataNetType_g = new int[] { - R.drawable.stat_sys_data_connected_g, - R.drawable.stat_sys_data_in_g, - R.drawable.stat_sys_data_out_g, - R.drawable.stat_sys_data_inandout_g, + private static final int[][] sDataNetType_g = { + { R.drawable.stat_sys_data_connected_g, + R.drawable.stat_sys_data_in_g, + R.drawable.stat_sys_data_out_g, + R.drawable.stat_sys_data_inandout_g }, + { R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0 } }; - private static final int[] sDataNetType_3g = new int[] { - R.drawable.stat_sys_data_connected_3g, - R.drawable.stat_sys_data_in_3g, - R.drawable.stat_sys_data_out_3g, - R.drawable.stat_sys_data_inandout_3g, + private static final int[][] sDataNetType_3g = { + { R.drawable.stat_sys_data_connected_3g, + R.drawable.stat_sys_data_in_3g, + R.drawable.stat_sys_data_out_3g, + R.drawable.stat_sys_data_inandout_3g }, + { R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0 } }; - private static final int[] sDataNetType_e = new int[] { - R.drawable.stat_sys_data_connected_e, - R.drawable.stat_sys_data_in_e, - R.drawable.stat_sys_data_out_e, - R.drawable.stat_sys_data_inandout_e, + private static final int[][] sDataNetType_e = { + { R.drawable.stat_sys_data_connected_e, + R.drawable.stat_sys_data_in_e, + R.drawable.stat_sys_data_out_e, + R.drawable.stat_sys_data_inandout_e }, + { R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0 } }; //3.5G - private static final int[] sDataNetType_h = new int[] { - R.drawable.stat_sys_data_connected_h, - R.drawable.stat_sys_data_in_h, - R.drawable.stat_sys_data_out_h, - R.drawable.stat_sys_data_inandout_h, + private static final int[][] sDataNetType_h = { + { R.drawable.stat_sys_data_connected_h, + R.drawable.stat_sys_data_in_h, + R.drawable.stat_sys_data_out_h, + R.drawable.stat_sys_data_inandout_h }, + { R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0 } }; //CDMA // Use 3G icons for EVDO data and 1x icons for 1XRTT data - private static final int[] sDataNetType_1x = new int[] { - R.drawable.stat_sys_data_connected_1x, - R.drawable.stat_sys_data_in_1x, - R.drawable.stat_sys_data_out_1x, - R.drawable.stat_sys_data_inandout_1x, - }; + private static final int[][] sDataNetType_1x = { + { R.drawable.stat_sys_data_connected_1x, + R.drawable.stat_sys_data_in_1x, + R.drawable.stat_sys_data_out_1x, + R.drawable.stat_sys_data_inandout_1x }, + { R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0, + R.drawable.stat_sys_roaming_cdma_0 } + }; // Assume it's all good unless we hear otherwise. We don't always seem // to get broadcasts that it *is* there. @@ -292,17 +315,22 @@ public class StatusBarPolicy { private boolean mBluetoothEnabled; // wifi - private static final int[] sWifiSignalImages = new int[] { - R.drawable.stat_sys_wifi_signal_1, - R.drawable.stat_sys_wifi_signal_2, - R.drawable.stat_sys_wifi_signal_3, - R.drawable.stat_sys_wifi_signal_4, + private static final int[][] sWifiSignalImages = { + { R.drawable.stat_sys_wifi_signal_1, + R.drawable.stat_sys_wifi_signal_2, + R.drawable.stat_sys_wifi_signal_3, + R.drawable.stat_sys_wifi_signal_4 }, + { R.drawable.stat_sys_data_in_e, + R.drawable.stat_sys_data_in_e, + R.drawable.stat_sys_data_in_e, + R.drawable.stat_sys_data_in_e } }; private static final int sWifiTemporarilyNotConnectedImage = R.drawable.stat_sys_wifi_signal_0; private int mLastWifiSignalLevel = -1; private boolean mIsWifiConnected = false; + private int mLastWifiInetConnectivityState = 0; // sync state // If sync is active the SyncActive icon is displayed. If sync is not active but @@ -353,6 +381,10 @@ public class StatusBarPolicy { else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) { updateTTY(intent); } + else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { + // TODO - stop using other means to get wifi/mobile info + updateConnectivity(intent); + } } }; @@ -389,7 +421,7 @@ public class StatusBarPolicy { mService.setIconVisibility("data_connection", false); // wifi - mService.setIcon("wifi", sWifiSignalImages[0], 0); + mService.setIcon("wifi", sWifiSignalImages[0][0], 0); mService.setIconVisibility("wifi", false); // wifi will get updated by the sticky intents @@ -456,6 +488,7 @@ public class StatusBarPolicy { filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION); + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); // load config to determine if to distinguish Hspa data icon @@ -659,6 +692,50 @@ public class StatusBarPolicy { } } + private void updateConnectivity(Intent intent) { + NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra( + ConnectivityManager.EXTRA_NETWORK_INFO)); + int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0); + Slog.d(TAG, "got CONNECTIVITY_ACTION - info=" + info + ", status = " + connectionStatus); + if (info.isConnected() == false) return; + + switch (info.getType()) { + case ConnectivityManager.TYPE_MOBILE: + if (info.isConnected()) { + updateDataNetType(info.getSubtype(), connectionStatus); + updateDataIcon(); + } + break; + case ConnectivityManager.TYPE_WIFI: + if (info.isConnected()) { + mIsWifiConnected = true; + mLastWifiInetConnectivityState = + (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0); + int iconId; + if (mLastWifiSignalLevel == -1) { + iconId = sWifiSignalImages[mLastWifiInetConnectivityState][0]; + } else { + iconId = sWifiSignalImages[mLastWifiInetConnectivityState] + [mLastWifiSignalLevel]; + } + + mService.setIcon("wifi", iconId, 0); + // Show the icon since wi-fi is connected + mService.setIconVisibility("wifi", true); + } else { + mLastWifiSignalLevel = -1; + mIsWifiConnected = false; + mLastWifiInetConnectivityState = 0; + int iconId = sWifiSignalImages[0][0]; + + mService.setIcon("wifi", iconId, 0); + // Hide the icon since we're not connected + mService.setIconVisibility("wifi", false); + } + break; + } + } + private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { @@ -686,7 +763,7 @@ public class StatusBarPolicy { @Override public void onDataConnectionStateChanged(int state, int networkType) { mDataState = state; - updateDataNetType(networkType); + updateDataNetType(networkType, 0); updateDataIcon(); } @@ -848,37 +925,38 @@ public class StatusBarPolicy { return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; } - private final void updateDataNetType(int net) { + private final void updateDataNetType(int net, int inetCondition) { + int connected = (inetCondition > INET_CONDITION_THRESHOLD ? 1 : 0); switch (net) { case TelephonyManager.NETWORK_TYPE_EDGE: - mDataIconList = sDataNetType_e; + mDataIconList = sDataNetType_e[connected]; break; case TelephonyManager.NETWORK_TYPE_UMTS: - mDataIconList = sDataNetType_3g; + mDataIconList = sDataNetType_3g[connected]; break; case TelephonyManager.NETWORK_TYPE_HSDPA: case TelephonyManager.NETWORK_TYPE_HSUPA: case TelephonyManager.NETWORK_TYPE_HSPA: if (mHspaDataDistinguishable) { - mDataIconList = sDataNetType_h; + mDataIconList = sDataNetType_h[connected]; } else { - mDataIconList = sDataNetType_3g; + mDataIconList = sDataNetType_3g[connected]; } break; case TelephonyManager.NETWORK_TYPE_CDMA: // display 1xRTT for IS95A/B - mDataIconList = this.sDataNetType_1x; + mDataIconList = sDataNetType_1x[connected]; break; case TelephonyManager.NETWORK_TYPE_1xRTT: - mDataIconList = this.sDataNetType_1x; + mDataIconList = sDataNetType_1x[connected]; break; case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through case TelephonyManager.NETWORK_TYPE_EVDO_A: case TelephonyManager.NETWORK_TYPE_EVDO_B: - mDataIconList = sDataNetType_3g; + mDataIconList = sDataNetType_3g[connected]; break; default: - mDataIconList = sDataNetType_g; + mDataIconList = sDataNetType_g[connected]; break; } } @@ -1019,34 +1097,6 @@ public class StatusBarPolicy { if (!enabled) { mService.setIconVisibility("wifi", false); } - } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - - final NetworkInfo networkInfo = (NetworkInfo) - intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); - - int iconId; - if (networkInfo != null && networkInfo.isConnected()) { - mIsWifiConnected = true; - if (mLastWifiSignalLevel == -1) { - iconId = sWifiSignalImages[0]; - } else { - iconId = sWifiSignalImages[mLastWifiSignalLevel]; - } - - mService.setIcon("wifi", iconId, 0); - // Show the icon since wi-fi is connected - mService.setIconVisibility("wifi", true); - - } else { - mLastWifiSignalLevel = -1; - mIsWifiConnected = false; - iconId = sWifiSignalImages[0]; - - mService.setIcon("wifi", iconId, 0); - // Hide the icon since we're not connected - mService.setIconVisibility("wifi", false); - } - } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { int iconId; final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200); @@ -1055,7 +1105,7 @@ public class StatusBarPolicy { if (newSignalLevel != mLastWifiSignalLevel) { mLastWifiSignalLevel = newSignalLevel; if (mIsWifiConnected) { - iconId = sWifiSignalImages[newSignalLevel]; + iconId = sWifiSignalImages[mLastWifiInetConnectivityState][newSignalLevel]; } else { iconId = sWifiTemporarilyNotConnectedImage; } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 4c81380..72e7435 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -92,6 +92,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { private Context mContext; private int mNetworkPreference; private int mActiveDefaultNetwork = -1; + // 0 is full bad, 100 is full good + private int mDefaultInetCondition = 0; + private int mDefaultInetConditionPublished = 0; + private boolean mInetConditionChangeInFlight = false; + private int mDefaultConnectionSequence = 0; private int mNumDnsEntries; @@ -1047,6 +1052,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo()); } + intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); sendStickyBroadcast(intent); } @@ -1165,6 +1171,14 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } mActiveDefaultNetwork = type; + // this will cause us to come up initially as unconnected and switching + // to connected after our normal pause unless somebody reports us as reall + // disconnected + mDefaultInetConditionPublished = 0; + mDefaultConnectionSequence++; + mInetConditionChangeInFlight = false; + // Don't do this - if we never sign in stay, grey + //reportNetworkCondition(mActiveDefaultNetwork, 100); } thisNet.setTeardownRequested(false); thisNet.updateNetworkSettings(); @@ -1467,6 +1481,70 @@ public class ConnectivityService extends IConnectivityManager.Stub { FeatureUser u = (FeatureUser)msg.obj; u.expire(); break; + case NetworkStateTracker.EVENT_INET_CONDITION_CHANGE: + if (DBG) { + Slog.d(TAG, "Inet connectivity change, net=" + + msg.arg1 + ", condition=" + msg.arg2 + + ",mActiveDefaultNetwork=" + mActiveDefaultNetwork); + } + if (mActiveDefaultNetwork == -1) { + if (DBG) Slog.d(TAG, "no active default network - aborting"); + break; + } + if (mActiveDefaultNetwork != msg.arg1) { + if (DBG) Slog.d(TAG, "given net not default - aborting"); + break; + } + mDefaultInetCondition = msg.arg2; + int delay; + if (mInetConditionChangeInFlight == false) { + if (DBG) Slog.d(TAG, "starting a change hold"); + // setup a new hold to debounce this + if (mDefaultInetCondition > 50) { + delay = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500); + } else { + delay = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000); + } + mInetConditionChangeInFlight = true; + sendMessageDelayed(obtainMessage( + NetworkStateTracker.EVENT_INET_CONDITION_HOLD_END, + mActiveDefaultNetwork, mDefaultConnectionSequence), delay); + } else { + // we've set the new condition, when this hold ends that will get + // picked up + if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt"); + } + break; + case NetworkStateTracker.EVENT_INET_CONDITION_HOLD_END: + if (DBG) { + Slog.d(TAG, "Inet hold end, net=" + msg.arg1 + + ", condition =" + mDefaultInetCondition + + ", published condition =" + mDefaultInetConditionPublished); + } + mInetConditionChangeInFlight = false; + + if (mActiveDefaultNetwork == -1) { + if (DBG) Slog.d(TAG, "no active default network - aborting"); + break; + } + if (mDefaultConnectionSequence != msg.arg2) { + if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting"); + break; + } + if (mDefaultInetConditionPublished == mDefaultInetCondition) { + if (DBG) Slog.d(TAG, "no change in condition - aborting"); + break; + } + NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); + if (networkInfo.isConnected() == false) { + if (DBG) Slog.d(TAG, "default network not connected - aborting"); + break; + } + mDefaultInetConditionPublished = mDefaultInetCondition; + sendConnectedBroadcast(networkInfo); + break; } } } @@ -1550,4 +1628,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); return tetherEnabledInSettings && mTetheringConfigValid; } + + // 100 percent is full good, 0 is full bad. + public void reportInetCondition(int networkType, int percentage) { + if (DBG) Slog.d(TAG, "reportNetworkCondition(" + networkType + ", " + percentage + ")"); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.STATUS_BAR, + "ConnectivityService"); + + mHandler.sendMessage(mHandler.obtainMessage( + NetworkStateTracker.EVENT_INET_CONDITION_CHANGE, networkType, percentage)); + } } |