• 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(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
151                 getPasspointConfiguration().getUniqueId());
152         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
153                 .thenReturn(true);
154 
155         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
156                 getPasspointConfiguration(), mMockWifiManager,
157                 false /* forSavedNetworksPage */);
158         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
159         entry.onDefaultNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
160 
161         assertThat(entry.getSummary()).isEqualTo("Connected");
162     }
163 
164     @Test
testGetSummary_connectedButNotDefault_doesNotShowConnected()165     public void testGetSummary_connectedButNotDefault_doesNotShowConnected() {
166         String summarySeparator = " / ";
167         String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
168                 "Authenticating", "Obtaining IP address", "Connected"};
169 
170         when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
171                 .thenReturn(summarySeparator);
172         when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
173                 .thenReturn(wifiStatusArray);
174         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
175         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
176         when(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
177                 getPasspointConfiguration().getUniqueId());
178         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
179                 .thenReturn(true);
180 
181         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
182                 getPasspointConfiguration(), mMockWifiManager,
183                 false /* forSavedNetworksPage */);
184         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
185 
186         assertThat(entry.getSummary()).isEqualTo("");
187     }
188 
189     @Test
testGetSecurityTypes_connectedWifiNetwork_showsCurrentSecurityType()190     public void testGetSecurityTypes_connectedWifiNetwork_showsCurrentSecurityType() {
191         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
192         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
193         when(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
194                 getPasspointConfiguration().getUniqueId());
195         when(mMockWifiInfo.getCurrentSecurityType())
196                 .thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
197 
198         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
199                 getPasspointConfiguration(), mMockWifiManager,
200                 false /* forSavedNetworksPage */);
201 
202         assertThat(entry.getSecurityTypes()).containsExactlyElementsIn(Arrays.asList(
203                 WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2,
204                 WifiInfo.SECURITY_TYPE_PASSPOINT_R3));
205 
206         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
207 
208         assertThat(entry.getSecurityTypes())
209                 .containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R1_R2);
210 
211         when(mMockWifiInfo.getCurrentSecurityType())
212                 .thenReturn(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
213         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
214 
215         assertThat(entry.getSecurityTypes()).containsExactly(WifiInfo.SECURITY_TYPE_PASSPOINT_R3);
216     }
217 
218     @Test
testGetSecurityString_showsPasspoint()219     public void testGetSecurityString_showsPasspoint() {
220         PasspointConfiguration passpointConfiguration = getPasspointConfiguration();
221         String passpointSecurity = "Passpoint";
222         when(mMockContext.getString(R.string.wifitrackerlib_wifi_security_passpoint))
223                 .thenReturn(passpointSecurity);
224 
225         PasspointWifiEntry passpointWifiEntry = new PasspointWifiEntry(mMockInjector,
226                 mTestHandler, passpointConfiguration, mMockWifiManager,
227                 false /* forSavedNetworksPage */);
228 
229         assertThat(passpointWifiEntry.getSecurityString(false)).isEqualTo(passpointSecurity);
230     }
231 
232     @Test
testShouldShowXLevelIcon_unvalidatedOrLowQuality_returnsTrue()233     public void testShouldShowXLevelIcon_unvalidatedOrLowQuality_returnsTrue() {
234         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
235         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
236         when(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
237                 getPasspointConfiguration().getUniqueId());
238 
239         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
240                 getPasspointConfiguration(), mMockWifiManager,
241                 false /* forSavedNetworksPage */);
242 
243         // Disconnected should return false;
244         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
245 
246         // Connected but validation attempt not complete, should not show X level icon yet.
247         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
248         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
249 
250         // Validation attempt complete, should show X level icon.
251         ConnectivityDiagnosticsManager.ConnectivityReport connectivityReport = mock(
252                 ConnectivityDiagnosticsManager.ConnectivityReport.class);
253         when(connectivityReport.getNetwork()).thenReturn(mMockNetwork);
254         entry.updateConnectivityReport(connectivityReport);
255         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
256 
257         // Internet validated, should not show X level icon.
258         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
259                 .thenReturn(true);
260         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
261         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
262 
263         // Cell becomes default (i.e. low quality wifi), show X level icon.
264         entry.onDefaultNetworkCapabilitiesChanged(Mockito.mock(Network.class),
265                 new NetworkCapabilities.Builder()
266                         .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
267         assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
268     }
269 
270     @Test
testGetMacAddress_wifiInfoAvailable_usesWifiInfoMacAddress()271     public void testGetMacAddress_wifiInfoAvailable_usesWifiInfoMacAddress() {
272         final String factoryMac = "01:23:45:67:89:ab";
273         final String wifiInfoMac = "11:23:45:67:89:ab";
274         when(mMockWifiManager.getFactoryMacAddresses()).thenReturn(new String[]{factoryMac});
275         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
276         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
277         when(mMockWifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
278         when(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
279                 getPasspointConfiguration().getUniqueId());
280         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
281                 getPasspointConfiguration(), mMockWifiManager,
282                 false /* forSavedNetworksPage */);
283 
284         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
285 
286         assertThat(entry.getMacAddress()).isEqualTo(wifiInfoMac);
287     }
288 
289     @Test
testIsAutoJoinEnabled_nullConfigs_returnsFalse()290     public void testIsAutoJoinEnabled_nullConfigs_returnsFalse() {
291         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
292                 getPasspointConfiguration(), mMockWifiManager,
293                 false /* forSavedNetworksPage */);
294 
295         entry.updatePasspointConfig(null);
296 
297         assertThat(entry.isAutoJoinEnabled()).isFalse();
298     }
299 
300     @Test
testCanSignIn_captivePortalCapability_returnsTrue()301     public void testCanSignIn_captivePortalCapability_returnsTrue() {
302         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
303                 getPasspointConfiguration(), mMockWifiManager,
304                 false /* forSavedNetworksPage */);
305 
306         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
307         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
308         when(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
309                 getPasspointConfiguration().getUniqueId());
310         when(mMockNetworkCapabilities.hasCapability(
311                 NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
312         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
313 
314         assertThat(entry.canSignIn()).isTrue();
315     }
316 
317     @Test
testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce()318     public void testUpdateNetworkCapabilities_userConnect_autoOpenCaptivePortalOnce() {
319         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
320                 getPasspointConfiguration(), mMockWifiManager,
321                 false /* forSavedNetworksPage */);
322 
323         MockitoSession session = mockitoSession().spyStatic(NonSdkApiWrapper.class).startMocking();
324         try {
325             // Simulate user tapping on the network and receiving captive portal capabilities.
326             // This should trigger the captive portal app.
327             entry.connect(null /* callback */);
328             when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
329             when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
330             when(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
331                     getPasspointConfiguration().getUniqueId());
332             when(mMockNetworkCapabilities.hasCapability(
333                     NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL)).thenReturn(true);
334             entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
335 
336             verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
337 
338             // Update network capabilities again. This should not trigger the captive portal app.
339             entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
340 
341             verify(() -> NonSdkApiWrapper.startCaptivePortalApp(any(), any()), times(1));
342         } finally {
343             session.finishMocking();
344         }
345 
346     }
347 
348     @Test
testDisconnect_noScansOrWifiConfig_disconnectIsSuccessful()349     public void testDisconnect_noScansOrWifiConfig_disconnectIsSuccessful() {
350         // Setup a connected PasspointWifiEntry
351         String summarySeparator = " / ";
352         String[] wifiStatusArray = new String[]{"", "Scanning", "Connecting",
353                 "Authenticating", "Obtaining IP address", "Connected"};
354         when(mMockContext.getString(R.string.wifitrackerlib_summary_separator))
355                 .thenReturn(summarySeparator);
356         when(mMockResources.getStringArray(R.array.wifitrackerlib_wifi_status))
357                 .thenReturn(wifiStatusArray);
358         when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
359         when(mMockWifiInfo.getPasspointFqdn()).thenReturn(FQDN);
360         when(mMockWifiInfo.getPasspointUniqueId()).thenReturn(
361                 getPasspointConfiguration().getUniqueId());
362         when(mMockNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
363                 .thenReturn(true);
364         PasspointWifiEntry entry = new PasspointWifiEntry(mMockInjector, mTestHandler,
365                 getPasspointConfiguration(), mMockWifiManager,
366                 false /* forSavedNetworksPage */);
367         entry.onNetworkCapabilitiesChanged(mMockNetwork, mMockNetworkCapabilities);
368 
369         // Disconnect the entry before it can be updated with scans and a WifiConfiguration
370         entry.disconnect(null);
371 
372         verify(mMockWifiManager).disableEphemeralNetwork(FQDN);
373         verify(mMockWifiManager).disconnect();
374     }
375 }
376