fix: 首次提交

This commit is contained in:
2024-12-09 11:25:23 +08:00
parent d0c01071e9
commit 2c2109a5f3
4741 changed files with 290641 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,136 @@
/*
* Copyright (C) 2023 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 com.android.wifitrackerlib.StandardWifiEntry.ssidAndSecurityTypeToStandardWifiEntryKey;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.wifi.WifiManager;
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.SharedConnectivityManager;
import android.os.Handler;
import android.os.test.TestLooper;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class KnownNetworkEntryTest {
@Mock private WifiEntry.WifiEntryCallback mMockListener;
@Mock private WifiEntry.ConnectCallback mMockConnectCallback;
@Mock private WifiTrackerInjector mMockInjector;
@Mock private Context mMockContext;
@Mock private WifiManager mMockWifiManager;
@Mock private SharedConnectivityManager mMockSharedConnectivityManager;
private TestLooper mTestLooper;
private Handler mTestHandler;
private static final KnownNetwork TEST_KNOWN_NETWORK_DATA = new KnownNetwork.Builder()
.setNetworkSource(KnownNetwork.NETWORK_SOURCE_NEARBY_SELF)
.setSsid("ssid")
.addSecurityType(SECURITY_TYPE_PSK)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("My Phone", "Pixel 7")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3)
.build())
.build();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper();
mTestHandler = new Handler(mTestLooper.getLooper());
when(mMockInjector.getContext()).thenReturn(mMockContext);
when(mMockContext.getString(eq(R.string.wifitrackerlib_known_network_summary), anyString()))
.thenAnswer(invocation -> {
Object[] args = invocation.getArguments();
return "Available from " + args[1];
});
}
@Test
public void testGetSummary_usesKnownNetworkData() {
final KnownNetworkEntry entry = new KnownNetworkEntry(
mMockInjector, mTestHandler,
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
mMockWifiManager, mMockSharedConnectivityManager, TEST_KNOWN_NETWORK_DATA);
assertThat(entry.getSummary()).isEqualTo("Available from My Phone");
}
@Test
public void testConnect_serviceCalled() {
final KnownNetworkEntry entry = new KnownNetworkEntry(
mMockInjector, mTestHandler,
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
mMockWifiManager, mMockSharedConnectivityManager, TEST_KNOWN_NETWORK_DATA);
entry.connect(null);
verify(mMockSharedConnectivityManager).connectKnownNetwork(TEST_KNOWN_NETWORK_DATA);
}
@Test
public void testConnect_nullManager_failureCallback() {
final KnownNetworkEntry entry = new KnownNetworkEntry(
mMockInjector, mTestHandler,
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
mMockWifiManager, /* sharedConnectivityManager= */ null, TEST_KNOWN_NETWORK_DATA);
entry.setListener(mMockListener);
entry.connect(mMockConnectCallback);
mTestLooper.dispatchAll();
verify(mMockConnectCallback)
.onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
}
@Test
public void testConnect_onConnectionStatusChanged_failureCallback() {
final KnownNetworkEntry entry = new KnownNetworkEntry(
mMockInjector, mTestHandler,
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_TYPE_PSK),
mMockWifiManager, mMockSharedConnectivityManager, TEST_KNOWN_NETWORK_DATA);
entry.setListener(mMockListener);
entry.connect(mMockConnectCallback);
mTestLooper.dispatchAll();
verify(mMockConnectCallback, never()).onConnectResult(anyInt());
entry.onConnectionStatusChanged(KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED);
mTestLooper.dispatchAll();
verify(mMockConnectCallback)
.onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wifitrackerlib;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.Looper;
import android.os.test.TestLooper;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MergedCarrierEntryTest {
@Mock private WifiTrackerInjector mMockInjector;
@Mock private WifiEntry.ConnectCallback mMockConnectCallback;
@Mock private WifiManager mMockWifiManager;
@Mock private WifiInfo mMockWifiInfo;
@Mock private Network mMockNetwork;
@Mock private NetworkCapabilities mMockNetworkCapabilities;
@Mock private Context mMockContext;
@Mock private Resources mMockResources;
private TestLooper mTestLooper;
private Handler mTestHandler;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
when(mMockWifiInfo.isPrimary()).thenReturn(true);
when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
mTestLooper = new TestLooper();
mTestHandler = new Handler(mTestLooper.getLooper());
when(mMockInjector.getContext()).thenReturn(mMockContext);
when(mMockContext.getMainLooper()).thenReturn(Looper.getMainLooper());
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator)).thenReturn("/");
when(mMockResources.getText(R.string.wifitrackerlib_wifi_wont_autoconnect_for_now))
.thenReturn("Wi-Fi won't auto-connect for now");
}
@Test
public void testGetConnectedState_wifiInfoMatches_returnsConnected() {
final int subId = 1;
final MergedCarrierEntry entry = new MergedCarrierEntry(mMockInjector, mTestHandler,
mMockWifiManager, false, subId);
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_CONNECTED);
}
@Test
public void testConnect_disablesNonCarrierMergedWifi() {
Looper.prepare();
final int subId = 1;
final MergedCarrierEntry entry = new MergedCarrierEntry(mMockInjector, mTestHandler,
mMockWifiManager, false, subId);
entry.connect(mMockConnectCallback);
mTestLooper.dispatchAll();
verify(mMockConnectCallback)
.onConnectResult(WifiEntry.ConnectCallback.CONNECT_STATUS_SUCCESS);
verify(mMockWifiManager).startRestrictingAutoJoinToSubscriptionId(subId);
}
@Test
public void testDisconnect_enablesNonCarrierMergedWifiAndTriggersScan() {
final int subId = 1;
final MergedCarrierEntry entry = new MergedCarrierEntry(mMockInjector, mTestHandler,
mMockWifiManager, false, subId);
entry.disconnect(null);
mTestLooper.dispatchAll();
verify(mMockWifiManager).stopRestrictingAutoJoinToSubscriptionId();
verify(mMockWifiManager).startScan();
}
@Test
public void testCanConnect_cellIsDefaultRoute_returnsFalse() {
final int subId = 1;
final MergedCarrierEntry entry = new MergedCarrierEntry(mMockInjector, mTestHandler,
mMockWifiManager, false, subId);
entry.updateIsCellDefaultRoute(false);
assertThat(entry.canConnect()).isTrue();
entry.updateIsCellDefaultRoute(true);
assertThat(entry.canConnect()).isFalse();
}
@Test
public void testGetSsid_connected_returnsSanitizedWifiInfoSsid() {
final int subId = 1;
final MergedCarrierEntry entry = new MergedCarrierEntry(mMockInjector, mTestHandler,
mMockWifiManager, false, subId);
when(mMockWifiInfo.isCarrierMerged()).thenReturn(true);
when(mMockWifiInfo.getSubscriptionId()).thenReturn(subId);
final String ssid = "ssid";
when(mMockWifiInfo.getSSID()).thenReturn("\"" + ssid + "\"");
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSsid()).isEqualTo(ssid);
}
}

