Add internal WifiTracker to get correct AccessPoint for
WifiNetworkRequestDialog
Use WifiTracker to get correct and constantly updated Wifi status of AccessPoint.
Bug: 117399926
Test: RunSettingsRoboTests
Change-Id: I5e4316f6acb7787dcaab150a293068852beb76e0
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index c627a2e..30c2cd9 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -30,6 +30,7 @@
import android.widget.BaseAdapter;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.internal.PreferenceImageView;
@@ -46,7 +47,10 @@
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.Utils;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.wifi.AccessPoint;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -62,10 +66,14 @@
/** Message sent to us to stop scanning wifi and pop up timeout dialog. */
private static final int MESSAGE_STOP_SCAN_WIFI_LIST = 0;
+ /** Spec defines there should be 5 wifi ap on the list at most. */
+ private static final int MAX_NUMBER_LIST_ITEM = 5;
+
/** Delayed time to stop scanning wifi. */
private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000;
private List<AccessPoint> mAccessPointList;
+ private FilterWifiTracker mFilterWifiTracker;
private AccessPointAdapter mDialogAdapter;
private NetworkRequestUserSelectionCallback mUserSelectionCallback;
@@ -159,6 +167,19 @@
if (wifiManager != null) {
wifiManager.unregisterNetworkRequestMatchCallback(this);
}
+
+ if (mFilterWifiTracker != null) {
+ mFilterWifiTracker.onPause();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mFilterWifiTracker != null) {
+ mFilterWifiTracker.onDestroy();
+ mFilterWifiTracker = null;
+ }
}
@Override
@@ -172,6 +193,11 @@
}
// Sets time-out to stop scanning.
mHandler.sendEmptyMessageDelayed(MESSAGE_STOP_SCAN_WIFI_LIST, DELAY_TIME_STOP_SCAN_MS);
+
+ if (mFilterWifiTracker == null) {
+ mFilterWifiTracker = new FilterWifiTracker(getActivity(), getSettingsLifecycle());
+ }
+ mFilterWifiTracker.onResume();
}
private final Handler mHandler = new Handler() {
@@ -268,17 +294,33 @@
@Override
public void onMatch(List<ScanResult> scanResults) {
- // TODO(b/119846365): Checks if we could escalate the converting effort.
- // Converts ScanResult to WifiConfiguration.
- List<WifiConfiguration> wifiConfigurations = null;
- final WifiManager wifiManager = getContext().getApplicationContext()
- .getSystemService(WifiManager.class);
- if (wifiManager != null) {
- wifiConfigurations = wifiManager.getAllMatchingWifiConfigs(scanResults);
+ mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
+ renewAccessPointList(scanResults);
+
+ notifyAdapterRefresh();
+ }
+
+ // Updates internal AccessPoint list from WifiTracker. scanResults are used to update key list
+ // of AccessPoint, and could be null if there is no necessary to update key list.
+ private void renewAccessPointList(List<ScanResult> scanResults) {
+ if (mFilterWifiTracker == null) {
+ return;
}
- setUpAccessPointList(wifiConfigurations);
+ // TODO(b/119846365): Checks if we could escalate the converting effort.
+ // Updates keys of scanResults into FilterWifiTracker for updating matched AccessPoints.
+ if (scanResults != null) {
+ mFilterWifiTracker.updateKeys(scanResults);
+ }
+ // Re-gets matched AccessPoints from WifiTracker.
+ final List<AccessPoint> list = getAccessPointList();
+ list.clear();
+ list.addAll(mFilterWifiTracker.getAccessPoints());
+ }
+
+ @VisibleForTesting
+ void notifyAdapterRefresh() {
if (getDialogAdapter() != null) {
getDialogAdapter().notifyDataSetChanged();
}
@@ -286,48 +328,99 @@
@Override
public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) {
- if (getDialogAdapter() != null) {
- updateAccessPointListItem(wificonfiguration);
- getDialogAdapter().notifyDataSetChanged();
- }
+ // Dismisses current dialog, since connection is success.
+ dismiss();
}
@Override
public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) {
- if (mDialogAdapter != null) {
- updateAccessPointListItem(wificonfiguration);
- getDialogAdapter().notifyDataSetChanged();
- }
+ stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
}
- private void updateAccessPointListItem(WifiConfiguration wificonfiguration) {
- if (wificonfiguration == null) {
- return;
+ private final class FilterWifiTracker {
+ private final List<String> mAccessPointKeys;
+ private final WifiTracker mWifiTracker;
+
+ public FilterWifiTracker(Context context, Lifecycle lifecycle) {
+ mWifiTracker = WifiTrackerFactory.create(context, mWifiListener,
+ lifecycle, /* includeSaved */ true, /* includeScans */ true);
+ mAccessPointKeys = new ArrayList<>();
}
- final List<AccessPoint> accessPointList = getAccessPointList();
- final int accessPointListSize = accessPointList.size();
-
- for (int i = 0; i < accessPointListSize; i++) {
- AccessPoint accessPoint = accessPointList.get(i);
- // It is the same AccessPoint SSID, and should be replaced to update latest properties.
- if (accessPoint.matches(wificonfiguration)) {
- accessPointList.set(i, new AccessPoint(getContext(), wificonfiguration));
- break;
+ /**
+ * Updates key list from input. {@code onMatch()} may be called in multi-times according
+ * wifi scanning result, so needs patchwork here.
+ */
+ public void updateKeys(List<ScanResult> scanResults) {
+ for (ScanResult scanResult : scanResults) {
+ final String key = AccessPoint.getKey(scanResult);
+ if (!mAccessPointKeys.contains(key)) {
+ mAccessPointKeys.add(key);
+ }
}
}
- }
- private void setUpAccessPointList(List<WifiConfiguration> wifiConfigurations) {
- // Grants for zero size input, since maybe current wifi is off or somethings are wrong.
- if (wifiConfigurations == null) {
- return;
+ /**
+ * Returns only AccessPoints whose key is in {@code mAccessPointKeys}.
+ *
+ * @return List of matched AccessPoints.
+ */
+ public List<AccessPoint> getAccessPoints() {
+ final List<AccessPoint> allAccessPoints = mWifiTracker.getAccessPoints();
+ final List<AccessPoint> result = new ArrayList<>();
+
+ // The order should be kept, because order means wifi score (sorting in WifiTracker).
+ int count = 0;
+ for (AccessPoint accessPoint : allAccessPoints) {
+ final String key = accessPoint.getKey();
+ if (mAccessPointKeys.contains(key)) {
+ result.add(accessPoint);
+
+ count++;
+ // Limits how many count of items could show.
+ if (count >= MAX_NUMBER_LIST_ITEM) {
+ break;
+ }
+ }
+ }
+
+ return result;
}
- final List<AccessPoint> accessPointList = getAccessPointList();
- accessPointList.clear();
- for (WifiConfiguration config : wifiConfigurations) {
- accessPointList.add(new AccessPoint(getContext(), config));
+ private WifiTracker.WifiListener mWifiListener = new WifiTracker.WifiListener() {
+
+ @Override
+ public void onWifiStateChanged(int state) {
+ notifyAdapterRefresh();
+ }
+
+ @Override
+ public void onConnectedChanged() {
+ notifyAdapterRefresh();
+ }
+
+ @Override
+ public void onAccessPointsChanged() {
+ notifyAdapterRefresh();
+ }
+ };
+
+ public void onDestroy() {
+ if (mWifiTracker != null) {
+ mWifiTracker.onDestroy();
+ }
+ }
+
+ public void onResume() {
+ if (mWifiTracker != null) {
+ mWifiTracker.onStart();
+ }
+ }
+
+ public void onPause() {
+ if (mWifiTracker != null) {
+ mWifiTracker.onStop();
+ }
}
}
}
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
index 48f8ec0..107da79 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogActivityTest.java
@@ -18,9 +18,13 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
import androidx.appcompat.app.AlertDialog;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,6 +38,10 @@
@Test
public void LaunchActivity_shouldShowNetworkRequestDialog() {
+ // Mocks fake WifiTracker, in case of exception in NetworkRequestDialogFragment.onResume().
+ WifiTracker wifiTracker = mock(WifiTracker.class);
+ WifiTrackerFactory.setTestingWifiTracker(wifiTracker);
+
Robolectric.setupActivity(NetworkRequestDialogActivity.class);
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index 343d170..e64fae7 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -51,6 +51,10 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
+
import org.robolectric.shadows.ShadowLooper;
@RunWith(RobolectricTestRunner.class)
@@ -58,16 +62,21 @@
public class NetworkRequestDialogFragmentTest {
private static final String KEY_SSID = "key_ssid";
+ private static final String KEY_SECURITY = "key_security";
private FragmentActivity mActivity;
private NetworkRequestDialogFragment networkRequestDialogFragment;
private Context mContext;
+ private WifiTracker mWifiTracker;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class);
networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
mContext = spy(RuntimeEnvironment.application);
+
+ mWifiTracker = mock(WifiTracker.class);
+ WifiTrackerFactory.setTestingWifiTracker(mWifiTracker);
}
@Test
@@ -140,71 +149,47 @@
}
@Test
- public void updateAccessPointList_onUserSelectionConnectSuccess_updateCorrectly() {
- List<AccessPoint> accessPointList = spy(new ArrayList<>());
- Bundle bundle = new Bundle();
- bundle.putString(KEY_SSID, "Test AP 1");
- accessPointList.add(new AccessPoint(mContext, bundle));
- bundle.putString(KEY_SSID, "Test AP 2");
- accessPointList.add(new AccessPoint(mContext, bundle));
- bundle.putString(KEY_SSID, "Test AP 3");
- accessPointList.add(new AccessPoint(mContext, bundle));
- bundle.putString(KEY_SSID, "Test AP 4");
- accessPointList.add(new AccessPoint(mContext, bundle));
-
+ public void updateAccessPointList_onUserSelectionConnectSuccess_shouldCloseTheDialog() {
+ List<AccessPoint> accessPointList = createAccessPointList();
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+ AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(alertDialog.isShowing()).isTrue();
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
- AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
- verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+ assertThat(alertDialog.isShowing()).isFalse();
}
@Test
- public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
- List<AccessPoint> accessPointList = spy(new ArrayList<>());
- Bundle bundle = new Bundle();
- bundle.putString(KEY_SSID, "Test AP 1");
- accessPointList.add(new AccessPoint(mContext, bundle));
- bundle.putString(KEY_SSID, "Test AP 2");
- accessPointList.add(new AccessPoint(mContext, bundle));
- bundle.putString(KEY_SSID, "Test AP 3");
- accessPointList.add(new AccessPoint(mContext, bundle));
- bundle.putString(KEY_SSID, "Test AP 4");
- accessPointList.add(new AccessPoint(mContext, bundle));
+ public void updateAccessPointList_onUserSelectionConnectFailure_shouldCallTimeoutDialog() {
+ FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
+ FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
+ List<AccessPoint> accessPointList = createAccessPointList();
+ when(spyFakeFragment.getAccessPointList()).thenReturn(accessPointList);
+ spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
- when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
- networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
+ AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ assertThat(alertDialog.isShowing()).isTrue();
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
- networkRequestDialogFragment.onUserSelectionConnectFailure(config);
+ fakeFragment.onUserSelectionConnectFailure(config);
- AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
- verify(accessPointList, times(1)).set(2, verifyAccessPoint);
+ assertThat(fakeFragment.bCalledStopAndPop).isTrue();
}
@Test
- public void onUserSelectionCallbackRegistration_shouldCallSelect() {
- List<AccessPoint> accessPointList = spy(new ArrayList<>());
- Bundle bundle = new Bundle();
- bundle.putString(KEY_SSID, "Test AP 1");
- accessPointList.add(new AccessPoint(mContext, bundle));
- bundle.putString(KEY_SSID, "Test AP 2");
- accessPointList.add(new AccessPoint(mContext, bundle));
-
- bundle.putString(KEY_SSID, "Test AP 3");
- AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
+ public void onUserSelectionCallbackRegistration_onClick_shouldCallSelect() {
+ // Assert.
+ final int indexClickItem = 3;
+ List<AccessPoint> accessPointList = createAccessPointList();
+ AccessPoint clickedAccessPoint = accessPointList.get(indexClickItem);
clickedAccessPoint.generateOpenNetworkConfig();
- accessPointList.add(clickedAccessPoint);
-
- bundle.putString(KEY_SSID, "Test AP 4");
- accessPointList.add(new AccessPoint(mContext, bundle));
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
NetworkRequestUserSelectionCallback selectionCallback = mock(
@@ -212,40 +197,66 @@
AlertDialog dialog = mock(AlertDialog.class);
networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
- networkRequestDialogFragment.onClick(dialog, 2);
+ // Act.
+ networkRequestDialogFragment.onClick(dialog, indexClickItem);
+ // Check.
verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
}
@Test
public void onMatch_shouldUpdatedList() {
- // Prepares WifiManager.
+ // Assert.
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
+ networkRequestDialogFragment.onResume();
- List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
- WifiConfiguration config = new WifiConfiguration();
+ List<AccessPoint> accessPointList = createAccessPointList();
+ when(mWifiTracker.getAccessPoints()).thenReturn(accessPointList);
+
final String SSID_AP1 = "Test AP 1";
- config.SSID = SSID_AP1;
- wifiConfigurationList.add(config);
- config = new WifiConfiguration();
final String SSID_AP2 = "Test AP 2";
- config.SSID = SSID_AP2;
- wifiConfigurationList.add(config);
-
- // Prepares callback converted data.
List<ScanResult> scanResults = new ArrayList<>();
- when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
+ ScanResult scanResult = new ScanResult();
+ scanResult.SSID = SSID_AP1;
+ scanResult.capabilities = "WEP";
+ scanResults.add(scanResult);
+ scanResult = new ScanResult();
+ scanResult.SSID = SSID_AP2;
+ scanResult.capabilities = "WEP";
+ scanResults.add(scanResult);
+ // Act.
networkRequestDialogFragment.onMatch(scanResults);
- List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
- assertThat(accessPointList).isNotEmpty();
- assertThat(accessPointList.size()).isEqualTo(2);
- assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
- assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
+ // Check.
+ List<AccessPoint> returnList = networkRequestDialogFragment.getAccessPointList();
+ assertThat(returnList).isNotEmpty();
+ assertThat(returnList.size()).isEqualTo(2);
+ assertThat(returnList.get(0).getSsid()).isEqualTo(SSID_AP1);
+ assertThat(returnList.get(1).getSsid()).isEqualTo(SSID_AP2);
+ }
+
+ private List<AccessPoint> createAccessPointList() {
+ List<AccessPoint> accessPointList = spy(new ArrayList<>());
+ Bundle bundle = new Bundle();
+ bundle.putString(KEY_SSID, "Test AP 1");
+ bundle.putInt(KEY_SECURITY, 1);
+ accessPointList.add(new AccessPoint(mContext, bundle));
+ bundle.putString(KEY_SSID, "Test AP 2");
+ bundle.putInt(KEY_SECURITY, 1);
+ accessPointList.add(new AccessPoint(mContext, bundle));
+ bundle.putString(KEY_SSID, "Test AP 3");
+ bundle.putInt(KEY_SECURITY, 2);
+ AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
+ accessPointList.add(clickedAccessPoint);
+ bundle.putString(KEY_SSID, "Test AP 4");
+ bundle.putInt(KEY_SECURITY, 0);
+ accessPointList.add(new AccessPoint(mContext, bundle));
+
+ return accessPointList;
}
}