summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorQuang Luong <qal@google.com>2020-02-25 17:52:33 -0800
committerQuang Luong <qal@google.com>2020-02-26 17:30:18 -0800
commit54a31806e0e074d061111c8457b1fff6e30f00b2 (patch)
tree341d28956822b2e616e069a790cbf301423aec36 /libs
parentb66edf6a39b0038c885b98134679d491ddfffd84 (diff)
[WifiTrackerLib] Implement manual and auto captive portal opening
Allow the user to sign in to captive portals through the wifi picker. The captive portal app will also auto-open on the wifi picker page and the Network Details page following a manual user connection to the network. Bug: 70983952 Bug: 149354973 Test: manual verification with local captive portal AP, atest WifiTrackerLibTests Change-Id: I9311bf38b861715c74b6415204ef63eab70ab717
Diffstat (limited to 'libs')
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java33
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java12
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java46
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java9
-rw-r--r--libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java12
-rw-r--r--libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java41
6 files changed, 132 insertions, 21 deletions
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
index 2fb162fc2..2c749ad2e 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
@@ -25,6 +25,7 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
@@ -124,7 +125,8 @@ public class BaseWifiTracker implements LifecycleObserver {
protected final long mScanIntervalMillis;
protected final ScanResultUpdater mScanResultUpdater;
- // Network request for listening on changes to Wifi link properties.
+ // Network request for listening on changes to Wifi link properties and network capabilities
+ // such as captive portal availability.
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities().addTransportType(TRANSPORT_WIFI).build();
@@ -134,6 +136,12 @@ public class BaseWifiTracker implements LifecycleObserver {
public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
handleLinkPropertiesChanged(lp);
}
+
+ @Override
+ public void onCapabilitiesChanged(Network network,
+ NetworkCapabilities networkCapabilities) {
+ handleNetworkCapabilitiesChanged(networkCapabilities);
+ }
};
/**
@@ -236,7 +244,7 @@ public class BaseWifiTracker implements LifecycleObserver {
@WorkerThread
protected void handleOnStart() {
// Do nothing.
- };
+ }
/**
* Handle receiving the WifiManager.WIFI_STATE_CHANGED_ACTION broadcast
@@ -244,7 +252,7 @@ public class BaseWifiTracker implements LifecycleObserver {
@WorkerThread
protected void handleWifiStateChangedAction() {
// Do nothing.
- };
+ }
/**
* Handle receiving the WifiManager.SCAN_RESULTS_AVAILABLE_ACTION broadcast
@@ -252,7 +260,7 @@ public class BaseWifiTracker implements LifecycleObserver {
@WorkerThread
protected void handleScanResultsAvailableAction(@NonNull Intent intent) {
// Do nothing.
- };
+ }
/**
* Handle receiving the WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION broadcast
@@ -260,7 +268,7 @@ public class BaseWifiTracker implements LifecycleObserver {
@WorkerThread
protected void handleConfiguredNetworksChangedAction(@NonNull Intent intent) {
// Do nothing.
- };
+ }
/**
* Handle receiving the WifiManager.NETWORK_STATE_CHANGED_ACTION broadcast
@@ -268,12 +276,23 @@ public class BaseWifiTracker implements LifecycleObserver {
@WorkerThread
protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
// Do nothing.
- };
+ }
+ /**
+ * Handle link property changes for the current connected Wifi network.
+ */
@WorkerThread
protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
// Do nothing.
- };
+ }
+
+ /**
+ * Handle network capability changes for the current connected Wifi network.
+ */
+ @WorkerThread
+ protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
+ // Do nothing.
+ }
/**
* Scanner to handle starting scans every SCAN_INTERVAL_MILLIS
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
index 5a95eb9b2..d30fcc407 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiConfiguration;
@@ -38,6 +39,7 @@ import android.text.TextUtils;
import androidx.annotation.AnyThread;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import androidx.lifecycle.Lifecycle;
@@ -130,12 +132,20 @@ class StandardNetworkDetailsTracker extends NetworkDetailsTracker {
@WorkerThread
@Override
- protected void handleLinkPropertiesChanged(@NonNull LinkProperties linkProperties) {
+ protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
if (mChosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
mChosenEntry.updateLinkProperties(linkProperties);
}
}
+ @WorkerThread
+ @Override
+ protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
+ if (mChosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+ mChosenEntry.updateNetworkCapabilities(capabilities);
+ }
+ }
+
/**
* 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 299c0f589..eab826ed3 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
@@ -109,6 +109,8 @@ public class StandardWifiEntry extends WifiEntry {
@Nullable private WifiConfiguration mWifiConfig;
@Nullable private String mRecommendationServiceLabel;
+ private boolean mShouldAutoOpenCaptivePortal = false;
+
StandardWifiEntry(@NonNull Context context, @NonNull Handler callbackHandler,
@NonNull String key,
@NonNull List<ScanResult> scanResults,
@@ -245,22 +247,21 @@ public class StandardWifiEntry extends WifiEntry {
}
// Check NetworkCapabilities.
- final ConnectivityManager cm =
- (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- final NetworkCapabilities nc =
- cm.getNetworkCapabilities(mWifiManager.getCurrentNetwork());
- if (nc != null) {
- if (nc.hasCapability(nc.NET_CAPABILITY_CAPTIVE_PORTAL)) {
+ if (mNetworkCapabilities != null) {
+ if (mNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)) {
return mContext.getString(mContext.getResources()
.getIdentifier("network_available_sign_in", "string", "android"));
}
- if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
+ if (mNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
return mContext.getString(R.string.wifi_limited_connection);
}
- if (!nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
- if (nc.isPrivateDnsBroken()) {
+ if (!mNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
+ if (mNetworkCapabilities.isPrivateDnsBroken()) {
return mContext.getString(R.string.private_dns_broken);
}
return mContext.getString(R.string.wifi_connected_no_internet);
@@ -383,6 +384,9 @@ public class StandardWifiEntry extends WifiEntry {
@Override
public void connect(@Nullable ConnectCallback callback) {
mConnectCallback = callback;
+ // We should flag this network to auto-open captive portal since this method represents
+ // the user manually connecting to a network (i.e. not auto-join).
+ mShouldAutoOpenCaptivePortal = true;
if (mWifiConfig == null) {
// Unsaved network
if (mSecurity == SECURITY_NONE
@@ -448,13 +452,19 @@ public class StandardWifiEntry extends WifiEntry {
@Override
public boolean canSignIn() {
- // TODO(b/70983952): Fill this method in
- return false;
+ return mNetworkCapabilities != null
+ && mNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
}
@Override
public void signIn(@Nullable SignInCallback callback) {
- // TODO(b/70983952): Fill this method in
+ if (canSignIn()) {
+ // canSignIn() implies that this WifiEntry is the currently connected network, so use
+ // getCurrentNetwork() to start the captive portal app.
+ ((ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+ .startCaptivePortalApp(mWifiManager.getCurrentNetwork());
+ }
}
/**
@@ -687,6 +697,18 @@ public class StandardWifiEntry extends WifiEntry {
notifyOnUpdated();
}
+ @WorkerThread
+ @Override
+ void updateNetworkCapabilities(@Nullable NetworkCapabilities capabilities) {
+ super.updateNetworkCapabilities(capabilities);
+
+ // Auto-open an available captive portal if the user manually connected to this network.
+ if (canSignIn() && mShouldAutoOpenCaptivePortal) {
+ mShouldAutoOpenCaptivePortal = false;
+ signIn(null /* callback */);
+ }
+ }
+
private void updateEapType(ScanResult result) {
if (result.capabilities.contains("RSN-EAP")) {
// WPA2-Enterprise and WPA3-Enterprise (non 192-bit) advertise RSN-EAP-CCMP
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
index 4f186ef26..34bac2ab5 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
@@ -22,6 +22,7 @@ import static androidx.core.util.Preconditions.checkNotNull;
import android.net.LinkAddress;
import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkUtils;
import android.net.RouteInfo;
@@ -190,6 +191,7 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
protected int mLevel = WIFI_LEVEL_UNREACHABLE;
protected WifiInfo mWifiInfo;
protected NetworkInfo mNetworkInfo;
+ protected NetworkCapabilities mNetworkCapabilities;
protected ConnectedInfo mConnectedInfo;
protected ConnectCallback mConnectCallback;
@@ -563,6 +565,7 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
}
} else { // Connection info doesn't matched, so this network is disconnected
mNetworkInfo = null;
+ mNetworkCapabilities = null;
mConnectedInfo = null;
if (mCalledDisconnect) {
mCalledDisconnect = false;
@@ -621,6 +624,12 @@ public abstract class WifiEntry implements Comparable<WifiEntry> {
notifyOnUpdated();
}
+ // Method for WifiTracker to update a connected WifiEntry's network capabilities.
+ @WorkerThread
+ void updateNetworkCapabilities(@Nullable NetworkCapabilities capabilities) {
+ mNetworkCapabilities = capabilities;
+ }
+
String getWifiInfoDescription() {
final StringJoiner sj = new StringJoiner(" ");
if (getConnectedState() == CONNECTED_STATE_CONNECTED && mWifiInfo != null) {
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
index 21d3f2c27..8b97040a3 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
@@ -34,6 +34,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkScoreManager;
import android.net.wifi.ScanResult;
@@ -240,13 +241,22 @@ public class WifiPickerTracker extends BaseWifiTracker {
@WorkerThread
@Override
- protected void handleLinkPropertiesChanged(@NonNull LinkProperties linkProperties) {
+ protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
if (mConnectedWifiEntry != null
&& mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
mConnectedWifiEntry.updateLinkProperties(linkProperties);
}
}
+ @WorkerThread
+ @Override
+ protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
+ if (mConnectedWifiEntry != null
+ && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+ mConnectedWifiEntry.updateNetworkCapabilities(capabilities);
+ }
+ }
+
/**
* Update the list returned by getWifiEntries() with the current states of the entry caches.
*/
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
index e4e6d49f6..e7d126097 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
@@ -43,6 +43,7 @@ import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.MacAddress;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkScoreManager;
import android.net.wifi.ScanResult;
@@ -72,6 +73,7 @@ public class StandardWifiEntryTest {
@Mock private WifiEntry.WifiEntryCallback mMockListener;
@Mock private WifiEntry.ConnectCallback mMockConnectCallback;
@Mock private WifiManager mMockWifiManager;
+ @Mock private ConnectivityManager mMockConnectivityManager;
@Mock private WifiInfo mMockWifiInfo;
@Mock private NetworkInfo mMockNetworkInfo;
@Mock private Context mMockContext;
@@ -623,4 +625,43 @@ public class StandardWifiEntryTest {
assertThat(entry.getMeteredChoice()).isEqualTo(WifiEntry.METERED_CHOICE_METERED);
}
+
+ @Test
+ public void testCanSignIn_captivePortalCapability_returnsTrue() {
+ final StandardWifiEntry entry = new StandardWifiEntry(mMockContext, mTestHandler,
+ ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_NONE),
+ Arrays.asList(
+ buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)),
+ mMockWifiManager, false /* forSavedNetworksPage */);
+ NetworkCapabilities captivePortalCapabilities = new NetworkCapabilities();
+ captivePortalCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+ entry.updateNetworkCapabilities(captivePortalCapabilities);
+
+ assertThat(entry.canSignIn()).isTrue();
+ }
+
+ @Test
+ public void testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce() {
+ when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+ .thenReturn(mMockConnectivityManager);
+ final StandardWifiEntry entry = new StandardWifiEntry(mMockContext, mTestHandler,
+ ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_NONE),
+ Arrays.asList(
+ buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)),
+ mMockWifiManager, false /* forSavedNetworksPage */);
+ NetworkCapabilities captivePortalCapabilities = new NetworkCapabilities();
+ captivePortalCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+
+ // Simulate user tapping on the network and receiving captive portal capabilities.
+ // This should trigger the captive portal app.
+ entry.connect(null /* callback */);
+ entry.updateNetworkCapabilities(captivePortalCapabilities);
+
+ verify(mMockConnectivityManager, times(1)).startCaptivePortalApp(any());
+
+ // Update network capabilities again. This should not trigger the captive portal app.
+ entry.updateNetworkCapabilities(captivePortalCapabilities);
+
+ verify(mMockConnectivityManager, times(1)).startCaptivePortalApp(any());
+ }
}