Improve Bluetooth tethering UI usability.

- Updated hint text for BT tethering checkbox to
  "[Sharing|not sharing] this [tablet|phone]'s mobile data connection".
- Show correct hint text when user enters tethering screen.
- Show correct status after user enables tethering when Bluetooth is off.
  When BluetoothPan.setBluetoothTethering(true) is called with BT off,
  BluetoothPanProfileHandler will add a broadcast receiver to enable
  tethering after BT turns on. This happens too late to show the correct
  status when TetherSettings gets the adapter state changed event, so set
  a flag (mBluetoothEnableForTether) instead, and call setBluetoothTethering
  ourselves after the state changes to ON. Also, clear the flag if the
  adapter state changes to OFF or ERROR.
- Show correct status when user enables tethering, then disables Bluetooth,
  then returns to the tethering screen. Previously it would show
  Bluetooth tethering enabled, even though adapter state was OFF.
- Show the number of connected devices in tethering preference screen.
- Distinguish between PANU and NAP in device profiles screen, and show
  appropriate text to clarify the direction of tethering.
- Remove profiles from device profiles list when the device removes the UUID
  (e.g. Mac OS X turning NAP on/off) and after a NAP disconnection when the
  remote device only supports PANU.

Bug: 3414575
Change-Id: I2c0830876d5b9bddb293e57c4d3ca74f105911b8
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 39f0535..1513d43 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -95,6 +95,8 @@
     private WifiManager mWifiManager;
     private WifiConfiguration mWifiConfig = null;
 
+    private boolean mBluetoothEnableForTether;
+
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -239,7 +241,8 @@
     private class TetherChangeReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context content, Intent intent) {
-            if (intent.getAction().equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
+            String action = intent.getAction();
+            if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
                 // TODO - this should understand the interface types
                 ArrayList<String> available = intent.getStringArrayListExtra(
                         ConnectivityManager.EXTRA_AVAILABLE_TETHER);
@@ -250,10 +253,27 @@
                 updateState(available.toArray(new String[available.size()]),
                         active.toArray(new String[active.size()]),
                         errored.toArray(new String[errored.size()]));
-            } else if (intent.getAction().equals(Intent.ACTION_MEDIA_SHARED) ||
-                       intent.getAction().equals(Intent.ACTION_MEDIA_UNSHARED)) {
+            } else if (action.equals(Intent.ACTION_MEDIA_SHARED) ||
+                       action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
                 updateState();
-            } else if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+            } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+                if (mBluetoothEnableForTether) {
+                    switch (intent
+                            .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
+                        case BluetoothAdapter.STATE_ON:
+                            mBluetoothPan.setBluetoothTethering(true);
+                            mBluetoothEnableForTether = false;
+                            break;
+
+                        case BluetoothAdapter.STATE_OFF:
+                        case BluetoothAdapter.ERROR:
+                            mBluetoothEnableForTether = false;
+                            break;
+
+                        default:
+                            // ignore transition states
+                    }
+                }
                 updateState();
             }
         }
@@ -281,6 +301,8 @@
 
         if (intent != null) mTetherChangeReceiver.onReceive(activity, intent);
         mWifiApEnabler.resume();
+
+        updateState();
     }
 
     @Override
@@ -368,22 +390,10 @@
 
     private void updateBluetoothState(String[] available, String[] tethered,
             String[] errored) {
-        ConnectivityManager cm =
-                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
-        int bluetoothError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
-        for (String s : available) {
-            for (String regex : mBluetoothRegexs) {
-                if (s.matches(regex)) {
-                    if (bluetoothError == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-                        bluetoothError = cm.getLastTetherError(s);
-                    }
-                }
-            }
-        }
-        boolean bluetoothTethered = false;
+        int bluetoothTethered = 0;
         for (String s : tethered) {
             for (String regex : mBluetoothRegexs) {
-                if (s.matches(regex)) bluetoothTethered = true;
+                if (s.matches(regex)) bluetoothTethered++;
             }
         }
         boolean bluetoothErrored = false;
@@ -401,17 +411,19 @@
         } else if (btState == BluetoothAdapter.STATE_TURNING_ON) {
             mBluetoothTether.setEnabled(false);
             mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
-        } else if (mBluetoothPan.isTetheringOn()) {
+        } else if (btState == BluetoothAdapter.STATE_ON && mBluetoothPan.isTetheringOn()) {
             mBluetoothTether.setChecked(true);
-            if (btState == BluetoothAdapter.STATE_ON) {
-                mBluetoothTether.setEnabled(true);
-                if (bluetoothTethered) {
-                    mBluetoothTether.setSummary(R.string.bluetooth_tethering_connected_subtext);
-                } else if (bluetoothErrored) {
-                    mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext);
-                } else {
-                    mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
-                }
+            mBluetoothTether.setEnabled(true);
+            if (bluetoothTethered > 1) {
+                String summary = getString(
+                        R.string.bluetooth_tethering_devices_connected_subtext, bluetoothTethered);
+                mBluetoothTether.setSummary(summary);
+            } else if (bluetoothTethered == 1) {
+                mBluetoothTether.setSummary(R.string.bluetooth_tethering_device_connected_subtext);
+            } else if (bluetoothErrored) {
+                mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext);
+            } else {
+                mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
             }
         } else {
             mBluetoothTether.setEnabled(true);
@@ -456,20 +468,21 @@
                 }
                 mUsbTether.setSummary("");
             }
-        } else if(preference == mBluetoothTether) {
+        } else if (preference == mBluetoothTether) {
             boolean bluetoothTetherState = mBluetoothTether.isChecked();
 
             if (bluetoothTetherState) {
                 // turn on Bluetooth first
                 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
                 if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
+                    mBluetoothEnableForTether = true;
                     adapter.enable();
                     mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
                     mBluetoothTether.setEnabled(false);
+                } else {
+                    mBluetoothPan.setBluetoothTethering(true);
+                    mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
                 }
-
-                mBluetoothPan.setBluetoothTethering(true);
-                mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
             } else {
                 boolean errored = false;