• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.server.wifi;
18 
19 import static org.hamcrest.CoreMatchers.not;
20 import static org.junit.Assert.*;
21 import static org.mockito.Mockito.*;
22 
23 import android.content.Context;
24 import android.content.pm.UserInfo;
25 import android.net.wifi.FakeKeys;
26 import android.net.wifi.WifiConfiguration;
27 import android.net.wifi.WifiConfiguration.AuthAlgorithm;
28 import android.net.wifi.WifiConfiguration.GroupCipher;
29 import android.net.wifi.WifiConfiguration.KeyMgmt;
30 import android.net.wifi.WifiConfiguration.PairwiseCipher;
31 import android.net.wifi.WifiConfiguration.Protocol;
32 import android.net.wifi.WifiEnterpriseConfig;
33 import android.net.wifi.WifiEnterpriseConfig.Eap;
34 import android.net.wifi.WifiEnterpriseConfig.Phase2;
35 import android.net.wifi.WifiScanner;
36 import android.os.Process;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.security.Credentials;
40 import android.security.KeyStore;
41 import android.support.test.InstrumentationRegistry;
42 import android.test.suitebuilder.annotation.SmallTest;
43 import android.text.TextUtils;
44 import android.util.Log;
45 import android.util.SparseArray;
46 
47 import com.android.server.net.DelayedDiskWrite;
48 import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
49 import com.android.server.wifi.hotspot2.omadm.PasspointManagementObjectManager;
50 import com.android.server.wifi.hotspot2.pps.Credential;
51 import com.android.server.wifi.hotspot2.pps.HomeSP;
52 
53 import org.junit.Before;
54 import org.junit.Test;
55 import org.mockito.Mock;
56 import org.mockito.MockitoAnnotations;
57 
58 import java.io.ByteArrayInputStream;
59 import java.io.ByteArrayOutputStream;
60 import java.io.DataInputStream;
61 import java.io.DataOutputStream;
62 import java.io.EOFException;
63 import java.io.File;
64 import java.io.FileOutputStream;
65 import java.io.IOException;
66 import java.lang.reflect.Field;
67 import java.math.BigInteger;
68 import java.security.cert.CertificateEncodingException;
69 import java.security.cert.X509Certificate;
70 import java.util.ArrayDeque;
71 import java.util.ArrayList;
72 import java.util.Arrays;
73 import java.util.BitSet;
74 import java.util.Collection;
75 import java.util.Collections;
76 import java.util.HashMap;
77 import java.util.HashSet;
78 import java.util.List;
79 import java.util.Map;
80 import java.util.Random;
81 import java.util.Set;
82 import java.util.TreeMap;
83 
84 /**
85  * Unit tests for {@link com.android.server.wifi.WifiConfigManager}.
86  */
87 @SmallTest
88 public class WifiConfigManagerTest {
89     private static final List<WifiConfiguration> CONFIGS = Arrays.asList(
90             WifiConfigurationTestUtil.generateWifiConfig(
91                     0, 1000000, "\"red\"", true, true, null, null),
92             WifiConfigurationTestUtil.generateWifiConfig(
93                     1, 1000001, "\"green\"", true, true, "example.com", "Green"),
94             WifiConfigurationTestUtil.generateWifiConfig(
95                     2, 1100000, "\"blue\"", false, true, "example.org", "Blue"),
96             WifiConfigurationTestUtil.generateWifiConfig(
97                     3, 1200000, "\"cyan\"", false, true, null, null));
98 
99     private static final int[] USER_IDS = {0, 10, 11};
100     private static final int MANAGED_PROFILE_USER_ID = 12;
101     private static final int MANAGED_PROFILE_PARENT_USER_ID = 0;
102     private static final SparseArray<List<UserInfo>> USER_PROFILES = new SparseArray<>();
103     static {
104         USER_PROFILES.put(0, Arrays.asList(new UserInfo(0, "Owner", 0),
105                 new UserInfo(12, "Managed Profile", 0)));
106         USER_PROFILES.put(10, Arrays.asList(new UserInfo(10, "Alice", 0)));
107         USER_PROFILES.put(11, Arrays.asList(new UserInfo(11, "Bob", 0)));
108     }
109 
110     private static final Map<Integer, List<WifiConfiguration>> VISIBLE_CONFIGS = new HashMap<>();
111     static {
112         for (int userId : USER_IDS) {
113             List<WifiConfiguration> configs = new ArrayList<>();
114             for (int i = 0; i < CONFIGS.size(); ++i) {
115                 if (WifiConfigurationUtil.isVisibleToAnyProfile(CONFIGS.get(i),
116                         USER_PROFILES.get(userId))) {
CONFIGS.get(i)117                     configs.add(CONFIGS.get(i));
118                 }
119             }
VISIBLE_CONFIGS.put(userId, configs)120             VISIBLE_CONFIGS.put(userId, configs);
121         }
122     }
123 
124     /**
125      * Set of WifiConfigs for HasEverConnected tests.
126      */
127     private static final int HAS_EVER_CONNECTED_USER = 20;
128     private static final WifiConfiguration BASE_HAS_EVER_CONNECTED_CONFIG =
129             WifiConfigurationTestUtil.generateWifiConfig(
130                     0, HAS_EVER_CONNECTED_USER, "testHasEverConnected", false, true, null, null, 0);
131 
132     public static final String TAG = "WifiConfigManagerTest";
133     @Mock private Context mContext;
134     @Mock private WifiNative mWifiNative;
135     @Mock private FrameworkFacade mFrameworkFacade;
136     @Mock private UserManager mUserManager;
137     @Mock private DelayedDiskWrite mWriter;
138     @Mock private PasspointManagementObjectManager mMOManager;
139     @Mock private Clock mClock;
140     private WifiConfigManager mWifiConfigManager;
141     private ConfigurationMap mConfiguredNetworks;
142     public byte[] mNetworkHistoryBytes;
143     private MockKeyStore mMockKeyStore;
144     private KeyStore mKeyStore;
145 
146     /**
147      * Called before each test
148      */
149     @Before
setUp()150     public void setUp() throws Exception {
151         MockitoAnnotations.initMocks(this);
152 
153         final Context realContext = InstrumentationRegistry.getContext();
154         when(mContext.getPackageName()).thenReturn(realContext.getPackageName());
155         when(mContext.getResources()).thenReturn(realContext.getResources());
156         when(mContext.getPackageManager()).thenReturn(realContext.getPackageManager());
157 
158         when(mUserManager.getProfiles(UserHandle.USER_SYSTEM))
159                 .thenReturn(USER_PROFILES.get(UserHandle.USER_SYSTEM));
160 
161         for (int userId : USER_IDS) {
162             when(mUserManager.getProfiles(userId)).thenReturn(USER_PROFILES.get(userId));
163         }
164 
165         mMockKeyStore = new MockKeyStore();
166 
167         mWifiConfigManager = new WifiConfigManager(mContext, mWifiNative, mFrameworkFacade, mClock,
168                 mUserManager, mMockKeyStore.createMock());
169 
170         final Field configuredNetworksField =
171                 WifiConfigManager.class.getDeclaredField("mConfiguredNetworks");
172         configuredNetworksField.setAccessible(true);
173         mConfiguredNetworks = (ConfigurationMap) configuredNetworksField.get(mWifiConfigManager);
174 
175         // Intercept writes to networkHistory.txt.
176         doAnswer(new AnswerWithArguments() {
177             public void answer(String filePath, DelayedDiskWrite.Writer writer) throws Exception {
178                 final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
179                 final DataOutputStream stream = new DataOutputStream(buffer);
180                 writer.onWriteCalled(stream);
181                 stream.close();
182                 mNetworkHistoryBytes = buffer.toByteArray();
183             }}).when(mWriter).write(anyString(), (DelayedDiskWrite.Writer) anyObject());
184         final Field writerField = WifiConfigManager.class.getDeclaredField("mWriter");
185         writerField.setAccessible(true);
186         writerField.set(mWifiConfigManager, mWriter);
187         final Field networkHistoryField =
188                 WifiConfigManager.class.getDeclaredField("mWifiNetworkHistory");
189         networkHistoryField.setAccessible(true);
190         WifiNetworkHistory wifiNetworkHistory =
191                 (WifiNetworkHistory) networkHistoryField.get(mWifiConfigManager);
192         final Field networkHistoryWriterField =
193                 WifiNetworkHistory.class.getDeclaredField("mWriter");
194         networkHistoryWriterField.setAccessible(true);
195         networkHistoryWriterField.set(wifiNetworkHistory, mWriter);
196 
197         when(mMOManager.isEnabled()).thenReturn(true);
198         final Field moManagerField = WifiConfigManager.class.getDeclaredField("mMOManager");
199         moManagerField.setAccessible(true);
200         moManagerField.set(mWifiConfigManager, mMOManager);
201     }
202 
switchUser(int newUserId)203     private void switchUser(int newUserId) {
204         when(mUserManager.getProfiles(newUserId))
205                 .thenReturn(USER_PROFILES.get(newUserId));
206         mWifiConfigManager.handleUserSwitch(newUserId);
207     }
208 
switchUserToCreatorOrParentOf(WifiConfiguration config)209     private void switchUserToCreatorOrParentOf(WifiConfiguration config) {
210         final int creatorUserId = UserHandle.getUserId(config.creatorUid);
211         if (creatorUserId == MANAGED_PROFILE_USER_ID) {
212             switchUser(MANAGED_PROFILE_PARENT_USER_ID);
213         } else {
214             switchUser(creatorUserId);
215         }
216     }
217 
addNetworks()218     private void addNetworks() throws Exception {
219         for (int i = 0; i < CONFIGS.size(); ++i) {
220             assertEquals(i, CONFIGS.get(i).networkId);
221             addNetwork(CONFIGS.get(i));
222         }
223     }
224 
addNetwork(WifiConfiguration config)225     private void addNetwork(WifiConfiguration config) throws Exception {
226         final int originalUserId = mWifiConfigManager.getCurrentUserId();
227 
228         when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenReturn(true);
229         when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject()))
230                 .thenReturn(true);
231 
232         switchUserToCreatorOrParentOf(config);
233         final WifiConfiguration configCopy = new WifiConfiguration(config);
234         int networkId = config.networkId;
235         config.networkId = -1;
236         when(mWifiNative.addNetwork()).thenReturn(networkId);
237         when(mWifiNative.getNetworkVariable(networkId, WifiConfiguration.ssidVarName))
238                 .thenReturn(encodeConfigSSID(config));
239         mWifiConfigManager.saveNetwork(config, configCopy.creatorUid);
240 
241         switchUser(originalUserId);
242     }
243 
encodeConfigSSID(WifiConfiguration config)244     private String encodeConfigSSID(WifiConfiguration config) throws Exception {
245         return new BigInteger(1, config.SSID.substring(1, config.SSID.length() - 1)
246                 .getBytes("UTF-8")).toString(16);
247     }
248 
249     /**
250      * Verifies that getConfiguredNetworksSize() returns the number of network configurations
251      * visible to the current user.
252      */
253     @Test
testGetConfiguredNetworksSize()254     public void testGetConfiguredNetworksSize() throws Exception {
255         addNetworks();
256         for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) {
257             switchUser(entry.getKey());
258             assertEquals(entry.getValue().size(), mWifiConfigManager.getConfiguredNetworksSize());
259         }
260     }
261 
verifyNetworkConfig(WifiConfiguration expectedConfig, WifiConfiguration actualConfig)262     private void verifyNetworkConfig(WifiConfiguration expectedConfig,
263             WifiConfiguration actualConfig) {
264         assertNotNull(actualConfig);
265         assertEquals(expectedConfig.SSID, actualConfig.SSID);
266         assertEquals(expectedConfig.FQDN, actualConfig.FQDN);
267         assertEquals(expectedConfig.providerFriendlyName,
268                 actualConfig.providerFriendlyName);
269         assertEquals(expectedConfig.configKey(), actualConfig.configKey(false));
270     }
271 
verifyNetworkConfigs(Collection<WifiConfiguration> expectedConfigs, Collection<WifiConfiguration> actualConfigs)272     private void verifyNetworkConfigs(Collection<WifiConfiguration> expectedConfigs,
273             Collection<WifiConfiguration> actualConfigs) {
274         assertEquals(expectedConfigs.size(), actualConfigs.size());
275         for (WifiConfiguration expectedConfig : expectedConfigs) {
276             WifiConfiguration actualConfig = null;
277             // Find the network configuration to test (assume that |actualConfigs| contains them in
278             // undefined order).
279             for (final WifiConfiguration candidate : actualConfigs) {
280                 if (candidate.networkId == expectedConfig.networkId) {
281                     actualConfig = candidate;
282                     break;
283                 }
284             }
285             verifyNetworkConfig(expectedConfig, actualConfig);
286         }
287     }
288 
289     /**
290      * Verifies that getConfiguredNetworksSize() returns the network configurations visible to the
291      * current user.
292      */
293     @Test
testGetConfiguredNetworks()294     public void testGetConfiguredNetworks() throws Exception {
295         addNetworks();
296         for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) {
297             switchUser(entry.getKey());
298             verifyNetworkConfigs(entry.getValue(), mWifiConfigManager.getSavedNetworks());
299         }
300     }
301 
302     /**
303      * Verifies that getPrivilegedConfiguredNetworks() returns the network configurations visible to
304      * the current user.
305      */
306     @Test
testGetPrivilegedConfiguredNetworks()307     public void testGetPrivilegedConfiguredNetworks() throws Exception {
308         addNetworks();
309         for (Map.Entry<Integer, List<WifiConfiguration>> entry : VISIBLE_CONFIGS.entrySet()) {
310             switchUser(entry.getKey());
311             verifyNetworkConfigs(entry.getValue(),
312                     mWifiConfigManager.getPrivilegedSavedNetworks());
313         }
314     }
315 
316     /**
317      * Verifies that getWifiConfiguration(int netId) can be used to access network configurations
318      * visible to the current user only.
319      */
320     @Test
testGetWifiConfigurationByNetworkId()321     public void testGetWifiConfigurationByNetworkId() throws Exception {
322         addNetworks();
323         for (int userId : USER_IDS) {
324             switchUser(userId);
325             for (WifiConfiguration expectedConfig: CONFIGS) {
326                 final WifiConfiguration actualConfig =
327                         mWifiConfigManager.getWifiConfiguration(expectedConfig.networkId);
328                 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig,
329                         USER_PROFILES.get(userId))) {
330                     verifyNetworkConfig(expectedConfig, actualConfig);
331                 } else {
332                     assertNull(actualConfig);
333                 }
334             }
335         }
336     }
337 
338     /**
339      * Verifies that getWifiConfiguration(String key) can be used to access network configurations
340      * visible to the current user only.
341      */
342     @Test
testGetWifiConfigurationByConfigKey()343     public void testGetWifiConfigurationByConfigKey() throws Exception {
344         addNetworks();
345         for (int userId : USER_IDS) {
346             switchUser(userId);
347             for (WifiConfiguration expectedConfig: CONFIGS) {
348                 final WifiConfiguration actualConfig =
349                         mWifiConfigManager.getWifiConfiguration(expectedConfig.configKey());
350                 if (WifiConfigurationUtil.isVisibleToAnyProfile(expectedConfig,
351                         USER_PROFILES.get(userId))) {
352                     verifyNetworkConfig(expectedConfig, actualConfig);
353                 } else {
354                     assertNull(actualConfig);
355                 }
356             }
357         }
358     }
359 
360     /**
361      * Verifies that enableAllNetworks() enables all temporarily disabled network configurations
362      * visible to the current user.
363      */
364     @Test
testEnableAllNetworks()365     public void testEnableAllNetworks() throws Exception {
366         addNetworks();
367         for (int userId : USER_IDS) {
368             switchUser(userId);
369 
370             for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
371                 final WifiConfiguration.NetworkSelectionStatus status =
372                         config.getNetworkSelectionStatus();
373                 status.setNetworkSelectionStatus(WifiConfiguration.NetworkSelectionStatus
374                         .NETWORK_SELECTION_TEMPORARY_DISABLED);
375                 status.setNetworkSelectionDisableReason(
376                         WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE);
377                 status.setDisableTime(System.currentTimeMillis() - 60 * 60 * 1000);
378             }
379 
380             mWifiConfigManager.enableAllNetworks();
381 
382             for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
383                 assertEquals(WifiConfigurationUtil.isVisibleToAnyProfile(config,
384                         USER_PROFILES.get(userId)),
385                         config.getNetworkSelectionStatus().isNetworkEnabled());
386             }
387         }
388     }
389 
390     /**
391      * Verifies that selectNetwork() disables all network configurations visible to the current user
392      * except the selected one.
393      */
394     @Test
testSelectNetwork()395     public void testSelectNetwork() throws Exception {
396         addNetworks();
397 
398         for (int userId : USER_IDS) {
399             switchUser(userId);
400 
401             for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
402                 // Enable all network configurations.
403                 for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) {
404                     config2.status = WifiConfiguration.Status.ENABLED;
405                 }
406 
407                 // Try to select a network configuration.
408                 reset(mWifiNative);
409                 when(mWifiNative.selectNetwork(config.networkId)).thenReturn(true);
410                 final boolean success =
411                         mWifiConfigManager.selectNetwork(config, false, config.creatorUid);
412                 if (!WifiConfigurationUtil.isVisibleToAnyProfile(config,
413                         USER_PROFILES.get(userId))) {
414                     // If the network configuration is not visible to the current user, verify that
415                     // nothing changed.
416                     assertFalse(success);
417                     verify(mWifiNative, never()).selectNetwork(anyInt());
418                     verify(mWifiNative, never()).enableNetwork(anyInt());
419                     for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) {
420                         assertEquals(WifiConfiguration.Status.ENABLED, config2.status);
421                     }
422                 } else {
423                     // If the network configuration is visible to the current user, verify that it
424                     // was enabled and all other network configurations visible to the user were
425                     // disabled.
426                     assertTrue(success);
427                     verify(mWifiNative).selectNetwork(config.networkId);
428                     verify(mWifiNative, never()).selectNetwork(intThat(not(config.networkId)));
429                     verify(mWifiNative, never()).enableNetwork(config.networkId);
430                     verify(mWifiNative, never()).enableNetwork(intThat(not(config.networkId)));
431                     for (WifiConfiguration config2 : mConfiguredNetworks.valuesForAllUsers()) {
432                         if (WifiConfigurationUtil.isVisibleToAnyProfile(config2,
433                                 USER_PROFILES.get(userId))
434                                 && config2.networkId != config.networkId) {
435                             assertEquals(WifiConfiguration.Status.DISABLED, config2.status);
436                         } else {
437                             assertEquals(WifiConfiguration.Status.ENABLED, config2.status);
438                         }
439                     }
440                 }
441             }
442         }
443     }
444 
445     /**
446      * Verifies that saveNetwork() correctly stores a network configuration in wpa_supplicant
447      * variables and the networkHistory.txt file.
448      * TODO: Test all variables. Currently, only the following variables are tested:
449      * - In the wpa_supplicant: "ssid", "id_str"
450      * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED"
451      */
verifySaveNetwork(int network)452     private void verifySaveNetwork(int network) throws Exception {
453         // Switch to the correct user.
454         switchUserToCreatorOrParentOf(CONFIGS.get(network));
455 
456         // Set up wpa_supplicant.
457         when(mWifiNative.addNetwork()).thenReturn(0);
458         when(mWifiNative.setNetworkVariable(eq(network), anyString(), anyString()))
459                 .thenReturn(true);
460         when(mWifiNative.setNetworkExtra(eq(network), anyString(),
461                 (Map<String, String>) anyObject())).thenReturn(true);
462         when(mWifiNative.getNetworkVariable(network, WifiConfiguration.ssidVarName))
463                 .thenReturn(encodeConfigSSID(CONFIGS.get(network)));
464         when(mWifiNative.getNetworkVariable(network, WifiConfiguration.pmfVarName))
465                 .thenReturn("");
466 
467         // Store a network configuration.
468         mWifiConfigManager.saveNetwork(CONFIGS.get(network), CONFIGS.get(network).creatorUid);
469 
470         // Verify that wpa_supplicant variables were written correctly for the network
471         // configuration.
472         final Map<String, String> metadata = new HashMap<String, String>();
473         if (CONFIGS.get(network).FQDN != null) {
474             metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(network).FQDN);
475         }
476         metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(network).configKey());
477         metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID,
478                 Integer.toString(CONFIGS.get(network).creatorUid));
479         verify(mWifiNative).setNetworkExtra(network, WifiConfigStore.ID_STRING_VAR_NAME,
480                 metadata);
481 
482         // Verify that an attempt to read back the requirePMF variable was made.
483         verify(mWifiNative).getNetworkVariable(network, WifiConfiguration.pmfVarName);
484 
485         // Verify that no wpa_supplicant variables were read or written for any other network
486         // configurations.
487         verify(mWifiNative, never()).setNetworkExtra(intThat(not(network)), anyString(),
488                 (Map<String, String>) anyObject());
489         verify(mWifiNative, never()).setNetworkVariable(intThat(not(network)), anyString(),
490                 anyString());
491         verify(mWifiNative, never()).getNetworkVariable(intThat(not(network)), anyString());
492 
493         // Parse networkHistory.txt.
494         assertNotNull(mNetworkHistoryBytes);
495         final DataInputStream stream =
496                 new DataInputStream(new ByteArrayInputStream(mNetworkHistoryBytes));
497         List<String> keys = new ArrayList<>();
498         List<String> values = new ArrayList<>();
499         try {
500             while (true) {
501                 final String[] tokens = stream.readUTF().split(":", 2);
502                 if (tokens.length == 2) {
503                     keys.add(tokens[0].trim());
504                     values.add(tokens[1].trim());
505                 }
506             }
507         } catch (EOFException e) {
508             // Ignore. This is expected.
509         }
510 
511         // Verify that a networkHistory.txt entry was written correctly for the network
512         // configuration.
513         assertTrue(keys.size() >= 3);
514         assertEquals(WifiNetworkHistory.CONFIG_KEY, keys.get(0));
515         assertEquals(CONFIGS.get(network).configKey(), values.get(0));
516         final int creatorUidIndex = keys.indexOf(WifiNetworkHistory.CREATOR_UID_KEY);
517         assertTrue(creatorUidIndex != -1);
518         assertEquals(Integer.toString(CONFIGS.get(network).creatorUid),
519                 values.get(creatorUidIndex));
520         final int sharedIndex = keys.indexOf(WifiNetworkHistory.SHARED_KEY);
521         assertTrue(sharedIndex != -1);
522         assertEquals(Boolean.toString(CONFIGS.get(network).shared), values.get(sharedIndex));
523 
524         // Verify that no networkHistory.txt entries were written for any other network
525         // configurations.
526         final int lastConfigIndex = keys.lastIndexOf(WifiNetworkHistory.CONFIG_KEY);
527         assertEquals(0, lastConfigIndex);
528     }
529 
530     /**
531      * Verifies that saveNetwork() correctly stores a regular network configuration.
532      */
533     @Test
testSaveNetworkRegular()534     public void testSaveNetworkRegular() throws Exception {
535         verifySaveNetwork(0);
536     }
537 
538     /**
539      * Verifies that saveNetwork() correctly stores a HotSpot 2.0 network configuration.
540      */
541     @Test
testSaveNetworkHotspot20()542     public void testSaveNetworkHotspot20() throws Exception {
543         verifySaveNetwork(1);
544     }
545 
546     /**
547      * Verifies that saveNetwork() correctly stores a private network configuration.
548      */
549     @Test
testSaveNetworkPrivate()550     public void testSaveNetworkPrivate() throws Exception {
551         verifySaveNetwork(2);
552     }
553 
554     /**
555      * Verifies that loadConfiguredNetworks() correctly reads data from the wpa_supplicant, the
556      * networkHistory.txt file and the MOManager, correlating the three sources based on the
557      * configKey and the FQDN for HotSpot 2.0 networks.
558      * TODO: Test all variables. Currently, only the following variables are tested:
559      * - In the wpa_supplicant: "ssid", "id_str"
560      * - In networkHistory.txt: "CONFIG", "CREATOR_UID_KEY", "SHARED"
561      */
562     @Test
testLoadConfiguredNetworks()563     public void testLoadConfiguredNetworks() throws Exception {
564         // Set up list of network configurations returned by wpa_supplicant.
565         final String header = "network id / ssid / bssid / flags";
566         String networks = header;
567         for (WifiConfiguration config : CONFIGS) {
568             networks += "\n" + Integer.toString(config.networkId) + "\t" + config.SSID + "\tany";
569         }
570         when(mWifiNative.listNetworks(anyInt())).thenReturn(header);
571         when(mWifiNative.listNetworks(-1)).thenReturn(networks);
572 
573         // Set up variables returned by wpa_supplicant for the individual network configurations.
574         for (int i = 0; i < CONFIGS.size(); ++i) {
575             when(mWifiNative.getNetworkVariable(i, WifiConfiguration.ssidVarName))
576                 .thenReturn(encodeConfigSSID(CONFIGS.get(i)));
577         }
578         // Legacy regular network configuration: No "id_str".
579         when(mWifiNative.getNetworkExtra(0, WifiConfigStore.ID_STRING_VAR_NAME))
580             .thenReturn(null);
581         // Legacy Hotspot 2.0 network configuration: Quoted FQDN in "id_str".
582         when(mWifiNative.getNetworkExtra(1, WifiConfigStore.ID_STRING_VAR_NAME))
583             .thenReturn(null);
584         when(mWifiNative.getNetworkVariable(1, WifiConfigStore.ID_STRING_VAR_NAME))
585             .thenReturn('"' + CONFIGS.get(1).FQDN + '"');
586         // Up-to-date Hotspot 2.0 network configuration: Metadata in "id_str".
587         Map<String, String> metadata = new HashMap<String, String>();
588         metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(2).configKey());
589         metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID,
590                 Integer.toString(CONFIGS.get(2).creatorUid));
591         metadata.put(WifiConfigStore.ID_STRING_KEY_FQDN, CONFIGS.get(2).FQDN);
592         when(mWifiNative.getNetworkExtra(2, WifiConfigStore.ID_STRING_VAR_NAME))
593             .thenReturn(metadata);
594         // Up-to-date regular network configuration: Metadata in "id_str".
595         metadata = new HashMap<String, String>();
596         metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, CONFIGS.get(3).configKey());
597         metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID,
598                 Integer.toString(CONFIGS.get(3).creatorUid));
599         when(mWifiNative.getNetworkExtra(3, WifiConfigStore.ID_STRING_VAR_NAME))
600             .thenReturn(metadata);
601 
602         // Set up networkHistory.txt file.
603         final File file = File.createTempFile("networkHistory.txt", null);
604         file.deleteOnExit();
605 
606         Field wifiNetworkHistoryConfigFile =
607                 WifiNetworkHistory.class.getDeclaredField("NETWORK_HISTORY_CONFIG_FILE");
608         wifiNetworkHistoryConfigFile.setAccessible(true);
609         wifiNetworkHistoryConfigFile.set(null, file.getAbsolutePath());
610 
611         final DataOutputStream stream = new DataOutputStream(new FileOutputStream(file));
612         for (WifiConfiguration config : CONFIGS) {
613             stream.writeUTF(WifiNetworkHistory.CONFIG_KEY + ":  " + config.configKey() + '\n');
614             stream.writeUTF(WifiNetworkHistory.CREATOR_UID_KEY + ":  "
615                     + Integer.toString(config.creatorUid) + '\n');
616             stream.writeUTF(WifiNetworkHistory.SHARED_KEY + ":  "
617                     + Boolean.toString(config.shared) + '\n');
618         }
619         stream.close();
620 
621         // Set up list of home service providers returned by MOManager.
622         final List<HomeSP> homeSPs = new ArrayList<HomeSP>();
623         for (WifiConfiguration config : CONFIGS) {
624             if (config.FQDN != null) {
625                 homeSPs.add(new HomeSP(null, config.FQDN, new HashSet<Long>(),
626                         new HashSet<String>(),
627                         new HashSet<Long>(), new ArrayList<Long>(),
628                         config.providerFriendlyName, null,
629                         new Credential(0, 0, null, false, null, null),
630                         null, 0, null, null, null, 0));
631             }
632         }
633         when(mMOManager.loadAllSPs()).thenReturn(homeSPs);
634 
635         // Load network configurations.
636         mWifiConfigManager.loadConfiguredNetworks();
637 
638         // Verify that network configurations were loaded and correlated correctly across the three
639         // sources.
640         verifyNetworkConfigs(CONFIGS, mConfiguredNetworks.valuesForAllUsers());
641     }
642 
643     /**
644      * Verifies that loadConfiguredNetworks() correctly handles duplicates when reading network
645      * configurations from the wpa_supplicant: The second configuration overwrites the first.
646      */
647     @Test
testLoadConfiguredNetworksEliminatesDuplicates()648     public void testLoadConfiguredNetworksEliminatesDuplicates() throws Exception {
649         final WifiConfiguration config = new WifiConfiguration(CONFIGS.get(0));
650         config.networkId = 1;
651 
652         // Set up list of network configurations returned by wpa_supplicant. The two configurations
653         // are identical except for their network IDs.
654         final String header = "network id / ssid / bssid / flags";
655         final String networks =
656                 header + "\n0\t" + config.SSID + "\tany\n1\t" + config.SSID + "\tany";
657         when(mWifiNative.listNetworks(anyInt())).thenReturn(header);
658         when(mWifiNative.listNetworks(-1)).thenReturn(networks);
659 
660         // Set up variables returned by wpa_supplicant.
661         when(mWifiNative.getNetworkVariable(anyInt(), eq(WifiConfiguration.ssidVarName)))
662             .thenReturn(encodeConfigSSID(config));
663         final Map<String, String> metadata = new HashMap<String, String>();
664         metadata.put(WifiConfigStore.ID_STRING_KEY_CONFIG_KEY, config.configKey());
665         metadata.put(WifiConfigStore.ID_STRING_KEY_CREATOR_UID,
666                 Integer.toString(config.creatorUid));
667         when(mWifiNative.getNetworkExtra(anyInt(), eq(WifiConfigStore.ID_STRING_VAR_NAME)))
668             .thenReturn(metadata);
669 
670         // Load network configurations.
671         mWifiConfigManager.loadConfiguredNetworks();
672 
673         // Verify that the second network configuration (network ID 1) overwrote the first (network
674         // ID 0).
675         verifyNetworkConfigs(Arrays.asList(config), mConfiguredNetworks.valuesForAllUsers());
676     }
677 
678     /**
679      * Verifies that handleUserSwitch() removes ephemeral network configurations, disables network
680      * configurations that should no longer be visible and enables network configurations that
681      * should become visible.
682      */
verifyHandleUserSwitch(int oldUserId, int newUserId, boolean makeOneConfigEphemeral)683     private void verifyHandleUserSwitch(int oldUserId, int newUserId,
684             boolean makeOneConfigEphemeral) throws Exception {
685         addNetworks();
686         switchUser(oldUserId);
687 
688         reset(mWifiNative);
689         final Field lastSelectedConfigurationField =
690                 WifiConfigManager.class.getDeclaredField("mLastSelectedConfiguration");
691         lastSelectedConfigurationField.setAccessible(true);
692         WifiConfiguration removedEphemeralConfig = null;
693         final Set<WifiConfiguration> oldUserOnlyConfigs = new HashSet<>();
694         final Set<WifiConfiguration> newUserOnlyConfigs = new HashSet<>();
695         final Set<WifiConfiguration> neitherUserConfigs = new HashSet<>();
696         final Collection<WifiConfiguration> oldConfigs = mConfiguredNetworks.valuesForAllUsers();
697         int expectedNumberOfConfigs = oldConfigs.size();
698         for (WifiConfiguration config : oldConfigs) {
699             if (WifiConfigurationUtil.isVisibleToAnyProfile(config, USER_PROFILES.get(oldUserId))) {
700                 config.status = WifiConfiguration.Status.ENABLED;
701                 if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
702                         USER_PROFILES.get(newUserId))) {
703                     if (makeOneConfigEphemeral && removedEphemeralConfig == null) {
704                         config.ephemeral = true;
705                         lastSelectedConfigurationField.set(mWifiConfigManager, config.configKey());
706                         removedEphemeralConfig = config;
707                     }
708                 } else {
709                     oldUserOnlyConfigs.add(config);
710                 }
711             } else {
712                 config.status = WifiConfiguration.Status.DISABLED;
713                 if (WifiConfigurationUtil.isVisibleToAnyProfile(config,
714                         USER_PROFILES.get(newUserId))) {
715                     newUserOnlyConfigs.add(config);
716                 } else {
717                     neitherUserConfigs.add(config);
718                 }
719             }
720         }
721 
722         when(mWifiNative.disableNetwork(anyInt())).thenReturn(true);
723         when(mWifiNative.removeNetwork(anyInt())).thenReturn(true);
724 
725         switchUser(newUserId);
726         if (makeOneConfigEphemeral) {
727             // Verify that the ephemeral network configuration was removed.
728             assertNotNull(removedEphemeralConfig);
729             assertNull(mConfiguredNetworks.getForAllUsers(removedEphemeralConfig.networkId));
730             assertNull(lastSelectedConfigurationField.get(mWifiConfigManager));
731             verify(mWifiNative).removeNetwork(removedEphemeralConfig.networkId);
732             --expectedNumberOfConfigs;
733         } else {
734             assertNull(removedEphemeralConfig);
735         }
736 
737         // Verify that the other network configurations were revealed/hidden and enabled/disabled as
738         // appropriate.
739         final Collection<WifiConfiguration> newConfigs = mConfiguredNetworks.valuesForAllUsers();
740         assertEquals(expectedNumberOfConfigs, newConfigs.size());
741         for (WifiConfiguration config : newConfigs) {
742             if (oldUserOnlyConfigs.contains(config)) {
743                 verify(mWifiNative).disableNetwork(config.networkId);
744                 assertEquals(WifiConfiguration.Status.DISABLED, config.status);
745             } else {
746                 verify(mWifiNative, never()).disableNetwork(config.networkId);
747                 if (neitherUserConfigs.contains(config)) {
748                     assertEquals(WifiConfiguration.Status.DISABLED, config.status);
749                 } else {
750                     // Only enabled in networkSelection.
751                     assertTrue(config.getNetworkSelectionStatus().isNetworkEnabled());
752                 }
753 
754             }
755         }
756     }
757 
758     /**
759      * Verifies that handleUserSwitch() behaves correctly when the user switch removes an ephemeral
760      * network configuration and reveals a private network configuration.
761      */
762     @Test
testHandleUserSwitchWithEphemeral()763     public void testHandleUserSwitchWithEphemeral() throws Exception {
764         verifyHandleUserSwitch(USER_IDS[2], USER_IDS[0], true);
765     }
766 
767     /**
768      * Verifies that handleUserSwitch() behaves correctly when the user switch hides a private
769      * network configuration.
770      */
771     @Test
testHandleUserSwitchWithoutEphemeral()772     public void testHandleUserSwitchWithoutEphemeral() throws Exception {
773         verifyHandleUserSwitch(USER_IDS[0], USER_IDS[2], false);
774     }
775 
776     @Test
testSaveLoadEapNetworks()777     public void testSaveLoadEapNetworks() {
778         testSaveLoadSingleEapNetwork("eap network", new EnterpriseConfig(Eap.TTLS)
779                 .setPhase2(Phase2.MSCHAPV2)
780                 .setIdentity("username", "password")
781                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0}));
782         testSaveLoadSingleEapNetwork("eap network", new EnterpriseConfig(Eap.TTLS)
783                 .setPhase2(Phase2.MSCHAPV2)
784                 .setIdentity("username", "password")
785                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT1, FakeKeys.CA_CERT0}));
786 
787     }
788 
testSaveLoadSingleEapNetwork(String ssid, EnterpriseConfig eapConfig)789     private void testSaveLoadSingleEapNetwork(String ssid, EnterpriseConfig eapConfig) {
790         final HashMap<String, String> networkVariables = new HashMap<String, String>();
791         reset(mWifiNative);
792         when(mWifiNative.addNetwork()).thenReturn(0);
793         when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())).thenAnswer(
794                 new AnswerWithArguments() {
795                     public boolean answer(int netId, String name, String value) {
796                         // Verify that no wpa_supplicant variables were written for any other
797                         // network configurations.
798                         assertEquals(netId, 0);
799                         networkVariables.put(name, value);
800                         return true;
801                     }
802                 });
803         when(mWifiNative.getNetworkVariable(anyInt(), anyString())).then(
804                 new AnswerWithArguments() {
805                     public String answer(int netId, String name) {
806                         // Verify that no wpa_supplicant variables were read for any other
807                         // network configurations.
808                         assertEquals(netId, 0);
809                         return networkVariables.get(name);
810                     }
811                 });
812         when(mWifiNative.setNetworkExtra(eq(0), anyString(), (Map<String, String>) anyObject()))
813                 .thenReturn(true);
814 
815         WifiConfiguration config = new WifiConfiguration();
816         config.SSID = ssid;
817         config.creatorUid = Process.WIFI_UID;
818         config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
819         config.enterpriseConfig = eapConfig.enterpriseConfig;
820 
821         // Store a network configuration.
822         mWifiConfigManager.saveNetwork(config, Process.WIFI_UID);
823 
824         // Verify that wpa_supplicant variables were written correctly for the network
825         // configuration.
826         verify(mWifiNative).addNetwork();
827         assertEquals(eapConfig.eap,
828                 unquote(networkVariables.get(WifiEnterpriseConfig.EAP_KEY)));
829         assertEquals(eapConfig.phase2,
830                 unquote(networkVariables.get(WifiEnterpriseConfig.PHASE2_KEY)));
831         assertEquals(eapConfig.identity,
832                 unquote(networkVariables.get(WifiEnterpriseConfig.IDENTITY_KEY)));
833         assertEquals(eapConfig.password,
834                 unquote(networkVariables.get(WifiEnterpriseConfig.PASSWORD_KEY)));
835         assertSavedCaCerts(eapConfig,
836                 unquote(networkVariables.get(WifiEnterpriseConfig.CA_CERT_KEY)));
837 
838         // Prepare the scan result.
839         final String header = "network id / ssid / bssid / flags";
840         String networks = header + "\n" + Integer.toString(0) + "\t" + ssid + "\tany";
841         when(mWifiNative.listNetworks(anyInt())).thenReturn(header);
842         when(mWifiNative.listNetworks(-1)).thenReturn(networks);
843 
844         // Load back the configuration.
845         mWifiConfigManager.loadConfiguredNetworks();
846         List<WifiConfiguration> configs = mWifiConfigManager.getSavedNetworks();
847         assertEquals(1, configs.size());
848         WifiConfiguration loadedConfig = configs.get(0);
849         assertEquals(ssid, unquote(loadedConfig.SSID));
850         BitSet keyMgmt = new BitSet();
851         keyMgmt.set(KeyMgmt.WPA_EAP);
852         assertEquals(keyMgmt, loadedConfig.allowedKeyManagement);
853         assertEquals(eapConfig.enterpriseConfig.getEapMethod(),
854                 loadedConfig.enterpriseConfig.getEapMethod());
855         assertEquals(eapConfig.enterpriseConfig.getPhase2Method(),
856                 loadedConfig.enterpriseConfig.getPhase2Method());
857         assertEquals(eapConfig.enterpriseConfig.getIdentity(),
858                 loadedConfig.enterpriseConfig.getIdentity());
859         assertEquals(eapConfig.enterpriseConfig.getPassword(),
860                 loadedConfig.enterpriseConfig.getPassword());
861         asserCaCertsAliasesMatch(eapConfig.caCerts,
862                 loadedConfig.enterpriseConfig.getCaCertificateAliases());
863     }
864 
unquote(String value)865     private String unquote(String value) {
866         if (value == null) {
867             return null;
868         }
869         int length = value.length();
870         if ((length > 1) && (value.charAt(0) == '"')
871                 && (value.charAt(length - 1) == '"')) {
872             return value.substring(1, length - 1);
873         } else {
874             return value;
875         }
876     }
877 
asserCaCertsAliasesMatch(X509Certificate[] certs, String[] aliases)878     private void asserCaCertsAliasesMatch(X509Certificate[] certs, String[] aliases) {
879         assertEquals(certs.length, aliases.length);
880         List<String> aliasList = new ArrayList<String>(Arrays.asList(aliases));
881         try {
882             for (int i = 0; i < certs.length; i++) {
883                 byte[] certPem = Credentials.convertToPem(certs[i]);
884                 boolean found = false;
885                 for (int j = 0; j < aliasList.size(); j++) {
886                     byte[] keystoreCert = mMockKeyStore.getKeyBlob(Process.WIFI_UID,
887                             Credentials.CA_CERTIFICATE + aliasList.get(j)).blob;
888                     if (Arrays.equals(keystoreCert, certPem)) {
889                         found = true;
890                         aliasList.remove(j);
891                         break;
892                     }
893                 }
894                 assertTrue(found);
895             }
896         } catch (CertificateEncodingException | IOException e) {
897             fail("Cannot convert CA certificate to encoded form.");
898         }
899     }
900 
assertSavedCaCerts(EnterpriseConfig eapConfig, String caCertVariable)901     private void assertSavedCaCerts(EnterpriseConfig eapConfig, String caCertVariable) {
902         ArrayList<String> aliases = new ArrayList<String>();
903         if (TextUtils.isEmpty(caCertVariable)) {
904             // Do nothing.
905         } else if (caCertVariable.startsWith(WifiEnterpriseConfig.CA_CERT_PREFIX)) {
906             aliases.add(caCertVariable.substring(WifiEnterpriseConfig.CA_CERT_PREFIX.length()));
907         } else if (caCertVariable.startsWith(WifiEnterpriseConfig.KEYSTORES_URI)) {
908             String[] encodedAliases = TextUtils.split(
909                     caCertVariable.substring(WifiEnterpriseConfig.KEYSTORES_URI.length()),
910                     WifiEnterpriseConfig.CA_CERT_ALIAS_DELIMITER);
911             for (String encodedAlias : encodedAliases) {
912                 String alias = WifiEnterpriseConfig.decodeCaCertificateAlias(encodedAlias);
913                 assertTrue(alias.startsWith(Credentials.CA_CERTIFICATE));
914                 aliases.add(alias.substring(Credentials.CA_CERTIFICATE.length()));
915             }
916         } else {
917             fail("Unrecognized ca_cert variable: " + caCertVariable);
918         }
919         asserCaCertsAliasesMatch(eapConfig.caCerts, aliases.toArray(new String[aliases.size()]));
920     }
921 
922     private static class EnterpriseConfig {
923         public String eap;
924         public String phase2;
925         public String identity;
926         public String password;
927         public X509Certificate[] caCerts;
928         public WifiEnterpriseConfig enterpriseConfig;
929 
EnterpriseConfig(int eapMethod)930         public EnterpriseConfig(int eapMethod) {
931             enterpriseConfig = new WifiEnterpriseConfig();
932             enterpriseConfig.setEapMethod(eapMethod);
933             eap = Eap.strings[eapMethod];
934         }
setPhase2(int phase2Method)935         public EnterpriseConfig setPhase2(int phase2Method) {
936             enterpriseConfig.setPhase2Method(phase2Method);
937             phase2 = "auth=" + Phase2.strings[phase2Method];
938             return this;
939         }
setIdentity(String identity, String password)940         public EnterpriseConfig setIdentity(String identity, String password) {
941             enterpriseConfig.setIdentity(identity);
942             enterpriseConfig.setPassword(password);
943             this.identity = identity;
944             this.password = password;
945             return this;
946         }
setCaCerts(X509Certificate[] certs)947         public EnterpriseConfig setCaCerts(X509Certificate[] certs) {
948             enterpriseConfig.setCaCertificates(certs);
949             caCerts = certs;
950             return this;
951         }
952     }
953 
954     /**
955      * Generates an array of unique random numbers below the specified maxValue.
956      * Values range from 0 to maxValue-1.
957      */
getUniqueRandomNumberValues( int seed, int maxValue, int numValues)958     private static ArrayDeque<Integer> getUniqueRandomNumberValues(
959             int seed,
960             int maxValue,
961             int numValues) {
962         assertTrue(numValues <= maxValue);
963         Random rand = new Random(WifiTestUtil.getTestMethod().hashCode() + seed);
964         ArrayDeque<Integer> randomNumberList = new ArrayDeque<>();
965         for (int i = 0; i < numValues; i++) {
966             int num = rand.nextInt(maxValue);
967             while (randomNumberList.contains(num)) {
968                 num = rand.nextInt(maxValue);
969             }
970             randomNumberList.push(num);
971         }
972         return randomNumberList;
973     }
974 
975     /**
976      * Verifies that the networks in pnoNetworkList is sorted in the same order as the
977      * network in expectedNetworkIDOrder list.
978      */
verifyPnoNetworkListOrder( ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList, ArrayList<Integer> expectedNetworkIdOrder)979     private static void verifyPnoNetworkListOrder(
980             ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList,
981             ArrayList<Integer> expectedNetworkIdOrder) throws Exception  {
982         int i = 0;
983         for (WifiScanner.PnoSettings.PnoNetwork pnoNetwork : pnoNetworkList) {
984             Log.i(TAG, "PNO Network List Index: " + i + ", networkID: " + pnoNetwork.networkId);
985             assertEquals("Expected network ID: " + pnoNetwork.networkId,
986                     pnoNetwork.networkId, expectedNetworkIdOrder.get(i++).intValue());
987         }
988     }
989 
990     /**
991      * Verifies the retrieveDisconnectedPnoNetworkList API. The test verifies that the list
992      * returned from the API is sorted as expected.
993      */
994     @Test
testDisconnectedPnoNetworkListCreation()995     public void testDisconnectedPnoNetworkListCreation() throws Exception {
996         addNetworks();
997 
998         Random rand = new Random(WifiTestUtil.getTestMethod().hashCode());
999 
1000         // First assign random |numAssociation| values and verify that the list is sorted
1001         // in descending order of |numAssociation| values. Keep NetworkSelectionStatus
1002         // values constant.
1003         for (int userId : USER_IDS) {
1004             switchUser(userId);
1005             TreeMap<Integer, Integer> numAssociationToNetworkIdMap =
1006                     new TreeMap<>(Collections.reverseOrder());
1007             ArrayDeque<Integer> numAssociationValues =
1008                     getUniqueRandomNumberValues(
1009                             1, 10000, mConfiguredNetworks.valuesForCurrentUser().size());
1010             for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1011                 config.numAssociation = numAssociationValues.pop();
1012                 config.priority = rand.nextInt(10000);
1013                 config.getNetworkSelectionStatus().setNetworkSelectionStatus(
1014                         WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
1015                 numAssociationToNetworkIdMap.put(config.numAssociation, config.networkId);
1016                 Log.i(TAG, "networkID: " + config.networkId + ", numAssociation: "
1017                         + config.numAssociation);
1018             }
1019             ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList =
1020                     mWifiConfigManager.retrieveDisconnectedPnoNetworkList();
1021             verifyPnoNetworkListOrder(pnoNetworkList,
1022                     new ArrayList(numAssociationToNetworkIdMap.values()));
1023         }
1024 
1025         // Assign random |priority| values and verify that the list is sorted in descending order
1026         // of |priority| values. Keep numAssociation/NetworkSelectionStatus values constant.
1027         for (int userId : USER_IDS) {
1028             switchUser(userId);
1029             TreeMap<Integer, Integer> priorityToNetworkIdMap =
1030                     new TreeMap<>(Collections.reverseOrder());
1031             ArrayDeque<Integer> priorityValues =
1032                     getUniqueRandomNumberValues(
1033                             2, 10000, mConfiguredNetworks.valuesForCurrentUser().size());
1034             for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1035                 config.numAssociation = 0;
1036                 config.priority = priorityValues.pop();
1037                 config.getNetworkSelectionStatus().setNetworkSelectionStatus(
1038                         WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
1039                 priorityToNetworkIdMap.put(config.priority, config.networkId);
1040                 Log.i(TAG, "networkID: " + config.networkId + ", priority: " + config.priority);
1041             }
1042             ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList =
1043                     mWifiConfigManager.retrieveDisconnectedPnoNetworkList();
1044             verifyPnoNetworkListOrder(pnoNetworkList,
1045                     new ArrayList(priorityToNetworkIdMap.values()));
1046         }
1047 
1048         // Now assign random |NetworkSelectionStatus| values and verify that the list is sorted in
1049         // ascending order of |NetworkSelectionStatus| values.
1050         for (int userId : USER_IDS) {
1051             switchUser(userId);
1052             TreeMap<Integer, Integer> networkSelectionStatusToNetworkIdMap = new TreeMap<>();
1053             ArrayDeque<Integer> networkSelectionStatusValues =
1054                     getUniqueRandomNumberValues(
1055                             3,
1056                             WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_STATUS_MAX,
1057                             mConfiguredNetworks.valuesForCurrentUser().size());
1058             for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1059                 config.numAssociation = rand.nextInt(10000);
1060                 config.priority = rand.nextInt(10000);
1061                 config.getNetworkSelectionStatus().setNetworkSelectionStatus(
1062                         networkSelectionStatusValues.pop());
1063                 networkSelectionStatusToNetworkIdMap.put(
1064                         config.getNetworkSelectionStatus().getNetworkSelectionStatus(),
1065                         config.networkId);
1066                 Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: "
1067                         + config.getNetworkSelectionStatus().getNetworkSelectionStatus());
1068             }
1069             ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList =
1070                     mWifiConfigManager.retrieveDisconnectedPnoNetworkList();
1071             verifyPnoNetworkListOrder(pnoNetworkList,
1072                     new ArrayList(networkSelectionStatusToNetworkIdMap.values()));
1073         }
1074     }
1075 
1076     /**
1077      * Verifies the retrieveConnectedPnoNetworkList API. The test verifies that the list
1078      * returned from the API is sorted as expected.
1079      */
1080     @Test
testConnectedPnoNetworkListCreation()1081     public void testConnectedPnoNetworkListCreation() throws Exception {
1082         addNetworks();
1083 
1084         Random rand = new Random(WifiTestUtil.getTestMethod().hashCode());
1085 
1086         // First assign |lastSeen| values and verify that the list is sorted
1087         // in descending order of |lastSeen| values. Keep NetworkSelectionStatus
1088         // values constant.
1089         for (int userId : USER_IDS) {
1090             switchUser(userId);
1091             TreeMap<Boolean, Integer> lastSeenToNetworkIdMap =
1092                     new TreeMap<>(Collections.reverseOrder());
1093             ArrayDeque<Integer> lastSeenValues = getUniqueRandomNumberValues(1, 2, 2);
1094             if (mConfiguredNetworks.valuesForCurrentUser().size() > 2) continue;
1095             for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1096                 config.numAssociation = rand.nextInt(10000);
1097                 config.priority = rand.nextInt(10000);
1098                 config.getNetworkSelectionStatus().setNetworkSelectionStatus(
1099                         WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
1100                 boolean lastSeenValue = (lastSeenValues.pop()  == 1);
1101                 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(
1102                         lastSeenValue);
1103                 lastSeenToNetworkIdMap.put(lastSeenValue, config.networkId);
1104                 Log.i(TAG, "networkID: " + config.networkId + ", lastSeen: " + lastSeenValue);
1105             }
1106             ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList =
1107                     mWifiConfigManager.retrieveConnectedPnoNetworkList();
1108             verifyPnoNetworkListOrder(pnoNetworkList,
1109                     new ArrayList(lastSeenToNetworkIdMap.values()));
1110         }
1111 
1112         // Assign random |numAssociation| values and verify that the list is sorted
1113         // in descending order of |numAssociation| values. Keep NetworkSelectionStatus/lastSeen
1114         // values constant.
1115         for (int userId : USER_IDS) {
1116             switchUser(userId);
1117             TreeMap<Integer, Integer> numAssociationToNetworkIdMap =
1118                     new TreeMap<>(Collections.reverseOrder());
1119             ArrayDeque<Integer> numAssociationValues =
1120                     getUniqueRandomNumberValues(
1121                             1, 10000, mConfiguredNetworks.valuesForCurrentUser().size());
1122             for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1123                 config.numAssociation = numAssociationValues.pop();
1124                 config.priority = rand.nextInt(10000);
1125                 config.getNetworkSelectionStatus().setNetworkSelectionStatus(
1126                         WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
1127                 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true);
1128                 numAssociationToNetworkIdMap.put(config.numAssociation, config.networkId);
1129                 Log.i(TAG, "networkID: " + config.networkId + ", numAssociation: "
1130                         + config.numAssociation);
1131             }
1132             ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList =
1133                     mWifiConfigManager.retrieveConnectedPnoNetworkList();
1134             verifyPnoNetworkListOrder(pnoNetworkList,
1135                     new ArrayList(numAssociationToNetworkIdMap.values()));
1136         }
1137 
1138         // Now assign random |NetworkSelectionStatus| values and verify that the list is sorted in
1139         // ascending order of |NetworkSelectionStatus| values.
1140         for (int userId : USER_IDS) {
1141             switchUser(userId);
1142             TreeMap<Integer, Integer> networkSelectionStatusToNetworkIdMap = new TreeMap<>();
1143             ArrayDeque<Integer> networkSelectionStatusValues =
1144                     getUniqueRandomNumberValues(
1145                             3,
1146                             WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_STATUS_MAX,
1147                             mConfiguredNetworks.valuesForCurrentUser().size());
1148             for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
1149                 config.numAssociation = rand.nextInt(10000);
1150                 config.priority = rand.nextInt(10000);
1151                 config.getNetworkSelectionStatus().setNetworkSelectionStatus(
1152                         networkSelectionStatusValues.pop());
1153                 networkSelectionStatusToNetworkIdMap.put(
1154                         config.getNetworkSelectionStatus().getNetworkSelectionStatus(),
1155                         config.networkId);
1156                 Log.i(TAG, "networkID: " + config.networkId + ", NetworkSelectionStatus: "
1157                         + config.getNetworkSelectionStatus().getNetworkSelectionStatus());
1158             }
1159             ArrayList<WifiScanner.PnoSettings.PnoNetwork> pnoNetworkList =
1160                     mWifiConfigManager.retrieveConnectedPnoNetworkList();
1161             verifyPnoNetworkListOrder(pnoNetworkList,
1162                     new ArrayList(networkSelectionStatusToNetworkIdMap.values()));
1163         }
1164     }
1165 
1166     /**
1167      * Verifies that hasEverConnected is false for a newly added network
1168      */
1169     @Test
testAddNetworkHasEverConnectedFalse()1170     public void testAddNetworkHasEverConnectedFalse() throws Exception {
1171         addNetwork(BASE_HAS_EVER_CONNECTED_CONFIG);
1172         WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(
1173                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1174         assertFalse("Adding a new network should not have hasEverConnected set to true.",
1175                 checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1176     }
1177 
1178 
1179     /**
1180      * Verifies that hasEverConnected is false for a newly added network even when new config has
1181      * mistakenly set HasEverConnected to true.
1182     */
1183     @Test
testAddNetworkOverridesHasEverConnectedWhenTrueInNewConfig()1184     public void testAddNetworkOverridesHasEverConnectedWhenTrueInNewConfig() throws Exception {
1185         WifiConfiguration newNetworkWithHasEverConnectedTrue =
1186                 new WifiConfiguration(BASE_HAS_EVER_CONNECTED_CONFIG);
1187         newNetworkWithHasEverConnectedTrue.getNetworkSelectionStatus().setHasEverConnected(true);
1188         addNetwork(newNetworkWithHasEverConnectedTrue);
1189         // check if addNetwork clears the bit.
1190         WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(
1191                 newNetworkWithHasEverConnectedTrue.networkId);
1192         assertFalse("Adding a new network should not have hasEverConnected set to true.",
1193                 checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1194     }
1195 
1196 
1197     /**
1198      * Verify that setting HasEverConnected with a config update can be read back.
1199      */
1200     @Test
testUpdateConfigToHasEverConnectedTrue()1201     public void testUpdateConfigToHasEverConnectedTrue() throws Exception {
1202         addNetwork(BASE_HAS_EVER_CONNECTED_CONFIG);
1203 
1204         // Get the newly saved config and update HasEverConnected
1205         WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(
1206                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1207         assertFalse("Adding a new network should not have hasEverConnected set to true.",
1208                 checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1209         checkConfig.getNetworkSelectionStatus().setHasEverConnected(true);
1210         mWifiConfigManager.addOrUpdateNetwork(checkConfig, HAS_EVER_CONNECTED_USER);
1211 
1212         // verify that HasEverConnected was properly written and read back
1213         checkHasEverConnectedTrue(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1214     }
1215 
1216 
1217     /**
1218      * Verifies that hasEverConnected is cleared when a network config preSharedKey is updated.
1219      */
1220     @Test
testUpdatePreSharedKeyClearsHasEverConnected()1221     public void testUpdatePreSharedKeyClearsHasEverConnected() throws Exception {
1222         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1223 
1224         testUpdateConfigToHasEverConnectedTrue();
1225 
1226         WifiConfiguration original = mWifiConfigManager.getWifiConfiguration(
1227                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1228 
1229         WifiConfiguration updatePreSharedKeyConfig = new WifiConfiguration();
1230         updatePreSharedKeyConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1231         updatePreSharedKeyConfig.SSID = original.SSID;
1232         updatePreSharedKeyConfig.preSharedKey = "newpassword";
1233         switchUserToCreatorOrParentOf(original);
1234         mWifiConfigManager.addOrUpdateNetwork(updatePreSharedKeyConfig,
1235                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1236 
1237         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1238         switchUser(originalUserId);
1239     }
1240 
1241     /**
1242      * Verifies that hasEverConnected is cleared when a network config allowedKeyManagement is
1243      * updated.
1244      */
1245     @Test
testUpdateAllowedKeyManagementChanged()1246     public void testUpdateAllowedKeyManagementChanged() throws Exception {
1247         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1248 
1249         testUpdateConfigToHasEverConnectedTrue();
1250 
1251         WifiConfiguration updateAllowedKeyManagementConfig = new WifiConfiguration();
1252         updateAllowedKeyManagementConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1253         updateAllowedKeyManagementConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1254         updateAllowedKeyManagementConfig.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
1255 
1256         // Set up mock to allow the new value to be read back into the config
1257         String allowedKeyManagementString = makeString(
1258                 updateAllowedKeyManagementConfig.allowedKeyManagement,
1259                     WifiConfiguration.KeyMgmt.strings);
1260         when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1261                 KeyMgmt.varName)).thenReturn(allowedKeyManagementString);
1262 
1263         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1264         mWifiConfigManager.addOrUpdateNetwork(updateAllowedKeyManagementConfig,
1265                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1266 
1267         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1268         switchUser(originalUserId);
1269     }
1270 
1271     /**
1272      * Verifies that hasEverConnected is cleared when a network config allowedProtocols is
1273      * updated.
1274      */
1275     @Test
testUpdateAllowedProtocolsChanged()1276     public void testUpdateAllowedProtocolsChanged() throws Exception {
1277         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1278 
1279         testUpdateConfigToHasEverConnectedTrue();
1280 
1281         WifiConfiguration updateAllowedProtocolsConfig = new WifiConfiguration();
1282         updateAllowedProtocolsConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1283         updateAllowedProtocolsConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1284         updateAllowedProtocolsConfig.allowedProtocols.set(
1285                 WifiConfiguration.Protocol.RSN);
1286 
1287         // Set up mock to allow the new value to be read back into the config
1288         String allowedProtocolsString = makeString(
1289                 updateAllowedProtocolsConfig.allowedProtocols,
1290                     WifiConfiguration.Protocol.strings);
1291         when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1292                 Protocol.varName)).thenReturn(allowedProtocolsString);
1293 
1294         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1295         mWifiConfigManager.addOrUpdateNetwork(updateAllowedProtocolsConfig,
1296                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1297 
1298         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1299         switchUser(originalUserId);
1300     }
1301 
1302     /**
1303      * Verifies that hasEverConnected is cleared when a network config allowedAuthAlgorithms is
1304      * updated.
1305      */
1306     @Test
testUpdateAllowedAuthAlgorithmsChanged()1307     public void testUpdateAllowedAuthAlgorithmsChanged() throws Exception {
1308         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1309 
1310         testUpdateConfigToHasEverConnectedTrue();
1311 
1312         WifiConfiguration updateAllowedAuthAlgorithmsConfig = new WifiConfiguration();
1313         updateAllowedAuthAlgorithmsConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1314         updateAllowedAuthAlgorithmsConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1315         updateAllowedAuthAlgorithmsConfig.allowedAuthAlgorithms.set(
1316                 WifiConfiguration.AuthAlgorithm.SHARED);
1317 
1318         // Set up mock to allow the new value to be read back into the config
1319         String allowedAuthAlgorithmsString = makeString(
1320                 updateAllowedAuthAlgorithmsConfig.allowedAuthAlgorithms,
1321                     WifiConfiguration.AuthAlgorithm.strings);
1322         when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1323                 AuthAlgorithm.varName)).thenReturn(allowedAuthAlgorithmsString);
1324 
1325         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1326         mWifiConfigManager.addOrUpdateNetwork(updateAllowedAuthAlgorithmsConfig,
1327                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1328 
1329         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1330         switchUser(originalUserId);
1331     }
1332 
1333     /**
1334      * Verifies that hasEverConnected is cleared when a network config allowedPairwiseCiphers is
1335      * updated.
1336      */
1337     @Test
testUpdateAllowedPairwiseCiphersChanged()1338     public void testUpdateAllowedPairwiseCiphersChanged() throws Exception {
1339         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1340 
1341         testUpdateConfigToHasEverConnectedTrue();
1342 
1343         WifiConfiguration updateAllowedPairwiseCiphersConfig = new WifiConfiguration();
1344         updateAllowedPairwiseCiphersConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1345         updateAllowedPairwiseCiphersConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1346         updateAllowedPairwiseCiphersConfig.allowedPairwiseCiphers.set(
1347                 WifiConfiguration.PairwiseCipher.CCMP);
1348 
1349         // Set up mock to allow the new value to be read back into the config
1350         String allowedPairwiseCiphersString = makeString(
1351                 updateAllowedPairwiseCiphersConfig.allowedPairwiseCiphers,
1352                     WifiConfiguration.PairwiseCipher.strings);
1353         when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1354                 PairwiseCipher.varName)).thenReturn(allowedPairwiseCiphersString);
1355 
1356         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1357         mWifiConfigManager.addOrUpdateNetwork(updateAllowedPairwiseCiphersConfig,
1358                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1359 
1360         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1361         switchUser(originalUserId);
1362     }
1363 
1364     /**
1365      * Verifies that hasEverConnected is cleared when a network config allowedGroupCiphers is
1366      * updated.
1367      */
1368     @Test
testUpdateAllowedGroupCiphersChanged()1369     public void testUpdateAllowedGroupCiphersChanged() throws Exception {
1370         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1371 
1372         testUpdateConfigToHasEverConnectedTrue();
1373 
1374         WifiConfiguration updateAllowedGroupCiphersConfig = new WifiConfiguration();
1375         updateAllowedGroupCiphersConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1376         updateAllowedGroupCiphersConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1377         updateAllowedGroupCiphersConfig.allowedGroupCiphers.set(
1378                 WifiConfiguration.GroupCipher.CCMP);
1379 
1380         // Set up mock to allow the new value to be read back into the config
1381         String allowedGroupCiphersString = makeString(
1382                 updateAllowedGroupCiphersConfig.allowedGroupCiphers,
1383                     WifiConfiguration.GroupCipher.strings);
1384         when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1385                 GroupCipher.varName)).thenReturn(allowedGroupCiphersString);
1386 
1387         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1388         mWifiConfigManager.addOrUpdateNetwork(updateAllowedGroupCiphersConfig,
1389                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1390 
1391         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1392         switchUser(originalUserId);
1393     }
1394 
1395     /**
1396      * Verifies that hasEverConnected is cleared when a network config wepKeys is
1397      * updated.
1398      */
1399     @Test
testUpdateWepKeysChanged()1400     public void testUpdateWepKeysChanged() throws Exception {
1401         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1402 
1403         testUpdateConfigToHasEverConnectedTrue();
1404 
1405         String tempKey = "hereisakey";
1406         WifiConfiguration updateWepKeysConfig = new WifiConfiguration();
1407         updateWepKeysConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1408         updateWepKeysConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1409         updateWepKeysConfig.wepKeys = new String[] {tempKey};
1410 
1411         // Set up mock to allow the new value to be read back into the config
1412         when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1413                 WifiConfiguration.wepKeyVarNames[0])).thenReturn(tempKey);
1414 
1415         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1416         mWifiConfigManager.addOrUpdateNetwork(updateWepKeysConfig,
1417                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1418 
1419         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1420         switchUser(originalUserId);
1421     }
1422 
1423     /**
1424      * Verifies that hasEverConnected is cleared when a network config hiddenSSID is
1425      * updated.
1426      */
1427     @Test
testUpdateHiddenSSIDChanged()1428     public void testUpdateHiddenSSIDChanged() throws Exception {
1429         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1430 
1431         testUpdateConfigToHasEverConnectedTrue();
1432 
1433         WifiConfiguration updateHiddenSSIDConfig = new WifiConfiguration();
1434         updateHiddenSSIDConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1435         updateHiddenSSIDConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1436         updateHiddenSSIDConfig.hiddenSSID = true;
1437 
1438         // Set up mock to allow the new value to be read back into the config
1439         when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1440                 WifiConfiguration.hiddenSSIDVarName)).thenReturn("1");
1441 
1442         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1443         mWifiConfigManager.addOrUpdateNetwork(updateHiddenSSIDConfig,
1444                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1445 
1446         checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1447         switchUser(originalUserId);
1448     }
1449 
1450     /**
1451      * Verifies that hasEverConnected is cleared when a network config pmfVarName is
1452      * updated.
1453      */
1454     @Test
testUpdateRequirePMFChanged()1455     public void testUpdateRequirePMFChanged() throws Exception {
1456         final int originalUserId = mWifiConfigManager.getCurrentUserId();
1457 
1458         testUpdateConfigToHasEverConnectedTrue();
1459 
1460         WifiConfiguration updateRequirePMFConfig = new WifiConfiguration();
1461         updateRequirePMFConfig.networkId = BASE_HAS_EVER_CONNECTED_CONFIG.networkId;
1462         updateRequirePMFConfig.SSID = BASE_HAS_EVER_CONNECTED_CONFIG.SSID;
1463         updateRequirePMFConfig.requirePMF = true;
1464 
1465         // Set up mock to allow the new value to be read back into the config
1466         // TODO: please see b/28088226  - this test is implemented as if WifiConfigStore correctly
1467         // read back the boolean value.  When fixed, uncomment the following line and the
1468         // checkHasEverConnectedFalse below.
1469         //when(mWifiNative.getNetworkVariable(BASE_HAS_EVER_CONNECTED_CONFIG.networkId,
1470         //        WifiConfiguration.pmfVarName)).thenReturn("2");
1471 
1472         switchUserToCreatorOrParentOf(BASE_HAS_EVER_CONNECTED_CONFIG);
1473         mWifiConfigManager.addOrUpdateNetwork(updateRequirePMFConfig,
1474                 BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1475 
1476         //checkHasEverConnectedFalse(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1477         checkHasEverConnectedTrue(BASE_HAS_EVER_CONNECTED_CONFIG.networkId);
1478         switchUser(originalUserId);
1479     }
1480 
1481     /**
1482      * Verify WifiEnterpriseConfig changes are detected in WifiConfigManager.
1483      */
1484     @Test
testEnterpriseConfigAdded()1485     public void testEnterpriseConfigAdded() {
1486         EnterpriseConfig eapConfig =  new EnterpriseConfig(Eap.TTLS)
1487                 .setPhase2(Phase2.MSCHAPV2)
1488                 .setIdentity("username", "password")
1489                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0});
1490 
1491         assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(null, eapConfig.enterpriseConfig));
1492     }
1493 
1494     /**
1495      * Verify WifiEnterpriseConfig eap change is detected.
1496      */
1497     @Test
testEnterpriseConfigEapChangeDetected()1498     public void testEnterpriseConfigEapChangeDetected() {
1499         EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS);
1500         EnterpriseConfig peapConfig = new EnterpriseConfig(Eap.PEAP);
1501 
1502         assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig,
1503                 peapConfig.enterpriseConfig));
1504     }
1505 
1506     /**
1507      * Verify WifiEnterpriseConfig phase2 method change is detected.
1508      */
1509     @Test
testEnterpriseConfigPhase2ChangeDetected()1510     public void testEnterpriseConfigPhase2ChangeDetected() {
1511         EnterpriseConfig eapConfig = new EnterpriseConfig(Eap.TTLS).setPhase2(Phase2.MSCHAPV2);
1512         EnterpriseConfig papConfig = new EnterpriseConfig(Eap.TTLS).setPhase2(Phase2.PAP);
1513 
1514         assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig,
1515                 papConfig.enterpriseConfig));
1516     }
1517 
1518     /**
1519      * Verify WifiEnterpriseConfig added Certificate is detected.
1520      */
1521     @Test
testCaCertificateAddedDetected()1522     public void testCaCertificateAddedDetected() {
1523         EnterpriseConfig eapConfigNoCerts =  new EnterpriseConfig(Eap.TTLS)
1524                 .setPhase2(Phase2.MSCHAPV2)
1525                 .setIdentity("username", "password");
1526 
1527         EnterpriseConfig eapConfig1Cert =  new EnterpriseConfig(Eap.TTLS)
1528                 .setPhase2(Phase2.MSCHAPV2)
1529                 .setIdentity("username", "password")
1530                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0});
1531 
1532         assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfigNoCerts.enterpriseConfig,
1533                 eapConfig1Cert.enterpriseConfig));
1534     }
1535 
1536     /**
1537      * Verify WifiEnterpriseConfig Certificate change is detected.
1538      */
1539     @Test
testDifferentCaCertificateDetected()1540     public void testDifferentCaCertificateDetected() {
1541         EnterpriseConfig eapConfig =  new EnterpriseConfig(Eap.TTLS)
1542                 .setPhase2(Phase2.MSCHAPV2)
1543                 .setIdentity("username", "password")
1544                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0});
1545 
1546         EnterpriseConfig eapConfigNewCert =  new EnterpriseConfig(Eap.TTLS)
1547                 .setPhase2(Phase2.MSCHAPV2)
1548                 .setIdentity("username", "password")
1549                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT1});
1550 
1551         assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig,
1552                 eapConfigNewCert.enterpriseConfig));
1553     }
1554 
1555     /**
1556      * Verify WifiEnterpriseConfig added Certificate changes are detected.
1557      */
1558     @Test
testCaCertificateChangesDetected()1559     public void testCaCertificateChangesDetected() {
1560         EnterpriseConfig eapConfig =  new EnterpriseConfig(Eap.TTLS)
1561                 .setPhase2(Phase2.MSCHAPV2)
1562                 .setIdentity("username", "password")
1563                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0});
1564 
1565         EnterpriseConfig eapConfigAddedCert =  new EnterpriseConfig(Eap.TTLS)
1566                 .setPhase2(Phase2.MSCHAPV2)
1567                 .setIdentity("username", "password")
1568                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
1569 
1570         assertTrue(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig,
1571                 eapConfigAddedCert.enterpriseConfig));
1572     }
1573 
1574     /**
1575      * Verify that WifiEnterpriseConfig does not detect changes for identical configs.
1576      */
1577     @Test
testWifiEnterpriseConfigNoChanges()1578     public void testWifiEnterpriseConfigNoChanges() {
1579         EnterpriseConfig eapConfig =  new EnterpriseConfig(Eap.TTLS)
1580                 .setPhase2(Phase2.MSCHAPV2)
1581                 .setIdentity("username", "password")
1582                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
1583 
1584         // Just to be clear that check is not against the same object
1585         EnterpriseConfig eapConfigSame =  new EnterpriseConfig(Eap.TTLS)
1586                 .setPhase2(Phase2.MSCHAPV2)
1587                 .setIdentity("username", "password")
1588                 .setCaCerts(new X509Certificate[] {FakeKeys.CA_CERT0, FakeKeys.CA_CERT1});
1589 
1590         assertFalse(mWifiConfigManager.wasEnterpriseConfigChange(eapConfig.enterpriseConfig,
1591                 eapConfigSame.enterpriseConfig));
1592     }
1593 
1594 
checkHasEverConnectedTrue(int networkId)1595     private void checkHasEverConnectedTrue(int networkId) {
1596         WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(networkId);
1597         assertTrue("hasEverConnected expected to be true.",
1598                 checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1599     }
1600 
checkHasEverConnectedFalse(int networkId)1601     private void checkHasEverConnectedFalse(int networkId) {
1602         WifiConfiguration checkConfig = mWifiConfigManager.getWifiConfiguration(networkId);
1603         assertFalse("Updating credentials network config should clear hasEverConnected.",
1604                 checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1605     }
1606 
1607     /**
1608      *  Helper function to translate from WifiConfiguration BitSet to String.
1609      */
makeString(BitSet set, String[] strings)1610     private static String makeString(BitSet set, String[] strings) {
1611         StringBuffer buf = new StringBuffer();
1612         int nextSetBit = -1;
1613 
1614         /* Make sure all set bits are in [0, strings.length) to avoid
1615          * going out of bounds on strings.  (Shouldn't happen, but...) */
1616         set = set.get(0, strings.length);
1617 
1618         while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
1619             buf.append(strings[nextSetBit].replace('_', '-')).append(' ');
1620         }
1621 
1622         // remove trailing space
1623         if (set.cardinality() > 0) {
1624             buf.setLength(buf.length() - 1);
1625         }
1626 
1627         return buf.toString();
1628     }
1629 
1630 
1631 }
1632