diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 03c620580423a..a29cf8449e51c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -99,6 +99,8 @@
Automatically connected via network rating provider
Connected via %1$s
+
+ %1$s by %2$s
Available via %1$s
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index af5a24f16222d..1ae1d56aacc81 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -41,6 +41,7 @@ import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
+import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Bundle;
import android.os.Parcelable;
@@ -182,6 +183,10 @@ public class AccessPoint implements Comparable {
public static final int UNREACHABLE_RSSI = Integer.MIN_VALUE;
+ public static final String KEY_PREFIX_AP = "AP:";
+ public static final String KEY_PREFIX_FQDN = "FQDN:";
+ public static final String KEY_PREFIX_OSU = "OSU:";
+
private final Context mContext;
private String ssid;
@@ -204,9 +209,6 @@ public class AccessPoint implements Comparable {
@Speed private int mSpeed = Speed.NONE;
private boolean mIsScoredNetworkMetered = false;
- // used to co-relate internal vs returned accesspoint.
- int mId;
-
/**
* Information associated with the {@link PasspointConfiguration}. Only maintaining
* the relevant info to preserve spaces.
@@ -215,6 +217,8 @@ public class AccessPoint implements Comparable {
private String mProviderFriendlyName;
private boolean mIsCarrierAp = false;
+
+ private OsuProvider mOsuProvider;
/**
* The EAP type {@link WifiEnterpriseConfig.Eap} associated with this AP if it is a carrier AP.
*/
@@ -280,14 +284,18 @@ public class AccessPoint implements Comparable {
// Calculate required fields
updateKey();
updateRssi();
-
- mId = sLastId.incrementAndGet();
}
+ /**
+ * Creates an AccessPoint with only a WifiConfiguration. This is used for the saved networks
+ * page.
+ *
+ * Passpoint Credential AccessPoints should be created with this.
+ * Make sure to call setScanResults after constructing with this.
+ */
public AccessPoint(Context context, WifiConfiguration config) {
mContext = context;
loadConfig(config);
- mId = sLastId.incrementAndGet();
}
/**
@@ -298,7 +306,19 @@ public class AccessPoint implements Comparable {
mContext = context;
mFqdn = config.getHomeSp().getFqdn();
mProviderFriendlyName = config.getHomeSp().getFriendlyName();
- mId = sLastId.incrementAndGet();
+ }
+
+ /**
+ * Initialize an AccessPoint object for a Passpoint OSU Provider.
+ * Make sure to call setScanResults after constructing with this.
+ */
+ public AccessPoint(Context context, OsuProvider provider) {
+ mContext = context;
+ mOsuProvider = provider;
+ mRssi = 1;
+ // TODO: This placeholder SSID is here to avoid null pointer exceptions.
+ ssid = "";
+ updateKey();
}
AccessPoint(Context context, Collection results) {
@@ -324,8 +344,6 @@ public class AccessPoint implements Comparable {
mIsCarrierAp = firstResult.isCarrierAp;
mCarrierApEapType = firstResult.carrierApEapType;
mCarrierName = firstResult.carrierName;
-
- mId = sLastId.incrementAndGet();
}
@VisibleForTesting void loadConfig(WifiConfiguration config) {
@@ -344,14 +362,19 @@ public class AccessPoint implements Comparable {
StringBuilder builder = new StringBuilder();
if (isPasspoint()) {
- builder.append(mConfig.FQDN);
- } else if (TextUtils.isEmpty(getSsidStr())) {
- builder.append(getBssid());
- } else {
- builder.append(getSsidStr());
+ builder.append(KEY_PREFIX_FQDN).append(mConfig.FQDN);
+ } else if (isOsuProvider()) {
+ builder.append(KEY_PREFIX_OSU).append(mOsuProvider.getOsuSsid());
+ builder.append(',').append(mOsuProvider.getServerUri());
+ } else { // Non-Passpoint AP
+ builder.append(KEY_PREFIX_AP);
+ if (TextUtils.isEmpty(getSsidStr())) {
+ builder.append(getBssid());
+ } else {
+ builder.append(getSsidStr());
+ }
+ builder.append(',').append(getSecurity());
}
-
- builder.append(',').append(getSecurity());
mKey = builder.toString();
}
@@ -396,8 +419,8 @@ public class AccessPoint implements Comparable {
return difference;
}
- // Sort by ssid.
- difference = getSsidStr().compareToIgnoreCase(other.getSsidStr());
+ // Sort by title.
+ difference = getTitle().compareToIgnoreCase(other.getTitle());
if (difference != 0) {
return difference;
}
@@ -595,6 +618,7 @@ public class AccessPoint implements Comparable {
public static String getKey(ScanResult result) {
StringBuilder builder = new StringBuilder();
+ builder.append(KEY_PREFIX_AP);
if (TextUtils.isEmpty(result.SSID)) {
builder.append(result.BSSID);
} else {
@@ -609,14 +633,17 @@ public class AccessPoint implements Comparable {
StringBuilder builder = new StringBuilder();
if (config.isPasspoint()) {
- builder.append(config.FQDN);
- } else if (TextUtils.isEmpty(config.SSID)) {
- builder.append(config.BSSID);
+ builder.append(KEY_PREFIX_FQDN).append(config.FQDN);
} else {
- builder.append(removeDoubleQuotes(config.SSID));
+ builder.append(KEY_PREFIX_AP);
+ if (TextUtils.isEmpty(config.SSID)) {
+ builder.append(config.BSSID);
+ } else {
+ builder.append(removeDoubleQuotes(config.SSID));
+ }
+ builder.append(',').append(getSecurity(config));
}
- builder.append(',').append(getSecurity(config));
return builder.toString();
}
@@ -839,91 +866,95 @@ public class AccessPoint implements Comparable {
public String getTitle() {
if (isPasspoint()) {
return mConfig.providerFriendlyName;
+ } else if (isOsuProvider()) {
+ return mOsuProvider.getFriendlyName();
} else {
return getSsidStr();
}
}
public String getSummary() {
- return getSettingsSummary(mConfig);
+ return getSettingsSummary();
}
public String getSettingsSummary() {
- return getSettingsSummary(mConfig);
- }
-
- private String getSettingsSummary(WifiConfiguration config) {
// Update to new summary
StringBuilder summary = new StringBuilder();
- if (isActive() && config != null && config.isPasspoint()) {
- // This is the active connection on passpoint
- summary.append(getSummary(mContext, getDetailedState(),
- false, config.providerFriendlyName));
- } else if (isActive() && config != null && getDetailedState() == DetailedState.CONNECTED
- && mIsCarrierAp) {
- summary.append(String.format(mContext.getString(R.string.connected_via_carrier), mCarrierName));
- } else if (isActive()) {
- // This is the active connection on non-passpoint network
- summary.append(getSummary(mContext, getDetailedState(),
- mInfo != null && mInfo.isEphemeral()));
- } else if (config != null && config.isPasspoint()
- && config.getNetworkSelectionStatus().isNetworkEnabled()) {
- String format = mContext.getString(R.string.available_via_passpoint);
- summary.append(String.format(format, config.providerFriendlyName));
- } else if (config != null && config.hasNoInternetAccess()) {
- int messageID = config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
- ? R.string.wifi_no_internet_no_reconnect
- : R.string.wifi_no_internet;
- summary.append(mContext.getString(messageID));
- } else if (config != null && !config.getNetworkSelectionStatus().isNetworkEnabled()) {
- WifiConfiguration.NetworkSelectionStatus networkStatus =
- config.getNetworkSelectionStatus();
- switch (networkStatus.getNetworkSelectionDisableReason()) {
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
- summary.append(mContext.getString(R.string.wifi_disabled_password_failure));
- break;
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
- summary.append(mContext.getString(R.string.wifi_check_password_try_again));
- break;
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_DNS_FAILURE:
- summary.append(mContext.getString(R.string.wifi_disabled_network_failure));
- break;
- case WifiConfiguration.NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
- summary.append(mContext.getString(R.string.wifi_disabled_generic));
- break;
+ if (isActive()) {
+ if (isPasspoint()) {
+ // This is the active connection on passpoint
+ summary.append(getSummary(mContext, ssid, getDetailedState(),
+ false, mConfig.providerFriendlyName));
+ } else if (mConfig != null && getDetailedState() == DetailedState.CONNECTED
+ && mIsCarrierAp) {
+ // This is the active connection on a carrier AP
+ summary.append(String.format(mContext.getString(R.string.connected_via_carrier),
+ mCarrierName));
+ } else {
+ // This is the active connection on non-passpoint network
+ summary.append(getSummary(mContext, getDetailedState(),
+ mInfo != null && mInfo.isEphemeral()));
}
- } else if (config != null && config.getNetworkSelectionStatus().isNotRecommended()) {
- summary.append(mContext.getString(R.string.wifi_disabled_by_recommendation_provider));
- } else if (mIsCarrierAp) {
- summary.append(String.format(mContext.getString(R.string.available_via_carrier), mCarrierName));
- } else if (!isReachable()) { // Wifi out of range
- summary.append(mContext.getString(R.string.wifi_not_in_range));
- } else { // In range, not disabled.
- if (config != null) { // Is saved network
- // Last attempt to connect to this failed. Show reason why
- switch (config.recentFailure.getAssociationStatus()) {
- case WifiConfiguration.RecentFailure.STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
- summary.append(mContext.getString(
- R.string.wifi_ap_unable_to_handle_new_sta));
+ } else { // not active
+ if (mConfig != null && mConfig.hasNoInternetAccess()) {
+ int messageID = mConfig.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()
+ ? R.string.wifi_no_internet_no_reconnect
+ : R.string.wifi_no_internet;
+ summary.append(mContext.getString(messageID));
+ } else if (mConfig != null && !mConfig.getNetworkSelectionStatus().isNetworkEnabled()) {
+ WifiConfiguration.NetworkSelectionStatus networkStatus =
+ mConfig.getNetworkSelectionStatus();
+ switch (networkStatus.getNetworkSelectionDisableReason()) {
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
+ summary.append(mContext.getString(R.string.wifi_disabled_password_failure));
break;
- default:
- // "Saved"
- summary.append(mContext.getString(R.string.wifi_remembered));
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
+ summary.append(mContext.getString(R.string.wifi_check_password_try_again));
break;
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_DNS_FAILURE:
+ summary.append(mContext.getString(R.string.wifi_disabled_network_failure));
+ break;
+ case WifiConfiguration.NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
+ summary.append(mContext.getString(R.string.wifi_disabled_generic));
+ break;
+ }
+ } else if (mConfig != null && mConfig.getNetworkSelectionStatus().isNotRecommended()) {
+ summary.append(mContext.getString(
+ R.string.wifi_disabled_by_recommendation_provider));
+ } else if (mIsCarrierAp) {
+ summary.append(String.format(mContext.getString(
+ R.string.available_via_carrier), mCarrierName));
+ } else if (!isReachable()) { // Wifi out of range
+ summary.append(mContext.getString(R.string.wifi_not_in_range));
+ } else { // In range, not disabled.
+ if (mConfig != null) { // Is saved network
+ // Last attempt to connect to this failed. Show reason why
+ switch (mConfig.recentFailure.getAssociationStatus()) {
+ case WifiConfiguration.RecentFailure.STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
+ summary.append(mContext.getString(
+ R.string.wifi_ap_unable_to_handle_new_sta));
+ break;
+ default:
+ // "Saved"
+ summary.append(mContext.getString(R.string.wifi_remembered));
+ break;
+ }
}
}
}
+
+
if (isVerboseLoggingEnabled()) {
- summary.append(WifiUtils.buildLoggingSummary(this, config));
+ summary.append(WifiUtils.buildLoggingSummary(this, mConfig));
}
- if (config != null && (WifiUtils.isMeteredOverridden(config) || config.meteredHint)) {
+ if (mConfig != null && (WifiUtils.isMeteredOverridden(mConfig) || mConfig.meteredHint)) {
return mContext.getResources().getString(
R.string.preference_summary_default_combination,
- WifiUtils.getMeteredLabel(mContext, config),
+ WifiUtils.getMeteredLabel(mContext, mConfig),
summary.toString());
}
@@ -975,6 +1006,13 @@ public class AccessPoint implements Comparable {
return mFqdn != null;
}
+ /**
+ * Return true if this AccessPoint represents an OSU Provider.
+ */
+ public boolean isOsuProvider() {
+ return mOsuProvider != null;
+ }
+
/**
* Return whether the given {@link WifiInfo} is for this access point.
* If the current AP does not have a network Id then the config is used to
@@ -1065,8 +1103,8 @@ public class AccessPoint implements Comparable {
void setScanResults(Collection scanResults) {
// Validate scan results are for current AP only by matching SSID/BSSID
- // Passpoint R1 networks are not bound to a specific SSID/BSSID, so skip this for passpoint.
- if (!isPasspoint()) {
+ // Passpoint networks are not bound to a specific SSID/BSSID, so skip this for passpoint.
+ if (!isPasspoint() && !isOsuProvider()) {
String key = getKey();
for (ScanResult result : scanResults) {
String scanResultKey = AccessPoint.getKey(result);
@@ -1119,7 +1157,17 @@ public class AccessPoint implements Comparable {
}
}
- /** Attempt to update the AccessPoint and return true if an update occurred. */
+ /**
+ * Attempt to update the AccessPoint with the current connection info.
+ * This is used to set an AccessPoint to the active one if the connection info matches, or
+ * conversely to set an AccessPoint to inactive if the connection info does not match. The RSSI
+ * is also updated upon a match. Listeners will be notified if an update occurred.
+ *
+ * This is called in {@link WifiTracker#updateAccessPoints} as well as in callbacks for handling
+ * NETWORK_STATE_CHANGED_ACTION, RSSI_CHANGED_ACTION, and onCapabilitiesChanged in WifiTracker.
+ *
+ * Returns true if an update occurred.
+ */
public boolean update(
@Nullable WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
@@ -1246,11 +1294,11 @@ public class AccessPoint implements Comparable {
public static String getSummary(Context context, String ssid, DetailedState state,
boolean isEphemeral, String passpointProvider) {
- if (state == DetailedState.CONNECTED && ssid == null) {
- if (TextUtils.isEmpty(passpointProvider) == false) {
+ if (state == DetailedState.CONNECTED) {
+ if (!TextUtils.isEmpty(passpointProvider)) {
// Special case for connected + passpoint networks.
- String format = context.getString(R.string.connected_via_passpoint);
- return String.format(format, passpointProvider);
+ String format = context.getString(R.string.ssid_by_passpoint_provider);
+ return String.format(format, ssid, passpointProvider);
} else if (isEphemeral) {
// Special case for connected + ephemeral networks.
final NetworkScoreManager networkScoreManager = context.getSystemService(
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 79a72402e232c..6d2889121c64f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -35,6 +35,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
import android.net.wifi.WifiNetworkScoreCache.CacheListener;
+import android.net.wifi.hotspot2.OsuProvider;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
@@ -584,7 +585,7 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
Map>> pairing : passpointConfigsAndScans) {
WifiConfiguration config = pairing.first;
- // TODO: Prioritize home networks before roaming networks
+ // TODO(b/118705403): Prioritize home networks before roaming networks
List scanResults = new ArrayList<>();
List homeScans =
@@ -618,6 +619,23 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
}
}
+ // Add Passpoint OSU Provider AccessPoints
+ // TODO(b/118705403): filter out OSU Providers which we already have credentials from.
+ Map> providersAndScans =
+ mWifiManager.getMatchingOsuProviders(cachedScanResults);
+ for (OsuProvider provider : providersAndScans.keySet()) {
+ AccessPoint accessPointOsu = new AccessPoint(mContext, provider);
+ // TODO(b/118705403): accessPointOsu.setScanResults(Matching ScanResult with best
+ // RSSI)
+ // TODO(b/118705403): Figure out if we would need to update an OSU AP (this will be
+ // used if we need to display it at the top of the picker as the "active" AP).
+ // Otherwise, OSU APs should ignore attempts to update the active connection
+ // info.
+ // accessPointOsu.update(connectionConfig, mLastInfo, mLastNetworkInfo);
+ accessPoints.add(accessPointOsu);
+ }
+
+
// If there were no scan results, create an AP for the currently connected network (if
// it exists).
if (accessPoints.isEmpty() && connectionConfig != null) {