summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArc Wang <arcwang@google.com>2020-01-09 05:52:01 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-01-09 05:52:01 +0000
commitfbc0dcb846cc397d5388f4a1080a900590a6a4a2 (patch)
tree45f39d13f2e9c65bd03559413605bea4c0f0a68b
parentc0d7e7318edaf31fd921472b0c0802457eb0c754 (diff)
parent059413165f41ac22f6ffd290fc649044252d043b (diff)
Merge changes Idaffbd88,Ia736951a,Ied9d85cc
* changes: Implement WifiEntry.getConnectedInfo() Implement mac randomization privacy setting APIs in StandardWifiEntry Add Provisioned Passpoint R1/R2 entries to Wifi Picker
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java26
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java339
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java12
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java84
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java158
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java131
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java19
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java38
8 files changed, 714 insertions, 93 deletions
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
index 28a2eb652..e52622e3c 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
@@ -16,11 +16,16 @@
package com.android.wifitrackerlib;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkRequest;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -30,6 +35,7 @@ import android.util.Log;
import androidx.annotation.AnyThread;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
@@ -118,6 +124,18 @@ public class BaseWifiTracker implements LifecycleObserver {
protected final long mScanIntervalMillis;
protected final ScanResultUpdater mScanResultUpdater;
+ // Network request for listening on changes to Wifi link properties.
+ private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
+ .clearCapabilities().addTransportType(TRANSPORT_WIFI).build();
+
+ private final ConnectivityManager.NetworkCallback mNetworkCallback =
+ new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
+ handleLinkPropertiesChanged(lp);
+ }
+ };
+
/**
* Constructor for BaseWifiTracker.
*
@@ -175,6 +193,8 @@ public class BaseWifiTracker implements LifecycleObserver {
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mContext.registerReceiver(mBroadcastReceiver, filter,
/* broadcastPermission */ null, mWorkerHandler);
+ mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
+ mWorkerHandler);
if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
mScanner.start();
} else {
@@ -192,6 +212,7 @@ public class BaseWifiTracker implements LifecycleObserver {
// TODO (b/70983952): Unregister score cache and receivers for network callbacks.
mScanner.stop();
mContext.unregisterReceiver(mBroadcastReceiver);
+ mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}
/**
@@ -249,6 +270,11 @@ public class BaseWifiTracker implements LifecycleObserver {
// Do nothing.
};
+ @WorkerThread
+ protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
+ // Do nothing.
+ };
+
/**
* Scanner to handle starting scans every SCAN_INTERVAL_MILLIS
*/
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
new file mode 100644
index 000000000..68d7adc8a
--- /dev/null
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wifitrackerlib;
+
+import static android.net.wifi.WifiInfo.removeDoubleQuotes;
+
+import static androidx.core.util.Preconditions.checkNotNull;
+
+import static com.android.wifitrackerlib.Utils.getBestScanResultByLevel;
+import static com.android.wifitrackerlib.Utils.getSecurityFromWifiConfiguration;
+
+import android.net.NetworkInfo;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.os.Handler;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * WifiEntry representation of a Passpoint network, uniquely identified by FQDN.
+ */
+class PasspointWifiEntry extends WifiEntry {
+ static final String KEY_PREFIX = "PasspointWifiEntry:";
+
+ private final List<ScanResult> mCurrentHomeScanResults = new ArrayList<>();
+ private final List<ScanResult> mCurrentRoamingScanResults = new ArrayList<>();
+
+ @NonNull private final String mKey;
+ @NonNull private String mFriendlyName;
+ @Nullable private PasspointConfiguration mPasspointConfig;
+ @Nullable private WifiConfiguration mWifiConfig;
+ private @Security int mSecurity;
+ private boolean mIsRoaming = false;
+ @Nullable private NetworkInfo mNetworkInfo;
+ @Nullable private WifiInfo mWifiInfo;
+ @Nullable private ConnectCallback mConnectCallback;
+ @Nullable private DisconnectCallback mDisconnectCallback;
+ @Nullable private ForgetCallback mForgetCallback;
+ private boolean mCalledConnect = false;
+ private boolean mCalledDisconnect = false;
+
+ private int mLevel = WIFI_LEVEL_UNREACHABLE;
+
+ /**
+ * Create a PasspointWifiEntry with the associated PasspointConfiguration
+ */
+ PasspointWifiEntry(@NonNull Handler callbackHandler,
+ @NonNull PasspointConfiguration passpointConfig,
+ @NonNull WifiManager wifiManager) throws IllegalArgumentException {
+ super(callbackHandler, false /* forSavedNetworksPage */, wifiManager);
+
+ checkNotNull(passpointConfig, "Cannot construct with null PasspointConfiguration!");
+
+ final HomeSp homeSp = passpointConfig.getHomeSp();
+ mKey = fqdnToPasspointWifiEntryKey(homeSp.getFqdn());
+ mFriendlyName = homeSp.getFriendlyName();
+ mSecurity = SECURITY_NONE; //TODO: Should this always be Enterprise?
+ }
+
+ @Override
+ public String getKey() {
+ return mKey;
+ }
+
+ @Override
+ @ConnectedState
+ public int getConnectedState() {
+ // TODO(b/70983952): Fill this method in
+ return CONNECTED_STATE_DISCONNECTED;
+ }
+
+ @Override
+ public String getTitle() {
+ return mFriendlyName;
+ }
+
+ @Override
+ public String getSummary() {
+ // TODO(b/70983952): Fill this method in
+ return "Passpoint"; // Placeholder string
+ }
+
+ @Override
+ public int getLevel() {
+ return mLevel;
+ }
+
+ @Override
+ public String getSsid() {
+ return mWifiConfig != null ? removeDoubleQuotes(mWifiConfig.SSID) : null;
+ }
+
+ @Override
+ @Security
+ public int getSecurity() {
+ // TODO(b/70983952): Fill this method in
+ return mSecurity;
+ }
+
+ @Override
+ public String getMacAddress() {
+ // TODO(b/70983952): Fill this method in
+ return null;
+ }
+
+ @Override
+ public boolean isMetered() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public boolean isSaved() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public boolean isSubscription() {
+ return true;
+ }
+
+ @Override
+ public WifiConfiguration getWifiConfiguration() {
+ return null;
+ }
+
+ @Override
+ public ConnectedInfo getConnectedInfo() {
+ // TODO(b/70983952): Fill this method in
+ return null;
+ }
+
+ @Override
+ public boolean canConnect() {
+ return mLevel != WIFI_LEVEL_UNREACHABLE
+ && getConnectedState() == CONNECTED_STATE_DISCONNECTED;
+ }
+
+ @Override
+ public void connect(@Nullable ConnectCallback callback) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @Override
+ public boolean canDisconnect() {
+ return getConnectedState() == CONNECTED_STATE_CONNECTED;
+ }
+
+ @Override
+ public void disconnect(@Nullable DisconnectCallback callback) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @Override
+ public boolean canForget() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public void forget(@Nullable ForgetCallback callback) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @Override
+ public boolean canSignIn() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public void signIn(@Nullable SignInCallback callback) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @Override
+ public boolean canShare() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public boolean canEasyConnect() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public String getQrCodeString() {
+ // TODO(b/70983952): Fill this method in
+ return null;
+ }
+
+ @Override
+ public boolean canSetPassword() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public void setPassword(@NonNull String password) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @Override
+ @MeteredChoice
+ public int getMeteredChoice() {
+ // TODO(b/70983952): Fill this method in
+ return METERED_CHOICE_UNKNOWN;
+ }
+
+ @Override
+ public boolean canSetMeteredChoice() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public void setMeteredChoice(int meteredChoice) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @Override
+ public boolean canSetPrivacy() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ @Privacy
+ public int getPrivacy() {
+ // TODO(b/70983952): Fill this method in
+ return PRIVACY_UNKNOWN;
+ }
+
+ @Override
+ public void setPrivacy(int privacy) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @Override
+ public boolean isAutoJoinEnabled() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public boolean canSetAutoJoinEnabled() {
+ // TODO(b/70983952): Fill this method in
+ return false;
+ }
+
+ @Override
+ public void setAutoJoinEnabled(boolean enabled) {
+ // TODO(b/70983952): Fill this method in
+ }
+
+ @WorkerThread
+ void updatePasspointConfig(@NonNull PasspointConfiguration passpointConfig) {
+ checkNotNull(passpointConfig, "Cannot update with null PasspointConfiguration!");
+ mPasspointConfig = passpointConfig;
+ mFriendlyName = passpointConfig.getHomeSp().getFriendlyName();
+ notifyOnUpdated();
+ }
+
+ @WorkerThread
+ void updateScanResultInfo(@NonNull WifiConfiguration wifiConfig,
+ @Nullable List<ScanResult> homeScanResults,
+ @Nullable List<ScanResult> roamingScanResults)
+ throws IllegalArgumentException {
+ mWifiConfig = wifiConfig;
+ mSecurity = getSecurityFromWifiConfiguration(wifiConfig);
+
+ if (homeScanResults == null) {
+ homeScanResults = new ArrayList<>();
+ }
+ if (roamingScanResults == null) {
+ roamingScanResults = new ArrayList<>();
+ }
+
+ ScanResult bestScanResult;
+ if (homeScanResults.isEmpty() && !roamingScanResults.isEmpty()) {
+ mIsRoaming = true;
+ bestScanResult = getBestScanResultByLevel(roamingScanResults);
+ } else {
+ mIsRoaming = false;
+ bestScanResult = getBestScanResultByLevel(homeScanResults);
+ }
+
+ if (bestScanResult == null) {
+ mLevel = WIFI_LEVEL_UNREACHABLE;
+ } else {
+ mLevel = mWifiManager.calculateSignalLevel(bestScanResult.level);
+ }
+
+ notifyOnUpdated();
+ }
+
+ @WorkerThread
+ @Override
+ protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
+ @NonNull NetworkInfo networkInfo) {
+ if (!wifiInfo.isPasspointAp()) {
+ return false;
+ }
+
+ return mWifiConfig != null && mWifiConfig.networkId == wifiInfo.getNetworkId();
+ }
+
+ @NonNull
+ static String fqdnToPasspointWifiEntryKey(@NonNull String fqdn) {
+ checkNotNull(fqdn, "Cannot create key with null fqdn!");
+ return KEY_PREFIX + fqdn;
+ }
+}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
index 3f0870dad..6190b98ce 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
@@ -20,12 +20,14 @@ import static androidx.core.util.Preconditions.checkNotNull;
import static com.android.wifitrackerlib.StandardWifiEntry.scanResultToStandardWifiEntryKey;
import static com.android.wifitrackerlib.StandardWifiEntry.wifiConfigToStandardWifiEntryKey;
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
import static java.util.stream.Collectors.toList;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiConfiguration;
@@ -71,6 +73,8 @@ class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
final NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
mChosenEntry.updateConnectionInfo(wifiInfo, networkInfo);
+ handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(
+ mWifiManager.getCurrentNetwork()));
}
@AnyThread
@@ -123,6 +127,14 @@ class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
(NetworkInfo) intent.getExtra(WifiManager.EXTRA_NETWORK_INFO));
}
+ @WorkerThread
+ @Override
+ protected void handleLinkPropertiesChanged(@NonNull LinkProperties linkProperties) {
+ if (mChosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+ mChosenEntry.updateLinkProperties(linkProperties);
+ }
+ }
+
/**
* Updates the tracked entry's scan results up to the max scan age (or more, if the last scan
* was unsuccessful). If Wifi is disabled, the tracked entry's level will be cleared.
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
index 149ba45a6..54dddcb8e 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
@@ -16,7 +16,6 @@
package com.android.wifitrackerlib;
-import static android.net.wifi.WifiInfo.INVALID_RSSI;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
import static androidx.core.util.Preconditions.checkNotNull;
@@ -55,15 +54,9 @@ class StandardWifiEntry extends WifiEntry {
@NonNull private final String mSsid;
private final @Security int mSecurity;
@Nullable private WifiConfiguration mWifiConfig;
- @Nullable private NetworkInfo mNetworkInfo;
- @Nullable private WifiInfo mWifiInfo;
@Nullable private ConnectCallback mConnectCallback;
@Nullable private DisconnectCallback mDisconnectCallback;
@Nullable private ForgetCallback mForgetCallback;
- private boolean mCalledConnect = false;
- private boolean mCalledDisconnect = false;
-
- private int mLevel = WIFI_LEVEL_UNREACHABLE;
StandardWifiEntry(@NonNull Handler callbackHandler, @NonNull List<ScanResult> scanResults,
@NonNull WifiManager wifiManager) throws IllegalArgumentException {
@@ -117,28 +110,6 @@ class StandardWifiEntry extends WifiEntry {
}
@Override
- @ConnectedState
- public int getConnectedState() {
- if (mNetworkInfo == null) {
- return CONNECTED_STATE_DISCONNECTED;
- }
-
- switch (mNetworkInfo.getDetailedState()) {
- case SCANNING:
- case CONNECTING:
- case AUTHENTICATING:
- case OBTAINING_IPADDR:
- case VERIFYING_POOR_LINK:
- case CAPTIVE_PORTAL_CHECK:
- return CONNECTED_STATE_CONNECTING;
- case CONNECTED:
- return CONNECTED_STATE_CONNECTED;
- default:
- return CONNECTED_STATE_DISCONNECTED;
- }
- }
-
- @Override
public String getTitle() {
return mSsid;
}
@@ -208,8 +179,7 @@ class StandardWifiEntry extends WifiEntry {
@Override
public ConnectedInfo getConnectedInfo() {
- // TODO(b/70983952): Fill this method in
- return null;
+ return mConnectedInfo;
}
@Override
@@ -287,6 +257,7 @@ class StandardWifiEntry extends WifiEntry {
}
}
+ @Override
public boolean canSignIn() {
// TODO(b/70983952): Fill this method in
return false;
@@ -400,8 +371,7 @@ class StandardWifiEntry extends WifiEntry {
@Override
public boolean canSetPrivacy() {
- // TODO(b/70983952): Fill this method in
- return false;
+ return isSaved();
}
@Override
@@ -420,7 +390,13 @@ class StandardWifiEntry extends WifiEntry {
@Override
public void setPrivacy(int privacy) {
- // TODO(b/70983952): Fill this method in
+ if (!canSetPrivacy()) {
+ return;
+ }
+
+ mWifiConfig.macRandomizationSetting = privacy == PRIVACY_RANDOMIZED_MAC
+ ? WifiConfiguration.RANDOMIZATION_PERSISTENT : WifiConfiguration.RANDOMIZATION_NONE;
+ mWifiManager.save(mWifiConfig, null /* listener */);
}
@Override
@@ -497,42 +473,14 @@ class StandardWifiEntry extends WifiEntry {
notifyOnUpdated();
}
- /**
- * Updates information regarding the current network connection. If the supplied WifiInfo and
- * NetworkInfo do not represent this WifiEntry, then the WifiEntry will update to be
- * unconnected.
- */
@WorkerThread
- void updateConnectionInfo(@Nullable WifiInfo wifiInfo, @Nullable NetworkInfo networkInfo) {
- if (mWifiConfig != null && wifiInfo != null
- && mWifiConfig.networkId == wifiInfo.getNetworkId()) {
- mNetworkInfo = networkInfo;
- mWifiInfo = wifiInfo;
- final int wifiInfoRssi = wifiInfo.getRssi();
- if (wifiInfoRssi != INVALID_RSSI) {
- mLevel = mWifiManager.calculateSignalLevel(wifiInfoRssi);
- }
- if (mCalledConnect && getConnectedState() == CONNECTED_STATE_CONNECTED) {
- mCalledConnect = false;
- mCallbackHandler.post(() -> {
- if (mConnectCallback != null) {
- mConnectCallback.onConnectResult(ConnectCallback.CONNECT_STATUS_SUCCESS);
- }
- });
- }
- } else {
- mNetworkInfo = null;
- }
- if (mCalledDisconnect && getConnectedState() == CONNECTED_STATE_DISCONNECTED) {
- mCalledDisconnect = false;
- mCallbackHandler.post(() -> {
- if (mDisconnectCallback != null) {
- mDisconnectCallback.onDisconnectResult(
- DisconnectCallback.DISCONNECT_STATUS_SUCCESS);
- }
- });
+ protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
+ @NonNull NetworkInfo networkInfo) {
+ if (wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) {
+ return false;
}
- notifyOnUpdated();
+
+ return mWifiConfig != null && mWifiConfig.networkId == wifiInfo.getNetworkId();
}
@NonNull
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
index 4752e8449..08801d045 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
@@ -16,9 +16,17 @@
package com.android.wifitrackerlib;
+import static android.net.wifi.WifiInfo.INVALID_RSSI;
+
import static androidx.core.util.Preconditions.checkNotNull;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkInfo;
+import android.net.NetworkUtils;
+import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
@@ -27,10 +35,17 @@ import androidx.annotation.IntDef;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
/**
* Abstract base class for an entry representing a Wi-Fi network in a Wi-Fi picker/settings.
@@ -136,6 +151,17 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
private WifiEntryCallback mListener;
protected Handler mCallbackHandler;
+ protected int mLevel = WIFI_LEVEL_UNREACHABLE;
+ protected WifiInfo mWifiInfo;
+ protected NetworkInfo mNetworkInfo;
+ protected ConnectedInfo mConnectedInfo;
+
+ protected ConnectCallback mConnectCallback;
+ protected DisconnectCallback mDisconnectCallback;
+
+ protected boolean mCalledConnect = false;
+ protected boolean mCalledDisconnect = false;
+
WifiEntry(@NonNull Handler callbackHandler, boolean forSavedNetworksPage,
@NonNull WifiManager wifiManager) throws IllegalArgumentException {
checkNotNull(callbackHandler, "Cannot construct with null handler!");
@@ -152,7 +178,26 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
/** Returns connection state of the network defined by the CONNECTED_STATE constants */
@ConnectedState
- public abstract int getConnectedState();
+ public int getConnectedState() {
+ if (mNetworkInfo == null) {
+ return CONNECTED_STATE_DISCONNECTED;
+ }
+
+ switch (mNetworkInfo.getDetailedState()) {
+ case SCANNING:
+ case CONNECTING:
+ case AUTHENTICATING:
+ case OBTAINING_IPADDR:
+ case VERIFYING_POOR_LINK:
+ case CAPTIVE_PORTAL_CHECK:
+ return CONNECTED_STATE_CONNECTING;
+ case CONNECTED:
+ return CONNECTED_STATE_CONNECTED;
+ default:
+ return CONNECTED_STATE_DISCONNECTED;
+ }
+ }
+
/** Returns the display title. This is most commonly the SSID of a network. */
public abstract String getTitle();
@@ -206,7 +251,9 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
*
* Returns null if getConnectedState() != CONNECTED_STATE_CONNECTED.
*/
- public abstract ConnectedInfo getConnectedInfo();
+ public ConnectedInfo getConnectedInfo() {
+ return mConnectedInfo;
+ }
/**
* Info associated with the active connection.
@@ -214,10 +261,10 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
public static class ConnectedInfo {
@Frequency
public int frequencyMhz;
- public List<String> dnsServers;
+ public List<String> dnsServers = new ArrayList<>();
public int linkSpeedMbps;
public String ipAddress;
- public List<String> ipv6Addresses;
+ public List<String> ipv6Addresses = new ArrayList<>();
public String gateway;
public String subnetMask;
}
@@ -408,6 +455,105 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
void onSignInResult(@SignInStatus int status);
}
+ /**
+ * Returns whether or not the supplied WifiInfo and NetworkInfo represent this WifiEntry
+ */
+ protected abstract boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo,
+ @NonNull NetworkInfo networkInfo);
+
+ /**
+ * Updates information regarding the current network connection. If the supplied WifiInfo and
+ * NetworkInfo do not match this WifiEntry, then the WifiEntry will update to be
+ * unconnected.
+ */
+ @WorkerThread
+ void updateConnectionInfo(@Nullable WifiInfo wifiInfo, @Nullable NetworkInfo networkInfo) {
+ if (wifiInfo != null && networkInfo != null
+ && connectionInfoMatches(wifiInfo, networkInfo)) {
+ // Connection info matches, so the WifiInfo/NetworkInfo represent this network and
+ // the network is currently connecting or connected.
+ mWifiInfo = wifiInfo;
+ mNetworkInfo = networkInfo;
+ final int wifiInfoRssi = wifiInfo.getRssi();
+ if (wifiInfoRssi != INVALID_RSSI) {
+ mLevel = mWifiManager.calculateSignalLevel(wifiInfoRssi);
+ }
+ if (getConnectedState() == CONNECTED_STATE_CONNECTED) {
+ if (mCalledConnect) {
+ mCalledConnect = false;
+ mCallbackHandler.post(() -> {
+ if (mConnectCallback != null) {
+ mConnectCallback.onConnectResult(
+ ConnectCallback.CONNECT_STATUS_SUCCESS);
+ }
+ });
+ }
+
+ if (mConnectedInfo == null) {
+ mConnectedInfo = new ConnectedInfo();
+ }
+ mConnectedInfo.frequencyMhz = wifiInfo.getFrequency();
+ mConnectedInfo.linkSpeedMbps = wifiInfo.getLinkSpeed();
+ }
+ } else { // Connection info doesn't matched, so this network is disconnected
+ mNetworkInfo = null;
+ mConnectedInfo = null;
+ if (mCalledDisconnect) {
+ mCalledDisconnect = false;
+ mCallbackHandler.post(() -> {
+ if (mDisconnectCallback != null) {
+ mDisconnectCallback.onDisconnectResult(
+ DisconnectCallback.DISCONNECT_STATUS_SUCCESS);
+ }
+ });
+ }
+ }
+ notifyOnUpdated();
+ }
+
+ // Method for WifiTracker to update the link properties, which is valid for all WifiEntry types.
+ @WorkerThread
+ void updateLinkProperties(@Nullable LinkProperties linkProperties) {
+ if (getConnectedState() != CONNECTED_STATE_CONNECTED) {
+ return;
+ }
+
+ if (mConnectedInfo == null) {
+ mConnectedInfo = new ConnectedInfo();
+ }
+ // Find IPv4 and IPv6 addresses, and subnet mask
+ List<String> ipv6Addresses = new ArrayList<>();
+ for (LinkAddress addr : linkProperties.getLinkAddresses()) {
+ if (addr.getAddress() instanceof Inet4Address) {
+ mConnectedInfo.ipAddress = addr.getAddress().getHostAddress();
+ try {
+ InetAddress all = InetAddress.getByAddress(
+ new byte[]{(byte) 255, (byte) 255, (byte) 255, (byte) 255});
+ mConnectedInfo.subnetMask = NetworkUtils.getNetworkPart(
+ all, addr.getPrefixLength()).getHostAddress();
+ } catch (UnknownHostException e) {
+ // Leave subnet null;
+ }
+ } else if (addr.getAddress() instanceof Inet6Address) {
+ ipv6Addresses.add(addr.getAddress().getHostAddress());
+ }
+ }
+ mConnectedInfo.ipv6Addresses = ipv6Addresses;
+
+ // Find IPv4 default gateway.
+ for (RouteInfo routeInfo : linkProperties.getRoutes()) {
+ if (routeInfo.isIPv4Default() && routeInfo.hasGateway()) {
+ mConnectedInfo.gateway = routeInfo.getGateway().getHostAddress();
+ break;
+ }
+ }
+
+ // Find DNS servers
+ mConnectedInfo.dnsServers = linkProperties.getDnsServers().stream()
+ .map(InetAddress::getHostAddress).collect(Collectors.toList());
+
+ notifyOnUpdated();
+ }
// TODO (b/70983952) Come up with a sorting scheme that does the right thing.
@Override
@@ -446,6 +592,10 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
.append(getLevel())
.append(",security:")
.append(getSecurity())
+ .append(",connected:")
+ .append(getConnectedState() == CONNECTED_STATE_CONNECTED ? "true" : "false")
+ .append(",connectedInfo:")
+ .append(getConnectedInfo())
.toString();
}
}
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
index abd9841fe..50b7a244b 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
@@ -26,19 +26,23 @@ import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkScoreManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import androidx.annotation.AnyThread;
import androidx.annotation.GuardedBy;
@@ -81,6 +85,10 @@ public class WifiPickerTracker extends BaseWifiTracker {
private WifiEntry mConnectedWifiEntry;
// Cache containing visible StandardWifiEntries. Must be accessed only by the worker thread.
private final Map<String, StandardWifiEntry> mStandardWifiEntryCache = new HashMap<>();
+ // Cache containing visible PasspointWifiEntries. Must be accessed only by the worker thread.
+ private final Map<String, PasspointWifiEntry> mPasspointWifiEntryCache = new HashMap<>();
+ // Cache containing saved PasspointConfigurations mapped by PasspointWifiEntry key.
+ private final Map<String, PasspointConfiguration> mPasspointConfigCache = new HashMap<>();
private int mNumSavedNetworks = 0;
@@ -149,22 +157,30 @@ public class WifiPickerTracker extends BaseWifiTracker {
*/
@AnyThread
public int getNumSavedSubscriptions() {
- //TODO(b/70983952): Use a cached value for this and update dynamically instead of calling
- // this expensive method every time.
- return mWifiManager.getPasspointConfigurations().size();
+ return mPasspointConfigCache.size();
}
@WorkerThread
@Override
protected void handleOnStart() {
- mScanResultUpdater.update(mWifiManager.getScanResults());
+ mScanResultUpdater.update(Utils.filterScanResultsByCapabilities(
+ mWifiManager.getScanResults(),
+ mWifiManager.isWpa3SaeSupported(),
+ mWifiManager.isWpa3SuiteBSupported(),
+ mWifiManager.isEnhancedOpenSupported()));
+ // PasspointConfigurations should be populated before ScanResults, so that the scan results
+ // have a PasspointConfiguration to map to.
+ updatePasspointWifiEntryConfigs(mWifiManager.getPasspointConfigurations());
conditionallyUpdateScanResults(true /* lastScanSucceeded */);
- updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks());
final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
final NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo();
- updateStandardWifiEntryConnectionInfo(wifiInfo, networkInfo);
+ updateConnectionInfo(wifiInfo, networkInfo);
// Create a StandardWifiEntry for the current connection if there are no scan results yet.
conditionallyCreateConnectedStandardWifiEntry(wifiInfo, networkInfo);
+ handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(
+ mWifiManager.getCurrentNetwork()));
+ notifyOnNumSavedNetworksChanged();
+ notifyOnNumSavedSubscriptionsChanged();
updateWifiEntries();
}
@@ -198,7 +214,12 @@ public class WifiPickerTracker extends BaseWifiTracker {
} else {
updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks());
}
+ updatePasspointWifiEntryConfigs(mWifiManager.getPasspointConfigurations());
+ // Update Passpoint scan results since adding a new PasspointConfiguration may result in
+ // current scans mapping to a new PasspointWifiEntry.
+ updatePasspointWifiEntryScans(mScanResultUpdater.getScanResults());
notifyOnNumSavedNetworksChanged();
+ notifyOnNumSavedSubscriptionsChanged();
updateWifiEntries();
}
@@ -206,11 +227,20 @@ public class WifiPickerTracker extends BaseWifiTracker {
@Override
protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
checkNotNull(intent, "Intent cannot be null!");
- updateStandardWifiEntryConnectionInfo(mWifiManager.getConnectionInfo(),
+ updateConnectionInfo(mWifiManager.getConnectionInfo(),
(NetworkInfo) intent.getExtra(WifiManager.EXTRA_NETWORK_INFO));
updateWifiEntries();
}
+ @WorkerThread
+ @Override
+ protected void handleLinkPropertiesChanged(@NonNull LinkProperties linkProperties) {
+ if (mConnectedWifiEntry != null
+ && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+ mConnectedWifiEntry.updateLinkProperties(linkProperties);
+ }
+ }
+
/**
* Update the list returned by getWifiEntries() with the current states of the entry caches.
*/
@@ -220,9 +250,8 @@ public class WifiPickerTracker extends BaseWifiTracker {
mWifiEntries.clear();
mWifiEntries.addAll(mStandardWifiEntryCache.values().stream().filter(entry ->
entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList()));
- // mWifiEntries.addAll(mPasspointWifiEntryCache);
- // mWifiEntries.addAll(mCarrierWifiEntryCache);
- // mWifiEntries.addAll(mSuggestionWifiEntryCache);
+ mWifiEntries.addAll(mPasspointWifiEntryCache.values().stream().filter(entry ->
+ entry.getConnectedState() == CONNECTED_STATE_DISCONNECTED).collect(toList()));
mConnectedWifiEntry = mStandardWifiEntryCache.values().stream().filter(entry -> {
final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState();
return connectedState == CONNECTED_STATE_CONNECTED
@@ -248,14 +277,8 @@ public class WifiPickerTracker extends BaseWifiTracker {
private void updateStandardWifiEntryScans(@NonNull List<ScanResult> scanResults) {
checkNotNull(scanResults, "Scan Result list should not be null!");
- // Filter out scan results with unsupported capabilities
- final List<ScanResult> filteredScans = Utils.filterScanResultsByCapabilities(scanResults,
- mWifiManager.isWpa3SaeSupported(),
- mWifiManager.isWpa3SuiteBSupported(),
- mWifiManager.isEnhancedOpenSupported());
-
// Group scans by StandardWifiEntry key
- final Map<String, List<ScanResult>> scanResultsByKey = filteredScans.stream()
+ final Map<String, List<ScanResult>> scanResultsByKey = scanResults.stream()
.filter(scanResult -> !TextUtils.isEmpty(scanResult.SSID))
.collect(groupingBy(StandardWifiEntry::scanResultToStandardWifiEntryKey));
@@ -278,6 +301,38 @@ public class WifiPickerTracker extends BaseWifiTracker {
updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks());
}
+ @WorkerThread
+ private void updatePasspointWifiEntryScans(@NonNull List<ScanResult> scanResults) {
+ checkNotNull(scanResults, "Scan Result list should not be null!");
+
+ List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> matchingWifiConfigs =
+ mWifiManager.getAllMatchingWifiConfigs(scanResults);
+ for (Pair<WifiConfiguration, Map<Integer, List<ScanResult>>> pair : matchingWifiConfigs) {
+ final WifiConfiguration wifiConfig = pair.first;
+ final List<ScanResult> homeScans =
+ pair.second.get(WifiManager.PASSPOINT_HOME_NETWORK);
+ final List<ScanResult> roamingScans =
+ pair.second.get(WifiManager.PASSPOINT_ROAMING_NETWORK);
+ final String key = PasspointWifiEntry.fqdnToPasspointWifiEntryKey(wifiConfig.FQDN);
+ // Skip in case the returned
+ if (!mPasspointConfigCache.containsKey(key)) {
+ continue;
+ }
+
+ // Create PasspointWifiEntry if one doesn't exist for the seen key yet.
+ if (!mPasspointWifiEntryCache.containsKey(key)) {
+ mPasspointWifiEntryCache.put(key, new PasspointWifiEntry(
+ mMainHandler, mPasspointConfigCache.get(key), mWifiManager));
+ }
+ mPasspointWifiEntryCache.get(key).updateScanResultInfo(wifiConfig,
+ homeScans, roamingScans);
+ }
+
+ // Remove entries that are now unreachable
+ mPasspointWifiEntryCache.entrySet()
+ .removeIf(entry -> entry.getValue().getLevel() == WIFI_LEVEL_UNREACHABLE);
+ }
+
/**
* Conditionally updates the WifiEntry scan results based on the current wifi state and
* whether the last scan succeeded or not.
@@ -286,19 +341,26 @@ public class WifiPickerTracker extends BaseWifiTracker {
private void conditionallyUpdateScanResults(boolean lastScanSucceeded) {
if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) {
updateStandardWifiEntryScans(Collections.emptyList());
+ updatePasspointWifiEntryScans(Collections.emptyList());
return;
}
long scanAgeWindow = mMaxScanAgeMillis;
if (lastScanSucceeded) {
// Scan succeeded, cache new scans
- mScanResultUpdater.update(mWifiManager.getScanResults());
+ mScanResultUpdater.update(Utils.filterScanResultsByCapabilities(
+ mWifiManager.getScanResults(),
+ mWifiManager.isWpa3SaeSupported(),
+ mWifiManager.isWpa3SuiteBSupported(),
+ mWifiManager.isEnhancedOpenSupported()));
} else {
// Scan failed, increase scan age window to prevent WifiEntry list from
// clearing prematurely.
scanAgeWindow += mScanIntervalMillis;
}
+
updateStandardWifiEntryScans(mScanResultUpdater.getScanResults(scanAgeWindow));
+ updatePasspointWifiEntryScans(mScanResultUpdater.getScanResults(scanAgeWindow));
}
/**
@@ -352,14 +414,17 @@ public class WifiPickerTracker extends BaseWifiTracker {
}
/**
- * Updates all StandardWifiEntries with the current connection info.
+ * Updates all WifiEntries with the current connection info.
* @param wifiInfo WifiInfo of the current connection
* @param networkInfo NetworkInfo of the current connection
*/
@WorkerThread
- private void updateStandardWifiEntryConnectionInfo(@Nullable WifiInfo wifiInfo,
+ private void updateConnectionInfo(@Nullable WifiInfo wifiInfo,
@Nullable NetworkInfo networkInfo) {
- for (StandardWifiEntry entry : mStandardWifiEntryCache.values()) {
+ for (WifiEntry entry : mStandardWifiEntryCache.values()) {
+ entry.updateConnectionInfo(wifiInfo, networkInfo);
+ }
+ for (WifiEntry entry : mPasspointWifiEntryCache.values()) {
entry.updateConnectionInfo(wifiInfo, networkInfo);
}
}
@@ -386,6 +451,30 @@ public class WifiPickerTracker extends BaseWifiTracker {
});
}
+ @WorkerThread
+ private void updatePasspointWifiEntryConfigs(@NonNull List<PasspointConfiguration> configs) {
+ checkNotNull(configs, "Config list should not be null!");
+
+ mPasspointConfigCache.clear();
+ mPasspointConfigCache.putAll(configs.stream().collect(
+ toMap((config) -> PasspointWifiEntry.fqdnToPasspointWifiEntryKey(
+ config.getHomeSp().getFqdn()), Function.identity())));
+
+ // Iterate through current entries and update each entry's config or remove if no config
+ // matches the entry anymore.
+ mPasspointWifiEntryCache.entrySet().removeIf((entry) -> {
+ final PasspointWifiEntry wifiEntry = entry.getValue();
+ final String key = wifiEntry.getKey();
+ final PasspointConfiguration cachedConfig = mPasspointConfigCache.get(key);
+ if (cachedConfig != null) {
+ wifiEntry.updatePasspointConfig(cachedConfig);
+ return false;
+ } else {
+ return true;
+ }
+ });
+ }
+
/**
* Posts onWifiEntryChanged callback on the main thread.
*/
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
index bb5f814bd..a94d2bd79 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.net.LinkProperties;
import android.net.MacAddress;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
@@ -497,6 +498,24 @@ public class StandardWifiEntryTest {
assertThat(oweWifiEntry.canEasyConnect()).isFalse();
}
+ @Test
+ public void testUpdateLinkProperties_updatesConnectedInfo() {
+ final WifiConfiguration config = new WifiConfiguration();
+ config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ config.SSID = "\"ssid\"";
+ config.networkId = 1;
+ final StandardWifiEntry entry = new StandardWifiEntry(mTestHandler, config,
+ mMockWifiManager);
+ when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+ when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
+ when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
+ entry.updateConnectionInfo(mMockWifiInfo, mMockNetworkInfo);
+
+ entry.updateLinkProperties(new LinkProperties());
+
+ assertThat(entry.getConnectedInfo()).isNotNull();
+ }
+
private StandardWifiEntry getSavedStandardWifiEntry(int wifiConfigurationSecureType) {
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
index f052e8df2..8bca9cd11 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
@@ -35,8 +35,11 @@ import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Handler;
import android.os.test.TestLooper;
+import android.util.Pair;
import androidx.lifecycle.Lifecycle;
@@ -50,7 +53,9 @@ import java.time.Clock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class WifiPickerTrackerTest {
@@ -493,4 +498,37 @@ public class WifiPickerTrackerTest {
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
}
+
+ /**
+ * Tests that a PasspointWifiEntry is returned when Passpoint scans are visible.
+ */
+ @Test
+ public void testGetWifiEntries_passpointInRange_returnsPasspointWifiEntry() {
+ final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+ final PasspointConfiguration passpointConfig = new PasspointConfiguration();
+ final HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("fqdn");
+ homeSp.setFriendlyName("friendlyName");
+ passpointConfig.setHomeSp(homeSp);
+ when(mMockWifiManager.getPasspointConfigurations())
+ .thenReturn(Collections.singletonList(passpointConfig));
+ wifiPickerTracker.onStart();
+ verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+ any(), any(), any());
+ mTestLooper.dispatchAll();
+
+ final WifiConfiguration wifiConfig = new WifiConfiguration();
+ wifiConfig.FQDN = "fqdn";
+ final Map<Integer, List<ScanResult>> mapping = new HashMap<>();
+ mapping.put(WifiManager.PASSPOINT_HOME_NETWORK, Collections.singletonList(
+ buildScanResult("ssid", "bssid", START_MILLIS)));
+ List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> allMatchingWifiConfigs =
+ Collections.singletonList(new Pair<>(wifiConfig, mapping));
+ when(mMockWifiManager.getAllMatchingWifiConfigs(any())).thenReturn(allMatchingWifiConfigs);
+ mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+ new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+
+ assertThat(wifiPickerTracker.getWifiEntries()).isNotEmpty();
+ assertThat(wifiPickerTracker.getWifiEntries().get(0).getTitle()).isEqualTo("friendlyName");
+ }
}