blob: 73d2f0f51d6e48cc9e0d0ad851a7cb5c33e03cc5 [file] [log] [blame]
/*
* Copyright (C) 2019 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.SECURITY_TYPE_PSK;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_SAE;
import static android.net.wifi.WifiInfo.SECURITY_TYPE_WEP;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.wifitrackerlib.TestUtils.BAD_RSSI;
import static com.android.wifitrackerlib.TestUtils.GOOD_LEVEL;
import static com.android.wifitrackerlib.TestUtils.GOOD_RSSI;
import static com.android.wifitrackerlib.TestUtils.buildScanResult;
import static com.android.wifitrackerlib.TestUtils.buildWifiConfiguration;
import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_DISCONNECTED;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.TransportInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
import android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback;
import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
import android.os.Handler;
import android.os.test.TestLooper;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class WifiPickerTrackerTest {
private static final long START_MILLIS = 123_456_789;
private static final long MAX_SCAN_AGE_MILLIS = 15_000;
private static final long SCAN_INTERVAL_MILLIS = 10_000;
@Mock private WifiTrackerInjector mInjector;
@Mock private Lifecycle mMockLifecycle;
@Mock private Context mMockContext;
@Mock private Resources mMockResources;
@Mock private WifiManager mMockWifiManager;
@Mock private WifiScanner mWifiScanner;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private ConnectivityDiagnosticsManager mMockConnectivityDiagnosticsManager;
@Mock private TelephonyManager mMockTelephonyManager;
@Mock private SubscriptionManager mMockSubscriptionManager;
@Mock private Clock mMockClock;
@Mock private WifiPickerTracker.WifiPickerTrackerCallback mMockCallback;
@Mock private WifiInfo mMockWifiInfo;
@Mock private Network mMockNetwork;
@Mock private NetworkCapabilities mMockNetworkCapabilities;
@Mock private NetworkCapabilities mMockVcnNetworkCapabilities;
@Mock private LinkProperties mMockLinkProperties;
@Mock private SharedConnectivityManager mMockSharedConnectivityManager;
private TestLooper mTestLooper;
private final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
mNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
mDefaultNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
private final ArgumentCaptor<SharedConnectivityClientCallback>
mSharedConnectivityCallbackCaptor =
ArgumentCaptor.forClass(SharedConnectivityClientCallback.class);
private WifiPickerTracker createTestWifiPickerTracker() {
final Handler testHandler = new Handler(mTestLooper.getLooper());
return new WifiPickerTracker(
mInjector,
mMockLifecycle,
mMockContext,
mMockWifiManager,
mMockConnectivityManager,
testHandler,
testHandler,
mMockClock,
MAX_SCAN_AGE_MILLIS,
SCAN_INTERVAL_MILLIS,
mMockCallback);
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper();
when(mMockWifiManager.getScanResults()).thenReturn(new ArrayList<>());
when(mMockWifiManager.getCurrentNetwork()).thenReturn(mMockNetwork);
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true);
when(mMockWifiManager.isWpa3SuiteBSupported()).thenReturn(true);
when(mMockWifiManager.isEnhancedOpenSupported()).thenReturn(true);
when(mMockWifiManager.calculateSignalLevel(TestUtils.GOOD_RSSI))
.thenReturn(TestUtils.GOOD_LEVEL);
when(mMockWifiManager.calculateSignalLevel(TestUtils.OKAY_RSSI))
.thenReturn(TestUtils.OKAY_LEVEL);
when(mMockWifiManager.calculateSignalLevel(TestUtils.BAD_RSSI))
.thenReturn(TestUtils.BAD_LEVEL);
when(mMockClock.millis()).thenReturn(START_MILLIS);
when(mMockWifiInfo.isPrimary()).thenReturn(true);
when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
when(mMockWifiInfo.makeCopy(anyLong())).thenReturn(mMockWifiInfo);
when(mMockWifiManager.getConnectionInfo()).thenReturn(mMockWifiInfo);
when(mMockNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(true);
when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
when(mMockVcnNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
.thenReturn(true);
// Use a placeholder TransportInfo since VcnTransportInfo is @hide.
// NonSdkApiWrapper is mocked to get the WifiInfo from these capabilities.
when(mMockVcnNetworkCapabilities.getTransportInfo()).thenReturn(
new TransportInfo() {
@NonNull
@Override
public TransportInfo makeCopy(long redactions) {
return TransportInfo.super.makeCopy(redactions);
}
});
// A real NetworkCapabilities is needed here in order to create a copy (with location info)
// using the NetworkCapabilities constructor in handleOnStart.
when(mMockConnectivityManager.getNetworkCapabilities(mMockNetwork))
.thenReturn(new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build());
when(mMockConnectivityManager.getLinkProperties(mMockNetwork))
.thenReturn(mMockLinkProperties);
when(mMockSharedConnectivityManager.unregisterCallback(any())).thenReturn(true);
when(mInjector.getContext()).thenReturn(mMockContext);
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getSystemService(TelephonyManager.class))
.thenReturn(mMockTelephonyManager);
when(mMockContext.getSystemService(SubscriptionManager.class))
.thenReturn(mMockSubscriptionManager);
when(mMockContext.getSystemService(ConnectivityDiagnosticsManager.class))
.thenReturn(mMockConnectivityDiagnosticsManager);
when(mMockContext.getSystemService(WifiScanner.class)).thenReturn(mWifiScanner);
when(mMockContext.getSystemService(SharedConnectivityManager.class))
.thenReturn(mMockSharedConnectivityManager);
when(mMockContext.getString(anyInt())).thenReturn("");
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status)).thenReturn(
new String[]{"", "Scanning", "Connecting", "Authenticating", "Obtaining IP address",
"Connected", "Suspended", "Disconnecting", "Unsuccessful", "Blocked",
"Temporarily avoiding poor connection"});
when(mInjector.isSharedConnectivityFeatureEnabled()).thenReturn(true);
}
/**
* Tests that receiving a wifi state change broadcast updates getWifiState().
*/
@Test
public void testWifiStateChangeBroadcast_updatesWifiState() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Set the wifi state to disabled
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)
.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED));
assertThat(wifiPickerTracker.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_DISABLED);
// Change the wifi state to enabled
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)
.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
assertThat(wifiPickerTracker.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED);
}
/**
* Tests that receiving a wifi state change broadcast notifies the listener.
*/
@Test
public void testWifiStateChangeBroadcast_notifiesListener() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
mTestLooper.dispatchAll();
verify(mMockCallback, atLeastOnce()).onWifiStateChanged();
}
/**
* Tests that a CONFIGURED_NETWORKS_CHANGED broadcast notifies the listener for
* numSavedNetworksChanged.
*/
@Test
public void testConfiguredNetworksChanged_notifiesListener() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
mTestLooper.dispatchAll();
verify(mMockCallback, atLeastOnce()).onNumSavedNetworksChanged();
}
/**
* Tests that receiving a scan results available broadcast notifies the listener.
*/
@Test
public void testScanResultsAvailableAction_notifiesListener() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
}
/**
* Tests that an empty list of WifiEntries is returned if no scans are available.
*/
@Test
public void testGetWifiEntries_noScans_emptyList() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
when(mMockWifiManager.getScanResults()).thenReturn(new ArrayList<>());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
}
/**
* Tests that a StandardWifiEntry is returned by getWifiEntries() for each non-null, non-empty
* SSID/Security pair in the tracked scan results.
*/
@Test
public void testGetWifiEntries_wifiNetworkEntries_createdForEachSsidAndSecurityPair() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final ScanResult openNetwork = buildScanResult("Open Network", "bssid0", START_MILLIS);
final ScanResult openNetworkDup = buildScanResult("Open Network", "bssid1", START_MILLIS);
final ScanResult secureNetwork = buildScanResult("Secure Network", "bssid2", START_MILLIS);
secureNetwork.capabilities = "EAP";
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
openNetwork,
openNetworkDup,
secureNetwork,
// Ignore null and empty SSIDs
buildScanResult(null, "bssidNull", START_MILLIS),
buildScanResult("", "bssidEmpty", START_MILLIS)));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
List<String> seenTitles = new ArrayList<>();
for (WifiEntry wifiEntry : wifiPickerTracker.getWifiEntries()) {
seenTitles.add(wifiEntry.getTitle());
}
assertThat(seenTitles).containsExactly("Open Network", "Secure Network");
}
/**
* Tests that old WifiEntries are timed out if their scans are older than the max scan age.
*/
@Test
public void testGetWifiEntries_wifiNetworkEntries_oldEntriesTimedOut() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Initial entries
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid0", "bssid0", START_MILLIS),
buildScanResult("ssid1", "bssid1", START_MILLIS),
buildScanResult("ssid2", "bssid2", START_MILLIS),
buildScanResult("ssid3", "bssid3", START_MILLIS),
buildScanResult("ssid4", "bssid4", START_MILLIS)));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
// Advance clock to max scan age. Entries should still be valid.
when(mMockClock.millis()).thenReturn(START_MILLIS + MAX_SCAN_AGE_MILLIS);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
assertThat(wifiPickerTracker.getWifiEntries()).isNotEmpty();
// Advance the clock to time out old entries
when(mMockClock.millis()).thenReturn(START_MILLIS + MAX_SCAN_AGE_MILLIS + 1);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
// All entries timed out
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
}
/**
* Tests that a failed scan will result in extending the max scan age by the scan interval.
* This is to allow the WifiEntry list to stay stable and not clear out if a single scan fails.
*/
@Test
public void testGetWifiEntries_wifiNetworkEntries_useOldEntriesOnFailedScan() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Initial entries
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid0", "bssid0", START_MILLIS),
buildScanResult("ssid1", "bssid1", START_MILLIS),
buildScanResult("ssid2", "bssid2", START_MILLIS),
buildScanResult("ssid3", "bssid3", START_MILLIS),
buildScanResult("ssid4", "bssid4", START_MILLIS)));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
final List<WifiEntry> previousEntries = wifiPickerTracker.getWifiEntries();
// Advance the clock to time out old entries and simulate failed scan
when(mMockClock.millis())
.thenReturn(START_MILLIS + MAX_SCAN_AGE_MILLIS + SCAN_INTERVAL_MILLIS);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, false));
// Failed scan should result in old WifiEntries still being shown
assertThat(previousEntries).containsExactlyElementsIn(wifiPickerTracker.getWifiEntries());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, true));
// Successful scan should time out old entries.
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
}
@Test
public void testGetWifiEntries_differentSsidSameBssid_returnsDifferentEntries() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
// Identical BSSID for 4 different SSIDs should return 4 entries.
buildScanResult("ssid0", "bssid0", START_MILLIS),
buildScanResult("ssid1", "bssid0", START_MILLIS),
buildScanResult("ssid2", "bssid0", START_MILLIS),
buildScanResult("ssid3", "bssid0", START_MILLIS),
// Another identical BSSID for 4 different SSIDs should return 4 more entries.
buildScanResult("ssid4", "bssid1", START_MILLIS),
buildScanResult("ssid5", "bssid1", START_MILLIS),
buildScanResult("ssid6", "bssid1", START_MILLIS),
buildScanResult("ssid7", "bssid1", START_MILLIS),
// Same SSID as the last for 2 different BSSIDs should not increase entries.
buildScanResult("ssid7", "bssid2", START_MILLIS),
buildScanResult("ssid7", "bssid3", START_MILLIS)));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
assertThat(wifiPickerTracker.getWifiEntries()).hasSize(8);
}
/**
* Tests that a CONFIGURED_NETWORKS_CHANGED broadcast updates the correct WifiEntry from
* unsaved to saved.
*/
@Test
public void testGetWifiEntries_configuredNetworksChanged_unsavedToSaved() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(entry.isSaved()).isFalse();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
assertThat(entry.isSaved()).isTrue();
}
/**
* Tests that a CONFIGURED_NETWORKS_CHANGED broadcast updates the correct WifiEntry from
* saved to unsaved.
*/
@Test
public void testGetWifiEntries_configuredNetworksChanged_savedToUnsaved() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(entry.isSaved()).isTrue();
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.emptyList());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
assertThat(entry.isSaved()).isFalse();
}
/**
* Tests that getConnectedEntry() returns the connected WifiEntry if we start already connected
* to a network.
*/
@Test
public void testGetConnectedEntry_alreadyConnectedOnStart_returnsConnectedEntry() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
}
/**
* Tests that connecting to a network will update getConnectedEntry() to return the connected
* WifiEntry and remove that entry from getWifiEntries().
*/
@Test
public void testGetConnectedEntry_connectToNetwork_returnsConnectedEntry() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(entry);
}
/**
* Tests that an L2 connected network (i.e. from NETWORK_STATE_CHANGED) will correctly be
* returned in getConnectedEntry() as the primary network.
*/
@Test
public void testGetConnectedEntry_networkL2Connected_returnsConnectedEntry() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(
mBroadcastReceiverCaptor.capture(), any(), any(), any());
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
// Simulate an L2 connected network that's still authenticating.
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
NetworkInfo mockNetworkInfo = mock(NetworkInfo.class);
when(mockNetworkInfo.getDetailedState())
.thenReturn(NetworkInfo.DetailedState.AUTHENTICATING);
Intent networkStateChanged = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
networkStateChanged.putExtra(WifiManager.EXTRA_NETWORK_INFO, mockNetworkInfo);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, networkStateChanged);
// Network should be returned in getConnectedWifiEntry() even though it's not L3 connected.
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(entry);
assertThat(entry.isPrimaryNetwork()).isTrue();
}
/**
* Tests that an L2 connected network request (i.e. from NETWORK_STATE_CHANGED) will correctly
* be returned in getConnectedEntry().
*/
@Test
public void testGetConnectedEntry_networkRequestL2Connected_returnsConnectedEntry() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
config.fromWifiNetworkSpecifier = true;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(
mBroadcastReceiverCaptor.capture(), any(), any(), any());
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
// Simulate an L2 connected network that's still authenticating.
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
NetworkInfo mockNetworkInfo = mock(NetworkInfo.class);
when(mockNetworkInfo.getDetailedState())
.thenReturn(NetworkInfo.DetailedState.AUTHENTICATING);
Intent networkStateChanged = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
networkStateChanged.putExtra(WifiManager.EXTRA_NETWORK_INFO, mockNetworkInfo);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, networkStateChanged);
// Network should be returned in getConnectedWifiEntry() even though it's not L3 connected.
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
}
/**
* Tests that connecting to a network will update getConnectedEntry() to return the connected
* WifiEntry if the framework times out and gives us an empty list of configs.
*/
@Test
public void testGetConnectedEntry_connectToNetworkWithoutConfigs_returnsConnectedEntry() {
// Simulate the framework timing out and giving us an empty list of configs.
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.emptyList());
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
// Populate the correct list of configs.
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
assertThat(wifiPickerTracker.getConnectedWifiEntry().getTitle()).isEqualTo("ssid");
}
/**
* Tests that disconnecting from a network will update getConnectedEntry() to return null.
*/
@Test
public void testGetConnectedEntry_disconnectFromNetwork_returnsNull() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
}
/**
* Tests that the wifi state changing to something other than WIFI_STATE_ENABLED will update
* getConnectedEntry() to return null.
*/
@Test
public void testGetConnectedEntry_wifiStateDisabled_returnsNull() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_DISABLED);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
}
/**
* Tests that a connected WifiEntry's isDefaultNetwork() will reflect updates from the default
* network changing.
*/
@Test
public void testGetConnectedEntry_defaultNetworkChanges_isDefaultNetworkChanges() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager)
.registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
// No default
assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
// Cell is default
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mock(Network.class),
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
// Other Wi-Fi network is default
Network otherWifiNetwork = mock(Network.class);
WifiInfo otherWifiInfo = mock(WifiInfo.class);
when(otherWifiInfo.getNetworkId()).thenReturn(2);
NetworkCapabilities otherNetworkCapabilities = mock(NetworkCapabilities.class);
when(otherNetworkCapabilities.getTransportInfo()).thenReturn(otherWifiInfo);
when(otherNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(true);
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(otherWifiNetwork,
otherNetworkCapabilities);
assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
// This Wi-Fi network is default
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
mMockNetworkCapabilities);
assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isTrue();
// Lose the default network
mDefaultNetworkCallbackCaptor.getValue().onLost(mock(Network.class));
assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
}
/**
* Tests that a connected WifiEntry will return "Low quality" as the summary if Wifi is
* validated but cell is the default route.
*/
@Test
public void testGetConnectedEntry_wifiValidatedCellDefault_isLowQuality() {
final String summarySeparator = " / ";
final String lowQuality = "Low quality";
final String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockContext.getString(R.string.wifi_connected_low_quality)).thenReturn(lowQuality);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager)
.registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
// Set cellular to be the default network
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
// Trigger a validation callback for the non-primary Wifi network.
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
WifiInfo nonPrimaryWifiInfo = Mockito.mock(WifiInfo.class);
when(nonPrimaryWifiInfo.makeCopy(anyLong())).thenReturn(nonPrimaryWifiInfo);
NetworkCapabilities nonPrimaryCap = new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setTransportInfo(nonPrimaryWifiInfo)
.addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
.build();
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mock(Network.class), nonPrimaryCap);
} finally {
session.finishMocking();
}
// Non-primary Wifi network validation should be ignored.
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isNotEqualTo(lowQuality);
when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
.thenReturn(true);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
// Cell default + primary network validation should trigger low quality
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isEqualTo(lowQuality);
// Cell + VPN is default should not trigger low quality, since the VPN underlying network is
// determined by the VPN app and not whether Wi-Fi is low quality or not.
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_VPN)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isNotEqualTo(lowQuality);
// Set Cell to the default but then lose the default network. Low quality should disappear
// since cell default was lost.
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
mDefaultNetworkCallbackCaptor.getValue().onLost(mock(Network.class));
assertThat(wifiPickerTracker.getConnectedWifiEntry().isDefaultNetwork()).isFalse();
}
/**
* Tests that a connected WifiEntry will show "Checking for internet access..." as the summary
* if the network hasn't finished the first validation attempt yet.
*/
@Test
public void testGetConnectedEntry_wifiNotValidatedYet_showsCheckingForInternetAccess() {
final String summarySeparator = " / ";
final String checkingForInternetAccess = "Checking for internet access..";
final String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockContext.getString(R.string.wifitrackerlib_checking_for_internet_access))
.thenReturn(checkingForInternetAccess);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
ArgumentCaptor<ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback>
diagnosticsCallbackCaptor = ArgumentCaptor.forClass(
ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback.class);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager)
.registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityDiagnosticsManager).registerConnectivityDiagnosticsCallback(
any(), any(), diagnosticsCallbackCaptor.capture());
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
// Still checking for internet access.
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary())
.isEqualTo(checkingForInternetAccess);
// Trigger a validation callback and connectivity report for the primary Wifi network.
when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
.thenReturn(true);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
ConnectivityDiagnosticsManager.ConnectivityReport report = mock(
ConnectivityDiagnosticsManager.ConnectivityReport.class);
when(report.getNetwork()).thenReturn(mMockNetwork);
diagnosticsCallbackCaptor.getValue().onConnectivityReportAvailable(report);
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
// Now we're fully connected
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isEqualTo("Connected");
}
/**
* Tests that a connected WifiEntry that is expected to have no internet will display
* "Connected to device. Can't provide internet" if the network is not validated.
*/
@Test
public void testGetConnectedEntry_wifiNotValidated_showsConnectedToDevice() {
final String summarySeparator = " / ";
final String connectedToDevice = "Connected to device. Can't provide internet";
final String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockContext.getString(R.string.wifitrackerlib_wifi_connected_cannot_provide_internet))
.thenReturn(connectedToDevice);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = spy(new WifiConfiguration());
config.SSID = "\"ssid\"";
config.networkId = 1;
when(config.isNoInternetAccessExpected()).thenReturn(true);
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
ArgumentCaptor<ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback>
diagnosticsCallbackCaptor = ArgumentCaptor.forClass(
ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback.class);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager)
.registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityDiagnosticsManager).registerConnectivityDiagnosticsCallback(
any(), any(), diagnosticsCallbackCaptor.capture());
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary())
.isEqualTo(connectedToDevice);
// Trigger a no-validation callback and connectivity report for the primary Wifi network.
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
ConnectivityDiagnosticsManager.ConnectivityReport report = mock(
ConnectivityDiagnosticsManager.ConnectivityReport.class);
when(report.getNetwork()).thenReturn(mMockNetwork);
diagnosticsCallbackCaptor.getValue().onConnectivityReportAvailable(report);
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary())
.isEqualTo(connectedToDevice);
}
/**
* Tests that getConnectedEntry() will return the correct primary network after an MBB sequence.
*/
@Test
public void testGetConnectedEntry_mbbFlow_matchesNewPrimary() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
final WifiConfiguration mbbConfig = new WifiConfiguration();
mbbConfig.SSID = "\"otherSsid\"";
mbbConfig.networkId = 2;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Arrays.asList(config, mbbConfig));
when(mMockWifiInfo.getNetworkId()).thenReturn(config.networkId);
when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
// Start off connected
WifiEntry originalConnectedEntry = wifiPickerTracker.getConnectedWifiEntry();
assertThat(originalConnectedEntry).isNotNull();
assertThat(originalConnectedEntry.getTitle()).isEqualTo("ssid");
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
// MBB network connected but not primary yet.
Network mbbNetwork = mock(Network.class);
NetworkCapabilities mbbNetworkCapabilities = mock(NetworkCapabilities.class);
WifiInfo mbbWifiInfo = mock(WifiInfo.class);
when(mbbWifiInfo.getNetworkId()).thenReturn(mbbConfig.networkId);
when(mbbWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
when(mbbNetworkCapabilities.getTransportInfo()).thenReturn(mbbWifiInfo);
doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(mbbWifiInfo));
mNetworkCallbackCaptor.getValue()
.onCapabilitiesChanged(mbbNetwork, mbbNetworkCapabilities);
// Original network should still be connected.
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(originalConnectedEntry);
// Original network becomes non-primary and MBB network becomes primary.
doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
mNetworkCallbackCaptor.getValue()
.onCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(mbbWifiInfo));
mNetworkCallbackCaptor.getValue()
.onCapabilitiesChanged(mbbNetwork, mbbNetworkCapabilities);
// MBB network should be connected now.
WifiEntry newConnectedEntry = wifiPickerTracker.getConnectedWifiEntry();
assertThat(newConnectedEntry).isNotNull();
assertThat(newConnectedEntry.getTitle()).isEqualTo("otherSsid");
assertThat(originalConnectedEntry.getConnectedState())
.isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
// Original network is lost. MBB network should still be connected
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(newConnectedEntry);
} finally {
session.finishMocking();
}
}
/**
* Tests that a PasspointWifiEntry is returned when Passpoint scans are visible.
*/
@Test
public void testGetWifiEntries_passpointInRange_returnsPasspointWifiEntry() {
final String passpointSsid = "passpointSsid";
final String friendlyName = "friendlyName";
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final PasspointConfiguration passpointConfig = new PasspointConfiguration();
final HomeSp homeSp = new HomeSp();
homeSp.setFqdn("fqdn");
homeSp.setFriendlyName(friendlyName);
passpointConfig.setHomeSp(homeSp);
passpointConfig.setCredential(new Credential());
when(mMockWifiManager.getPasspointConfigurations())
.thenReturn(Collections.singletonList(passpointConfig));
final ScanResult passpointScan =
buildScanResult(passpointSsid, "bssid", START_MILLIS, GOOD_LEVEL);
when(mMockWifiManager.getScanResults())
.thenReturn(Collections.singletonList(passpointScan));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final WifiConfiguration wifiConfig = spy(new WifiConfiguration());
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
mapping.put(WifiManager.PASSPOINT_HOME_NETWORK, Collections.singletonList(passpointScan));
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));
// Only the Passpoint entry should be present. The corresponding StandardWifiEntry with
// matching SSID should be filtered out.
assertThat(wifiPickerTracker.getWifiEntries().size()).isEqualTo(1);
final WifiEntry passpointEntry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(passpointEntry.isSubscription()).isTrue();
assertThat(passpointEntry.getTitle()).isEqualTo(friendlyName);
}
/**
* Tests that the same PasspointWifiEntry from getWifiEntries() is returned when it becomes the
* connected entry
*/
@Test
public void testGetWifiEntries_connectToPasspoint_returnsSamePasspointWifiEntry() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final PasspointConfiguration passpointConfig = new PasspointConfiguration();
final HomeSp homeSp = new HomeSp();
homeSp.setFqdn("fqdn");
homeSp.setFriendlyName("friendlyName");
passpointConfig.setHomeSp(homeSp);
passpointConfig.setCredential(new Credential());
when(mMockWifiManager.getPasspointConfigurations())
.thenReturn(Collections.singletonList(passpointConfig));
final WifiConfiguration wifiConfig = spy(new WifiConfiguration());
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
when(wifiConfig.isPasspoint()).thenReturn(true);
wifiConfig.networkId = 1;
final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
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);
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(wifiConfig));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
assertThat(wifiPickerTracker.getWifiEntries()).isNotEmpty();
final WifiEntry entry = wifiPickerTracker.getWifiEntries().get(0);
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn("fqdn");
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(entry);
}
/**
* Tests that a PasspointWifiEntry will disappear from getWifiEntries() once it is out of range.
*/
@Test
public void testGetWifiEntries_passpointOutOfRange_returnsNull() {
// Create conditions for one PasspointWifiEntry in getWifiEntries()
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final PasspointConfiguration passpointConfig = new PasspointConfiguration();
final HomeSp homeSp = new HomeSp();
homeSp.setFqdn("fqdn");
homeSp.setFriendlyName("friendlyName");
passpointConfig.setHomeSp(homeSp);
passpointConfig.setCredential(new Credential());
when(mMockWifiManager.getPasspointConfigurations())
.thenReturn(Collections.singletonList(passpointConfig));
final WifiConfiguration wifiConfig = spy(new WifiConfiguration());
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
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);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Age out the scans and get out of range of Passpoint AP
when(mMockClock.millis()).thenReturn(START_MILLIS + MAX_SCAN_AGE_MILLIS + 1);
when(mMockWifiManager.getAllMatchingWifiConfigs(any())).thenReturn(new ArrayList<>());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
// getWifiEntries() should be empty now
assertThat(wifiPickerTracker.getWifiEntries()).isEmpty();
}
/**
* Verifies that the WifiEntries returned in WifiPickerTracker.getWifiEntries() are returned in
* the order defined by the default WifiEntry.WIFI_PICKER_COMPARATOR.
*/
@Test
public void testGetWifiEntries_defaultSortingCriteria_returnsEntriesinCorrectOrder() {
List<ScanResult> currentScans = new ArrayList<>();
List<WifiConfiguration> currentConfiguredNetworks = new ArrayList<>();
// Set up Passpoint entry
final PasspointConfiguration passpointConfig = new PasspointConfiguration();
final HomeSp homeSp = new HomeSp();
homeSp.setFqdn("fqdn");
homeSp.setFriendlyName("friendlyName");
passpointConfig.setHomeSp(homeSp);
passpointConfig.setCredential(new Credential());
when(mMockWifiManager.getPasspointConfigurations())
.thenReturn(Collections.singletonList(passpointConfig));
final WifiConfiguration wifiConfig = spy(new WifiConfiguration());
when(wifiConfig.getKey()).thenReturn(passpointConfig.getUniqueId());
final Map<Integer, List<ScanResult>> mapping = new ArrayMap<>();
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);
// Set up saved entry
WifiConfiguration savedConfig = new WifiConfiguration();
savedConfig.fromWifiNetworkSuggestion = false;
savedConfig.SSID = "\"ssid\"";
savedConfig.networkId = 1;
currentConfiguredNetworks.add(savedConfig);
currentScans.add(buildScanResult("ssid", "bssid", START_MILLIS));
// Set up suggestion entry
WifiConfiguration suggestionConfig = new WifiConfiguration(savedConfig);
suggestionConfig.networkId = 2;
suggestionConfig.creatorName = "creator1";
suggestionConfig.carrierId = 1;
suggestionConfig.subscriptionId = 1;
suggestionConfig.fromWifiNetworkSuggestion = true;
currentConfiguredNetworks.add(suggestionConfig);
when(mMockWifiManager.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()))
.thenReturn(Arrays.asList(suggestionConfig));
// Set up high level entry
currentScans.add(buildScanResult("high", "bssid", START_MILLIS, GOOD_RSSI));
// Set up low level entry with high priority title
String highPriorityTitle = "A";
currentScans.add(buildScanResult(highPriorityTitle, "bssid", START_MILLIS, BAD_RSSI));
// Set up low level entry with low priority title
String lowPriorityTitle = "Z";
currentScans.add(buildScanResult(lowPriorityTitle, "bssid", START_MILLIS, BAD_RSSI));
// Set up EAP-SIM entry without SIM
WifiConfiguration eapSimConfig = new WifiConfiguration();
eapSimConfig.SSID = "\"eap-sim\"";
eapSimConfig.networkId = 3;
eapSimConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
eapSimConfig.enterpriseConfig = mock(WifiEnterpriseConfig.class);
when(eapSimConfig.enterpriseConfig.isAuthenticationSimBased()).thenReturn(true);
currentConfiguredNetworks.add(eapSimConfig);
ScanResult eapSimScan = buildScanResult("eap-sim", "bssid", START_MILLIS, GOOD_RSSI);
eapSimScan.capabilities = "[EAP/SHA1]";
currentScans.add(eapSimScan);
// Set up WifiManager mocks
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(currentConfiguredNetworks);
when(mMockWifiManager.getScanResults()).thenReturn(currentScans);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
List<WifiEntry> entries = wifiPickerTracker.getWifiEntries();
assertThat(entries.size()).isEqualTo(7);
// Subscription
assertThat(entries.get(0).isSubscription()).isTrue();
// Saved
assertThat(entries.get(1).isSaved()).isTrue();
// Suggestion
assertThat(entries.get(2).isSuggestion()).isTrue();
// High level
assertThat(entries.get(3).getLevel()).isEqualTo(GOOD_LEVEL);
// High Title
assertThat(entries.get(4).getTitle()).isEqualTo(highPriorityTitle);
// Low Title
assertThat(entries.get(5).getTitle()).isEqualTo(lowPriorityTitle);
// Non-connectable
assertThat(entries.get(6).canConnect()).isEqualTo(false);
}
/**
* Tests that multiple wifi entries are returned for multiple suggestions for the same network.
*/
@Test
public void testGetWifiEntries_multipleSuggestions_returnsMultipleEntries() {
WifiConfiguration savedConfig = new WifiConfiguration();
savedConfig.fromWifiNetworkSuggestion = false;
savedConfig.SSID = "\"ssid\"";
savedConfig.networkId = 1;
WifiConfiguration suggestionConfig1 = new WifiConfiguration(savedConfig);
suggestionConfig1.networkId = 2;
suggestionConfig1.creatorName = "creator1";
suggestionConfig1.carrierId = 1;
suggestionConfig1.subscriptionId = 1;
suggestionConfig1.fromWifiNetworkSuggestion = true;
WifiConfiguration suggestionConfig2 = new WifiConfiguration(savedConfig);
suggestionConfig2.networkId = 3;
suggestionConfig1.creatorName = "creator2";
suggestionConfig1.carrierId = 2;
suggestionConfig1.subscriptionId = 2;
suggestionConfig2.fromWifiNetworkSuggestion = true;
// Initial entries
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(suggestionConfig1, suggestionConfig2));
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiManager.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()))
.thenReturn(Arrays.asList(suggestionConfig1, suggestionConfig2));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// 2 suggestion entries, no unsaved entry
assertThat(wifiPickerTracker.getWifiEntries().size()).isEqualTo(2);
for (WifiEntry entry : wifiPickerTracker.getWifiEntries()) {
assertThat(entry.getTitle()).isEqualTo("ssid");
}
assertThat(wifiPickerTracker.getWifiEntries().stream()
.filter(WifiEntry::isSuggestion)
.count()).isEqualTo(2);
// Add a saved entry
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(savedConfig, suggestionConfig1, suggestionConfig2));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
// Saved entry should appear alongside suggestions
assertThat(wifiPickerTracker.getWifiEntries().size()).isEqualTo(3);
for (WifiEntry entry : wifiPickerTracker.getWifiEntries()) {
assertThat(entry.getTitle()).isEqualTo("ssid");
}
assertThat(wifiPickerTracker.getWifiEntries().stream()
.filter(WifiEntry::isSuggestion)
.count())
.isEqualTo(2);
assertThat(wifiPickerTracker.getWifiEntries().stream()
.filter(WifiEntry::isSaved)
.count()).isEqualTo(1);
}
/**
* Tests that a suggestion entry is returned after a user shared suggestion config is added.
*/
@Test
public void testGetWifiEntries_userSharedSuggestionConfigAdded_returnsSuggestion() {
// Start out with non-saved network.
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS)));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
assertThat(wifiPickerTracker.getWifiEntries().size()).isEqualTo(1);
WifiEntry wifiEntry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(wifiEntry.getTitle()).isEqualTo("ssid");
assertThat(wifiEntry.isSuggestion()).isFalse();
// Update configs with suggestion config.
WifiConfiguration suggestionConfig = new WifiConfiguration();
suggestionConfig.SSID = "\"ssid\"";
suggestionConfig.networkId = 2;
suggestionConfig.creatorName = "creator1";
suggestionConfig.carrierId = 1;
suggestionConfig.subscriptionId = 1;
suggestionConfig.fromWifiNetworkSuggestion = true;
when(mMockWifiManager.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()))
.thenReturn(Arrays.asList(suggestionConfig));
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(suggestionConfig));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
// Non-saved network should turn into suggestion
assertThat(wifiPickerTracker.getWifiEntries().size()).isEqualTo(1);
wifiEntry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(wifiEntry.getTitle()).isEqualTo("ssid");
assertThat(wifiEntry.isSuggestion()).isTrue();
}
/**
* Tests that a suggestion entry is not returned after a non-shared suggestion config is added.
*/
@Test
public void testGetWifiEntries_nonSharedSuggestionConfigAdded_returnsNotSuggestion() {
// Start out with non-saved network.
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS)));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
assertThat(wifiPickerTracker.getWifiEntries().size()).isEqualTo(1);
WifiEntry wifiEntry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(wifiEntry.getTitle()).isEqualTo("ssid");
assertThat(wifiEntry.isSuggestion()).isFalse();
// Update configs with non-shared suggestion config.
WifiConfiguration suggestionConfig = new WifiConfiguration();
suggestionConfig.SSID = "\"ssid\"";
suggestionConfig.networkId = 2;
suggestionConfig.creatorName = "creator1";
suggestionConfig.carrierId = 1;
suggestionConfig.subscriptionId = 1;
suggestionConfig.fromWifiNetworkSuggestion = true;
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(suggestionConfig));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
// Non-saved network should not turn into suggestion
assertThat(wifiPickerTracker.getWifiEntries().size()).isEqualTo(1);
wifiEntry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(wifiEntry.getTitle()).isEqualTo("ssid");
assertThat(wifiEntry.isSuggestion()).isFalse();
}
/**
* Tests that a suggestion entry created before scan results are available will be updated to
* user shareable after scans become available.
*/
@Test
public void testGetWifiEntries_preConnectedSuggestion_becomesUserShareable() {
WifiConfiguration suggestionConfig = new WifiConfiguration();
suggestionConfig.SSID = "\"ssid\"";
suggestionConfig.networkId = 1;
suggestionConfig.creatorName = "creator";
suggestionConfig.carrierId = 1;
suggestionConfig.subscriptionId = 1;
suggestionConfig.fromWifiNetworkSuggestion = true;
// Initial entries
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(suggestionConfig));
when(mMockWifiInfo.getNetworkId()).thenReturn(suggestionConfig.networkId);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
WifiEntry suggestionEntry = wifiPickerTracker.getConnectedWifiEntry();
assertThat(suggestionEntry).isNotNull();
// Update with user-shareable scan results for the suggestion
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS)));
when(mMockWifiManager.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any()))
.thenReturn(Arrays.asList(suggestionConfig));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
// Disconnect from network to verify its usershareability in the picker list
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
// Suggestion entry should be in picker list now
suggestionEntry = wifiPickerTracker.getWifiEntries().get(0);
assertThat(suggestionEntry.isSuggestion()).isTrue();
}
@Test
public void testGetConnectedEntry_alreadyConnectedToPasspoint_returnsPasspointEntry() {
final String fqdn = "fqdn";
final String friendlyName = "friendlyName";
final int networkId = 1;
// Create a passpoint configuration to match with the current network
final PasspointConfiguration passpointConfig = new PasspointConfiguration();
final HomeSp homeSp = new HomeSp();
homeSp.setFqdn(fqdn);
homeSp.setFriendlyName(friendlyName);
passpointConfig.setHomeSp(homeSp);
passpointConfig.setCredential(new Credential());
when(mMockWifiManager.getPasspointConfigurations())
.thenReturn(Collections.singletonList(passpointConfig));
// Create a wifi config to match the WifiInfo netId and unique id of the passpoint config
final WifiConfiguration config = Mockito.mock(WifiConfiguration.class);
config.SSID = "\"ssid\"";
config.networkId = networkId;
config.allowedKeyManagement = new BitSet();
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
config.subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
when(config.isPasspoint()).thenReturn(true);
when(config.getKey()).thenReturn(passpointConfig.getUniqueId());
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(fqdn);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry().getTitle()).isEqualTo(friendlyName);
}
@Test
public void testGetConnectedEntry_passpointWithoutScans_returnsPasspointEntry() {
final String fqdn = "fqdn";
final String friendlyName = "friendlyName";
final int networkId = 1;
// Create a passpoint configuration to match with the current network
final PasspointConfiguration passpointConfig = new PasspointConfiguration();
final HomeSp homeSp = new HomeSp();
homeSp.setFqdn(fqdn);
homeSp.setFriendlyName(friendlyName);
passpointConfig.setHomeSp(homeSp);
passpointConfig.setCredential(new Credential());
when(mMockWifiManager.getPasspointConfigurations())
.thenReturn(Collections.singletonList(passpointConfig));
// Create a wifi config to match the WifiInfo netId and unique id of the passpoint config
final WifiConfiguration config = Mockito.mock(WifiConfiguration.class);
config.SSID = "\"ssid\"";
config.networkId = networkId;
config.allowedKeyManagement = new BitSet();
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
config.subscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
when(config.isPasspoint()).thenReturn(true);
when(config.getKey()).thenReturn(passpointConfig.getUniqueId());
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(fqdn);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Update with SCAN_RESULTS_AVAILABLE action while there are no scan results available yet.
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mTestLooper.dispatchAll();
verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
assertThat(wifiPickerTracker.getConnectedWifiEntry().getTitle()).isEqualTo(friendlyName);
}
/**
* Tests that getConnectedEntry will return the correct network request if there are multiple
* active requests
*/
@Test
public void testGetConnectedEntry_multipleNetworkRequests_returnsConnectedRequest() {
final WifiConfiguration requestConfig1 = new WifiConfiguration();
requestConfig1.SSID = "\"ssid1\"";
requestConfig1.networkId = 1;
requestConfig1.fromWifiNetworkSpecifier = true;
final WifiConfiguration requestConfig2 = new WifiConfiguration();
requestConfig2.SSID = "\"ssid2\"";
requestConfig2.networkId = 2;
requestConfig2.fromWifiNetworkSpecifier = true;
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(requestConfig1, requestConfig2));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
// WifiInfo has network id 1, so the connected entry should correspond to request 1
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSsid()).isEqualTo("ssid1");
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
when(mMockWifiInfo.getNetworkId()).thenReturn(2);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
// WifiInfo has network id 2, so the connected entry should correspond to request 2
assertThat(wifiPickerTracker.getConnectedWifiEntry().getSsid()).isEqualTo("ssid2");
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
when(mMockWifiInfo.getNetworkId()).thenReturn(-1);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
// WifiInfo matches no request configs, so the connected entry should be null
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
}
/**
* Tests that getActiveWifiEntries() returns the connected primary WifiEntry if we start already
* connected to a network.
*/
@Test
public void testGetActiveWifiEntries_alreadyConnectedOnStart_returnsConnectedEntry() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
assertThat(wifiPickerTracker.getActiveWifiEntries()).isNotEmpty();
assertThat(wifiPickerTracker.getActiveWifiEntries().get(0))
.isEqualTo(wifiPickerTracker.getConnectedWifiEntry());
}
/**
* Tests that getActiveWifiEntries() returns the connected primary WifiEntry first, and any
* secondary OEM networks that are connected.
*/
@Test
public void testGetActiveWifiEntries_oemNetworksConnected_returnsPrimaryAndOemNetworks() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
final WifiConfiguration primaryConfig = new WifiConfiguration();
primaryConfig.SSID = "\"primary\"";
primaryConfig.networkId = 1;
final WifiConfiguration oemConfig = new WifiConfiguration();
oemConfig.SSID = "\"oem\"";
oemConfig.networkId = 2;
final WifiConfiguration oemPrivateConfig = new WifiConfiguration();
oemPrivateConfig.SSID = "\"oemPrivate\"";
oemPrivateConfig.networkId = 3;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Arrays.asList(primaryConfig, oemConfig, oemPrivateConfig));
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
// Connect to primary network
when(mMockWifiInfo.getNetworkId()).thenReturn(primaryConfig.networkId);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
// Connect to OEM network
Network oemNetwork = mock(Network.class);
NetworkCapabilities oemCapabilities = mock(NetworkCapabilities.class);
WifiInfo oemWifiInfo = mock(WifiInfo.class);
when(oemWifiInfo.getNetworkId()).thenReturn(oemConfig.networkId);
when(oemWifiInfo.getRssi()).thenReturn(-50);
doReturn(false).when(() -> NonSdkApiWrapper.isPrimary(oemWifiInfo));
doReturn(true).when(() -> NonSdkApiWrapper.isOemCapabilities(oemCapabilities));
when(oemCapabilities.getTransportInfo()).thenReturn(oemWifiInfo);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
oemNetwork, oemCapabilities);
WifiEntry primaryWifiEntry = wifiPickerTracker.getActiveWifiEntries().get(0);
WifiEntry oemWifiEntry = wifiPickerTracker.getActiveWifiEntries().get(1);
// Primary should go first, then the OEM network.
assertThat(primaryWifiEntry.getTitle()).isEqualTo("primary");
assertThat(oemWifiEntry.getTitle()).isEqualTo("oem");
// Both entries should be connected
assertThat(primaryWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
assertThat(oemWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
// Only the primary network should be primary
assertThat(primaryWifiEntry.isPrimaryNetwork()).isTrue();
assertThat(oemWifiEntry.isPrimaryNetwork()).isFalse();
// The primary should be returned in getWifiEntries()
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(primaryWifiEntry);
// Disconnect primary. Secondary OEM network should not be primary
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
assertThat(primaryWifiEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_DISCONNECTED);
assertThat(wifiPickerTracker.getActiveWifiEntries()).containsExactly(oemWifiEntry);
assertThat(oemWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
// OEM network becomes primary.
doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(oemWifiInfo));
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
oemNetwork, oemCapabilities);
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isEqualTo(oemWifiEntry);
assertThat(wifiPickerTracker.getActiveWifiEntries()).containsExactly(oemWifiEntry);
assertThat(oemWifiEntry.isPrimaryNetwork()).isTrue();
// Disconnect the OEM network.
mNetworkCallbackCaptor.getValue().onLost(oemNetwork);
assertThat(oemWifiEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_DISCONNECTED);
assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNull();
assertThat(wifiPickerTracker.getActiveWifiEntries()).isEmpty();
} finally {
session.finishMocking();
}
}
/**
* Tests that SCAN_RESULTS_AVAILABLE_ACTION calls WifiManager#getMatchingOsuProviders()
*/
@Test
public void testScanResultsAvailableAction_callsGetMatchingOsuProviders() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
verify(mMockWifiManager, atLeastOnce()).getMatchingOsuProviders(any());
}
/**
* Tests that a connected MergedCarrierEntry is returned if the current WifiInfo has a matching
* subscription id.
*/
@Test
public void testGetMergedCarrierEntry_wifiInfoHasMatchingSubId_entryIsConnected() {
final int subId = 1;
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final Intent intent = new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intent.putExtra("subscription", subId);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
assertThat(wifiPickerTracker.getMergedCarrierEntry().getConnectedState())
.isEqualTo(CONNECTED_STATE_CONNECTED);
}
/**
* Tests that getMergedCarrierEntry returns a new MergedCarrierEntry with the correct
* subscription ID if the default subscription ID changes.
*/
@Test
public void testGetMergedCarrierEntry_subscriptionIdChanges_entryChanges() {
final int subId1 = 1;
final int subId2 = 2;
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final Intent intent1 =
new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intent1.putExtra("subscription", subId1);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, intent1);
final Intent intent2 =
new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intent2.putExtra("subscription", subId2);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, intent2);
assertThat(wifiPickerTracker.getMergedCarrierEntry().getSubscriptionId())
.isEqualTo(subId2);
}
/**
* Tests that getWifiEntries returns separate WifiEntries for each security family for scans
* with the same SSID
*/
@Test
public void testGetWifiEntries_sameSsidDifferentSecurity_entriesMergedBySecurityFamily() {
final ArrayList scanList = new ArrayList();
final String ssid = "ssid";
final String bssid = "bssid";
int bssidNum = 0;
for (String capabilities : Arrays.asList(
"",
"[OWE]",
"[OWE_TRANSITION]",
"[WEP]",
"[PSK]",
"[SAE]",
"[PSK][SAE]",
"[EAP/SHA1]",
"[RSN-EAP/SHA1+EAP/SHA256][MFPC]",
"[RSN-EAP/SHA256][MFPC][MFPR]",
"[RSN-SUITE_B_192][MFPR]"
)) {
final ScanResult scan = buildScanResult(ssid, bssid + bssidNum++, START_MILLIS);
scan.capabilities = capabilities;
scanList.add(scan);
}
when(mMockWifiManager.getScanResults()).thenReturn(scanList);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Open/OWE, PSK/SAE, EAP/EAP-WPA3 should be merged to a single entry
List<WifiEntry> wifiEntries = wifiPickerTracker.getWifiEntries();
assertThat(wifiEntries.size()).isEqualTo(5);
assertThat(wifiEntries.stream()
.map(entry -> entry.getSecurityTypes())
.collect(Collectors.toList()))
.containsExactly(
Arrays.asList(WifiInfo.SECURITY_TYPE_OPEN, WifiInfo.SECURITY_TYPE_OWE),
Arrays.asList(WifiInfo.SECURITY_TYPE_WEP),
Arrays.asList(WifiInfo.SECURITY_TYPE_PSK, WifiInfo.SECURITY_TYPE_SAE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP,
WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT));
// Use a PSK config, EAP config, and Open config, and see that the security types returned
// for those grouped entries change to reflect the available configs.
WifiConfiguration openConfig = buildWifiConfiguration(ssid);
openConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
openConfig.networkId = 1;
WifiConfiguration pskConfig = buildWifiConfiguration(ssid);
pskConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
pskConfig.networkId = 2;
WifiConfiguration eapConfig = buildWifiConfiguration(ssid);
eapConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
eapConfig.networkId = 3;
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(openConfig, pskConfig, eapConfig));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
mTestLooper.dispatchAll();
// Open/OWE becomes Open, PSK/SAE becomes PSK, EAP/EAP-WPA3 does not change since EAP config
// also works for EAP-WPA3.
wifiEntries = wifiPickerTracker.getWifiEntries();
assertThat(wifiEntries.size()).isEqualTo(5);
assertThat(wifiEntries.stream()
.map(entry -> entry.getSecurityTypes())
.collect(Collectors.toList()))
.containsExactly(
Arrays.asList(WifiInfo.SECURITY_TYPE_OPEN),
Arrays.asList(WifiInfo.SECURITY_TYPE_WEP),
Arrays.asList(WifiInfo.SECURITY_TYPE_PSK),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP,
WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT));
// Use SAE config, EAP-WPA3 config, and OWE config
WifiConfiguration oweConfig = buildWifiConfiguration(ssid);
oweConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
oweConfig.networkId = 1;
WifiConfiguration saeConfig = buildWifiConfiguration(ssid);
saeConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
saeConfig.networkId = 2;
WifiConfiguration eapWpa3Config = buildWifiConfiguration(ssid);
eapWpa3Config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
eapWpa3Config.networkId = 3;
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(oweConfig, saeConfig, eapWpa3Config));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
mTestLooper.dispatchAll();
// Open/OWE becomes OWE, PSK/SAE becomes SAE, EAP/EAP-WPA3 becomes EAP-WPA3
wifiEntries = wifiPickerTracker.getWifiEntries();
assertThat(wifiEntries.size()).isEqualTo(5);
assertThat(wifiEntries.stream()
.map(entry -> entry.getSecurityTypes())
.collect(Collectors.toList()))
.containsExactly(
Arrays.asList(WifiInfo.SECURITY_TYPE_OWE),
Arrays.asList(WifiInfo.SECURITY_TYPE_WEP),
Arrays.asList(WifiInfo.SECURITY_TYPE_SAE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT));
// Now use configs for all the security types in the family
when(mMockWifiManager.getPrivilegedConfiguredNetworks()).thenReturn(
Arrays.asList(openConfig, oweConfig, pskConfig, saeConfig, eapConfig,
eapWpa3Config));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
mTestLooper.dispatchAll();
// All of the security types in the family should be returned.
wifiEntries = wifiPickerTracker.getWifiEntries();
assertThat(wifiEntries.size()).isEqualTo(5);
assertThat(wifiEntries.stream()
.map(entry -> entry.getSecurityTypes())
.collect(Collectors.toList()))
.containsExactly(
Arrays.asList(WifiInfo.SECURITY_TYPE_OPEN, WifiInfo.SECURITY_TYPE_OWE),
Arrays.asList(WifiInfo.SECURITY_TYPE_WEP),
Arrays.asList(WifiInfo.SECURITY_TYPE_PSK, WifiInfo.SECURITY_TYPE_SAE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP,
WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT));
}
/**
* Tests that getNumSavedNetworks() returns the correct number of networks based on number of
* unique network IDs even for split configs which may have the same network ID but different
* security types.
*/
@Test
public void testGetNumSavedNetworks_splitConfigs_returnsNetworkIdCount() {
WifiConfiguration openConfig = buildWifiConfiguration("ssid");
openConfig.networkId = 1;
// PSK + SAE split config with the same network ID
WifiConfiguration pskConfig = buildWifiConfiguration("ssid");
pskConfig.setSecurityParams(WifiInfo.SECURITY_TYPE_PSK);
pskConfig.networkId = 2;
WifiConfiguration saeConfig = buildWifiConfiguration("ssid");
saeConfig.setSecurityParams(WifiInfo.SECURITY_TYPE_SAE);
saeConfig.networkId = 2;
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Arrays.asList(openConfig, pskConfig, saeConfig));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
// 1 open config + 2 split configs with same network ID should be treated as 2 networks.
assertThat(wifiPickerTracker.getNumSavedNetworks()).isEqualTo(2);
}
/**
* Tests that the MergedCarrierEntry is the default network when it is connected and Wifi is
* the default network.
*/
@Test
public void testGetMergedCarrierEntry_wifiIsDefault_entryIsDefaultNetwork() {
final int subId = 1;
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final Intent intent = new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intent.putExtra("subscription", subId);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
MergedCarrierEntry mergedCarrierEntry = wifiPickerTracker.getMergedCarrierEntry();
assertThat(mergedCarrierEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_CONNECTED);
// Wifi isn't default yet, so isDefaultNetwork returns false
assertThat(mergedCarrierEntry.isDefaultNetwork()).isFalse();
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
// Now Wifi is default, so isDefaultNetwork returns true
assertThat(mergedCarrierEntry.isDefaultNetwork()).isTrue();
}
/**
* Tests that the MergedCarrierEntry is the default network when it is connected and
* VCN-over-Wifi is the default network.
*/
@Test
public void testGetMergedCarrierEntry_vcnWifiIsDefault_entryIsDefaultNetwork() {
final int subId = 1;
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final Intent intent = new Intent(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
intent.putExtra("subscription", subId);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
// Connect to VCN-over-Wifi network
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
doReturn(mMockWifiInfo).when(() ->
NonSdkApiWrapper.getVcnWifiInfo(mMockVcnNetworkCapabilities));
doReturn(true).when(() -> NonSdkApiWrapper.isPrimary(mMockWifiInfo));
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockVcnNetworkCapabilities);
MergedCarrierEntry mergedCarrierEntry = wifiPickerTracker.getMergedCarrierEntry();
assertThat(mergedCarrierEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_CONNECTED);
// Wifi isn't default yet, so isDefaultNetwork returns false
assertThat(mergedCarrierEntry.isDefaultNetwork()).isFalse();
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
mMockVcnNetworkCapabilities);
// Now VCN-over-Wifi is default, so isDefaultNetwork returns true
assertThat(mergedCarrierEntry.isDefaultNetwork()).isTrue();
} finally {
session.finishMocking();
}
}
/**
* Tests that a MergedCarrierEntry is returned even if WifiPickerTracker hasn't been initialized
* via handleOnStart() yet.
*/
@Test
public void testGetMergedCarrierEntry_trackerNotInitialized_entryIsNotNull() {
final int subId = 1;
MockitoSession session = mockitoSession().spyStatic(SubscriptionManager.class)
.startMocking();
try {
doReturn(subId).when(SubscriptionManager::getDefaultDataSubscriptionId);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
MergedCarrierEntry mergedCarrierEntry = wifiPickerTracker.getMergedCarrierEntry();
assertThat(mergedCarrierEntry).isNotNull();
} finally {
session.finishMocking();
}
}
/**
* Verifies that the BroadcastReceiver and network callbacks are unregistered by the onStop()
* worker thread runnable.
*/
@Test
public void testBroadcastReceiverAndNetworkCallbacks_onStopRunnable_unregistersCallbacks() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
wifiPickerTracker.onStop();
mTestLooper.dispatchAll();
verify(mMockContext).unregisterReceiver(mBroadcastReceiverCaptor.getValue());
verify(mMockConnectivityManager).unregisterNetworkCallback(
mDefaultNetworkCallbackCaptor.getValue());
verify(mMockConnectivityManager).unregisterNetworkCallback(
mDefaultNetworkCallbackCaptor.getValue());
}
/**
* Verifies that the BroadcastReceiver and network callbacks are unregistered by onDestroyed().
*/
@Test
public void testBroadcastReceiverAndNetworkCallbacks_onDestroyed_unregistersCallbacks() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
verify(mMockConnectivityManager, atLeast(0)).registerSystemDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
verify(mMockConnectivityManager, atLeast(0)).registerDefaultNetworkCallback(
mDefaultNetworkCallbackCaptor.capture(), any());
wifiPickerTracker.onStop();
wifiPickerTracker.onDestroy();
verify(mMockContext).unregisterReceiver(mBroadcastReceiverCaptor.getValue());
verify(mMockConnectivityManager).unregisterNetworkCallback(
mDefaultNetworkCallbackCaptor.getValue());
verify(mMockConnectivityManager).unregisterNetworkCallback(
mDefaultNetworkCallbackCaptor.getValue());
}
/**
* Tests that the BaseWifiTracker.Scanner continues scanning with WifiManager.startScan() after
* the first WifiScanner result is received.
*/
@Test
public void testScanner_wifiScannerResultReceived_scannerContinues() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION).putExtra(
WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
ArgumentCaptor<WifiScanner.ScanListener> mScanListenerCaptor =
ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
verify(mWifiScanner).startScan(any(), mScanListenerCaptor.capture());
mTestLooper.moveTimeForward(SCAN_INTERVAL_MILLIS);
mTestLooper.dispatchAll();
verify(mMockWifiManager, never()).startScan();
mScanListenerCaptor.getValue().onResults(null);
mTestLooper.dispatchAll();
verify(mMockWifiManager).startScan();
}
/**
* Tests that the BaseWifiTracker.Scanner continues scanning with WifiManager.startScan() after
* the first WifiScanner scan fails.
*/
@Test
public void testScanner_wifiScannerFailed_scannerContinues() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION).putExtra(
WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
ArgumentCaptor<WifiScanner.ScanListener> mScanListenerCaptor =
ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
verify(mWifiScanner).startScan(any(), mScanListenerCaptor.capture());
mTestLooper.moveTimeForward(SCAN_INTERVAL_MILLIS);
mTestLooper.dispatchAll();
verify(mMockWifiManager, never()).startScan();
mScanListenerCaptor.getValue().onFailure(0, "Reason");
mTestLooper.dispatchAll();
verify(mMockWifiManager).startScan();
}
@Test
public void testScanner_startAfterOnStop_doesNotStart() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Stop and then get WIFI_STATE_ENABLED afterwards to trigger starting the scanner.
wifiPickerTracker.onStop();
mTestLooper.dispatchAll();
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)
.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
// Scanner should not have started
verify(mMockWifiManager, never()).startScan();
// Start again and get WIFI_STATE_ENABLED
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION)
.putExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_ENABLED));
// Scanner should start now
verify(mMockWifiManager, never()).startScan();
}
@Test
public void testSharedConnectivityManager_onStart_registersCallback() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
}
@Test
public void testSharedConnectivityManager_onServiceConnected_gettersCalled() {
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).getKnownNetworks();
verify(mMockSharedConnectivityManager).getHotspotNetworks();
}
@Test
public void testKnownNetworks_noMatchingScanResult_entryNotIncluded() {
final KnownNetwork testKnownNetwork = new KnownNetwork.Builder()
.setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
.setSsid("ssid")
.addSecurityType(SECURITY_TYPE_PSK)
.addSecurityType(SECURITY_TYPE_SAE)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.build();
when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
Collections.singletonList(testKnownNetwork));
when(mMockWifiManager.getScanResults()).thenReturn(
Collections.singletonList(buildScanResult("other_ssid", "bssid", START_MILLIS,
"[WEP]")));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof KnownNetworkEntry).toList()).isEmpty();
}
@Test
public void testKnownNetworks_matchingScanResult_entryIncluded() {
final KnownNetwork testKnownNetwork = new KnownNetwork.Builder()
.setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
.setSsid("ssid")
.addSecurityType(SECURITY_TYPE_PSK)
.addSecurityType(SECURITY_TYPE_SAE)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.build();
when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
Collections.singletonList(testKnownNetwork));
when(mMockWifiManager.getScanResults()).thenReturn(
Collections.singletonList(buildScanResult("ssid", "bssid", START_MILLIS,
"[PSK/SAE]")));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof KnownNetworkEntry).toList()).hasSize(1);
}
@Test
public void testKnownNetworks_matchingConnectedScanResult_entryNotIncluded() {
final KnownNetwork testKnownNetwork = new KnownNetwork.Builder()
.setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
.setSsid("ssid")
.addSecurityType(SECURITY_TYPE_PSK)
.addSecurityType(SECURITY_TYPE_SAE)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.build();
when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
Collections.singletonList(testKnownNetwork));
when(mMockWifiManager.getScanResults()).thenReturn(
Collections.singletonList(buildScanResult("ssid", "bssid", START_MILLIS,
"[PSK/SAE]")));
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
when(mMockWifiInfo.getCurrentSecurityType()).thenReturn(SECURITY_TYPE_PSK);
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof KnownNetworkEntry).toList()).isEmpty();
assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
entry -> entry instanceof KnownNetworkEntry).toList()).isEmpty();
assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
entry -> entry instanceof StandardWifiEntry).toList()).hasSize(1);
}
@Test
public void testKnownNetworks_onKnownNetworkConnectionStatusChanged_matchingEntryCalled() {
final KnownNetwork testKnownNetwork1 = new KnownNetwork.Builder()
.setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
.setSsid("ssid1")
.addSecurityType(SECURITY_TYPE_PSK)
.addSecurityType(SECURITY_TYPE_SAE)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.build();
final KnownNetwork testKnownNetwork2 = new KnownNetwork.Builder()
.setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
.setSsid("ssid2")
.addSecurityType(SECURITY_TYPE_WEP)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Work Phone", "Pixel 6")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(90)
.setConnectionStrength(2)
.build())
.build();
final ScanResult testScanResult1 = buildScanResult("ssid1", "bssid1", START_MILLIS,
"[PSK/SAE]");
final ScanResult testScanResult2 = buildScanResult("ssid2", "bssid2", START_MILLIS,
"[WEP]");
when(mMockSharedConnectivityManager.getKnownNetworks()).thenReturn(
List.of(testKnownNetwork1, testKnownNetwork2));
when(mMockWifiManager.getScanResults()).thenReturn(
List.of(testScanResult1, testScanResult2));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries()).hasSize(2);
assertThat(wifiPickerTracker.getWifiEntries().get(0).getSsid()).isEqualTo("ssid1");
final WifiEntry.ConnectCallback connectCallback1 = mock(WifiEntry.ConnectCallback.class);
final WifiEntry.ConnectCallback connectCallback2 = mock(WifiEntry.ConnectCallback.class);
wifiPickerTracker.getWifiEntries().get(0).connect(connectCallback1);
wifiPickerTracker.getWifiEntries().get(1).connect(connectCallback2);
mSharedConnectivityCallbackCaptor.getValue().onKnownNetworkConnectionStatusChanged(
new KnownNetworkConnectionStatus.Builder()
.setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED)
.setKnownNetwork(testKnownNetwork1)
.build());
mTestLooper.dispatchAll();
verify(connectCallback1).onConnectResult(anyInt());
verify(connectCallback2, never()).onConnectResult(anyInt());
}
@Test
public void testHotspotNetworks_noActiveHotspot_virtualEntryIncluded() {
final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
.setDeviceId(1)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
.setNetworkName("Google Fi")
.build();
when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
Collections.singletonList(testHotspotNetwork));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
WifiEntry hotspotNetworkEntry = wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof HotspotNetworkEntry).findFirst().orElseThrow();
assertThat(((HotspotNetworkEntry) hotspotNetworkEntry).getHotspotNetworkEntryKey()
.isVirtualEntry()).isTrue();
}
@Test
public void testHotspotNetworks_activeHotspot_nonVirtualEntryIncluded() {
final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
.setDeviceId(1)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
.setNetworkName("Google Fi")
.setHotspotSsid("Instant Hotspot abcde")
.setHotspotBssid("0a:0b:0c:0d:0e:0f")
.addHotspotSecurityType(SECURITY_TYPE_PSK)
.addHotspotSecurityType(SECURITY_TYPE_SAE)
.build();
when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
Collections.singletonList(testHotspotNetwork));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
WifiEntry hotspotNetworkEntry = wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof HotspotNetworkEntry).findFirst().orElseThrow();
assertThat(((HotspotNetworkEntry) hotspotNetworkEntry).getHotspotNetworkEntryKey()
.isVirtualEntry()).isFalse();
}
@Test
public void testHotspotNetworks_duplicatesStandardEntry_standardEntryExcluded() {
final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
.setDeviceId(1)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
.setNetworkName("Google Fi")
.setHotspotSsid("Instant Hotspot abcde")
.setHotspotBssid("0a:0b:0c:0d:0e:0f")
.addHotspotSecurityType(SECURITY_TYPE_PSK)
.addHotspotSecurityType(SECURITY_TYPE_SAE)
.build();
when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
Collections.singletonList(testHotspotNetwork));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
buildScanResult("Instant Hotspot abcde", "0a:0b:0c:0d:0e:0f", START_MILLIS,
"[PSK/SAE]")));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof StandardWifiEntry).toList()).hasSize(1);
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof HotspotNetworkEntry).toList()).isEmpty();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof StandardWifiEntry).toList()).isEmpty();
assertThat(wifiPickerTracker.getWifiEntries().stream().filter(
entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
}
@Test
public void testHotspotNetworks_duplicatesActiveStandardEntry_standardEntryExcluded() {
final HotspotNetwork testHotspotNetwork = new HotspotNetwork.Builder()
.setDeviceId(1)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
.setNetworkName("Google Fi")
.setHotspotSsid("Instant Hotspot abcde")
.setHotspotBssid("0a:0b:0c:0d:0e:0f")
.addHotspotSecurityType(SECURITY_TYPE_PSK)
.addHotspotSecurityType(SECURITY_TYPE_SAE)
.build();
when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
Collections.singletonList(testHotspotNetwork));
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"Instant Hotspot abcde\"";
config.BSSID = "0a:0b:0c:0d:0e:0f";
config.networkId = 1;
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
when(mMockWifiInfo.getBSSID()).thenReturn("0a:0b:0c:0d:0e:0f");
when(mMockWifiInfo.getCurrentSecurityType()).thenReturn(SECURITY_TYPE_PSK);
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
buildScanResult("Instant Hotspot abcde", "0a:0b:0c:0d:0e:0f", START_MILLIS,
"[PSK/SAE]")));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
entry -> entry instanceof StandardWifiEntry).toList()).isEmpty();
assertThat(wifiPickerTracker.getActiveWifiEntries().stream().filter(
entry -> entry instanceof HotspotNetworkEntry).toList()).hasSize(1);
}
@Test
public void testHotspotNetworks_onHotspotNetworkConnectionStatusChanged_matchingEntryCalled() {
final HotspotNetwork testHotspotNetwork1 = new HotspotNetwork.Builder()
.setDeviceId(1)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
.setNetworkName("Google Fi")
.build();
final HotspotNetwork testHotspotNetwork2 = new HotspotNetwork.Builder()
.setDeviceId(2)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Work Phone", "Pixel 6")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(90)
.setConnectionStrength(2)
.build())
.setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
.setNetworkName("T-Mobile")
.build();
when(mMockSharedConnectivityManager.getHotspotNetworks()).thenReturn(
List.of(testHotspotNetwork1, testHotspotNetwork2));
final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
wifiPickerTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockSharedConnectivityManager).registerCallback(any(),
mSharedConnectivityCallbackCaptor.capture());
mSharedConnectivityCallbackCaptor.getValue().onServiceConnected();
mTestLooper.dispatchAll();
assertThat(wifiPickerTracker.getWifiEntries()).hasSize(2);
assertThat(((HotspotNetworkEntry) wifiPickerTracker.getWifiEntries().get(0))
.getHotspotNetworkEntryKey().getDeviceId()).isEqualTo(1);
final WifiEntry.ConnectCallback connectCallback1 = mock(WifiEntry.ConnectCallback.class);
final WifiEntry.ConnectCallback connectCallback2 = mock(WifiEntry.ConnectCallback.class);
wifiPickerTracker.getWifiEntries().get(0).connect(connectCallback1);
wifiPickerTracker.getWifiEntries().get(1).connect(connectCallback2);
mSharedConnectivityCallbackCaptor.getValue().onHotspotNetworkConnectionStatusChanged(
new HotspotNetworkConnectionStatus.Builder()
.setStatus(HotspotNetworkConnectionStatus
.CONNECTION_STATUS_PROVISIONING_FAILED)
.setHotspotNetwork(testHotspotNetwork1)
.build());
mTestLooper.dispatchAll();
verify(connectCallback1).onConnectResult(anyInt());
verify(connectCallback2, never()).onConnectResult(anyInt());
}
}