View File

@@ -0,0 +1,144 @@
/*
* 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 com.android.wifitrackerlib.NetworkDetailsTracker.createNetworkDetailsTracker;
import static com.android.wifitrackerlib.StandardWifiEntry.ScanResultKey;
import static com.android.wifitrackerlib.StandardWifiEntry.StandardWifiEntryKey;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
import android.os.Handler;
import android.os.test.TestLooper;
import androidx.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Collections;
public class NetworkDetailsTrackerTest {
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 mResources;
@Mock private WifiManager mMockWifiManager;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private Clock mMockClock;
private TestLooper mTestLooper;
private NetworkDetailsTracker createTestNetworkDetailsTracker(String key) {
final Handler testHandler = new Handler(mTestLooper.getLooper());
return createNetworkDetailsTracker(
mInjector,
mMockLifecycle,
mMockContext,
mMockWifiManager,
mMockConnectivityManager,
testHandler,
testHandler,
mMockClock,
MAX_SCAN_AGE_MILLIS,
SCAN_INTERVAL_MILLIS,
key);
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper();
when(mMockWifiManager.getScanResults()).thenReturn(new ArrayList<>());
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
when(mMockClock.millis()).thenReturn(START_MILLIS);
when(mMockContext.getResources()).thenReturn(mResources);
}
/**
* Tests that an invalid WifiEntry key passed into the constructor throws an exception.
*/
@Test
public void testCreateNetworkDetailsTracker_invalidKey_throwsError() {
try {
createTestNetworkDetailsTracker("Invalid Key");
fail("Invalid key should have thrown an error!");
} catch (IllegalArgumentException e) {
// Test succeeded
}
}
/**
* Tests that createNetworkDetailsTracker() returns a StandardNetworkDetailsTracker if a
* StandardWifiEntry key is passed in.
*/
@Test
public void testCreateNetworkDetailsTracker_returnsStandardNetworkDetailsTracker()
throws Exception {
final NetworkDetailsTracker tracker = createTestNetworkDetailsTracker(
new StandardWifiEntryKey(new ScanResultKey("ssid",
Collections.singletonList(WifiEntry.SECURITY_NONE))).toString());
assertThat(tracker).isInstanceOf(StandardNetworkDetailsTracker.class);
}
/**
* Tests that createNetworkDetailsTracker() returns a HotspotNetworkDetailsTracker if a
* HotspotNetworkEntry key is passed in.
*/
@Test
public void testCreateNetworkDetailsTracker_returnsHotspotNetworkDetailsTracker()
throws Exception {
final NetworkDetailsTracker tracker = createTestNetworkDetailsTracker(
new HotspotNetworkEntry.HotspotNetworkEntryKey(new HotspotNetwork.Builder()
.setDeviceId(1)
.setNetworkProviderInfo(new NetworkProviderInfo
.Builder("Phone", "Pixel")
.setDeviceType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
.setBatteryPercentage(100)
.setConnectionStrength(3).build())
.setHostNetworkType(HotspotNetwork.NETWORK_TYPE_CELLULAR)
.setNetworkName("Google Fi")
.setHotspotSsid("SSID")
.setHotspotBssid("BSSID")
.addHotspotSecurityType(WifiInfo.SECURITY_TYPE_WEP)
.build()).toString());
assertThat(tracker).isInstanceOf(HotspotNetworkDetailsTracker.class);
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2021 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 com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.NetworkCapabilities;
import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.text.Annotation;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.ClickableSpan;
import org.junit.Test;
public class NonSdkApiWrapperTest {
@Test
public void testLinkifyAnnotation_annotation_returnTextWithClickableSpan() {
final String annotationId = "id";
final CharSequence testText = "test text ";
final CharSequence testLink = "link";
final CharSequence expectedText = "test text link";
final SpannableStringBuilder builder = new SpannableStringBuilder(testText);
builder.append(testLink, new Annotation("key", annotationId),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
final CharSequence output = NonSdkApiWrapper.linkifyAnnotation(
mock(Context.class), builder, annotationId, "url");
final SpannableString outputSpannableString = new SpannableString(output);
assertEquals(output.toString(), expectedText.toString());
assertEquals(outputSpannableString.getSpans(0, outputSpannableString.length(),
ClickableSpan.class).length, 1);
}
@Test
public void testLinkifyAnnotation_annotationWithEmptyUriString_returnOriginalText() {
final String annotationId = "url";
final CharSequence testText = "test text ";
final CharSequence testLink = "Learn More";
final CharSequence expectedText = "test text Learn More";
final SpannableStringBuilder builder = new SpannableStringBuilder(testText);
builder.append(testLink, new Annotation("key", annotationId),
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
final CharSequence output = NonSdkApiWrapper.linkifyAnnotation(
mock(Context.class), builder, annotationId, "");
final SpannableString outputSpannableString = new SpannableString(output);
assertEquals(output.toString(), expectedText.toString());
assertEquals(outputSpannableString.getSpans(0, outputSpannableString.length(),
ClickableSpan.class).length, 0);
}
/**
* Verifies the functionality of {@link NonSdkApiWrapper#getWifiInfoIfVcn(NetworkCapabilities)}
*/
@Test
public void testGetVcnWifiInfo() {
NetworkCapabilities networkCapabilities = mock(NetworkCapabilities.class);
assertThat(NonSdkApiWrapper.getWifiInfoIfVcn(networkCapabilities)).isNull();
VcnTransportInfo vcnTransportInfo = mock(VcnTransportInfo.class);
when(networkCapabilities.getTransportInfo()).thenReturn(vcnTransportInfo);
assertThat(NonSdkApiWrapper.getWifiInfoIfVcn(networkCapabilities)).isNull();
WifiInfo wifiInfo = mock(WifiInfo.class);
when(vcnTransportInfo.getWifiInfo()).thenReturn(wifiInfo);
assertThat(NonSdkApiWrapper.getWifiInfoIfVcn(networkCapabilities)).isEqualTo(wifiInfo);
}
}

View File

@@ -0,0 +1,363 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wifitrackerlib;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Handler;
import android.os.test.TestLooper;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import java.util.Arrays;
public class PasspointWifiEntryTest {
@Mock private WifiTrackerInjector mMockInjector;
@Mock private Context mMockContext;
@Mock private WifiManager mMockWifiManager;
@Mock private Resources mMockResources;
@Mock private WifiInfo mMockWifiInfo;
@Mock private Network mMockNetwork;
@Mock private NetworkCapabilities mMockNetworkCapabilities;
@Mock private ConnectivityManager mMockConnectivityManager;
private TestLooper mTestLooper;
private Handler mTestHandler;
private static final String FQDN = "fqdn";
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper();
mTestHandler = new Handler(mTestLooper.getLooper());
when(mMockWifiInfo.isPrimary()).thenReturn(true);
when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
when(mMockInjector.getContext()).thenReturn(mMockContext);
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator)).thenReturn("/");
when(mMockContext.getSystemService(ConnectivityManager.class))
.thenReturn(mMockConnectivityManager);
}
@Test
public void testGetSummary_expiredTimeNotAvailable_notShowExpired() {
// default SubscriptionExpirationTimeInMillis is unset
PasspointConfiguration passpointConfiguration = getPasspointConfiguration();
String expired = "Expired";
when(mMockContext.getString(R.string.wifitrackerlib_wifi_passpoint_expired))
.thenReturn(expired);
PasspointWifiEntry passpointWifiEntry = new PasspointWifiEntry(mMockInjector,
mTestHandler, passpointConfiguration, mMockWifiManager,
false /* forSavedNetworksPage */);
assertThat(passpointWifiEntry.getSummary()).isNotEqualTo(expired);
}
@Test
public void testGetSummary_expired_showExpired() {
PasspointConfiguration passpointConfiguration = getPasspointConfiguration();
String expired = "Expired";
when(mMockContext.getString(R.string.wifitrackerlib_wifi_passpoint_expired))
.thenReturn(expired);
PasspointWifiEntry passpointWifiEntry = new PasspointWifiEntry(mMockInjector,
mTestHandler, passpointConfiguration, mMockWifiManager,
false /* forSavedNetworksPage */);
PasspointWifiEntry spyEntry = spy(passpointWifiEntry);
when(spyEntry.isExpired()).thenReturn(true);
assertThat(spyEntry.getSummary()).isEqualTo(expired);
}
private PasspointConfiguration getPasspointConfiguration() {
PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
HomeSp homeSp = new HomeSp();
homeSp.setFqdn(FQDN);
passpointConfiguration.setHomeSp(homeSp);
passpointConfiguration.setCredential(new Credential());
return passpointConfiguration;
}
@Test
public void testGetMeteredChoice_afterSetMeteredChoice_getCorrectValue() {
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
entry.setMeteredChoice(WifiEntry.METERED_CHOICE_UNMETERED);
assertThat(entry.getMeteredChoice()).isEqualTo(WifiEntry.METERED_CHOICE_UNMETERED);
}
@Test
public void testGetSummary_connectedWifiNetwork_showsConnected() {
String summarySeparator = " / ";
String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
.thenReturn(true);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
entry.onDefaultNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSummary()).isEqualTo("Connected");
}
@Test
public void testGetSummary_connectedButNotDefault_doesNotShowConnected() {
String summarySeparator = " / ";
String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
.thenReturn(true);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSummary()).isEqualTo("");
}
@Test
public void testGetSecurityTypes_connectedWifiNetwork_showsCurrentSecurityType() {
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
when(mMockWifiInfo.getCurrentSecurityType())
.thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
assertThat(entry.getSecurityTypes()).containsExactlyElementsIn(Arrays.asList(
WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2,
WifiInfo.SECURITY_TYPE_PASSPOINT_R3));
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSecurityTypes())
.containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
when(mMockWifiInfo.getCurrentSecurityType())
.thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getSecurityTypes()).containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
}
@Test
public void testGetSecurityString_showsPasspoint() {
PasspointConfiguration passpointConfiguration = getPasspointConfiguration();
String passpointSecurity = "Passpoint";
when(mMockContext.getString(R.string.wifitrackerlib_wifi_security_passpoint))
.thenReturn(passpointSecurity);
PasspointWifiEntry passpointWifiEntry = new PasspointWifiEntry(mMockInjector,
mTestHandler, passpointConfiguration, mMockWifiManager,
false /* forSavedNetworksPage */);
assertThat(passpointWifiEntry.getSecurityString(false)).isEqualTo(passpointSecurity);
}
@Test
public void testShouldShowXLevelIcon_unvalidatedOrLowQuality_returnsTrue() {
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
// Disconnected should return false;
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
// Connected but validation attempt not complete, should not show X level icon yet.
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
// Validation attempt complete, should show X level icon.
ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport = mock(
ConnectivityDiagnosticsManager.ConnectivityReport.class);
when(connectivityReport.getNetwork()).thenReturn(mMockNetwork);
entry.updateConnectivityReport(connectivityReport);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
// Internet validated, should not show X level icon.
when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
.thenReturn(true);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
// Cell becomes default (i.e. low quality wifi), show X level icon.
entry.onDefaultNetworkCapabilitiesChanged(Mockito.mock(Network.class),
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
}
@Test
public void testGetMacAddress_wifiInfoAvailable_usesWifiInfoMacAddress() {
final String factoryMac = "01:23:45:67:89:ab";
final String wifiInfoMac = "11:23:45:67:89:ab";
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
config.FQDN = FQDN;
when(mMockWifiManager.getFactoryMacAddresses()).thenReturn(new String[]{factoryMac});
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
when(mMockWifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getMacAddress()).isEqualTo(wifiInfoMac);
}
@Test
public void testIsAutoJoinEnabled_nullConfigs_returnsFalse() {
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
entry.updatePasspointConfig(null);
assertThat(entry.isAutoJoinEnabled()).isFalse();
}
@Test
public void testCanSignIn_captivePortalCapability_returnsTrue() {
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
when(mMockNetworkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.canSignIn()).isTrue();
}
@Test
public void testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce() {
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
try {
// Simulate user tapping on the network and receiving captive portal capabilities.
// This should trigger the captive portal app.
entry.connect(null /* callback */);
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
when(mMockNetworkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
// Update network capabilities again. This should not trigger the captive portal app.
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
} finally {
session.finishMocking();
}
}
@Test
public void testDisconnect_noScansOrWifiConfig_disconnectIsSuccessful() {
// Setup a connected PasspointWifiEntry
String summarySeparator = " / ";
String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
"Authenticating", "Obtaining IP address", "Connected"};
when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
.thenReturn(summarySeparator);
when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
.thenReturn(wifiStatusArray);
when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
.thenReturn(true);
PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
getPasspointConfiguration(), mMockWifiManager,
false /* forSavedNetworksPage */);
entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
// Disconnect the entry before it can be updated with scans and a WifiConfiguration
entry.disconnect(null);
verify(mMockWifiManager).disableEphemeralNetwork(FQDN);
verify(mMockWifiManager).disconnect();
}
}

