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