private static final long TIMEOUT = Duration.ofSeconds(10).toMillis();
// Be static to avoid too much object not be reset.
- private static CountDownTimer mTimer;
+ @VisibleForTesting
+ static CountDownTimer mTimer;
private AccessPoint mAccessPoint;
private final ConnectivityManager mConnectivityManager;
@Override
public void onLost(Network network) {
- final boolean lostCurrentNetwork = network.equals(mNetwork);
- if (lostCurrentNetwork) {
- // Should update as disconnect but not exit. Except for ephemeral network which
- // should not show on saved network list.
- if (!mIsEphemeral) {
- return;
- }
-
+ // Ephemeral network not a saved network, leave detail page once disconnected
+ if (mIsEphemeral && network.equals(mNetwork)) {
exitActivity();
}
}
};
- private final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
+ @VisibleForTesting
+ final WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
/** Called when the state of Wifi has changed. */
public void onWifiStateChanged(int state) {
Log.d(TAG, "onWifiStateChanged(" + state + ")");
/** Called when the connection state of wifi has changed. */
public void onConnectedChanged() {
- updateAccessPointFromScannedList();
- if (mConnected != mAccessPoint.isActive()) {
- Log.d(TAG, "Connection state changed!");
- mConnected = mAccessPoint.isActive();
- if (mAccessPoint.isActive()) {
- updateConnectingState(STATE_CONNECTED);
- } else {
- updateConnectingState(STATE_DISCONNECTED);
- }
- }
+ refreshPage();
}
/**
refreshMacAddress();
}
- private boolean updateAccessPoint() {
+ @VisibleForTesting
+ boolean updateAccessPoint() {
boolean changed = false;
- if (mWifiTracker != null) {
- // remember mIsOutOfRange as old before updated
- boolean oldState = mIsOutOfRange;
- updateAccessPointFromScannedList();
- // refresh UI if signal level changed for disconnect network.
- changed = mRssiSignalLevel != mAccessPoint.getLevel();
- changed |= oldState != mIsOutOfRange;
- }
+ // remember mIsOutOfRange as old before updated
+ boolean oldState = mIsOutOfRange;
+ updateAccessPointFromScannedList();
if (mAccessPoint.isActive()) {
- // Sometimes {@link WifiManager#getCurrentNetwork()} return null after connected,
- // refresh it if needed.
- if (mNetwork == null) {
- updateNetworkInfo();
- }
+ updateNetworkInfo();
mNetworkInfo = mConnectivityManager.getNetworkInfo(mNetwork);
mWifiInfo = mWifiManager.getConnectionInfo();
if (mNetwork == null || mNetworkInfo == null || mWifiInfo == null) {
- // Once connected, can't get mNetworkInfo immediately, return false and wait for
- // next time to update UI.
+ // Once connected, can't get mNetwork immediately, return false and wait for
+ // next time to update UI. also reset {@code mIsOutOfRange}
+ mIsOutOfRange = oldState;
return false;
}
-
changed |= mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
- // If feature for saved network not enabled, always return true.
- return mWifiTracker == null || changed;
+ }
+
+ // signal level changed
+ changed |= mRssiSignalLevel != mAccessPoint.getLevel();
+ // In/Out of range changed
+ changed |= oldState != mIsOutOfRange;
+ // connect state changed
+ if (mConnected != mAccessPoint.isActive()) {
+ mConnected = mAccessPoint.isActive();
+ changed = true;
+ updateConnectingState(mAccessPoint.isActive() ? STATE_CONNECTED : STATE_DISCONNECTED);
}
return changed;
}
private void updateAccessPointFromScannedList() {
- if (mWifiTracker == null) return;
-
mIsOutOfRange = true;
if (mAccessPoint.getConfig() == null) {
return FeatureFlagUtils.isEnabled(context, FeatureFlags.WIFI_DETAILS_DATAUSAGE_HEADER);
}
- private void connectNetwork() {
+ @VisibleForTesting
+ void connectNetwork() {
final Activity activity = mFragment.getActivity();
// error handling, connected/saved network should have mWifiConfig.
if (mWifiConfig == null) {
mAccessPoint.getTitle()),
Toast.LENGTH_SHORT).show();
- updateNetworkInfo();
refreshPage();
} else if (state == STATE_NOT_IN_RANGE) {
Log.d(TAG, "AP not in range");
.setButton3Enabled(false);
break;
case STATE_CONNECTED:
- mButtonsPref.setButton3Visible(false);
+ // init button state and set as invisible
+ mButtonsPref.setButton3Text(R.string.wifi_connect)
+ .setButton3Icon(R.drawable.ic_settings_wireless)
+ .setButton3Enabled(true)
+ .setButton3Visible(false);
break;
case STATE_DISCONNECTED:
case STATE_NOT_IN_RANGE:
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.content.pm.PackageManager;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowToast;
import java.net.Inet4Address;
import java.net.InetAddress;
}
@Test
+ public void testConnectButton_shouldInvisibleForConnectNetwork() {
+ setUpForConnectedNetwork();
+
+ displayAndResume();
+
+ verify(mockButtonsPref, times(1)).setButton3Visible(false);
+ }
+
+ @Test
+ public void testConnectButton_shouldVisibleForDisconnectNetwork() {
+ setUpForDisconnectedNetwork();
+
+ displayAndResume();
+
+ verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
+ }
+
+ private void setUpForToast() {
+ Resources res = mContext.getResources();
+ when(mockActivity.getResources()).thenReturn(res);
+ }
+
+ @Test
+ public void testConnectButton_clickConnect_displayAsSuccess() {
+ setUpForDisconnectedNetwork();
+ when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+ InOrder inOrder = inOrder(mockButtonsPref);
+ String label = "title";
+ when(mockAccessPoint.getTitle()).thenReturn(label);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check display button as connecting
+ verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+
+ // update as connected
+ when(mockAccessPoint.isActive()).thenReturn(true);
+ mController.updateAccessPoint();
+
+ // check connect button invisible, be init as default state and toast success message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(false);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_connected_to_message, label));
+ }
+
+ @Test
+ public void testConnectButton_clickConnectButFailed_displayFailMessage() {
+ setUpForDisconnectedNetwork();
+ ArgumentCaptor<WifiManager.ActionListener> connectListenerCaptor =
+ ArgumentCaptor.forClass(WifiManager.ActionListener.class);
+ when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+ InOrder inOrder = inOrder(mockButtonsPref);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check display button as connecting
+ verify(mockWifiManager, times(1)).connect(anyInt(), connectListenerCaptor.capture());
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+
+ // update as failed
+ connectListenerCaptor.getValue().onFailure(-1);
+
+ // check connect button visible, be init as default and toast failed message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_failed_connect_message));
+ }
+
+ private void verifyConnectBtnSetUpAsVisible(InOrder inOrder) {
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Icon(R.drawable.ic_settings_wireless);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ }
+
+ private void verifyConnectBtnSetUpAsConnecting(InOrder inOrder) {
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connecting);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Enabled(false);
+ }
+
+ private void verifyConnectBtnBeInitAsDefault(InOrder inOrder) {
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Icon(R.drawable.ic_settings_wireless);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Enabled(true);
+ }
+
+ @Test
+ public void testConnectButton_clickConnectButTimeout_displayFailMessage() {
+ setUpForDisconnectedNetwork();
+ when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+ InOrder inOrder = inOrder(mockButtonsPref);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check display button as connecting
+ verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+
+ // update as failed
+ mController.mTimer.onFinish();
+
+ // check connect button visible, be init as default and toast failed message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_failed_connect_message));
+ }
+
+ @Test
+ public void testConnectButton_clickConnectButTimeout_displayNotInRangeMessage() {
+ setUpForNotInRangeNetwork();
+ when(mockWifiManager.isWifiEnabled()).thenReturn(true);
+ InOrder inOrder = inOrder(mockButtonsPref);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check display button as connecting
+ verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+
+ // update as failed
+ mController.mTimer.onFinish();
+
+ // check connect button visible, be init as default and toast failed message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_not_in_range_message));
+ }
+
+ @Test
+ public void testConnectButton_clickConnectWhenWiFiDisabled_displaySuccessMessage() {
+ setUpForDisconnectedNetwork();
+ when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+ InOrder inOrder = inOrder(mockButtonsPref);
+ String label = "title";
+ when(mockAccessPoint.getTitle()).thenReturn(label);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+ verify(mockWifiManager, times(1)).setWifiEnabled(true);
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_turned_on_message));
+
+ // notify Wi-Fi enabled
+ mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
+
+ // check had connect network and icon display as expected
+ verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+
+ // update as connected
+ when(mockAccessPoint.isActive()).thenReturn(true);
+ mController.updateAccessPoint();
+
+ // check connect button invisible, be init as default state and toast success message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(false);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_connected_to_message, label));
+ }
+
+ @Test
+ public void testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWiFi() {
+ setUpForDisconnectedNetwork();
+ when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+ InOrder inOrder = inOrder(mockButtonsPref);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+ verify(mockWifiManager, times(1)).setWifiEnabled(true);
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_turned_on_message));
+
+ // notify Wi-Fi enabled
+ mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
+
+ // check had connect network and icon display as expected
+ verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+
+ // update as failed
+ mController.mTimer.onFinish();
+
+ // check connect button visible, be init as default and toast failed message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_failed_connect_message));
+ }
+
+ @Test
+ public void
+ testConnectButton_clickConnectWhenWiFiDisabled_failedToConnectWifiBecauseNotInRange() {
+ setUpForNotInRangeNetwork();
+ when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+ InOrder inOrder = inOrder(mockButtonsPref);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+ verify(mockWifiManager, times(1)).setWifiEnabled(true);
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_turned_on_message));
+
+ // notify Wi-Fi enabled
+ mController.mWifiListener.onWifiStateChanged(WifiManager.WIFI_STATE_ENABLED);
+
+ // check had connect network and icon display as expected
+ verify(mockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+
+ // update as failed
+ mController.mTimer.onFinish();
+
+ // check connect button visible, be init as default and toast failed message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_not_in_range_message));
+ }
+
+ @Test
+ public void testConnectButton_clickConnectWhenWiFiDisabled_failedToEnableWifi() {
+ setUpForDisconnectedNetwork();
+ when(mockWifiManager.isWifiEnabled()).thenReturn(false); // wifi disabled
+ InOrder inOrder = inOrder(mockButtonsPref);
+ setUpForToast();
+
+ displayAndResume();
+
+ // check connect button exist
+ verifyConnectBtnSetUpAsVisible(inOrder);
+
+ // click connect button
+ mController.connectNetwork();
+
+ // check turn on Wi-Fi, display button as connecting and toast turn on Wi-Fi message
+ verify(mockWifiManager, times(1)).setWifiEnabled(true);
+ verifyConnectBtnSetUpAsConnecting(inOrder);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_turned_on_message));
+
+ // notify turn on Wi-Fi failed
+ mController.mTimer.onFinish();
+
+ // check connect button visible, be init as default and toast failed message
+ verifyConnectBtnBeInitAsDefault(inOrder);
+ inOrder.verify(mockButtonsPref, times(1)).setButton3Visible(true);
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
+ mContext.getString(R.string.wifi_failed_connect_message));
+ }
+
+ @Test
+ public void updateAccessPoint_returnFalseForNothingChanged() {
+ setUpForDisconnectedNetwork();
+
+ displayAndResume();
+ boolean changed = mController.updateAccessPoint();
+
+ assertThat(changed).isFalse();
+ }
+
+ @Test
+ public void updateAccessPoint_returnTrueForSignalLevelChanged() {
+ setUpForDisconnectedNetwork();
+
+ displayAndResume();
+
+ // Level changed
+ when(mockAccessPoint.getLevel()).thenReturn(LEVEL + 1);
+ boolean changed = mController.updateAccessPoint();
+
+ assertThat(changed).isTrue();
+ }
+
+ @Test
+ public void updateAccessPoint_returnTrueForChangeAsNotInRange() {
+ setUpForDisconnectedNetwork();
+
+ displayAndResume();
+
+ // change as not in range
+ when(mockAccessPoint.matches(any(WifiConfiguration.class))).thenReturn(false);
+ boolean changed = mController.updateAccessPoint();
+
+ assertThat(changed).isTrue();
+ }
+
+ @Test
+ public void updateAccessPoint_returnTrueForChangeAsInRange() {
+ setUpForNotInRangeNetwork();
+
+ displayAndResume();
+
+ // change as in range
+ when(mockAccessPoint.matches(any(WifiConfiguration.class))).thenReturn(true);
+ boolean changed = mController.updateAccessPoint();
+
+ assertThat(changed).isTrue();
+ }
+
+ @Test
+ public void updateAccessPoint_returnTrueForChangeAsConnected() {
+ setUpForDisconnectedNetwork();
+
+ displayAndResume();
+
+ // change as connected
+ when(mockAccessPoint.isActive()).thenReturn(true);
+ boolean changed = mController.updateAccessPoint();
+
+ assertThat(changed).isTrue();
+ }
+
+ @Test
+ public void updateAccessPoint_returnTrueForChangeAsDisconnected() {
+ setUpForConnectedNetwork();
+
+ displayAndResume();
+
+ // change as disconnected
+ when(mockAccessPoint.isActive()).thenReturn(false);
+ boolean changed = mController.updateAccessPoint();
+
+ assertThat(changed).isTrue();
+ }
+
+ @Test
+ public void updateAccessPoint_returnTrueForAccessPointUpdated() {
+ setUpForConnectedNetwork();
+
+ displayAndResume();
+
+ // change as disconnected
+ when(mockAccessPoint.update(mockWifiConfig, mockWifiInfo, mockNetworkInfo))
+ .thenReturn(true);
+ boolean changed = mController.updateAccessPoint();
+
+ assertThat(changed).isTrue();
+ }
+
+ @Test
public void testRefreshRssiViews_shouldNotUpdateIfLevelIsSameForConnectedNetwork() {
setUpForConnectedNetwork();
displayAndResume();