View File

@@ -0,0 +1,750 @@
/*
* 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 com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
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.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
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.verify;
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.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.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Handler;
import android.os.test.TestLooper;
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.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class SavedNetworkTrackerTest {
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;
private static final String TEST_CACERT_NOT_REQUIRED_ALIAS = "cacert_not_required";
@Mock private WifiTrackerInjector mInjector;
@Mock private Lifecycle mMockLifecycle;
@Mock private Context mMockContext;
@Mock private Resources mResources;
@Mock private WifiManager mMockWifiManager;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private ConnectivityDiagnosticsManager mMockConnectivityDiagnosticsManager;
@Mock private Clock mMockClock;
@Mock private SavedNetworkTracker.SavedNetworkTrackerCallback mMockCallback;
@Mock private WifiInfo mMockWifiInfo;
@Mock private Network mMockNetwork;
@Mock private NetworkCapabilities mMockNetworkCapabilities;
@Mock private LinkProperties mMockLinkProperties;
private TestLooper mTestLooper;
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<BroadcastReceiver> mBroadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
private SavedNetworkTracker createTestSavedNetworkTracker() {
final Handler testHandler = new Handler(mTestLooper.getLooper());
return new SavedNetworkTracker(
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.getConnectionInfo()).thenReturn(mMockWifiInfo);
when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true);
when(mMockWifiManager.isWpa3SuiteBSupported()).thenReturn(true);
when(mMockWifiManager.isEnhancedOpenSupported()).thenReturn(true);
when(mMockWifiManager.getCurrentNetwork()).thenReturn(mMockNetwork);
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
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(mMockNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
.thenReturn(true);
when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
// 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(mInjector.getContext()).thenReturn(mMockContext);
when(mMockContext.getResources()).thenReturn(mResources);
when(mMockContext.getSystemService(ConnectivityDiagnosticsManager.class))
.thenReturn(mMockConnectivityDiagnosticsManager);
when(mMockClock.millis()).thenReturn(START_MILLIS);
}
/**
* Tests that receiving a wifi state change broadcast updates getWifiState().
*/
@Test
public void testWifiStateChangeBroadcast_updatesWifiState() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.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(savedNetworkTracker.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(savedNetworkTracker.getWifiState()).isEqualTo(WifiManager.WIFI_STATE_ENABLED);
}
/**
* Tests that receiving a wifi state change broadcast notifies the listener.
*/
@Test
public void testWifiStateChangeBroadcast_notifiesListener() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.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
* onSavedWifiEntriesChanged().
*/
@Test
public void testConfiguredNetworksChanged_notifiesListener() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.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()).onSavedWifiEntriesChanged();
}
/**
* Tests that a WifiEntry is created for each configured network for getSavedWifiEntries().
*/
@Test
public void testGetSavedWifiEntries_onStart_entryForEachConfiguredNetwork() {
when(mMockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(
buildWifiConfiguration("ssid0"),
buildWifiConfiguration("ssid1"),
buildWifiConfiguration("ssid2")
));
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
assertThat(savedNetworkTracker.getSavedWifiEntries().stream()
.map(WifiEntry::getTitle)
.collect(Collectors.toSet()))
.containsExactly("ssid0", "ssid1", "ssid2");
}
/**
* Tests that a CONFIGURED_NETWORKS_CHANGED broadcast after adding a config
* adds the corresponding WifiEntry from getSavedWifiEntries().
*/
@Test
public void testGetSavedWifiEntries_configuredNetworksChanged_addsEntry() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
assertThat(savedNetworkTracker.getSavedWifiEntries()).isEmpty();
final WifiConfiguration config = buildWifiConfiguration("ssid");
when(mMockWifiManager.getConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
assertThat(savedNetworkTracker.getSavedWifiEntries().stream()
.filter(entry -> entry.mForSavedNetworksPage)
.collect(Collectors.toSet()))
.hasSize(1);
}
/**
* Tests that a CONFIGURED_NETWORKS_CHANGED broadcast after removing a config
* removes the corresponding WifiEntry from getSavedWifiEntries().
*/
@Test
public void testGetSavedWifiEntries_configuredNetworksChanged_removesEntry() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = buildWifiConfiguration("ssid");
when(mMockWifiManager.getConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
assertThat(savedNetworkTracker.getSavedWifiEntries()).hasSize(1);
when(mMockWifiManager.getConfiguredNetworks())
.thenReturn(Collections.emptyList());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
assertThat(savedNetworkTracker.getSavedWifiEntries()).isEmpty();
}
/**
* Tests that receiving a scan results available broadcast notifies the listener.
*/
@Test
public void testScanResultsAvailableAction_notifiesListener() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.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()).onSavedWifiEntriesChanged();
}
/**
* Tests that the scan results available broadcast changes the level of saved WifiEntries.
*/
@Test
public void testGetSavedWifiEntries_scanResultsAvailableAction_changesLevel() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = buildWifiConfiguration("ssid");
config.networkId = 1;
when(mMockWifiManager.getConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
assertThat(entry.getLevel()).isEqualTo(WifiEntry.WIFI_LEVEL_UNREACHABLE);
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(
buildScanResult("ssid", "bssid", START_MILLIS, -50 /* rssi */)));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
assertThat(entry.getLevel()).isNotEqualTo(WifiEntry.WIFI_LEVEL_UNREACHABLE);
when(mMockClock.millis()).thenReturn(START_MILLIS + MAX_SCAN_AGE_MILLIS + 1);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
assertThat(entry.getLevel()).isEqualTo(WifiEntry.WIFI_LEVEL_UNREACHABLE);
}
@Test
public void testGetSubscriptionWifiEntries_returnsPasspointEntries() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
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));
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
assertThat(savedNetworkTracker.getSubscriptionWifiEntries()).isNotEmpty();
assertThat(savedNetworkTracker.getSubscriptionWifiEntries().get(0).getTitle())
.isEqualTo("friendlyName");
}
@Test
public void testGetSavedNetworks_splitConfigs_entriesMergedBySecurityFamily() {
final String ssid = "ssid";
WifiConfiguration openConfig = buildWifiConfiguration(ssid);
openConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
openConfig.networkId = 1;
WifiConfiguration oweConfig = buildWifiConfiguration(ssid);
oweConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
oweConfig.networkId = 1;
WifiConfiguration wepConfig = buildWifiConfiguration(ssid);
wepConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WEP);
wepConfig.wepKeys = new String[]{"key"};
wepConfig.networkId = 2;
WifiConfiguration pskConfig = buildWifiConfiguration(ssid);
pskConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
pskConfig.networkId = 3;
WifiConfiguration saeConfig = buildWifiConfiguration(ssid);
saeConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
saeConfig.networkId = 3;
WifiConfiguration eapConfig = buildWifiConfiguration(ssid);
eapConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
eapConfig.networkId = 4;
WifiConfiguration eapWpa3Config = buildWifiConfiguration(ssid);
eapWpa3Config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE);
eapWpa3Config.networkId = 4;
WifiConfiguration eapWpa3SuiteBConfig = buildWifiConfiguration(ssid);
eapWpa3SuiteBConfig.setSecurityParams(
WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT);
eapWpa3SuiteBConfig.networkId = 5;
when(mMockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(
openConfig, oweConfig, wepConfig, pskConfig, saeConfig, eapConfig, eapWpa3Config,
eapWpa3SuiteBConfig
));
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
final List<WifiEntry> savedWifiEntries = savedNetworkTracker.getSavedWifiEntries();
assertThat(savedWifiEntries.size()).isEqualTo(5);
assertThat(savedWifiEntries.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 entries with configs that have scans matching the security family but NOT the
* actual configs on hand will ignore the scans and be returned as saved with the configs.
*/
@Test
public void testGetSavedNetworks_mismatchedScans_returnsCorrectEntries() {
// Set up scans for Open, PSK, WPA2-Enterprise
final ArrayList scanList = new ArrayList();
final String ssid = "ssid";
final String bssid = "bssid";
int bssidNum = 0;
for (String capabilities : Arrays.asList(
"",
"[PSK]",
"[EAP/SHA1]"
)) {
final ScanResult scan = buildScanResult(ssid, bssid + bssidNum++, START_MILLIS);
scan.capabilities = capabilities;
scanList.add(scan);
}
when(mMockWifiManager.getScanResults()).thenReturn(scanList);
// Set up configs for OWE, SAE, WPA3-Enterprise
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.getConfiguredNetworks())
.thenReturn(Arrays.asList(oweConfig, saeConfig, eapWpa3Config));
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
// Entries should appear correctly in the saved entry list with the security type of their
// configs, ignoring the scans present.
final List<WifiEntry> savedWifiEntries = savedNetworkTracker.getSavedWifiEntries();
assertThat(savedWifiEntries.size()).isEqualTo(3);
assertThat(savedWifiEntries.stream()
.map(entry -> entry.getSecurityTypes())
.collect(Collectors.toList()))
.containsExactly(
Arrays.asList(WifiInfo.SECURITY_TYPE_OWE),
Arrays.asList(WifiInfo.SECURITY_TYPE_SAE),
Arrays.asList(WifiInfo.SECURITY_TYPE_EAP_WPA3_ENTERPRISE));
}
/**
* Tests that a saved network has CONNECTED_STATE_CONNECTED if it is the connected network on
* start.
*/
@Test
public void testConnectedEntry_alreadyConnectedOnStart_isConnected() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
}
/**
* Tests that connecting to a network will update that network to CONNECTED_STATE_CONNECTED.
*/
@Test
public void testDisconnectedEntry_connectToNetwork_becomesConnected() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
buildScanResult("ssid", "bssid", START_MILLIS)));
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
when(mMockWifiInfo.getNetworkId()).thenReturn(1);
when(mMockWifiInfo.getRssi()).thenReturn(-50);
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(
mMockNetwork, mMockNetworkCapabilities);
assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
}
/**
* Tests that disconnecting from a network will update that network to
* CONNECTED_STATE_DISCONNECTED.
*/
@Test
public void testConnectedEntry_disconnectFromNetwork_becomesDisconnected() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getConfiguredNetworks())
.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);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
mNetworkCallbackCaptor.getValue().onLost(mMockNetwork);
assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
}
/**
* Tests that disconnecting from a network during the stopped state will result in the network
* being disconnected once we've started again.
*/
@Test
public void testGetConnectedEntry_disconnectFromNetworkWhileStopped_becomesDisconnected() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getConfiguredNetworks())
.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);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
final WifiEntry entry = savedNetworkTracker.getSavedWifiEntries().get(0);
assertThat(entry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
// Simulate network disconnecting while in stopped state
savedNetworkTracker.onStop();
mTestLooper.dispatchAll();
when(mMockWifiManager.getCurrentNetwork()).thenReturn(null);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
assertThat(entry.getConnectedState()).isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
}
/**
* Tests that getConnectedEntry() will return the correct primary network after an MBB sequence.
*/
@Test
public void testConnectedEntry_mbbFlow_matchesNewPrimary() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
final WifiConfiguration mbbConfig = new WifiConfiguration();
mbbConfig.SSID = "\"otherSsid\"";
mbbConfig.networkId = 2;
when(mMockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(config, mbbConfig));
when(mMockWifiInfo.getNetworkId()).thenReturn(config.networkId);
when(mMockWifiInfo.getRssi()).thenReturn(GOOD_RSSI);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockConnectivityManager).registerNetworkCallback(
any(), mNetworkCallbackCaptor.capture(), any());
// Start off connected
List<WifiEntry> savedEntries = savedNetworkTracker.getSavedWifiEntries();
assertThat(savedEntries.size()).isEqualTo(2);
WifiEntry originalEntry = null;
WifiEntry mbbEntry = null;
for (WifiEntry entry : savedNetworkTracker.getSavedWifiEntries()) {
if (entry.getTitle().equals("ssid")) {
originalEntry = entry;
} else if (entry.getTitle().equals("otherSsid")) {
mbbEntry = entry;
}
}
assertThat(originalEntry).isNotNull();
assertThat(originalEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_CONNECTED);
assertThat(mbbEntry).isNotNull();
assertThat(mbbEntry.getConnectedState())
.isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
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(originalEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_CONNECTED);
assertThat(mbbEntry.getConnectedState())
.isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
// 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.
assertThat(originalEntry.getConnectedState())
.isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
assertThat(mbbEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_CONNECTED);
// Original network is lost. MBB network should still be connected
assertThat(originalEntry.getConnectedState())
.isEqualTo(WifiEntry.CONNECTED_STATE_DISCONNECTED);
assertThat(mbbEntry.getConnectedState())
.isEqualTo(CONNECTED_STATE_CONNECTED);
} finally {
session.finishMocking();
}
}
@Test
public void testCertificateRequired() throws Exception {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PEAP);
when(mMockWifiManager.getConfiguredNetworks())
.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);
savedNetworkTracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
// Check another CA cert alias.
assertFalse(savedNetworkTracker.isCertificateRequired(TEST_CACERT_NOT_REQUIRED_ALIAS));
assertEquals(0, savedNetworkTracker
.getCertificateRequesterNames(TEST_CACERT_NOT_REQUIRED_ALIAS).size());
}
/**
* Tests that a connected WifiEntry's isDefaultNetwork() will reflect updates from the default
* network changing.
*/
@Test
public void testGetConnectedEntry_defaultNetworkChanges_isDefaultNetworkChanges() {
final SavedNetworkTracker savedNetworkTracker = createTestSavedNetworkTracker();
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"ssid\"";
config.networkId = 1;
when(mMockWifiManager.getConfiguredNetworks())
.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);
savedNetworkTracker.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());
WifiEntry connectedWifiEntry = savedNetworkTracker.getSavedWifiEntries().get(0);
assertThat(connectedWifiEntry).isNotNull();
assertThat(connectedWifiEntry.getConnectedState()).isEqualTo(CONNECTED_STATE_CONNECTED);
// No default
assertThat(connectedWifiEntry.isDefaultNetwork()).isFalse();
// Cell is default
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(Mockito.mock(Network.class),
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
assertThat(connectedWifiEntry.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(connectedWifiEntry.isDefaultNetwork()).isFalse();
// This Wi-Fi network is default
mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
mMockNetworkCapabilities);
assertThat(connectedWifiEntry.isDefaultNetwork()).isTrue();
// Lose the default network
mDefaultNetworkCallbackCaptor.getValue().onLost(mock(Network.class));
assertThat(connectedWifiEntry.isDefaultNetwork()).isFalse();
}
}

