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
This commit is contained in:
cosmohsieh
2018-12-15 01:20:27 +08:00
parent 6c403a876d
commit 65c8d1df69
3 changed files with 213 additions and 101 deletions

View File

@@ -30,6 +30,7 @@ import android.os.Message;
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.R;
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 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
/** 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 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
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 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
}
// 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 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
@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 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
@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();
/**
* 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);
}
}
}
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;
/**
* 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;
}
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();
}
}
}
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;
}
final List<AccessPoint> accessPointList = getAccessPointList();
accessPointList.clear();
for (WifiConfiguration config : wifiConfigurations) {
accessPointList.add(new AccessPoint(getContext(), config));
}
}
}