WifiStateMachineTest.java revision 54c9cf8d299b99f8b999bc2cf4adcda1eba81469
1/* 2 * Copyright (C) 2015 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 17package com.android.server.wifi; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertFalse; 21import static org.junit.Assert.assertTrue; 22import static org.mockito.Mockito.any; 23import static org.mockito.Mockito.anyBoolean; 24import static org.mockito.Mockito.anyInt; 25import static org.mockito.Mockito.anyObject; 26import static org.mockito.Mockito.anyString; 27import static org.mockito.Mockito.eq; 28import static org.mockito.Mockito.mock; 29import static org.mockito.Mockito.never; 30import static org.mockito.Mockito.verify; 31import static org.mockito.Mockito.when; 32import static org.mockito.Mockito.withSettings; 33 34import android.content.ContentResolver; 35import android.content.Context; 36import android.content.pm.PackageManager; 37import android.content.pm.UserInfo; 38import android.content.res.Resources; 39import android.net.ConnectivityManager; 40import android.net.DhcpResults; 41import android.net.LinkProperties; 42import android.net.dhcp.DhcpClient; 43import android.net.ip.IpManager; 44import android.net.wifi.ScanResult; 45import android.net.wifi.SupplicantState; 46import android.net.wifi.WifiConfiguration; 47import android.net.wifi.WifiManager; 48import android.net.wifi.WifiScanner; 49import android.net.wifi.WifiSsid; 50import android.net.wifi.p2p.IWifiP2pManager; 51import android.os.BatteryStats; 52import android.os.Binder; 53import android.os.Handler; 54import android.os.HandlerThread; 55import android.os.IBinder; 56import android.os.IInterface; 57import android.os.INetworkManagementService; 58import android.os.IPowerManager; 59import android.os.Looper; 60import android.os.Message; 61import android.os.Messenger; 62import android.os.PowerManager; 63import android.os.UserHandle; 64import android.os.UserManager; 65import android.provider.Settings; 66import android.security.KeyStore; 67import android.telephony.TelephonyManager; 68import android.test.suitebuilder.annotation.SmallTest; 69import android.util.Base64; 70import android.util.Log; 71 72import com.android.internal.R; 73import com.android.internal.app.IBatteryStats; 74import com.android.internal.util.AsyncChannel; 75import com.android.internal.util.IState; 76import com.android.internal.util.StateMachine; 77import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 78import com.android.server.wifi.hotspot2.NetworkDetail; 79import com.android.server.wifi.hotspot2.Utils; 80import com.android.server.wifi.p2p.WifiP2pServiceImpl; 81 82import org.junit.After; 83import org.junit.Before; 84import org.junit.Test; 85import org.mockito.ArgumentCaptor; 86import org.mockito.Mock; 87import org.mockito.MockitoAnnotations; 88 89import java.io.ByteArrayOutputStream; 90import java.io.PrintWriter; 91import java.lang.reflect.Field; 92import java.lang.reflect.InvocationTargetException; 93import java.lang.reflect.Method; 94import java.util.ArrayList; 95import java.util.Arrays; 96import java.util.HashMap; 97import java.util.HashSet; 98import java.util.List; 99import java.util.Map; 100import java.util.Set; 101 102/** 103 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}. 104 */ 105@SmallTest 106public class WifiStateMachineTest { 107 public static final String TAG = "WifiStateMachineTest"; 108 109 private static final int MANAGED_PROFILE_UID = 1100000; 110 private static final int OTHER_USER_UID = 1200000; 111 112 private long mBinderToken; 113 114 private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) { 115 return mock(class1, withSettings().extraInterfaces(interfaces)); 116 } 117 118 private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) { 119 T tImpl = mockWithInterfaces(class1, iface); 120 IBinder binder = mock(IBinder.class); 121 when(((IInterface) tImpl).asBinder()).thenReturn(binder); 122 when(binder.queryLocalInterface(iface.getCanonicalName())) 123 .thenReturn((IInterface) tImpl); 124 return binder; 125 } 126 127 private void enableDebugLogs() { 128 mWsm.enableVerboseLogging(1); 129 } 130 131 private class TestIpManager extends IpManager { 132 TestIpManager(Context context, String ifname, IpManager.Callback callback) { 133 // Call dependency-injection superclass constructor. 134 super(context, ifname, callback, mock(INetworkManagementService.class)); 135 } 136 137 @Override 138 public void startProvisioning(IpManager.ProvisioningConfiguration config) {} 139 140 @Override 141 public void stop() {} 142 143 @Override 144 public void confirmConfiguration() {} 145 146 void injectDhcpSuccess(DhcpResults dhcpResults) { 147 mCallback.onNewDhcpResults(dhcpResults); 148 mCallback.onProvisioningSuccess(new LinkProperties()); 149 } 150 151 void injectDhcpFailure() { 152 mCallback.onNewDhcpResults(null); 153 mCallback.onProvisioningFailure(new LinkProperties()); 154 } 155 } 156 157 private FrameworkFacade getFrameworkFacade() throws Exception { 158 FrameworkFacade facade = mock(FrameworkFacade.class); 159 160 when(facade.makeBaseLogger()).thenReturn(mock(BaseWifiLogger.class)); 161 when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn( 162 mockWithInterfaces(IBinder.class, INetworkManagementService.class)); 163 164 IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class); 165 when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder); 166 167 WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface( 168 IWifiP2pManager.class.getCanonicalName()); 169 170 final Object sync = new Object(); 171 synchronized (sync) { 172 mP2pThread = new HandlerThread("WifiP2pMockThread") { 173 @Override 174 protected void onLooperPrepared() { 175 synchronized (sync) { 176 sync.notifyAll(); 177 } 178 } 179 }; 180 181 mP2pThread.start(); 182 sync.wait(); 183 } 184 185 Handler handler = new Handler(mP2pThread.getLooper()); 186 when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler)); 187 188 IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class); 189 when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder); 190 191 when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class))) 192 .then(new AnswerWithArguments() { 193 public IpManager answer( 194 Context context, String ifname, IpManager.Callback callback) { 195 mTestIpManager = new TestIpManager(context, ifname, callback); 196 return mTestIpManager; 197 } 198 }); 199 200 when(facade.checkUidPermission(eq(android.Manifest.permission.OVERRIDE_WIFI_CONFIG), 201 anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); 202 203 when(facade.makeWifiConfigManager(any(Context.class), any(WifiStateMachine.class), 204 any(WifiNative.class), any(FrameworkFacade.class), any(Clock.class), 205 any(UserManager.class), any(KeyStore.class))).then(new AnswerWithArguments() { 206 public WifiConfigManager answer(Context context, WifiStateMachine wifiStateMachine, 207 WifiNative wifiNative, FrameworkFacade frameworkFacade, Clock clock, 208 UserManager userManager, KeyStore keyStore){ 209 mWifiConfigManager = new WifiConfigManager(context, wifiStateMachine, wifiNative, 210 frameworkFacade, clock, userManager, keyStore); 211 return mWifiConfigManager; 212 } 213 }); 214 return facade; 215 } 216 217 private Context getContext() throws Exception { 218 PackageManager pkgMgr = mock(PackageManager.class); 219 when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true); 220 221 Context context = mock(Context.class); 222 when(context.getPackageManager()).thenReturn(pkgMgr); 223 when(context.getContentResolver()).thenReturn(mock(ContentResolver.class)); 224 225 MockResources resources = new com.android.server.wifi.MockResources(); 226 when(context.getResources()).thenReturn(resources); 227 228 ContentResolver cr = mock(ContentResolver.class); 229 when(context.getContentResolver()).thenReturn(cr); 230 231 when(context.getSystemService(Context.POWER_SERVICE)).thenReturn( 232 new PowerManager(context, mock(IPowerManager.class), new Handler())); 233 234 mAlarmManager = new MockAlarmManager(); 235 when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( 236 mAlarmManager.getAlarmManager()); 237 238 when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( 239 mock(ConnectivityManager.class)); 240 241 when(context.getSystemService(Context.WIFI_SCANNING_SERVICE)).thenReturn(mWifiScanner); 242 243 return context; 244 } 245 246 private Resources getMockResources() { 247 MockResources resources = new MockResources(); 248 resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false); 249 return resources; 250 } 251 252 private IState getCurrentState() throws 253 NoSuchMethodException, InvocationTargetException, IllegalAccessException { 254 Method method = StateMachine.class.getDeclaredMethod("getCurrentState"); 255 method.setAccessible(true); 256 return (IState) method.invoke(mWsm); 257 } 258 259 private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws 260 NoSuchFieldException, InvocationTargetException, IllegalAccessException { 261 Field field = StateMachine.class.getDeclaredField("mSmThread"); 262 field.setAccessible(true); 263 return (HandlerThread) field.get(wsm); 264 } 265 266 private static void stopLooper(final Looper looper) throws Exception { 267 new Handler(looper).post(new Runnable() { 268 @Override 269 public void run() { 270 looper.quitSafely(); 271 } 272 }); 273 } 274 275 private void dumpState() { 276 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 277 PrintWriter writer = new PrintWriter(stream); 278 mWsm.dump(null, writer, null); 279 writer.flush(); 280 Log.d(TAG, "WifiStateMachine state -" + stream.toString()); 281 } 282 283 private static ScanDetail getGoogleGuestScanDetail(int rssi) { 284 ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1]; 285 ie[0] = ScanResults.generateSsidIe(sSSID); 286 NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq); 287 ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq, 288 Long.MAX_VALUE, /* needed so that scan results aren't rejected because 289 there older than scan start */ 290 ie, new ArrayList<String>()); 291 return detail; 292 } 293 294 private ArrayList<ScanDetail> getMockScanResults() { 295 ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825); 296 ArrayList<ScanDetail> list = sr.getScanDetailArrayList(); 297 298 int rssi = -65; 299 list.add(getGoogleGuestScanDetail(rssi)); 300 return list; 301 } 302 303 static final String sSSID = "\"GoogleGuest\""; 304 static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); 305 static final String sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", ""); 306 static final String sBSSID = "01:02:03:04:05:06"; 307 static final int sFreq = 2437; 308 309 WifiStateMachine mWsm; 310 HandlerThread mWsmThread; 311 HandlerThread mP2pThread; 312 HandlerThread mSyncThread; 313 AsyncChannel mWsmAsyncChannel; 314 MockAlarmManager mAlarmManager; 315 MockWifiMonitor mWifiMonitor; 316 TestIpManager mTestIpManager; 317 MockLooper mLooper; 318 WifiConfigManager mWifiConfigManager; 319 320 @Mock WifiNative mWifiNative; 321 @Mock WifiScanner mWifiScanner; 322 @Mock SupplicantStateTracker mSupplicantStateTracker; 323 @Mock WifiMetrics mWifiMetrics; 324 @Mock UserManager mUserManager; 325 @Mock WifiApConfigStore mApConfigStore; 326 @Mock BackupManagerProxy mBackupManagerProxy; 327 @Mock WifiCountryCode mCountryCode; 328 329 public WifiStateMachineTest() throws Exception { 330 } 331 332 @Before 333 public void setUp() throws Exception { 334 Log.d(TAG, "Setting up ..."); 335 336 // Ensure looper exists 337 mLooper = new MockLooper(); 338 339 MockitoAnnotations.initMocks(this); 340 341 /** uncomment this to enable logs from WifiStateMachines */ 342 // enableDebugLogs(); 343 344 TestUtil.installWlanWifiNative(mWifiNative); 345 mWifiMonitor = new MockWifiMonitor(); 346 mWifiMetrics = mock(WifiMetrics.class); 347 WifiInjector wifiInjector = mock(WifiInjector.class); 348 when(wifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 349 FrameworkFacade factory = getFrameworkFacade(); 350 Context context = getContext(); 351 352 Resources resources = getMockResources(); 353 when(context.getResources()).thenReturn(resources); 354 355 when(factory.getIntegerSetting(context, 356 Settings.Global.WIFI_FREQUENCY_BAND, 357 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn( 358 WifiManager.WIFI_FREQUENCY_BAND_AUTO); 359 360 when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy))) 361 .thenReturn(mApConfigStore); 362 363 when(factory.makeSupplicantStateTracker( 364 any(Context.class), any(WifiConfigManager.class), 365 any(Handler.class))).thenReturn(mSupplicantStateTracker); 366 367 when(mUserManager.getProfileParent(11)) 368 .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0)); 369 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList( 370 new UserInfo(UserHandle.USER_SYSTEM, "owner", 0), 371 new UserInfo(11, "managed profile", 0))); 372 373 mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(), 374 mUserManager, wifiInjector, mBackupManagerProxy, mCountryCode); 375 mWsmThread = getWsmHandlerThread(mWsm); 376 377 final AsyncChannel channel = new AsyncChannel(); 378 Handler handler = new Handler(mLooper.getLooper()) { 379 @Override 380 public void handleMessage(Message msg) { 381 switch (msg.what) { 382 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 383 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 384 mWsmAsyncChannel = channel; 385 } else { 386 Log.d(TAG, "Failed to connect Command channel " + this); 387 } 388 break; 389 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 390 Log.d(TAG, "Command channel disconnected" + this); 391 break; 392 } 393 } 394 }; 395 396 channel.connect(context, handler, mWsm.getMessenger()); 397 mLooper.dispatchAll(); 398 /* Now channel is supposed to be connected */ 399 400 mBinderToken = Binder.clearCallingIdentity(); 401 } 402 403 @After 404 public void cleanUp() throws Exception { 405 Binder.restoreCallingIdentity(mBinderToken); 406 407 if (mSyncThread != null) stopLooper(mSyncThread.getLooper()); 408 if (mWsmThread != null) stopLooper(mWsmThread.getLooper()); 409 if (mP2pThread != null) stopLooper(mP2pThread.getLooper()); 410 411 mWsmThread = null; 412 mP2pThread = null; 413 mSyncThread = null; 414 mWsmAsyncChannel = null; 415 mWsm = null; 416 } 417 418 @Test 419 public void createNew() throws Exception { 420 assertEquals("InitialState", getCurrentState().getName()); 421 422 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 423 mLooper.dispatchAll(); 424 assertEquals("InitialState", getCurrentState().getName()); 425 } 426 427 @Test 428 public void loadComponents() throws Exception { 429 when(mWifiNative.loadDriver()).thenReturn(true); 430 when(mWifiNative.startHal()).thenReturn(true); 431 when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true); 432 mWsm.setSupplicantRunning(true); 433 mLooper.dispatchAll(); 434 435 assertEquals("SupplicantStartingState", getCurrentState().getName()); 436 437 when(mWifiNative.setBand(anyInt())).thenReturn(true); 438 when(mWifiNative.setDeviceName(anyString())).thenReturn(true); 439 when(mWifiNative.setManufacturer(anyString())).thenReturn(true); 440 when(mWifiNative.setModelName(anyString())).thenReturn(true); 441 when(mWifiNative.setModelNumber(anyString())).thenReturn(true); 442 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 443 when(mWifiNative.setConfigMethods(anyString())).thenReturn(true); 444 when(mWifiNative.setDeviceType(anyString())).thenReturn(true); 445 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 446 when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true); 447 when(mWifiNative.enableBackgroundScan(anyBoolean(), 448 any(ArrayList.class))).thenReturn(true); 449 450 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 451 mLooper.dispatchAll(); 452 453 assertEquals("DisconnectedState", getCurrentState().getName()); 454 } 455 456 @Test 457 public void loadComponentsFailure() throws Exception { 458 when(mWifiNative.loadDriver()).thenReturn(false); 459 when(mWifiNative.startHal()).thenReturn(false); 460 when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(false); 461 462 mWsm.setSupplicantRunning(true); 463 mLooper.dispatchAll(); 464 assertEquals("InitialState", getCurrentState().getName()); 465 466 when(mWifiNative.loadDriver()).thenReturn(true); 467 mWsm.setSupplicantRunning(true); 468 mLooper.dispatchAll(); 469 assertEquals("InitialState", getCurrentState().getName()); 470 471 when(mWifiNative.startHal()).thenReturn(true); 472 mWsm.setSupplicantRunning(true); 473 mLooper.dispatchAll(); 474 assertEquals("InitialState", getCurrentState().getName()); 475 } 476 477 private void addNetworkAndVerifySuccess() throws Exception { 478 addNetworkAndVerifySuccess(false); 479 } 480 481 private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception { 482 loadComponents(); 483 484 final HashMap<String, String> nameToValue = new HashMap<String, String>(); 485 486 when(mWifiNative.addNetwork()).thenReturn(0); 487 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())) 488 .then(new AnswerWithArguments() { 489 public boolean answer(int netId, String name, String value) { 490 if (netId != 0) { 491 Log.d(TAG, "Can't set var " + name + " for " + netId); 492 return false; 493 } 494 495 Log.d(TAG, "Setting var " + name + " to " + value + " for " + netId); 496 nameToValue.put(name, value); 497 return true; 498 } 499 }); 500 501 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 502 .then(new AnswerWithArguments() { 503 public boolean answer(int netId, String name, Map<String, String> values) { 504 if (netId != 0) { 505 Log.d(TAG, "Can't set extra " + name + " for " + netId); 506 return false; 507 } 508 509 Log.d(TAG, "Setting extra for " + netId); 510 return true; 511 } 512 }); 513 514 when(mWifiNative.getNetworkVariable(anyInt(), anyString())) 515 .then(new AnswerWithArguments() { 516 public String answer(int netId, String name) throws Throwable { 517 if (netId != 0) { 518 Log.d(TAG, "Can't find var " + name + " for " + netId); 519 return null; 520 } 521 String value = nameToValue.get(name); 522 if (value != null) { 523 Log.d(TAG, "Returning var " + name + " to " + value + " for " + netId); 524 } else { 525 Log.d(TAG, "Can't find var " + name + " for " + netId); 526 } 527 return value; 528 } 529 }); 530 531 WifiConfiguration config = new WifiConfiguration(); 532 config.SSID = sSSID; 533 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 534 config.hiddenSSID = isHidden; 535 mLooper.startAutoDispatch(); 536 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 537 mLooper.stopAutoDispatch(); 538 539 verify(mWifiNative).addNetwork(); 540 verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID); 541 if (isHidden) { 542 verify(mWifiNative).setNetworkVariable(0, "scan_ssid", Integer.toString(1)); 543 } 544 545 mLooper.startAutoDispatch(); 546 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 547 mLooper.stopAutoDispatch(); 548 assertEquals(1, configs.size()); 549 550 WifiConfiguration config2 = configs.get(0); 551 assertEquals("\"GoogleGuest\"", config2.SSID); 552 assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); 553 } 554 555 private void addNetworkAndVerifyFailure() throws Exception { 556 loadComponents(); 557 558 final WifiConfiguration config = new WifiConfiguration(); 559 config.SSID = sSSID; 560 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 561 562 mLooper.startAutoDispatch(); 563 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 564 mLooper.stopAutoDispatch(); 565 566 verify(mWifiNative, never()).addNetwork(); 567 verify(mWifiNative, never()).setNetworkVariable(anyInt(), anyString(), anyString()); 568 569 mLooper.startAutoDispatch(); 570 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 571 mLooper.stopAutoDispatch(); 572 } 573 574 /** 575 * Verifies that the current foreground user is allowed to add a network. 576 */ 577 @Test 578 public void addNetworkAsCurrentUser() throws Exception { 579 addNetworkAndVerifySuccess(); 580 } 581 582 /** 583 * Verifies that a managed profile of the current foreground user is allowed to add a network. 584 */ 585 @Test 586 public void addNetworkAsCurrentUsersManagedProfile() throws Exception { 587 BinderUtil.setUid(MANAGED_PROFILE_UID); 588 addNetworkAndVerifySuccess(); 589 } 590 591 /** 592 * Verifies that a background user is not allowed to add a network. 593 */ 594 @Test 595 public void addNetworkAsOtherUser() throws Exception { 596 BinderUtil.setUid(OTHER_USER_UID); 597 addNetworkAndVerifyFailure(); 598 } 599 600 private void removeNetworkAndVerifySuccess() throws Exception { 601 when(mWifiNative.removeNetwork(0)).thenReturn(true); 602 mLooper.startAutoDispatch(); 603 assertTrue(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0)); 604 mLooper.stopAutoDispatch(); 605 606 mLooper.startAutoDispatch(); 607 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 608 mLooper.stopAutoDispatch(); 609 } 610 611 private void removeNetworkAndVerifyFailure() throws Exception { 612 mLooper.startAutoDispatch(); 613 assertFalse(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0)); 614 mLooper.stopAutoDispatch(); 615 616 mLooper.startAutoDispatch(); 617 assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size()); 618 mLooper.stopAutoDispatch(); 619 verify(mWifiNative, never()).removeNetwork(anyInt()); 620 } 621 622 /** 623 * Verifies that the current foreground user is allowed to remove a network. 624 */ 625 @Test 626 public void removeNetworkAsCurrentUser() throws Exception { 627 addNetworkAndVerifySuccess(); 628 removeNetworkAndVerifySuccess(); 629 } 630 631 /** 632 * Verifies that a managed profile of the current foreground user is allowed to remove a 633 * network. 634 */ 635 @Test 636 public void removeNetworkAsCurrentUsersManagedProfile() throws Exception { 637 addNetworkAndVerifySuccess(); 638 BinderUtil.setUid(MANAGED_PROFILE_UID); 639 removeNetworkAndVerifySuccess(); 640 } 641 642 /** 643 * Verifies that a background user is not allowed to remove a network. 644 */ 645 @Test 646 public void removeNetworkAsOtherUser() throws Exception { 647 addNetworkAndVerifySuccess(); 648 BinderUtil.setUid(OTHER_USER_UID); 649 removeNetworkAndVerifyFailure(); 650 } 651 652 private void enableNetworkAndVerifySuccess() throws Exception { 653 when(mWifiNative.selectNetwork(0)).thenReturn(true); 654 655 mLooper.startAutoDispatch(); 656 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 657 mLooper.stopAutoDispatch(); 658 659 verify(mWifiNative).selectNetwork(0); 660 } 661 662 private void enableNetworkAndVerifyFailure() throws Exception { 663 mLooper.startAutoDispatch(); 664 assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 665 mLooper.stopAutoDispatch(); 666 667 verify(mWifiNative, never()).selectNetwork(anyInt()); 668 } 669 670 /** 671 * Verifies that the current foreground user is allowed to enable a network. 672 */ 673 @Test 674 public void enableNetworkAsCurrentUser() throws Exception { 675 addNetworkAndVerifySuccess(); 676 enableNetworkAndVerifySuccess(); 677 } 678 679 /** 680 * Verifies that a managed profile of the current foreground user is allowed to enable a 681 * network. 682 */ 683 @Test 684 public void enableNetworkAsCurrentUsersManagedProfile() throws Exception { 685 addNetworkAndVerifySuccess(); 686 BinderUtil.setUid(MANAGED_PROFILE_UID); 687 enableNetworkAndVerifySuccess(); 688 } 689 690 /** 691 * Verifies that a background user is not allowed to enable a network. 692 */ 693 @Test 694 public void enableNetworkAsOtherUser() throws Exception { 695 addNetworkAndVerifySuccess(); 696 BinderUtil.setUid(OTHER_USER_UID); 697 enableNetworkAndVerifyFailure(); 698 } 699 700 private void forgetNetworkAndVerifySuccess() throws Exception { 701 when(mWifiNative.removeNetwork(0)).thenReturn(true); 702 mLooper.startAutoDispatch(); 703 final Message result = 704 mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0); 705 mLooper.stopAutoDispatch(); 706 assertEquals(WifiManager.FORGET_NETWORK_SUCCEEDED, result.what); 707 result.recycle(); 708 mLooper.startAutoDispatch(); 709 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 710 mLooper.stopAutoDispatch(); 711 } 712 713 private void forgetNetworkAndVerifyFailure() throws Exception { 714 mLooper.startAutoDispatch(); 715 final Message result = 716 mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0); 717 mLooper.stopAutoDispatch(); 718 assertEquals(WifiManager.FORGET_NETWORK_FAILED, result.what); 719 result.recycle(); 720 mLooper.startAutoDispatch(); 721 assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size()); 722 mLooper.stopAutoDispatch(); 723 verify(mWifiNative, never()).removeNetwork(anyInt()); 724 } 725 726 /** 727 * Verifies that the current foreground user is allowed to forget a network. 728 */ 729 @Test 730 public void forgetNetworkAsCurrentUser() throws Exception { 731 addNetworkAndVerifySuccess(); 732 forgetNetworkAndVerifySuccess(); 733 } 734 735 /** 736 * Verifies that a managed profile of the current foreground user is allowed to forget a 737 * network. 738 */ 739 @Test 740 public void forgetNetworkAsCurrentUsersManagedProfile() throws Exception { 741 addNetworkAndVerifySuccess(); 742 BinderUtil.setUid(MANAGED_PROFILE_UID); 743 forgetNetworkAndVerifySuccess(); 744 } 745 746 /** 747 * Verifies that a background user is not allowed to forget a network. 748 */ 749 @Test 750 public void forgetNetworkAsOtherUser() throws Exception { 751 addNetworkAndVerifySuccess(); 752 BinderUtil.setUid(OTHER_USER_UID); 753 forgetNetworkAndVerifyFailure(); 754 } 755 756 private void verifyScan(int band, int reportEvents, Set<Integer> configuredNetworkIds) { 757 ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor = 758 ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); 759 ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor = 760 ArgumentCaptor.forClass(WifiScanner.ScanListener.class); 761 verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture()); 762 WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue(); 763 assertEquals("band", band, actualSettings.band); 764 assertEquals("reportEvents", reportEvents, actualSettings.reportEvents); 765 766 if (configuredNetworkIds == null) { 767 configuredNetworkIds = new HashSet<>(); 768 } 769 Set<Integer> actualConfiguredNetworkIds = new HashSet<>(); 770 if (actualSettings.hiddenNetworkIds != null) { 771 for (int i = 0; i < actualSettings.hiddenNetworkIds.length; ++i) { 772 actualConfiguredNetworkIds.add(actualSettings.hiddenNetworkIds[i]); 773 } 774 } 775 assertEquals("configured networks", configuredNetworkIds, actualConfiguredNetworkIds); 776 777 when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); 778 mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); 779 780 mLooper.dispatchAll(); 781 782 List<ScanResult> reportedResults = mWsm.syncGetScanResultsList(); 783 assertEquals(8, reportedResults.size()); 784 } 785 786 @Test 787 public void scan() throws Exception { 788 addNetworkAndVerifySuccess(); 789 790 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 791 mWsm.startScan(-1, 0, null, null); 792 mLooper.dispatchAll(); 793 794 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 795 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 796 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null); 797 } 798 799 @Test 800 public void scanWithHiddenNetwork() throws Exception { 801 addNetworkAndVerifySuccess(true); 802 803 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 804 mWsm.startScan(-1, 0, null, null); 805 mLooper.dispatchAll(); 806 807 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 808 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 809 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 810 mWifiConfigManager.getHiddenConfiguredNetworkIds()); 811 } 812 813 @Test 814 public void connect() throws Exception { 815 addNetworkAndVerifySuccess(); 816 817 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 818 mLooper.dispatchAll(); 819 820 mLooper.startAutoDispatch(); 821 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 822 mLooper.stopAutoDispatch(); 823 824 verify(mWifiNative).selectNetwork(0); 825 826 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 827 mLooper.dispatchAll(); 828 829 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 830 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 831 mLooper.dispatchAll(); 832 833 assertEquals("ObtainingIpState", getCurrentState().getName()); 834 835 DhcpResults dhcpResults = new DhcpResults(); 836 dhcpResults.setGateway("1.2.3.4"); 837 dhcpResults.setIpAddress("192.168.1.100", 0); 838 dhcpResults.addDns("8.8.8.8"); 839 dhcpResults.setLeaseDuration(3600); 840 841 mTestIpManager.injectDhcpSuccess(dhcpResults); 842 mLooper.dispatchAll(); 843 844 assertEquals("ConnectedState", getCurrentState().getName()); 845 } 846 847 @Test 848 public void testDhcpFailure() throws Exception { 849 addNetworkAndVerifySuccess(); 850 851 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 852 mLooper.dispatchAll(); 853 854 mLooper.startAutoDispatch(); 855 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 856 mLooper.stopAutoDispatch(); 857 858 verify(mWifiNative).selectNetwork(0); 859 860 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 861 mLooper.dispatchAll(); 862 863 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 864 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 865 mLooper.dispatchAll(); 866 867 assertEquals("ObtainingIpState", getCurrentState().getName()); 868 869 mTestIpManager.injectDhcpFailure(); 870 mLooper.dispatchAll(); 871 872 assertEquals("DisconnectingState", getCurrentState().getName()); 873 } 874 875 @Test 876 public void testBadNetworkEvent() throws Exception { 877 addNetworkAndVerifySuccess(); 878 879 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 880 mLooper.dispatchAll(); 881 882 mLooper.startAutoDispatch(); 883 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 884 mLooper.stopAutoDispatch(); 885 886 verify(mWifiNative).selectNetwork(0); 887 888 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); 889 mLooper.dispatchAll(); 890 891 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 892 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 893 mLooper.dispatchAll(); 894 895 assertEquals("DisconnectedState", getCurrentState().getName()); 896 } 897 898 899 @Test 900 public void smToString() throws Exception { 901 assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString( 902 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED)); 903 assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString( 904 DhcpClient.CMD_PRE_DHCP_ACTION)); 905 assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString( 906 WifiStateMachine.CMD_IP_REACHABILITY_LOST)); 907 } 908 909 @Test 910 public void disconnect() throws Exception { 911 connect(); 912 913 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06"); 914 mLooper.dispatchAll(); 915 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 916 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); 917 mLooper.dispatchAll(); 918 919 assertEquals("DisconnectedState", getCurrentState().getName()); 920 } 921 922 @Test 923 public void handleUserSwitch() throws Exception { 924 assertEquals(UserHandle.USER_SYSTEM, mWsm.getCurrentUserId()); 925 926 mWsm.handleUserSwitch(10); 927 mLooper.dispatchAll(); 928 929 assertEquals(10, mWsm.getCurrentUserId()); 930 } 931 932 @Test 933 public void iconQueryTest() throws Exception { 934 /* enable wi-fi */ 935 addNetworkAndVerifySuccess(); 936 937 long bssid = 0x1234567800FFL; 938 String filename = "iconFileName.png"; 939 String command = "REQ_HS20_ICON " + Utils.macToString(bssid) + " " + filename; 940 941 when(mWifiNative.doCustomSupplicantCommand(command)).thenReturn("OK"); 942 943 mLooper.startAutoDispatch(); 944 boolean result = mWsm.syncQueryPasspointIcon(mWsmAsyncChannel, bssid, filename); 945 mLooper.stopAutoDispatch(); 946 947 verify(mWifiNative).doCustomSupplicantCommand(command); 948 assertEquals(true, result); 949 } 950 951 private String createSimChallengeRequest(byte[] challengeValue) { 952 // Produce a base64 encoded length byte + data. 953 byte[] challengeLengthAndValue = new byte[challengeValue.length + 1]; 954 challengeLengthAndValue[0] = (byte) challengeValue.length; 955 for (int i = 0; i < challengeValue.length; ++i) { 956 challengeLengthAndValue[i + 1] = challengeValue[i]; 957 } 958 return Base64.encodeToString(challengeLengthAndValue, android.util.Base64.NO_WRAP); 959 } 960 961 private String createSimAuthResponse(byte[] sresValue, byte[] kcValue) { 962 // Produce a base64 encoded sres length byte + sres + kc length byte + kc. 963 int overallLength = sresValue.length + kcValue.length + 2; 964 byte[] result = new byte[sresValue.length + kcValue.length + 2]; 965 int idx = 0; 966 result[idx++] = (byte) sresValue.length; 967 for (int i = 0; i < sresValue.length; ++i) { 968 result[idx++] = sresValue[i]; 969 } 970 result[idx++] = (byte) kcValue.length; 971 for (int i = 0; i < kcValue.length; ++i) { 972 result[idx++] = kcValue[i]; 973 } 974 return Base64.encodeToString(result, Base64.NO_WRAP); 975 } 976 977 /** Verifies function getGsmSimAuthResponse method. */ 978 @Test 979 public void getGsmSimAuthResponseTest() throws Exception { 980 TelephonyManager tm = mock(TelephonyManager.class); 981 final String[] invalidRequests = { null, "", "XXXX" }; 982 assertEquals("", mWsm.getGsmSimAuthResponse(invalidRequests, tm)); 983 984 final String[] failedRequests = { "5E5F" }; 985 when(tm.getIccSimChallengeResponse(anyInt(), 986 eq(createSimChallengeRequest(new byte[] { 0x5e, 0x5f })))).thenReturn(null); 987 assertEquals(null, mWsm.getGsmSimAuthResponse(failedRequests, tm)); 988 989 when(tm.getIccSimChallengeResponse(2, createSimChallengeRequest(new byte[] { 0x1a, 0x2b }))) 990 .thenReturn(null); 991 when(tm.getIccSimChallengeResponse(1, createSimChallengeRequest(new byte[] { 0x1a, 0x2b }))) 992 .thenReturn(createSimAuthResponse(new byte[] { 0x1D, 0x2C }, 993 new byte[] { 0x3B, 0x4A })); 994 when(tm.getIccSimChallengeResponse(1, createSimChallengeRequest(new byte[] { 0x01, 0x23 }))) 995 .thenReturn(createSimAuthResponse(new byte[] { 0x33, 0x22 }, 996 new byte[] { 0x11, 0x00 })); 997 assertEquals(":3b4a:1d2c:1100:3322", mWsm.getGsmSimAuthResponse( 998 new String[] { "1A2B", "0123" }, tm)); 999 } 1000} 1001