View File

@@ -0,0 +1,148 @@
/*
* 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 com.android.wifitrackerlib.TestUtils.buildScanResult;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import android.net.wifi.ScanResult;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.time.Clock;
import java.util.Arrays;
import java.util.List;
public class ScanResultUpdaterTest {
private static final String SSID = "ssid";
private static final String BSSID_1 = "11:11:11:11:11:11";
private static final String BSSID_2 = "22:22:22:22:22:22";
private static final String BSSID_3 = "33:33:33:33:33:33";
private static final long NOW_MILLIS = 123_456_789;
@Mock private Clock mMockClock;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mMockClock.millis()).thenReturn(NOW_MILLIS);
}
/**
* Verify that scan results of the same BSSID are merged to latest one.
*/
@Test
public void testGetScanResults_mergeSameBssid() {
ScanResult oldResult = buildScanResult(SSID, BSSID_1, 10);
ScanResult newResult = buildScanResult(SSID, BSSID_1, 20);
// Add initial scan result. List should have 1 scan.
ScanResultUpdater sru = new ScanResultUpdater(mMockClock);
sru.update(Arrays.asList(oldResult));
assertThat(sru.getScanResults()).containsExactly(oldResult);
// Add new scan result. Old scan result should be replaced.
sru.update(Arrays.asList(newResult));
assertThat(sru.getScanResults()).containsExactly(newResult);
// Add old scan result back. New scan result should still remain.
sru.update(Arrays.asList(oldResult));
assertThat(sru.getScanResults()).containsExactly(newResult);
}
/**
* Verify that scan results are filtered out by age.
*/
@Test
public void testGetScanResults_filtersOldScans() {
long maxScanAge = 15_000;
ScanResult oldResult = buildScanResult(SSID, BSSID_1, NOW_MILLIS - (maxScanAge + 1));
ScanResult newResult = buildScanResult(SSID, BSSID_2, NOW_MILLIS);
// Add a new scan result and an out-of-date scan result.
ScanResultUpdater sru = new ScanResultUpdater(mMockClock);
sru.update(Arrays.asList(newResult, oldResult));
// New scan result should remain and out-of-date scan result should not be returned.
assertThat(sru.getScanResults(maxScanAge)).containsExactly(newResult);
}
/**
* Verify that an exception is thrown if the getScanResults max scan age is larger than the
* constructor's max scan age.
*/
@Test
public void testGetScanResults_invalidMaxScanAgeMillis_throwsException() {
ScanResultUpdater sru = new ScanResultUpdater(mMockClock, 15_000);
try {
sru.getScanResults(20_000);
fail("Should have thrown exception for maxScanAgeMillis too large.");
} catch (IllegalArgumentException ok) {
// Expected
}
}
/**
* Verify that the constructor max scan age is obeyed when getting scan results.
*/
@Test
public void testConstructor_maxScanAge_filtersOldScans() {
ScanResultUpdater sru = new ScanResultUpdater(mMockClock, 15_000);
ScanResult scan1 = buildScanResult(SSID, BSSID_1, NOW_MILLIS - 10_000);
ScanResult scan2 = buildScanResult(SSID, BSSID_2, NOW_MILLIS - 15_000);
ScanResult scan3 = buildScanResult(SSID, BSSID_3, NOW_MILLIS - 20_000);
sru.update(Arrays.asList(scan1, scan2, scan3));
List<ScanResult> scanResults = sru.getScanResults();
assertThat(scanResults).containsExactly(scan1, scan2);
}
/**
* Verify that getScanResults returns results aged by the passed in max scan age even if there
* is a max scan age set by the constructor.
*/
@Test
public void testGetScanResults_overridesConstructorMaxScanAge() {
ScanResultUpdater sru = new ScanResultUpdater(mMockClock, 15_000);
ScanResult scan1 = buildScanResult(SSID, BSSID_1, NOW_MILLIS - 10_000);
ScanResult scan2 = buildScanResult(SSID, BSSID_2, NOW_MILLIS - 15_000);
ScanResult scan3 = buildScanResult(SSID, BSSID_3, NOW_MILLIS - 20_000);
sru.update(Arrays.asList(scan1, scan2, scan3));
// Aged getScanResults should override the constructor max scan age.
List<ScanResult> scanResults = sru.getScanResults(11_000);
assertThat(scanResults).containsExactly(scan1);
// Non-aged getScanResults should revert to the constructor max scan age.
scanResults = sru.getScanResults();
assertThat(scanResults).containsExactly(scan1, scan2);
}
}

