From 9d62bc1c10c29d162fe7fb94df8c187606f7af76 Mon Sep 17 00:00:00 2001 From: Quang Luong Date: Wed, 5 Feb 2020 12:23:11 -0800 Subject: [WifiTrackerLib] Allow OSU provisioning from wifi picker Tapping on an OSU entry (i.e. "Tap to sign-up") will open a web view for OSU provisioning. Test: manual - tap on OSU entry in wifi picker and observe provisioning flow opening Bug: 70983952 Change-Id: Id8cdc487f7fb3f91283b7b70a46ff4718caea543 (cherry picked from commit c6263d9770a4289f20b097a231eefbc01aafa71c) Merged-In: Id8cdc487f7fb3f91283b7b70a46ff4718caea543 --- libs/WifiTrackerLib/res/values/strings.xml | 18 ++++ .../com/android/wifitrackerlib/OsuWifiEntry.java | 116 +++++++++++++++++++-- .../android/wifitrackerlib/PasspointWifiEntry.java | 20 ++-- .../android/wifitrackerlib/WifiPickerTracker.java | 44 ++++++-- 4 files changed, 167 insertions(+), 31 deletions(-) (limited to 'libs') diff --git a/libs/WifiTrackerLib/res/values/strings.xml b/libs/WifiTrackerLib/res/values/strings.xml index 8758183da..1b49b299a 100644 --- a/libs/WifiTrackerLib/res/values/strings.xml +++ b/libs/WifiTrackerLib/res/values/strings.xml @@ -144,4 +144,22 @@ Expired + + + Tap to sign up + + + Opening %1$s + + + Couldn\u2019t connect + + + Completing sign-up\u2026 + + + Couldn\u2019t complete sign-up. Tap to try again. + + + Sign-up complete. Connecting\u2026 diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java index 244dd7949..97467d559 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java @@ -19,7 +19,9 @@ package com.android.wifitrackerlib; import static androidx.core.util.Preconditions.checkNotNull; import static com.android.wifitrackerlib.Utils.getBestScanResultByLevel; +import static com.android.wifitrackerlib.WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN; +import android.annotation.MainThread; import android.content.Context; import android.net.NetworkInfo; import android.net.wifi.ScanResult; @@ -27,14 +29,20 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.net.wifi.hotspot2.OsuProvider; +import android.net.wifi.hotspot2.PasspointConfiguration; +import android.net.wifi.hotspot2.ProvisioningCallback; import android.os.Handler; +import android.text.TextUtils; +import android.util.Pair; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; /** * WifiEntry representation of an Online Sign-up entry, uniquely identified by FQDN. @@ -45,9 +53,9 @@ class OsuWifiEntry extends WifiEntry { @NonNull private final List mCurrentScanResults = new ArrayList<>(); @NonNull private final String mKey; - @NonNull private String mFriendlyName; @NonNull private final Context mContext; @NonNull private OsuProvider mOsuProvider; + private String mOsuStatusString; private int mLevel = WIFI_LEVEL_UNREACHABLE; @@ -84,8 +92,9 @@ class OsuWifiEntry extends WifiEntry { @Override public String getSummary(boolean concise) { - // TODO(b/70983952): Fill this method in - return "Osu (Placeholder Text)"; // Placeholder string + // TODO(b/70983952): Add verbose summary + return mOsuStatusString != null + ? mOsuStatusString : mContext.getString(R.string.tap_to_sign_up); } @Override @@ -139,7 +148,9 @@ class OsuWifiEntry extends WifiEntry { @Override public void connect(@Nullable ConnectCallback callback) { - // TODO(b/70983952): Fill this method in. + mConnectCallback = callback; + mWifiManager.startSubscriptionProvisioning(mOsuProvider, mContext.getMainExecutor(), + new OsuWifiEntryProvisioningCallback()); } // Exiting from the OSU flow should disconnect from the network. @@ -283,8 +294,8 @@ class OsuWifiEntry extends WifiEntry { @Override protected boolean connectionInfoMatches(@NonNull WifiInfo wifiInfo, @NonNull NetworkInfo networkInfo) { - // TODO(b/70983952): Fill this method in. - return false; + return wifiInfo.isOsuAp() && TextUtils.equals( + wifiInfo.getPasspointProviderFriendlyName(), mOsuProvider.getFriendlyName()); } @Override @@ -292,4 +303,97 @@ class OsuWifiEntry extends WifiEntry { // TODO(b/70983952): Fill this method in. return ""; } + + OsuProvider getOsuProvider() { + return mOsuProvider; + } + + class OsuWifiEntryProvisioningCallback extends ProvisioningCallback { + @Override + @MainThread public void onProvisioningFailure(int status) { + if (TextUtils.equals( + mOsuStatusString, mContext.getString(R.string.osu_completing_sign_up))) { + mOsuStatusString = mContext.getString(R.string.osu_sign_up_failed); + } else { + mOsuStatusString = mContext.getString(R.string.osu_connect_failed); + } + if (mConnectCallback != null) { + mConnectCallback.onConnectResult(CONNECT_STATUS_FAILURE_UNKNOWN); + } + notifyOnUpdated(); + } + + @Override + @MainThread public void onProvisioningStatus(int status) { + String newStatusString = null; + switch (status) { + case OSU_STATUS_AP_CONNECTING: + case OSU_STATUS_AP_CONNECTED: + case OSU_STATUS_SERVER_CONNECTING: + case OSU_STATUS_SERVER_VALIDATED: + case OSU_STATUS_SERVER_CONNECTED: + case OSU_STATUS_INIT_SOAP_EXCHANGE: + case OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE: + newStatusString = String.format(mContext.getString( + R.string.osu_opening_provider), + mOsuProvider.getFriendlyName()); + break; + case OSU_STATUS_REDIRECT_RESPONSE_RECEIVED: + case OSU_STATUS_SECOND_SOAP_EXCHANGE: + case OSU_STATUS_THIRD_SOAP_EXCHANGE: + case OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS: + newStatusString = mContext.getString(R.string.osu_completing_sign_up); + break; + } + boolean updated = !TextUtils.equals(mOsuStatusString, newStatusString); + mOsuStatusString = newStatusString; + if (updated) { + notifyOnUpdated(); + } + } + + @Override + @MainThread public void onProvisioningComplete() { + mOsuStatusString = mContext.getString(R.string.osu_sign_up_complete); + notifyOnUpdated(); + + PasspointConfiguration passpointConfig = mWifiManager + .getMatchingPasspointConfigsForOsuProviders(Collections.singleton(mOsuProvider)) + .get(mOsuProvider); + if (passpointConfig == null) { + // Failed to find the config we just provisioned + if (mConnectCallback != null) { + mConnectCallback.onConnectResult(CONNECT_STATUS_FAILURE_UNKNOWN); + } + return; + } + String uniqueId = passpointConfig.getUniqueId(); + for (Pair>> pairing : + mWifiManager.getAllMatchingWifiConfigs(mWifiManager.getScanResults())) { + WifiConfiguration config = pairing.first; + if (TextUtils.equals(config.getKey(), uniqueId)) { + List homeScans = + pairing.second.get(WifiManager.PASSPOINT_HOME_NETWORK); + List roamingScans = + pairing.second.get(WifiManager.PASSPOINT_ROAMING_NETWORK); + ScanResult bestScan; + if (homeScans != null && !homeScans.isEmpty()) { + bestScan = getBestScanResultByLevel(homeScans); + } else if (roamingScans != null && !roamingScans.isEmpty()) { + bestScan = getBestScanResultByLevel(roamingScans); + } else { + break; + } + config.SSID = "\"" + bestScan.SSID + "\""; + mWifiManager.connect(config, null /* ActionListener */); + return; + } + } + + // Failed to find the network we provisioned for + if (mConnectCallback != null) { + mConnectCallback.onConnectResult(CONNECT_STATUS_FAILURE_UNKNOWN); + } + } + } } diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java index 3e2419faf..ec16f8d93 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java @@ -346,26 +346,18 @@ public class PasspointWifiEntry extends WifiEntry { throws IllegalArgumentException { mWifiConfig = wifiConfig; mSecurity = getSecurityTypeFromWifiConfiguration(wifiConfig); - - if (homeScanResults == null) { - homeScanResults = new ArrayList<>(); - } - if (roamingScanResults == null) { - roamingScanResults = new ArrayList<>(); - } - - ScanResult bestScanResult; - if (homeScanResults.isEmpty() && !roamingScanResults.isEmpty()) { + mIsRoaming = false; + ScanResult bestScanResult = null; + if (homeScanResults != null && !homeScanResults.isEmpty()) { + bestScanResult = getBestScanResultByLevel(homeScanResults); + } else if (roamingScanResults != null && !roamingScanResults.isEmpty()) { mIsRoaming = true; bestScanResult = getBestScanResultByLevel(roamingScanResults); - } else { - mIsRoaming = false; - bestScanResult = getBestScanResultByLevel(homeScanResults); } - if (bestScanResult == null) { mLevel = WIFI_LEVEL_UNREACHABLE; } else { + mWifiConfig.SSID = "\"" + bestScanResult.SSID + "\""; mLevel = mWifiManager.calculateSignalLevel(bestScanResult.level); } diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java index 21d3f2c27..e452003f7 100644 --- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java +++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java @@ -61,6 +61,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -217,8 +218,11 @@ public class WifiPickerTracker extends BaseWifiTracker { updateStandardWifiEntryConfigs(mWifiManager.getConfiguredNetworks()); } updatePasspointWifiEntryConfigs(mWifiManager.getPasspointConfigurations()); - updateStandardWifiEntryScans(mScanResultUpdater.getScanResults()); - updatePasspointWifiEntryScans(mScanResultUpdater.getScanResults()); + // Update scans since config changes may result in different entries being shown. + final List scanResults = mScanResultUpdater.getScanResults(); + updateStandardWifiEntryScans(scanResults); + updatePasspointWifiEntryScans(scanResults); + updateOsuWifiEntryScans(scanResults); notifyOnNumSavedNetworksChanged(); notifyOnNumSavedSubscriptionsChanged(); updateWifiEntries(); @@ -272,6 +276,13 @@ public class WifiPickerTracker extends BaseWifiTracker { || connectedState == CONNECTED_STATE_CONNECTING; }).findAny().orElse(null /* other */); } + if (mConnectedWifiEntry == null) { + mConnectedWifiEntry = mOsuWifiEntryCache.values().stream().filter(entry -> { + final @WifiEntry.ConnectedState int connectedState = entry.getConnectedState(); + return connectedState == CONNECTED_STATE_CONNECTED + || connectedState == CONNECTED_STATE_CONNECTING; + }).findAny().orElse(null /* other */); + } Collections.sort(mWifiEntries); if (isVerboseLoggingEnabled()) { Log.v(TAG, "Connected WifiEntry: " + mConnectedWifiEntry); @@ -360,18 +371,26 @@ public class WifiPickerTracker extends BaseWifiTracker { Map> osuProviderToScans = mWifiManager.getMatchingOsuProviders(scanResults); - for (OsuProvider osuProvider : osuProviderToScans.keySet()) { - final String key = osuProviderToOsuWifiEntryKey(osuProvider); - if (!mOsuWifiEntryCache.containsKey(key)) { - mOsuWifiEntryCache.put(key, new OsuWifiEntry(mContext, - mMainHandler, osuProvider, mWifiManager, false /* forSavedNetworksPage */)); - } - mOsuWifiEntryCache.get(key).updateScanResultInfo(osuProviderToScans.get(osuProvider)); + Set alreadyProvisioned = + mWifiManager.getMatchingPasspointConfigsForOsuProviders(osuProviderToScans.keySet()) + .keySet(); + // Update each OsuWifiEntry with new scans (or empty scans). + for (OsuWifiEntry entry : mOsuWifiEntryCache.values()) { + entry.updateScanResultInfo(osuProviderToScans.remove(entry.getOsuProvider())); } - // Remove entries that are now unreachable + // Create a new entry for each OsuProvider not already matched to an OsuWifiEntry + for (OsuProvider provider : osuProviderToScans.keySet()) { + OsuWifiEntry newEntry = new OsuWifiEntry(mContext, mMainHandler, provider, mWifiManager, + false /* forSavedNetworksPage */); + newEntry.updateScanResultInfo(osuProviderToScans.get(provider)); + mOsuWifiEntryCache.put(osuProviderToOsuWifiEntryKey(provider), newEntry); + } + + // Remove entries that are now unreachable or already provisioned mOsuWifiEntryCache.entrySet() - .removeIf(entry -> entry.getValue().getLevel() == WIFI_LEVEL_UNREACHABLE); + .removeIf(entry -> entry.getValue().getLevel() == WIFI_LEVEL_UNREACHABLE + || alreadyProvisioned.contains(entry.getValue().getOsuProvider())); } /** @@ -487,6 +506,9 @@ public class WifiPickerTracker extends BaseWifiTracker { for (WifiEntry entry : mPasspointWifiEntryCache.values()) { entry.updateConnectionInfo(wifiInfo, networkInfo); } + for (WifiEntry entry : mOsuWifiEntryCache.values()) { + entry.updateConnectionInfo(wifiInfo, networkInfo); + } } /** -- cgit v1.2.3