Merge "Use SoftAp API to get number of connected device"
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
index fa10607..11f1f59 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
@@ -24,6 +24,7 @@
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
 import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
 import android.support.v7.preference.PreferenceScreen;
 import android.text.BidiFormatter;
 
@@ -51,7 +52,11 @@
     private final WifiManager mWifiManager;
     private final Lifecycle mLifecycle;
     private WifiTetherSwitchBarController mSwitchController;
-    private MasterSwitchPreference mPreference;
+    private int mSoftApState;
+    @VisibleForTesting
+    MasterSwitchPreference mPreference;
+    @VisibleForTesting
+    WifiTetherSoftApManager mWifiTetherSoftApManager;
 
     static {
         WIFI_TETHER_INTENT_FILTER = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
@@ -60,6 +65,12 @@
     }
 
     public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) {
+        this(context, lifecycle, true /* initSoftApManager */);
+    }
+
+    @VisibleForTesting
+    WifiTetherPreferenceController(Context context, Lifecycle lifecycle,
+            boolean initSoftApManager) {
         super(context);
         mConnectivityManager =
                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -69,6 +80,9 @@
         if (lifecycle != null) {
             lifecycle.addObserver(this);
         }
+        if (initSoftApManager) {
+            initWifiTetherSoftApManager();
+        }
     }
 
     @Override
@@ -101,6 +115,9 @@
         if (mPreference != null) {
             mContext.registerReceiver(mReceiver, WIFI_TETHER_INTENT_FILTER);
             clearSummaryForAirplaneMode();
+            if (mWifiTetherSoftApManager != null) {
+                mWifiTetherSoftApManager.registerSoftApCallback();
+            }
         }
     }
 
@@ -108,9 +125,36 @@
     public void onStop() {
         if (mPreference != null) {
             mContext.unregisterReceiver(mReceiver);
+            if (mWifiTetherSoftApManager != null) {
+                mWifiTetherSoftApManager.unRegisterSoftApCallback();
+            }
         }
     }
 
+    @VisibleForTesting
+    void initWifiTetherSoftApManager() {
+        // This manager only handles the number of connected devices, other parts are handled by
+        // normal BroadcastReceiver in this controller
+        mWifiTetherSoftApManager = new WifiTetherSoftApManager(mWifiManager,
+                new WifiTetherSoftApManager.WifiTetherSoftApCallback() {
+                    @Override
+                    public void onStateChanged(int state, int failureReason) {
+                        mSoftApState = state;
+                    }
+
+                    @Override
+                    public void onNumClientsChanged(int numClients) {
+                        if (mPreference != null
+                                && mSoftApState == WifiManager.WIFI_AP_STATE_ENABLED) {
+                            // Only show the number of clients when state is on
+                            mPreference.setSummary(mContext.getResources().getQuantityString(
+                                    R.plurals.wifi_tether_connected_summary, numClients,
+                                    numClients));
+                        }
+                    }
+                });
+    }
+
     //
     // Everything below is copied from WifiApEnabler
     //
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java b/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java
new file mode 100644
index 0000000..77a44b0
--- /dev/null
+++ b/src/com/android/settings/wifi/tether/WifiTetherSoftApManager.java
@@ -0,0 +1,47 @@
+package com.android.settings.wifi.tether;
+
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+
+/**
+ * Wrapper for {@link android.net.wifi.WifiManager.SoftApCallback} to pass the robo test
+ */
+public class WifiTetherSoftApManager {
+
+    private WifiManager mWifiManager;
+    private WifiTetherSoftApCallback mWifiTetherSoftApCallback;
+
+    private WifiManager.SoftApCallback mSoftApCallback = new WifiManager.SoftApCallback() {
+        @Override
+        public void onStateChanged(int state, int failureReason) {
+            mWifiTetherSoftApCallback.onStateChanged(state, failureReason);
+        }
+
+        @Override
+        public void onNumClientsChanged(int numClients) {
+            mWifiTetherSoftApCallback.onNumClientsChanged(numClients);
+        }
+    };
+    private Handler mHandler;
+
+    WifiTetherSoftApManager(WifiManager wifiManager,
+            WifiTetherSoftApCallback wifiTetherSoftApCallback) {
+        mWifiManager = wifiManager;
+        mWifiTetherSoftApCallback = wifiTetherSoftApCallback;
+        mHandler = new Handler();
+    }
+
+    public void registerSoftApCallback() {
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+    }
+
+    public void unRegisterSoftApCallback() {
+        mWifiManager.unregisterSoftApCallback(mSoftApCallback);
+    }
+
+    public interface WifiTetherSoftApCallback {
+        void onStateChanged(int state, int failureReason);
+
+        void onNumClientsChanged(int numClients);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
index 00d9585..dca6974 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
@@ -18,11 +18,15 @@
 
 import static android.arch.lifecycle.Lifecycle.Event.ON_START;
 import static android.arch.lifecycle.Lifecycle.Event.ON_STOP;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -65,6 +69,7 @@
         shadows = {
                 WifiTetherPreferenceControllerTest.ShadowWifiTetherSettings.class,
                 WifiTetherPreferenceControllerTest.ShadowWifiTetherSwitchBarController.class,
+                WifiTetherPreferenceControllerTest.ShadowWifiTetherSoftApManager.class
         })
 public class WifiTetherPreferenceControllerTest {
 
@@ -94,8 +99,9 @@
         when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
         when(mScreen.findPreference(anyString())).thenReturn(mPreference);
 
-        when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[] {"1", "2"});
-        mController = new WifiTetherPreferenceController(mContext, mLifecycle);
+        when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
+        mController = new WifiTetherPreferenceController(mContext, mLifecycle,
+                false /* initSoftApManager */);
     }
 
     @After
@@ -105,8 +111,9 @@
 
     @Test
     public void isAvailable_noTetherRegex_shouldReturnFalse() {
-        when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[] {});
-        mController = new WifiTetherPreferenceController(mContext, mLifecycle);
+        when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{});
+        mController = new WifiTetherPreferenceController(mContext, mLifecycle,
+                false /* initSoftApManager */);
 
         assertThat(mController.isAvailable()).isFalse();
     }
@@ -244,6 +251,19 @@
         }
     }
 
+    @Implements(WifiTetherSoftApManager.class)
+    public static final class ShadowWifiTetherSoftApManager {
+        @Implementation
+        public void registerSoftApCallback() {
+            // do nothing
+        }
+
+        @Implementation
+        public void unRegisterSoftApCallback() {
+            // do nothing
+        }
+    }
+
     @Implements(WifiTetherSwitchBarController.class)
     public static final class ShadowWifiTetherSwitchBarController {