• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wifitrackerlib;
18 
19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static org.mockito.ArgumentMatchers.any;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.spy;
27 import static org.mockito.Mockito.times;
28 import static org.mockito.Mockito.when;
29 
30 import android.content.Context;
31 import android.content.res.Resources;
32 import android.net.ConnectivityDiagnosticsManager;
33 import android.net.ConnectivityManager;
34 import android.net.Network;
35 import android.net.NetworkCapabilities;
36 import android.net.wifi.WifiConfiguration;
37 import android.net.wifi.WifiInfo;
38 import android.net.wifi.WifiManager;
39 import android.net.wifi.hotspot2.PasspointConfiguration;
40 import android.net.wifi.hotspot2.pps.Credential;
41 import android.net.wifi.hotspot2.pps.HomeSp;
42 import android.os.Handler;
43 import android.os.test.TestLooper;
44 
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.mockito.Mock;
48 import org.mockito.Mockito;
49 import org.mockito.MockitoAnnotations;
50 import org.mockito.MockitoSession;
51 
52 import java.util.Arrays;
53 
54 public class PasspointWifiEntryTest {
55     @Mock private WifiTrackerInjector mMockInjector;
56     @Mock private Context mMockContext;
57     @Mock private WifiManager mMockWifiManager;
58     @Mock private Resources mMockResources;
59     @Mock private WifiInfo mMockWifiInfo;
60     @Mock private Network mMockNetwork;
61     @Mock private NetworkCapabilities mMockNetworkCapabilities;
62     @Mock private ConnectivityManager mMockConnectivityManager;
63 
64     private TestLooper mTestLooper;
65     private Handler mTestHandler;
66 
67     private static final String FQDN = "fqdn";
68 
69     @Before
setUp()70     public void setUp() {
71         MockitoAnnotations.initMocks(this);
72 
73         mTestLooper = new TestLooper();
74         mTestHandler = new Handler(mTestLooper.getLooper());
75 
76         when(mMockWifiInfo.isPrimary()).thenReturn(true);
77         when(mMockWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
78         when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
79         when(mMockNetworkCapabilities.getTransportInfo()).thenReturn(mMockWifiInfo);
80         when(mMockInjector.getContext()).thenReturn(mMockContext);
81         when(mMockContext.getResources()).thenReturn(mMockResources);
82         when(mMockContext.getString(R.string.wifitrackerlib_summary_separator)).thenReturn("/");
83 
84         when(mMockContext.getSystemService(ConnectivityManager.class))
85                 .thenReturn(mMockConnectivityManager);
86     }
87 
88     @Test
testGetSummary_expiredTimeNotAvailable_notShowExpired()89     public void testGetSummary_expiredTimeNotAvailable_notShowExpired() {
90         // default SubscriptionExpirationTimeInMillis is unset
91         PasspointConfiguration passpointConfiguration = getPasspointConfiguration();
92         String expired = "Expired";
93         when(mMockContext.getString(R.string.wifitrackerlib_wifi_passpoint_expired))
94                 .thenReturn(expired);
95 
96         PasspointWifiEntry passpointWifiEntry = new PasspointWifiEntry(mMockInjector,
97                 mTestHandler, passpointConfiguration, mMockWifiManager,
98                 false /* forSavedNetworksPage */);
99 
100         assertThat(passpointWifiEntry.getSummary()).isNotEqualTo(expired);
101     }
102 
103     @Test
testGetSummary_expired_showExpired()104     public void testGetSummary_expired_showExpired() {
105         PasspointConfiguration passpointConfiguration = getPasspointConfiguration();
106         String expired = "Expired";
107         when(mMockContext.getString(R.string.wifitrackerlib_wifi_passpoint_expired))
108                 .thenReturn(expired);
109         PasspointWifiEntry passpointWifiEntry = new PasspointWifiEntry(mMockInjector,
110                 mTestHandler, passpointConfiguration, mMockWifiManager,
111                 false /* forSavedNetworksPage */);
112         PasspointWifiEntry spyEntry = spy(passpointWifiEntry);
113         when(spyEntry.isExpired()).thenReturn(true);
114 
115         assertThat(spyEntry.getSummary()).isEqualTo(expired);
116     }
117 
getPasspointConfiguration()118     private PasspointConfiguration getPasspointConfiguration() {
119         PasspointConfiguration passpointConfiguration = new PasspointConfiguration();
120         HomeSp homeSp = new HomeSp();
121         homeSp.setFqdn(FQDN);
122         passpointConfiguration.setHomeSp(homeSp);
123         passpointConfiguration.setCredential(new Credential());
124         return passpointConfiguration;
125     }
126 
127     @Test
testGetMeteredChoice_afterSetMeteredChoice_getCorrectValue()128     public void testGetMeteredChoice_afterSetMeteredChoice_getCorrectValue() {
129         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
130                 getPasspointConfiguration(), mMockWifiManager,
131                 false /* forSavedNetworksPage */);
132 
133         entry.setMeteredChoice(WifiEntry.METERED_CHOICE_UNMETERED);
134 
135         assertThat(entry.getMeteredChoice()).isEqualTo(WifiEntry.METERED_CHOICE_UNMETERED);
136     }
137 
138     @Test
testGetSummary_connectedWifiNetwork_showsConnected()139     public void testGetSummary_connectedWifiNetwork_showsConnected() {
140         String summarySeparator = " / ";
141         String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
142                 "Authenticating", "Obtaining IP address", "Connected"};
143 
144         when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
145                 .thenReturn(summarySeparator);
146         when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
147                 .thenReturn(wifiStatusArray);
148         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
149         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
150         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
151                 .thenReturn(true);
152 
153         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
154                 getPasspointConfiguration(), mMockWifiManager,
155                 false /* forSavedNetworksPage */);
156         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
157         entry.onDefaultNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
158 
159         assertThat(entry.getSummary()).isEqualTo("Connected");
160     }
161 
162     @Test
testGetSummary_connectedButNotDefault_doesNotShowConnected()163     public void testGetSummary_connectedButNotDefault_doesNotShowConnected() {
164         String summarySeparator = " / ";
165         String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
166                 "Authenticating", "Obtaining IP address", "Connected"};
167 
168         when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
169                 .thenReturn(summarySeparator);
170         when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
171                 .thenReturn(wifiStatusArray);
172         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
173         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
174         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
175                 .thenReturn(true);
176 
177         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
178                 getPasspointConfiguration(), mMockWifiManager,
179                 false /* forSavedNetworksPage */);
180         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
181 
182         assertThat(entry.getSummary()).isEqualTo("");
183     }
184 
185     @Test
testGetSecurityTypes_connectedWifiNetwork_showsCurrentSecurityType()186     public void testGetSecurityTypes_connectedWifiNetwork_showsCurrentSecurityType() {
187         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
188         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
189         when(mMockWifiInfo.getCurrentSecurityType())
190                 .thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
191 
192         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
193                 getPasspointConfiguration(), mMockWifiManager,
194                 false /* forSavedNetworksPage */);
195 
196         assertThat(entry.getSecurityTypes()).containsExactlyElementsIn(Arrays.asList(
197                 WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2,
198                 WifiInfo.SECURITY_TYPE_PASSPOINT_R3));
199 
200         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
201 
202         assertThat(entry.getSecurityTypes())
203                 .containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
204 
205         when(mMockWifiInfo.getCurrentSecurityType())
206                 .thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
207         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
208 
209         assertThat(entry.getSecurityTypes()).containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
210     }
211 
212     @Test
testGetSecurityString_showsPasspoint()213     public void testGetSecurityString_showsPasspoint() {
214         PasspointConfiguration passpointConfiguration = getPasspointConfiguration();
215         String passpointSecurity = "Passpoint";
216         when(mMockContext.getString(R.string.wifitrackerlib_wifi_security_passpoint))
217                 .thenReturn(passpointSecurity);
218 
219         PasspointWifiEntry passpointWifiEntry = new PasspointWifiEntry(mMockInjector,
220                 mTestHandler, passpointConfiguration, mMockWifiManager,
221                 false /* forSavedNetworksPage */);
222 
223         assertThat(passpointWifiEntry.getSecurityString(false)).isEqualTo(passpointSecurity);
224     }
225 
226     @Test
testShouldShowXLevelIcon_unvalidatedOrLowQuality_returnsTrue()227     public void testShouldShowXLevelIcon_unvalidatedOrLowQuality_returnsTrue() {
228         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
229         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
230 
231         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
232                 getPasspointConfiguration(), mMockWifiManager,
233                 false /* forSavedNetworksPage */);
234 
235         // Disconnected should return false;
236         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
237 
238         // Connected but validation attempt not complete, should not show X level icon yet.
239         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
240         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
241 
242         // Validation attempt complete, should show X level icon.
243         ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport = mock(
244                 ConnectivityDiagnosticsManager.ConnectivityReport.class);
245         when(connectivityReport.getNetwork()).thenReturn(mMockNetwork);
246         entry.updateConnectivityReport(connectivityReport);
247         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
248 
249         // Internet validated, should not show X level icon.
250         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
251                 .thenReturn(true);
252         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
253         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
254 
255         // Cell becomes default (i.e. low quality wifi), show X level icon.
256         entry.onDefaultNetworkCapabilitiesChanged(Mockito.mock(Network.class),
257                 new NetworkCapabilities.Builder()
258                         .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
259         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
260     }
261 
262     @Test
testGetMacAddress_wifiInfoAvailable_usesWifiInfoMacAddress()263     public void testGetMacAddress_wifiInfoAvailable_usesWifiInfoMacAddress() {
264         final String factoryMac = "01:23:45:67:89:ab";
265         final String wifiInfoMac = "11:23:45:67:89:ab";
266         final WifiConfiguration config = new WifiConfiguration();
267         config.SSID = "\"ssid\"";
268         config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
269         config.FQDN = FQDN;
270         when(mMockWifiManager.getFactoryMacAddresses()).thenReturn(new String[]{factoryMac});
271         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
272         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
273         when(mMockWifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
274         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
275                 getPasspointConfiguration(), mMockWifiManager,
276                 false /* forSavedNetworksPage */);
277 
278         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
279 
280         assertThat(entry.getMacAddress()).isEqualTo(wifiInfoMac);
281     }
282 
283     @Test
testIsAutoJoinEnabled_nullConfigs_returnsFalse()284     public void testIsAutoJoinEnabled_nullConfigs_returnsFalse() {
285         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
286                 getPasspointConfiguration(), mMockWifiManager,
287                 false /* forSavedNetworksPage */);
288 
289         entry.updatePasspointConfig(null);
290 
291         assertThat(entry.isAutoJoinEnabled()).isFalse();
292     }
293 
294     @Test
testCanSignIn_captivePortalCapability_returnsTrue()295     public void testCanSignIn_captivePortalCapability_returnsTrue() {
296         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
297                 getPasspointConfiguration(), mMockWifiManager,
298                 false /* forSavedNetworksPage */);
299 
300         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
301         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
302         when(mMockNetworkCapabilities.hasCapability(
303                 NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
304         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
305 
306         assertThat(entry.canSignIn()).isTrue();
307     }
308 
309     @Test
testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce()310     public void testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce() {
311         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
312                 getPasspointConfiguration(), mMockWifiManager,
313                 false /* forSavedNetworksPage */);
314 
315         MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
316         try {
317             // Simulate user tapping on the network and receiving captive portal capabilities.
318             // This should trigger the captive portal app.
319             entry.connect(null /* callback */);
320             when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
321             when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
322             when(mMockNetworkCapabilities.hasCapability(
323                     NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
324             entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
325 
326             verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
327 
328             // Update network capabilities again. This should not trigger the captive portal app.
329             entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
330 
331             verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
332         } finally {
333             session.finishMocking();
334         }
335 
336     }
337 
338     @Test
testDisconnect_noScansOrWifiConfig_disconnectIsSuccessful()339     public void testDisconnect_noScansOrWifiConfig_disconnectIsSuccessful() {
340         // Setup a connected PasspointWifiEntry
341         String summarySeparator = " / ";
342         String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
343                 "Authenticating", "Obtaining IP address", "Connected"};
344         when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
345                 .thenReturn(summarySeparator);
346         when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
347                 .thenReturn(wifiStatusArray);
348         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
349         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
350         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
351                 .thenReturn(true);
352         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
353                 getPasspointConfiguration(), mMockWifiManager,
354                 false /* forSavedNetworksPage */);
355         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
356 
357         // Disconnect the entry before it can be updated with scans and a WifiConfiguration
358         entry.disconnect(null);
359 
360         verify(mMockWifiManager).disableEphemeralNetwork(FQDN);
361         verify(mMockWifiManager).disconnect();
362     }
363 }
364