View File

@@ -0,0 +1,320 @@
/*
* 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 com.android.wifitrackerlib.StandardWifiEntry.StandardWifiEntryKey;
import static com.android.wifitrackerlib.StandardWifiEntry.ssidAndSecurityTypeToStandardWifiEntryKey;
import static com.android.wifitrackerlib.TestUtils.BAD_LEVEL;
import static com.android.wifitrackerlib.TestUtils.BAD_RSSI;
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.SECURITY_NONE;
import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
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.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.os.Handler;
import android.os.test.TestLooper;
import androidx.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.time.Clock;
import java.util.ArrayList;
import java.util.Collections;
public class StandardNetworkDetailsTrackerTest {
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 mResources;
@Mock private WifiManager mMockWifiManager;
@Mock private WifiScanner mWifiScanner;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private ConnectivityDiagnosticsManager mMockConnectivityDiagnosticsManager;
@Mock private Clock mMockClock;
private TestLooper mTestLooper;
private final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
private StandardNetworkDetailsTracker createTestStandardNetworkDetailsTracker(
String key) {
final Handler testHandler = new Handler(mTestLooper.getLooper());
return new StandardNetworkDetailsTracker(
mInjector,
mMockLifecycle,
mMockContext,
mMockWifiManager,
mMockConnectivityManager,
testHandler,
testHandler,
mMockClock,
MAX_SCAN_AGE_MILLIS,
SCAN_INTERVAL_MILLIS,
key);
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper();
when(mMockWifiManager.isWpa3SaeSupported()).thenReturn(true);
when(mMockWifiManager.isWpa3SuiteBSupported()).thenReturn(true);
when(mMockWifiManager.isEnhancedOpenSupported()).thenReturn(true);
when(mMockWifiManager.getScanResults()).thenReturn(new ArrayList<>());
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_ENABLED);
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(mMockContext.getResources()).thenReturn(mResources);
when(mMockContext.getSystemService(ConnectivityDiagnosticsManager.class))
.thenReturn(mMockConnectivityDiagnosticsManager);
when(mMockContext.getSystemService(WifiScanner.class)).thenReturn(mWifiScanner);
when(mMockClock.millis()).thenReturn(START_MILLIS);
}
/**
* Tests that the key of the created WifiEntry matches the key passed into the constructor.
*/
@Test
public void testGetWifiEntry_HasCorrectKey() throws Exception {
final StandardWifiEntryKey key =
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_NONE);
final StandardNetworkDetailsTracker tracker =
createTestStandardNetworkDetailsTracker(key.toString());
assertThat(tracker.getWifiEntry().getKey()).isEqualTo(key.toString());
}
/**
* Tests that SCAN_RESULTS_AVAILABLE_ACTION updates the level of the entry.
*/
@Test
public void testScanResultsAvailableAction_updates_getLevel() throws Exception {
// Starting without any scans available should make level WIFI_LEVEL_UNREACHABLE
final ScanResult scan = buildScanResult("ssid", "bssid", START_MILLIS, -50 /* rssi */);
final StandardWifiEntryKey key =
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_NONE);
final StandardNetworkDetailsTracker tracker =
createTestStandardNetworkDetailsTracker(key.toString());
tracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final WifiEntry wifiEntry = tracker.getWifiEntry();
assertThat(wifiEntry.getLevel()).isEqualTo(WIFI_LEVEL_UNREACHABLE);
// Received fresh scan. Level should not be WIFI_LEVEL_UNREACHABLE anymore
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(scan));
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, true));
assertThat(wifiEntry.getLevel()).isNotEqualTo(WIFI_LEVEL_UNREACHABLE);
// Scan returned with no scans, old scans timed out. Level should be WIFI_LEVEL_UNREACHABLE.
when(mMockWifiManager.getScanResults()).thenReturn(Collections.emptyList());
when(mMockClock.millis()).thenReturn(START_MILLIS + MAX_SCAN_AGE_MILLIS + 1);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, true));
assertThat(wifiEntry.getLevel()).isEqualTo(WIFI_LEVEL_UNREACHABLE);
}
/**
* Tests that CONFIGURED_NETWORKS_CHANGED_ACTION updates the isSaved() value of the entry.
*/
@Test
public void testConfiguredNetworksChangedAction_updates_isSaved() throws Exception {
// Initialize with no config. isSaved() should return false.
final StandardWifiEntryKey key =
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_NONE);
final StandardNetworkDetailsTracker tracker =
createTestStandardNetworkDetailsTracker(key.toString());
tracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final WifiEntry wifiEntry = tracker.getWifiEntry();
assertThat(wifiEntry.isSaved()).isFalse();
// Add a config and send a broadcast. isSaved() should return true.
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(wifiEntry.isSaved()).isTrue();
// Remove the config and send a broadcast. isSaved() should be false.
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.emptyList());
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION));
assertThat(wifiEntry.isSaved()).isFalse();
}
/**
* Tests that WIFI_STATE_DISABLED will clear the scan results of the chosen entry regardless if
* the scan results are still valid.
*/
@Test
public void testWifiStateChanged_disabled_clearsLevel() throws Exception {
// Start with scan result and wifi state enabled. Level should not be unreachable.
final ScanResult scan = buildScanResult("ssid", "bssid", START_MILLIS, -50 /* rssi */);
final StandardWifiEntryKey key =
ssidAndSecurityTypeToStandardWifiEntryKey("ssid", SECURITY_NONE);
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(scan));
final StandardNetworkDetailsTracker tracker =
createTestStandardNetworkDetailsTracker(key.toString());
tracker.onStart();
mTestLooper.dispatchAll();
verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
any(), any(), any());
final WifiEntry wifiEntry = tracker.getWifiEntry();
assertThat(wifiEntry.getLevel()).isNotEqualTo(WIFI_LEVEL_UNREACHABLE);
// Disable wifi. Level should be unreachable.
when(mMockWifiManager.getWifiState()).thenReturn(WifiManager.WIFI_STATE_DISABLED);
mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
assertThat(wifiEntry.getLevel()).isEqualTo(WIFI_LEVEL_UNREACHABLE);
}
@Test
public void testSecurityTargeting_pskScansWithSaeConfig_correspondsToNewNetworkTargeting() {
final String ssid = "ssid";
final WifiConfiguration config = buildWifiConfiguration(ssid);
config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
final ScanResult scan = buildScanResult(ssid, "bssid", START_MILLIS, -50 /* rssi */);
scan.capabilities = "[PSK]";
when(mMockWifiManager.getScanResults()).thenReturn(Collections.singletonList(scan));
// Start without targeting new networks
StandardNetworkDetailsTracker tracker = createTestStandardNetworkDetailsTracker(
ssidAndSecurityTypeToStandardWifiEntryKey(ssid, SECURITY_TYPE_PSK).toString());
tracker.onStart();
mTestLooper.dispatchAll();
// WifiEntry should correspond to the saved config
WifiEntry wifiEntry = tracker.getWifiEntry();
assertThat(wifiEntry.getSecurityTypes().get(0)).isEqualTo(WifiInfo.SECURITY_TYPE_SAE);
assertThat(wifiEntry.getLevel()).isEqualTo(WIFI_LEVEL_UNREACHABLE);
// Now target new networks as if we got the key from WifiPickerTracker
tracker = createTestStandardNetworkDetailsTracker(
ssidAndSecurityTypeToStandardWifiEntryKey(ssid, SECURITY_TYPE_PSK,
true /* isTargetingNewNetworks */).toString());
tracker.onStart();
mTestLooper.dispatchAll();
// WifiEntry should correspond to the unsaved scan
wifiEntry = tracker.getWifiEntry();
assertThat(wifiEntry.getSecurityTypes().get(0)).isEqualTo(SECURITY_TYPE_PSK);
assertThat(wifiEntry.getLevel()).isNotEqualTo(WIFI_LEVEL_UNREACHABLE);
}
/**
* Tests that we update the chosen entry's ScanResults correctly after a WifiScanner scan.
*/
@Test
public void testScanner_wifiScannerResultReceived_scanResultsUpdated() {
final String ssid = "ssid";
final WifiConfiguration config = buildWifiConfiguration(ssid);
when(mMockWifiManager.getPrivilegedConfiguredNetworks())
.thenReturn(Collections.singletonList(config));
StandardNetworkDetailsTracker tracker = createTestStandardNetworkDetailsTracker(
ssidAndSecurityTypeToStandardWifiEntryKey(ssid, SECURITY_NONE).toString());
tracker.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());
ScanResult[] scanResults = new ScanResult[]{
buildScanResult(ssid, "bssid", START_MILLIS, BAD_RSSI),
buildScanResult("different ssid", "bssid", START_MILLIS, GOOD_RSSI),
};
WifiScanner.ScanData scanData = mock(WifiScanner.ScanData.class);
when(scanData.getResults()).thenReturn(scanResults);
mScanListenerCaptor.getValue().onResults(new WifiScanner.ScanData[]{scanData});
mTestLooper.dispatchAll();
// Updated with the correct SSID and ignored the different SSID.
assertThat(tracker.getWifiEntry().getLevel()).isEqualTo(BAD_LEVEL);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,72 @@
/*
* 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 android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiSsid;
import java.nio.charset.StandardCharsets;
/**
* Utility methods for testing purposes.
*/
class TestUtils {
public static final int GOOD_RSSI = -50;
public static final int OKAY_RSSI = -60;
public static final int BAD_RSSI = -70;
public static final int GOOD_LEVEL = 5;
public static final int OKAY_LEVEL = 3;
public static final int BAD_LEVEL = 1;
/**
* Creates a mock scan result with SSID, BSSID, and timestamp.
*/
static ScanResult buildScanResult(String utf8Ssid, String bssid, long timestampMillis) {
final ScanResult result = new ScanResult();
result.SSID = utf8Ssid;
if (utf8Ssid != null) {
result.setWifiSsid(WifiSsid.fromBytes(utf8Ssid.getBytes(StandardCharsets.UTF_8)));
}
result.BSSID = bssid;
result.timestamp = timestampMillis * 1000;
result.capabilities = "";
return result;
}
static ScanResult buildScanResult(
String utf8Ssid, String bssid, long timestampMillis, int rssi) {
final ScanResult result = buildScanResult(utf8Ssid, bssid, timestampMillis);
result.level = rssi;
result.capabilities = "";
return result;
}
static ScanResult buildScanResult(
String utf8Ssid, String bssid, long timestampMillis, String securityTypesString) {
final ScanResult result = buildScanResult(utf8Ssid, bssid, timestampMillis);
result.capabilities = securityTypesString;
return result;
}
static WifiConfiguration buildWifiConfiguration(String utf8Ssid) {
final WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"" + utf8Ssid + "\"";
return config;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wifitrackerlib.shadow;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
/**
* A shadow object of {@link System}.
*/
@Implements(System.class)
public class ShadowSystem {
/**
* Implements {@link System#currentTimeMillis}.
*
* @return a fixed time milli throughout tests.
*/
@Implementation
public static long currentTimeMillis() {
// It's 2100/01/02 00:00:00.
return 4102531200000L;
}
}