resolved conflicts for merge of ec52c98d to master

Change-Id: I31297232c9d918a967b93c3ae977f81b6a94f2ed
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 05ebd07..653e353 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -105,6 +105,14 @@
      * 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
@@ -575,4 +583,16 @@
             return false;
         }
     }
+
+    /*
+     * @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 f31fb75..9f2fc17 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -78,4 +78,6 @@
     String[] getTetherableBluetoothRegexs();
 
     void requestNetworkTransitionWakelock(in String forWhom);
+
+    void reportInetCondition(int networkType, int percentage);
 }
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 420992b..5420d8f 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -71,6 +71,18 @@
     public static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 7;
 
     /**
+     * msg.arg1 = network type
+     * msg.arg2 = condition (0 bad, 100 good)
+     */
+    public static final int EVENT_INET_CONDITION_CHANGE = 8;
+
+    /**
+     * msg.arg1 = network type
+     * msg.arg2 = default connection sequence number
+     */
+    public static final int EVENT_INET_CONDITION_HOLD_END = 9;
+
+    /**
      * -------------------------------------------------------------
      * Control Interface
      * -------------------------------------------------------------
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 567ee93..6af6a81 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3471,6 +3471,21 @@
         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.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 @@
 
     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 @@
     };
 
     //***** 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 @@
     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 @@
             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 @@
         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 @@
         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 @@
         }
     }
 
+    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 @@
         @Override
         public void onDataConnectionStateChanged(int state, int networkType) {
             mDataState = state;
-            updateDataNetType(networkType);
+            updateDataNetType(networkType, 0);
             updateDataIcon();
         }
 
@@ -848,37 +925,38 @@
         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 @@
             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 @@
             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 b6d725f..579051c 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -102,6 +102,11 @@
     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;
 
@@ -1077,6 +1082,7 @@
             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
                     info.getExtraInfo());
         }
+        intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
         sendStickyBroadcast(intent);
     }
 
@@ -1203,6 +1209,14 @@
                 }
             }
             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);
         updateNetworkSettings(thisNet);
@@ -1623,6 +1637,7 @@
                     FeatureUser u = (FeatureUser)msg.obj;
                     u.expire();
                     break;
+<<<<<<< HEAD:services/java/com/android/server/ConnectivityService.java
                 case NetworkStateTracker.EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
                     String causedBy = null;
                     synchronized (ConnectivityService.this) {
@@ -1636,6 +1651,71 @@
                         Slog.d(TAG, "NetTransition Wakelock for " +
                                 causedBy + " released by timeout");
                     }
+=======
+                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);
+>>>>>>> ec52c98d:services/java/com/android/server/ConnectivityService.java
                     break;
             }
         }
@@ -1748,4 +1828,15 @@
                 mNetTransitionWakeLockTimeout);
         return;
     }
+
+    // 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));
+    }
 }