WifiStateMachineTest.java revision af0e32cfa2f7402c60b9df88a0d9bd19f421026c
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.assertNull; 22import static org.junit.Assert.assertTrue; 23import static org.mockito.Mockito.*; 24 25import android.app.ActivityManager; 26import android.app.test.MockAnswerUtil.AnswerWithArguments; 27import android.app.test.TestAlarmManager; 28import android.content.Context; 29import android.content.pm.PackageManager; 30import android.content.pm.UserInfo; 31import android.content.res.Resources; 32import android.net.ConnectivityManager; 33import android.net.DhcpResults; 34import android.net.LinkProperties; 35import android.net.dhcp.DhcpClient; 36import android.net.ip.IpManager; 37import android.net.wifi.IApInterface; 38import android.net.wifi.IClientInterface; 39import android.net.wifi.IWificond; 40import android.net.wifi.ScanResult; 41import android.net.wifi.SupplicantState; 42import android.net.wifi.WifiConfiguration; 43import android.net.wifi.WifiInfo; 44import android.net.wifi.WifiManager; 45import android.net.wifi.WifiScanner; 46import android.net.wifi.WifiSsid; 47import android.net.wifi.WpsInfo; 48import android.net.wifi.hotspot2.PasspointConfiguration; 49import android.net.wifi.hotspot2.pps.HomeSp; 50import android.net.wifi.p2p.IWifiP2pManager; 51import android.os.BatteryStats; 52import android.os.Binder; 53import android.os.Bundle; 54import android.os.Handler; 55import android.os.HandlerThread; 56import android.os.IBinder; 57import android.os.IInterface; 58import android.os.INetworkManagementService; 59import android.os.IPowerManager; 60import android.os.Looper; 61import android.os.Message; 62import android.os.Messenger; 63import android.os.PowerManager; 64import android.os.RemoteException; 65import android.os.UserHandle; 66import android.os.UserManager; 67import android.os.test.TestLooper; 68import android.provider.Settings; 69import android.security.KeyStore; 70import android.test.mock.MockContentProvider; 71import android.test.mock.MockContentResolver; 72import android.test.suitebuilder.annotation.SmallTest; 73import android.util.Log; 74import android.util.SparseArray; 75 76import com.android.internal.R; 77import com.android.internal.app.IBatteryStats; 78import com.android.internal.util.AsyncChannel; 79import com.android.internal.util.IState; 80import com.android.internal.util.StateMachine; 81import com.android.server.wifi.hotspot2.NetworkDetail; 82import com.android.server.wifi.hotspot2.PasspointManager; 83import com.android.server.wifi.p2p.WifiP2pServiceImpl; 84 85import org.junit.After; 86import org.junit.Before; 87import org.junit.Test; 88import org.mockito.ArgumentCaptor; 89import org.mockito.Mock; 90import org.mockito.MockitoAnnotations; 91 92import java.io.ByteArrayOutputStream; 93import java.io.PrintWriter; 94import java.lang.reflect.Field; 95import java.lang.reflect.InvocationTargetException; 96import java.lang.reflect.Method; 97import java.util.ArrayList; 98import java.util.Arrays; 99import java.util.HashSet; 100import java.util.List; 101import java.util.Map; 102import java.util.Set; 103import java.util.concurrent.CountDownLatch; 104 105/** 106 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}. 107 */ 108@SmallTest 109public class WifiStateMachineTest { 110 public static final String TAG = "WifiStateMachineTest"; 111 112 private static final int MANAGED_PROFILE_UID = 1100000; 113 private static final int OTHER_USER_UID = 1200000; 114 private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE = 115 (ActivityManager.isLowRamDeviceStatic() 116 ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY 117 : WifiStateMachine.NUM_LOG_RECS_VERBOSE); 118 private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\""; 119 120 private long mBinderToken; 121 122 private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) { 123 return mock(class1, withSettings().extraInterfaces(interfaces)); 124 } 125 126 private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) { 127 T tImpl = mockWithInterfaces(class1, iface); 128 IBinder binder = mock(IBinder.class); 129 when(((IInterface) tImpl).asBinder()).thenReturn(binder); 130 when(binder.queryLocalInterface(iface.getCanonicalName())) 131 .thenReturn((IInterface) tImpl); 132 return binder; 133 } 134 135 private void enableDebugLogs() { 136 mWsm.enableVerboseLogging(1); 137 } 138 139 private class TestIpManager extends IpManager { 140 TestIpManager(Context context, String ifname, IpManager.Callback callback) { 141 // Call dependency-injection superclass constructor. 142 super(context, ifname, callback, mock(INetworkManagementService.class)); 143 } 144 145 @Override 146 public void startProvisioning(IpManager.ProvisioningConfiguration config) {} 147 148 @Override 149 public void stop() {} 150 151 @Override 152 public void confirmConfiguration() {} 153 154 void injectDhcpSuccess(DhcpResults dhcpResults) { 155 mCallback.onNewDhcpResults(dhcpResults); 156 mCallback.onProvisioningSuccess(new LinkProperties()); 157 } 158 159 void injectDhcpFailure() { 160 mCallback.onNewDhcpResults(null); 161 mCallback.onProvisioningFailure(new LinkProperties()); 162 } 163 } 164 165 private FrameworkFacade getFrameworkFacade() throws Exception { 166 FrameworkFacade facade = mock(FrameworkFacade.class); 167 168 when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn( 169 mockWithInterfaces(IBinder.class, INetworkManagementService.class)); 170 171 IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class); 172 when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder); 173 174 WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface( 175 IWifiP2pManager.class.getCanonicalName()); 176 177 final CountDownLatch untilDone = new CountDownLatch(1); 178 mP2pThread = new HandlerThread("WifiP2pMockThread") { 179 @Override 180 protected void onLooperPrepared() { 181 untilDone.countDown(); 182 } 183 }; 184 185 mP2pThread.start(); 186 untilDone.await(); 187 188 Handler handler = new Handler(mP2pThread.getLooper()); 189 when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler)); 190 191 IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class); 192 when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder); 193 194 when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class))) 195 .then(new AnswerWithArguments() { 196 public IpManager answer( 197 Context context, String ifname, IpManager.Callback callback) { 198 mTestIpManager = new TestIpManager(context, ifname, callback); 199 return mTestIpManager; 200 } 201 }); 202 203 return facade; 204 } 205 206 private Context getContext() throws Exception { 207 PackageManager pkgMgr = mock(PackageManager.class); 208 when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true); 209 210 Context context = mock(Context.class); 211 when(context.getPackageManager()).thenReturn(pkgMgr); 212 213 MockResources resources = new com.android.server.wifi.MockResources(); 214 when(context.getResources()).thenReturn(resources); 215 216 MockContentResolver mockContentResolver = new MockContentResolver(); 217 mockContentResolver.addProvider(Settings.AUTHORITY, 218 new MockContentProvider(context) { 219 @Override 220 public Bundle call(String method, String arg, Bundle extras) { 221 return new Bundle(); 222 } 223 }); 224 when(context.getContentResolver()).thenReturn(mockContentResolver); 225 226 when(context.getSystemService(Context.POWER_SERVICE)).thenReturn( 227 new PowerManager(context, mock(IPowerManager.class), new Handler())); 228 229 mAlarmManager = new TestAlarmManager(); 230 when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( 231 mAlarmManager.getAlarmManager()); 232 233 when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( 234 mock(ConnectivityManager.class)); 235 236 return context; 237 } 238 239 private Resources getMockResources() { 240 MockResources resources = new MockResources(); 241 resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false); 242 return resources; 243 } 244 245 private IState getCurrentState() throws 246 NoSuchMethodException, InvocationTargetException, IllegalAccessException { 247 Method method = StateMachine.class.getDeclaredMethod("getCurrentState"); 248 method.setAccessible(true); 249 return (IState) method.invoke(mWsm); 250 } 251 252 private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws 253 NoSuchFieldException, InvocationTargetException, IllegalAccessException { 254 Field field = StateMachine.class.getDeclaredField("mSmThread"); 255 field.setAccessible(true); 256 return (HandlerThread) field.get(wsm); 257 } 258 259 private static void stopLooper(final Looper looper) throws Exception { 260 new Handler(looper).post(new Runnable() { 261 @Override 262 public void run() { 263 looper.quitSafely(); 264 } 265 }); 266 } 267 268 private void dumpState() { 269 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 270 PrintWriter writer = new PrintWriter(stream); 271 mWsm.dump(null, writer, null); 272 writer.flush(); 273 Log.d(TAG, "WifiStateMachine state -" + stream.toString()); 274 } 275 276 private static ScanDetail getGoogleGuestScanDetail(int rssi) { 277 ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1]; 278 ie[0] = ScanResults.generateSsidIe(sSSID); 279 NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq); 280 ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq, 281 Long.MAX_VALUE, /* needed so that scan results aren't rejected because 282 there older than scan start */ 283 ie, new ArrayList<String>()); 284 return detail; 285 } 286 287 private ArrayList<ScanDetail> getMockScanResults() { 288 ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825); 289 ArrayList<ScanDetail> list = sr.getScanDetailArrayList(); 290 291 int rssi = -65; 292 list.add(getGoogleGuestScanDetail(rssi)); 293 return list; 294 } 295 296 static final String sSSID = "\"GoogleGuest\""; 297 static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); 298 static final String sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", ""); 299 static final String sBSSID = "01:02:03:04:05:06"; 300 static final int sFreq = 2437; 301 302 WifiStateMachine mWsm; 303 HandlerThread mWsmThread; 304 HandlerThread mP2pThread; 305 HandlerThread mSyncThread; 306 AsyncChannel mWsmAsyncChannel; 307 TestAlarmManager mAlarmManager; 308 MockWifiMonitor mWifiMonitor; 309 TestIpManager mTestIpManager; 310 TestLooper mLooper; 311 312 @Mock WifiScanner mWifiScanner; 313 @Mock SupplicantStateTracker mSupplicantStateTracker; 314 @Mock WifiMetrics mWifiMetrics; 315 @Mock UserManager mUserManager; 316 @Mock WifiApConfigStore mApConfigStore; 317 @Mock BackupManagerProxy mBackupManagerProxy; 318 @Mock WifiCountryCode mCountryCode; 319 @Mock WifiInjector mWifiInjector; 320 @Mock WifiLastResortWatchdog mWifiLastResortWatchdog; 321 @Mock PropertyService mPropertyService; 322 @Mock BuildProperties mBuildProperties; 323 @Mock IWificond mWificond; 324 @Mock IApInterface mApInterface; 325 @Mock IClientInterface mClientInterface; 326 @Mock IBinder mApInterfaceBinder; 327 @Mock IBinder mClientInterfaceBinder; 328 @Mock WifiConfigManager mWifiConfigManager; 329 @Mock WifiNative mWifiNative; 330 @Mock WifiConnectivityManager mWifiConnectivityManager; 331 @Mock SoftApManager mSoftApManager; 332 @Mock WifiStateTracker mWifiStateTracker; 333 @Mock PasspointManager mPasspointManager; 334 335 public WifiStateMachineTest() throws Exception { 336 } 337 338 @Before 339 public void setUp() throws Exception { 340 Log.d(TAG, "Setting up ..."); 341 342 // Ensure looper exists 343 mLooper = new TestLooper(); 344 345 MockitoAnnotations.initMocks(this); 346 347 /** uncomment this to enable logs from WifiStateMachines */ 348 // enableDebugLogs(); 349 350 mWifiMonitor = new MockWifiMonitor(); 351 when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 352 when(mWifiInjector.getClock()).thenReturn(new Clock()); 353 when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); 354 when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService); 355 when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties); 356 when(mWifiInjector.getKeyStore()).thenReturn(mock(KeyStore.class)); 357 when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class)); 358 when(mWifiInjector.makeWifiDiagnostics(anyObject())).thenReturn( 359 mock(BaseWifiDiagnostics.class)); 360 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 361 when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); 362 when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); 363 when(mWifiInjector.getWifiNetworkSelector()).thenReturn(mock(WifiNetworkSelector.class)); 364 when(mWifiInjector.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean())) 365 .thenReturn(mWifiConnectivityManager); 366 when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class), 367 any(SoftApManager.Listener.class), any(IApInterface.class), 368 any(WifiConfiguration.class))) 369 .thenReturn(mSoftApManager); 370 when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager); 371 when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker); 372 when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor); 373 when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); 374 375 when(mWifiNative.setupForClientMode()).thenReturn(mClientInterface); 376 when(mWifiNative.setupForSoftApMode()).thenReturn(mApInterface); 377 when(mWifiNative.getInterfaceName()).thenReturn("mockWlan"); 378 when(mWifiNative.enableSupplicant()).thenReturn(true); 379 when(mWifiNative.disableSupplicant()).thenReturn(true); 380 when(mWifiNative.getFrameworkNetworkId(anyInt())).thenReturn(0); 381 382 383 FrameworkFacade factory = getFrameworkFacade(); 384 Context context = getContext(); 385 386 Resources resources = getMockResources(); 387 when(context.getResources()).thenReturn(resources); 388 389 when(factory.getIntegerSetting(context, 390 Settings.Global.WIFI_FREQUENCY_BAND, 391 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn( 392 WifiManager.WIFI_FREQUENCY_BAND_AUTO); 393 394 when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy))) 395 .thenReturn(mApConfigStore); 396 397 when(factory.makeSupplicantStateTracker( 398 any(Context.class), any(WifiConfigManager.class), 399 any(Handler.class))).thenReturn(mSupplicantStateTracker); 400 401 when(mUserManager.getProfileParent(11)) 402 .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0)); 403 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList( 404 new UserInfo(UserHandle.USER_SYSTEM, "owner", 0), 405 new UserInfo(11, "managed profile", 0))); 406 407 when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder); 408 when(mClientInterface.asBinder()).thenReturn(mClientInterfaceBinder); 409 410 mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(), 411 mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative); 412 mWsmThread = getWsmHandlerThread(mWsm); 413 414 final AsyncChannel channel = new AsyncChannel(); 415 Handler handler = new Handler(mLooper.getLooper()) { 416 @Override 417 public void handleMessage(Message msg) { 418 switch (msg.what) { 419 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 420 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 421 mWsmAsyncChannel = channel; 422 } else { 423 Log.d(TAG, "Failed to connect Command channel " + this); 424 } 425 break; 426 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 427 Log.d(TAG, "Command channel disconnected" + this); 428 break; 429 } 430 } 431 }; 432 433 channel.connect(context, handler, mWsm.getMessenger()); 434 mLooper.dispatchAll(); 435 /* Now channel is supposed to be connected */ 436 437 mBinderToken = Binder.clearCallingIdentity(); 438 } 439 440 @After 441 public void cleanUp() throws Exception { 442 Binder.restoreCallingIdentity(mBinderToken); 443 444 if (mSyncThread != null) stopLooper(mSyncThread.getLooper()); 445 if (mWsmThread != null) stopLooper(mWsmThread.getLooper()); 446 if (mP2pThread != null) stopLooper(mP2pThread.getLooper()); 447 448 mWsmThread = null; 449 mP2pThread = null; 450 mSyncThread = null; 451 mWsmAsyncChannel = null; 452 mWsm = null; 453 } 454 455 @Test 456 public void createNew() throws Exception { 457 assertEquals("InitialState", getCurrentState().getName()); 458 459 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 460 mLooper.dispatchAll(); 461 assertEquals("InitialState", getCurrentState().getName()); 462 } 463 464 @Test 465 public void loadComponentsInStaMode() throws Exception { 466 startSupplicantAndDispatchMessages(); 467 468 assertEquals("DisconnectedState", getCurrentState().getName()); 469 } 470 471 @Test 472 public void loadComponentsInApMode() throws Exception { 473 mWsm.setHostApRunning(new WifiConfiguration(), true); 474 mLooper.dispatchAll(); 475 476 assertEquals("SoftApState", getCurrentState().getName()); 477 478 verify(mSoftApManager).start(); 479 } 480 481 @Test 482 public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception { 483 when(mWifiNative.enableSupplicant()).thenReturn(false); 484 mWsm.setSupplicantRunning(true); 485 mLooper.dispatchAll(); 486 assertEquals("InitialState", getCurrentState().getName()); 487 } 488 489 @Test 490 public void shouldRequireWificondToLeaveInitialState() throws Exception { 491 // We start out with valid default values, break them going backwards so that 492 // we test all the bailout cases. 493 494 // ClientInterface dies after creation. 495 doThrow(new RemoteException()).when(mClientInterfaceBinder).linkToDeath(any(), anyInt()); 496 mWsm.setSupplicantRunning(true); 497 mLooper.dispatchAll(); 498 assertEquals("InitialState", getCurrentState().getName()); 499 500 // Failed to even create the client interface. 501 when(mWificond.createClientInterface()).thenReturn(null); 502 mWsm.setSupplicantRunning(true); 503 mLooper.dispatchAll(); 504 assertEquals("InitialState", getCurrentState().getName()); 505 506 // Failed to get wificond proxy. 507 when(mWifiInjector.makeWificond()).thenReturn(null); 508 mWsm.setSupplicantRunning(true); 509 mLooper.dispatchAll(); 510 assertEquals("InitialState", getCurrentState().getName()); 511 } 512 513 @Test 514 public void loadComponentsFailure() throws Exception { 515 when(mWifiNative.startHal(anyBoolean())).thenReturn(false); 516 when(mWifiNative.enableSupplicant()).thenReturn(false); 517 518 mWsm.setSupplicantRunning(true); 519 mLooper.dispatchAll(); 520 assertEquals("InitialState", getCurrentState().getName()); 521 522 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 523 mWsm.setSupplicantRunning(true); 524 mLooper.dispatchAll(); 525 assertEquals("InitialState", getCurrentState().getName()); 526 } 527 528 @Test 529 public void checkInitialStateStickyWhenDisabledMode() throws Exception { 530 mLooper.dispatchAll(); 531 assertEquals("InitialState", getCurrentState().getName()); 532 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 533 534 mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE); 535 mLooper.dispatchAll(); 536 assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); 537 assertEquals("InitialState", getCurrentState().getName()); 538 } 539 540 @Test 541 public void shouldStartSupplicantWhenConnectModeRequested() throws Exception { 542 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 543 544 // The first time we start out in InitialState, we sit around here. 545 mLooper.dispatchAll(); 546 assertEquals("InitialState", getCurrentState().getName()); 547 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 548 549 // But if someone tells us to enter connect mode, we start up supplicant 550 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 551 mLooper.dispatchAll(); 552 assertEquals("SupplicantStartingState", getCurrentState().getName()); 553 } 554 555 /** 556 * Test that mode changes accurately reflect the value for isWifiEnabled. 557 */ 558 @Test 559 public void checkIsWifiEnabledForModeChanges() throws Exception { 560 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 561 562 // Check initial state 563 mLooper.dispatchAll(); 564 assertEquals("InitialState", getCurrentState().getName()); 565 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 566 567 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); 568 startSupplicantAndDispatchMessages(); 569 mWsm.setSupplicantRunning(true); 570 mLooper.dispatchAll(); 571 assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); 572 assertEquals("ScanModeState", getCurrentState().getName()); 573 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 574 575 // switch to connect mode and verify wifi is reported as enabled 576 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 577 mLooper.dispatchAll(); 578 assertEquals("DisconnectedState", getCurrentState().getName()); 579 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 580 assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); 581 582 // now go back to scan mode with "wifi disabled" to verify the reported wifi state. 583 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE); 584 mLooper.dispatchAll(); 585 assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE, 586 mWsm.getOperationalModeForTest()); 587 assertEquals("ScanModeState", getCurrentState().getName()); 588 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 589 590 // now go to AP mode 591 mWsm.setSupplicantRunning(false); 592 mWsm.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP); 593 mWsm.sendMessage(WifiMonitor.SUP_DISCONNECTION_EVENT); 594 mWsm.setHostApRunning(new WifiConfiguration(), true); 595 mLooper.dispatchAll(); 596 assertEquals("SoftApState", getCurrentState().getName()); 597 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 598 } 599 600 601 /** 602 * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant 603 * is started. 604 */ 605 @Test 606 public void checkStartInCorrectStateAfterChangingInitialState() throws Exception { 607 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 608 609 // Check initial state 610 mLooper.dispatchAll(); 611 assertEquals("InitialState", getCurrentState().getName()); 612 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 613 614 // Update the mode 615 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); 616 mLooper.dispatchAll(); 617 assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); 618 619 // Start supplicant so we move to the next state 620 startSupplicantAndDispatchMessages(); 621 622 assertEquals("ScanModeState", getCurrentState().getName()); 623 } 624 625 /** 626 * Verifies that configs can be removed when in client mode. 627 */ 628 @Test 629 public void canRemoveNetworkConfigInClientMode() throws Exception { 630 boolean result; 631 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 632 addNetworkAndVerifySuccess(); 633 mLooper.startAutoDispatch(); 634 result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0); 635 mLooper.stopAutoDispatch(); 636 assertTrue(result); 637 } 638 639 /** 640 * Verifies that configs can be removed when not in client mode. 641 */ 642 @Test 643 public void canRemoveNetworkConfigWhenWifiDisabled() { 644 boolean result; 645 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 646 mLooper.startAutoDispatch(); 647 result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0); 648 mLooper.stopAutoDispatch(); 649 650 assertTrue(result); 651 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 652 } 653 654 /** 655 * Verifies that configs can be forgotten when in client mode. 656 */ 657 @Test 658 public void canForgetNetworkConfigInClientMode() throws Exception { 659 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 660 addNetworkAndVerifySuccess(); 661 mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID); 662 mLooper.dispatchAll(); 663 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 664 } 665 666 /** 667 * Verifies that configs can be removed when not in client mode. 668 */ 669 @Test 670 public void canForgetNetworkConfigWhenWifiDisabled() throws Exception { 671 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 672 mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID); 673 mLooper.dispatchAll(); 674 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 675 } 676 677 /** 678 * Helper method to move through SupplicantStarting and SupplicantStarted states. 679 */ 680 private void startSupplicantAndDispatchMessages() throws Exception { 681 mWsm.setSupplicantRunning(true); 682 mLooper.dispatchAll(); 683 684 assertEquals("SupplicantStartingState", getCurrentState().getName()); 685 686 when(mWifiNative.setDeviceName(anyString())).thenReturn(true); 687 when(mWifiNative.setManufacturer(anyString())).thenReturn(true); 688 when(mWifiNative.setModelName(anyString())).thenReturn(true); 689 when(mWifiNative.setModelNumber(anyString())).thenReturn(true); 690 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 691 when(mWifiNative.setConfigMethods(anyString())).thenReturn(true); 692 when(mWifiNative.setDeviceType(anyString())).thenReturn(true); 693 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 694 when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true); 695 696 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 697 mLooper.dispatchAll(); 698 } 699 700 private void addNetworkAndVerifySuccess() throws Exception { 701 addNetworkAndVerifySuccess(false); 702 } 703 704 private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception { 705 loadComponentsInStaMode(); 706 707 WifiConfiguration config = new WifiConfiguration(); 708 config.SSID = sSSID; 709 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 710 config.hiddenSSID = isHidden; 711 712 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) 713 .thenReturn(new NetworkUpdateResult(0)); 714 when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config)); 715 when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config); 716 717 mLooper.startAutoDispatch(); 718 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 719 mLooper.stopAutoDispatch(); 720 721 verify(mWifiConfigManager).addOrUpdateNetwork(eq(config), anyInt()); 722 723 mLooper.startAutoDispatch(); 724 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 725 mLooper.stopAutoDispatch(); 726 assertEquals(1, configs.size()); 727 728 WifiConfiguration config2 = configs.get(0); 729 assertEquals("\"GoogleGuest\"", config2.SSID); 730 assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); 731 } 732 733 /** 734 * Helper method to retrieve WifiConfiguration by SSID. 735 * 736 * Returns the associated WifiConfiguration if it is found, null otherwise. 737 */ 738 private WifiConfiguration getWifiConfigurationForNetwork(String ssid) { 739 mLooper.startAutoDispatch(); 740 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 741 mLooper.stopAutoDispatch(); 742 743 for (WifiConfiguration checkConfig : configs) { 744 if (checkConfig.SSID.equals(ssid)) { 745 return checkConfig; 746 } 747 } 748 return null; 749 } 750 751 private void verifyScan(int band, int reportEvents, Set<String> hiddenNetworkSSIDSet) { 752 ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor = 753 ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); 754 ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor = 755 ArgumentCaptor.forClass(WifiScanner.ScanListener.class); 756 verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(), 757 eq(null)); 758 WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue(); 759 assertEquals("band", band, actualSettings.band); 760 assertEquals("reportEvents", reportEvents, actualSettings.reportEvents); 761 762 if (hiddenNetworkSSIDSet == null) { 763 hiddenNetworkSSIDSet = new HashSet<>(); 764 } 765 Set<String> actualHiddenNetworkSSIDSet = new HashSet<>(); 766 if (actualSettings.hiddenNetworks != null) { 767 for (int i = 0; i < actualSettings.hiddenNetworks.length; ++i) { 768 actualHiddenNetworkSSIDSet.add(actualSettings.hiddenNetworks[i].ssid); 769 } 770 } 771 assertEquals("hidden networks", hiddenNetworkSSIDSet, actualHiddenNetworkSSIDSet); 772 773 when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); 774 mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); 775 776 mLooper.dispatchAll(); 777 778 List<ScanResult> reportedResults = mWsm.syncGetScanResultsList(); 779 assertEquals(8, reportedResults.size()); 780 } 781 782 @Test 783 public void scan() throws Exception { 784 addNetworkAndVerifySuccess(); 785 786 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 787 mWsm.startScan(-1, 0, null, null); 788 mLooper.dispatchAll(); 789 790 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 791 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 792 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null); 793 } 794 795 @Test 796 public void scanWithHiddenNetwork() throws Exception { 797 addNetworkAndVerifySuccess(true); 798 799 Set<String> hiddenNetworkSet = new HashSet<>(); 800 hiddenNetworkSet.add(sSSID); 801 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList = new ArrayList<>(); 802 hiddenNetworkList.add(new WifiScanner.ScanSettings.HiddenNetwork(sSSID)); 803 when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(hiddenNetworkList); 804 805 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 806 mWsm.startScan(-1, 0, null, null); 807 mLooper.dispatchAll(); 808 809 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 810 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 811 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 812 hiddenNetworkSet); 813 } 814 815 @Test 816 public void connect() throws Exception { 817 addNetworkAndVerifySuccess(); 818 when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(true); 819 when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(true); 820 821 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 822 mLooper.dispatchAll(); 823 verify(mWifiNative).removeAllNetworks(); 824 825 mLooper.startAutoDispatch(); 826 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 827 mLooper.stopAutoDispatch(); 828 829 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 830 verify(mWifiConnectivityManager).setUserConnectChoice(eq(0)); 831 832 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 833 mLooper.dispatchAll(); 834 835 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 836 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 837 mLooper.dispatchAll(); 838 839 assertEquals("ObtainingIpState", getCurrentState().getName()); 840 841 DhcpResults dhcpResults = new DhcpResults(); 842 dhcpResults.setGateway("1.2.3.4"); 843 dhcpResults.setIpAddress("192.168.1.100", 0); 844 dhcpResults.addDns("8.8.8.8"); 845 dhcpResults.setLeaseDuration(3600); 846 847 mTestIpManager.injectDhcpSuccess(dhcpResults); 848 mLooper.dispatchAll(); 849 850 assertEquals("ConnectedState", getCurrentState().getName()); 851 } 852 853 @Test 854 public void connectWithNoEnablePermission() throws Exception { 855 addNetworkAndVerifySuccess(); 856 when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(false); 857 when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(false); 858 859 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 860 mLooper.dispatchAll(); 861 verify(mWifiNative).removeAllNetworks(); 862 863 mLooper.startAutoDispatch(); 864 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 865 mLooper.stopAutoDispatch(); 866 867 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 868 verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0)); 869 870 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 871 mLooper.dispatchAll(); 872 873 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 874 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 875 mLooper.dispatchAll(); 876 877 assertEquals("ObtainingIpState", getCurrentState().getName()); 878 879 DhcpResults dhcpResults = new DhcpResults(); 880 dhcpResults.setGateway("1.2.3.4"); 881 dhcpResults.setIpAddress("192.168.1.100", 0); 882 dhcpResults.addDns("8.8.8.8"); 883 dhcpResults.setLeaseDuration(3600); 884 885 mTestIpManager.injectDhcpSuccess(dhcpResults); 886 mLooper.dispatchAll(); 887 888 assertEquals("ConnectedState", getCurrentState().getName()); 889 } 890 891 @Test 892 public void enableWithInvalidNetworkId() throws Exception { 893 addNetworkAndVerifySuccess(); 894 when(mWifiConfigManager.getConfiguredNetwork(eq(0))).thenReturn(null); 895 896 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 897 mLooper.dispatchAll(); 898 verify(mWifiNative).removeAllNetworks(); 899 900 mLooper.startAutoDispatch(); 901 assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 902 mLooper.stopAutoDispatch(); 903 904 verify(mWifiConfigManager, never()).enableNetwork(eq(0), eq(true), anyInt()); 905 verify(mWifiConfigManager, never()).checkAndUpdateLastConnectUid(eq(0), anyInt()); 906 } 907 908 /** 909 * If caller tries to connect to a network that is already connected, the connection request 910 * should succeed. 911 * 912 * Test: Create and connect to a network, then try to reconnect to the same network. Verify 913 * that connection request returns with CONNECT_NETWORK_SUCCEEDED. 914 */ 915 @Test 916 public void reconnectToConnectedNetwork() throws Exception { 917 addNetworkAndVerifySuccess(); 918 919 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 920 mLooper.dispatchAll(); 921 verify(mWifiNative).removeAllNetworks(); 922 923 mLooper.startAutoDispatch(); 924 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 925 mLooper.stopAutoDispatch(); 926 927 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 928 929 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 930 mLooper.dispatchAll(); 931 932 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 933 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 934 mLooper.dispatchAll(); 935 936 assertEquals("ObtainingIpState", getCurrentState().getName()); 937 938 // try to reconnect 939 mLooper.startAutoDispatch(); 940 Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.CONNECT_NETWORK, 0); 941 mLooper.stopAutoDispatch(); 942 943 assertEquals(WifiManager.CONNECT_NETWORK_SUCCEEDED, reply.what); 944 } 945 946 @Test 947 public void testDhcpFailure() throws Exception { 948 addNetworkAndVerifySuccess(); 949 950 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 951 mLooper.dispatchAll(); 952 953 mLooper.startAutoDispatch(); 954 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 955 mLooper.stopAutoDispatch(); 956 957 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 958 959 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 960 mLooper.dispatchAll(); 961 962 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 963 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 964 mLooper.dispatchAll(); 965 966 assertEquals("ObtainingIpState", getCurrentState().getName()); 967 968 mTestIpManager.injectDhcpFailure(); 969 mLooper.dispatchAll(); 970 971 assertEquals("DisconnectingState", getCurrentState().getName()); 972 } 973 974 @Test 975 public void testBadNetworkEvent() throws Exception { 976 addNetworkAndVerifySuccess(); 977 978 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 979 mLooper.dispatchAll(); 980 981 mLooper.startAutoDispatch(); 982 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 983 mLooper.stopAutoDispatch(); 984 985 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 986 987 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); 988 mLooper.dispatchAll(); 989 990 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 991 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 992 mLooper.dispatchAll(); 993 994 assertEquals("DisconnectedState", getCurrentState().getName()); 995 } 996 997 998 @Test 999 public void smToString() throws Exception { 1000 assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString( 1001 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED)); 1002 assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString( 1003 DhcpClient.CMD_PRE_DHCP_ACTION)); 1004 assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString( 1005 WifiStateMachine.CMD_IP_REACHABILITY_LOST)); 1006 } 1007 1008 @Test 1009 public void disconnect() throws Exception { 1010 connect(); 1011 1012 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06"); 1013 mLooper.dispatchAll(); 1014 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1015 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); 1016 mLooper.dispatchAll(); 1017 1018 assertEquals("DisconnectedState", getCurrentState().getName()); 1019 } 1020 1021 /** 1022 * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected 1023 * to true. 1024 * 1025 * Test: Successfully create and connect to a network. Check the config and verify 1026 * WifiConfiguration.getHasEverConnected() is true. 1027 */ 1028 @Test 1029 public void setHasEverConnectedTrueOnConnect() throws Exception { 1030 connect(); 1031 verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0); 1032 } 1033 1034 /** 1035 * Fail network connection attempt and verify HasEverConnected remains false. 1036 * 1037 * Test: Successfully create a network but fail when connecting. Check the config and verify 1038 * WifiConfiguration.getHasEverConnected() is false. 1039 */ 1040 @Test 1041 public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception { 1042 testDhcpFailure(); 1043 verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0); 1044 } 1045 1046 @Test 1047 public void iconQueryTest() throws Exception { 1048 // TODO(b/31065385): Passpoint config management. 1049 } 1050 1051 @Test 1052 public void verboseLogRecSizeIsGreaterThanNormalSize() { 1053 assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL); 1054 } 1055 1056 /** 1057 * Verifies that, by default, we allow only the "normal" number of log records. 1058 */ 1059 @Test 1060 public void normalLogRecSizeIsUsedByDefault() { 1061 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize()); 1062 } 1063 1064 /** 1065 * Verifies that, in verbose mode, we allow a larger number of log records. 1066 */ 1067 @Test 1068 public void enablingVerboseLoggingUpdatesLogRecSize() { 1069 mWsm.enableVerboseLogging(1); 1070 assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecMaxSize()); 1071 } 1072 1073 @Test 1074 public void disablingVerboseLoggingClearsRecords() { 1075 mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT); 1076 mLooper.dispatchAll(); 1077 assertTrue(mWsm.getLogRecSize() >= 1); 1078 1079 mWsm.enableVerboseLogging(0); 1080 assertEquals(0, mWsm.getLogRecSize()); 1081 } 1082 1083 @Test 1084 public void disablingVerboseLoggingUpdatesLogRecSize() { 1085 mWsm.enableVerboseLogging(1); 1086 mWsm.enableVerboseLogging(0); 1087 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize()); 1088 } 1089 1090 /** Verifies that enabling verbose logging sets the hal log property in eng builds. */ 1091 @Test 1092 public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() { 1093 reset(mPropertyService); // Ignore calls made in setUp() 1094 when(mBuildProperties.isEngBuild()).thenReturn(true); 1095 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 1096 when(mBuildProperties.isUserBuild()).thenReturn(false); 1097 mWsm.enableVerboseLogging(1); 1098 verify(mPropertyService).set("log.tag.WifiHAL", "V"); 1099 } 1100 1101 /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */ 1102 @Test 1103 public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() { 1104 reset(mPropertyService); // Ignore calls made in setUp() 1105 when(mBuildProperties.isUserdebugBuild()).thenReturn(true); 1106 when(mBuildProperties.isEngBuild()).thenReturn(false); 1107 when(mBuildProperties.isUserBuild()).thenReturn(false); 1108 mWsm.enableVerboseLogging(1); 1109 verify(mPropertyService).set("log.tag.WifiHAL", "V"); 1110 } 1111 1112 /** Verifies that enabling verbose logging does NOT set the hal log property in user builds. */ 1113 @Test 1114 public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() { 1115 reset(mPropertyService); // Ignore calls made in setUp() 1116 when(mBuildProperties.isUserBuild()).thenReturn(true); 1117 when(mBuildProperties.isEngBuild()).thenReturn(false); 1118 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 1119 mWsm.enableVerboseLogging(1); 1120 verify(mPropertyService, never()).set(anyString(), anyString()); 1121 } 1122 1123 private int testGetSupportedFeaturesCase(int supportedFeatures, boolean rttConfigured) { 1124 AsyncChannel channel = mock(AsyncChannel.class); 1125 Message reply = Message.obtain(); 1126 reply.arg1 = supportedFeatures; 1127 reset(mPropertyService); // Ignore calls made in setUp() 1128 when(channel.sendMessageSynchronously(WifiStateMachine.CMD_GET_SUPPORTED_FEATURES)) 1129 .thenReturn(reply); 1130 when(mPropertyService.getBoolean("config.disable_rtt", false)) 1131 .thenReturn(rttConfigured); 1132 return mWsm.syncGetSupportedFeatures(channel); 1133 } 1134 1135 /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ 1136 @Test 1137 public void syncGetSupportedFeatures() { 1138 final int featureAware = WifiManager.WIFI_FEATURE_AWARE; 1139 final int featureInfra = WifiManager.WIFI_FEATURE_INFRA; 1140 final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; 1141 final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; 1142 1143 assertEquals(0, testGetSupportedFeaturesCase(0, false)); 1144 assertEquals(0, testGetSupportedFeaturesCase(0, true)); 1145 assertEquals(featureAware | featureInfra, 1146 testGetSupportedFeaturesCase(featureAware | featureInfra, false)); 1147 assertEquals(featureAware | featureInfra, 1148 testGetSupportedFeaturesCase(featureAware | featureInfra, true)); 1149 assertEquals(featureInfra | featureD2dRtt, 1150 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, false)); 1151 assertEquals(featureInfra, 1152 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, true)); 1153 assertEquals(featureInfra | featureD2apRtt, 1154 testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, false)); 1155 assertEquals(featureInfra, 1156 testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, true)); 1157 assertEquals(featureInfra | featureD2dRtt | featureD2apRtt, 1158 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, false)); 1159 assertEquals(featureInfra, 1160 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, true)); 1161 } 1162 1163 /** 1164 * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager} 1165 * and returning the result that's returned from {@link PasspointManager}. 1166 */ 1167 @Test 1168 public void syncAddOrUpdatePasspointConfig() throws Exception { 1169 when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class))) 1170 .thenReturn(true); 1171 mLooper.startAutoDispatch(); 1172 assertTrue(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel, 1173 new PasspointConfiguration())); 1174 mLooper.stopAutoDispatch(); 1175 reset(mPasspointManager); 1176 1177 when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class))) 1178 .thenReturn(false); 1179 mLooper.startAutoDispatch(); 1180 assertFalse(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel, 1181 new PasspointConfiguration())); 1182 mLooper.stopAutoDispatch(); 1183 } 1184 1185 /** 1186 * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager} 1187 * and returning the result that's returned from {@link PasspointManager}. 1188 */ 1189 @Test 1190 public void syncRemovePasspointConfig() throws Exception { 1191 String fqdn = "test.com"; 1192 when(mPasspointManager.removeProvider(fqdn)).thenReturn(true); 1193 mLooper.startAutoDispatch(); 1194 assertTrue(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn)); 1195 mLooper.stopAutoDispatch(); 1196 reset(mPasspointManager); 1197 1198 when(mPasspointManager.removeProvider(fqdn)).thenReturn(false); 1199 mLooper.startAutoDispatch(); 1200 assertFalse(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn)); 1201 mLooper.stopAutoDispatch(); 1202 } 1203 1204 /** 1205 * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager} 1206 * and returning the result that's returned from {@link PasspointManager} when in client mode. 1207 */ 1208 @Test 1209 public void syncRemovePasspointConfigInClientMode() throws Exception { 1210 loadComponentsInStaMode(); 1211 syncRemovePasspointConfig(); 1212 } 1213 1214 /** 1215 * Verify that syncGetPasspointConfigs will redirect calls to {@link PasspointManager} 1216 * and returning the result that's returned from {@link PasspointManager}. 1217 */ 1218 @Test 1219 public void syncGetPasspointConfigs() throws Exception { 1220 // Setup expected configs. 1221 List<PasspointConfiguration> expectedConfigs = new ArrayList<>(); 1222 PasspointConfiguration config = new PasspointConfiguration(); 1223 HomeSp homeSp = new HomeSp(); 1224 homeSp.setFqdn("test.com"); 1225 config.setHomeSp(homeSp); 1226 expectedConfigs.add(config); 1227 1228 when(mPasspointManager.getProviderConfigs()).thenReturn(expectedConfigs); 1229 mLooper.startAutoDispatch(); 1230 assertEquals(expectedConfigs, mWsm.syncGetPasspointConfigs(mWsmAsyncChannel)); 1231 mLooper.stopAutoDispatch(); 1232 reset(mPasspointManager); 1233 1234 when(mPasspointManager.getProviderConfigs()) 1235 .thenReturn(new ArrayList<PasspointConfiguration>()); 1236 mLooper.startAutoDispatch(); 1237 assertTrue(mWsm.syncGetPasspointConfigs(mWsmAsyncChannel).isEmpty()); 1238 mLooper.stopAutoDispatch(); 1239 } 1240 1241 /** 1242 * Verify that syncGetMatchingWifiConfig will redirect calls to {@link PasspointManager} 1243 * with expected {@link WifiConfiguration} being returned when in client mode. 1244 * 1245 * @throws Exception 1246 */ 1247 @Test 1248 public void syncGetMatchingWifiConfigInClientMode() throws Exception { 1249 loadComponentsInStaMode(); 1250 1251 when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))).thenReturn(null); 1252 mLooper.startAutoDispatch(); 1253 assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel)); 1254 mLooper.stopAutoDispatch(); 1255 reset(mPasspointManager); 1256 1257 WifiConfiguration expectedConfig = new WifiConfiguration(); 1258 expectedConfig.SSID = "TestSSID"; 1259 when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))) 1260 .thenReturn(expectedConfig); 1261 mLooper.startAutoDispatch(); 1262 WifiConfiguration actualConfig = mWsm.syncGetMatchingWifiConfig(new ScanResult(), 1263 mWsmAsyncChannel); 1264 mLooper.stopAutoDispatch(); 1265 assertEquals(expectedConfig.SSID, actualConfig.SSID); 1266 } 1267 1268 /** 1269 * Verify that syncGetMatchingWifiConfig will be a no-op and return {@code null} when not in 1270 * client mode. 1271 * 1272 * @throws Exception 1273 */ 1274 @Test 1275 public void syncGetMatchingWifiConfigInNonClientMode() throws Exception { 1276 mLooper.startAutoDispatch(); 1277 assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel)); 1278 mLooper.stopAutoDispatch(); 1279 verify(mPasspointManager, never()).getMatchingWifiConfig(any(ScanResult.class)); 1280 } 1281 1282 /** 1283 * Verify successful Wps PBC network connection. 1284 */ 1285 @Test 1286 public void wpsPbcConnectSuccess() throws Exception { 1287 loadComponentsInStaMode(); 1288 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1289 mLooper.dispatchAll(); 1290 1291 when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(true); 1292 WpsInfo wpsInfo = new WpsInfo(); 1293 wpsInfo.setup = WpsInfo.PBC; 1294 wpsInfo.BSSID = sBSSID; 1295 1296 mLooper.startAutoDispatch(); 1297 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1298 mLooper.stopAutoDispatch(); 1299 verify(mWifiNative).startWpsPbc(eq(sBSSID)); 1300 1301 assertEquals("WpsRunningState", getCurrentState().getName()); 1302 1303 setupMocksForWpsNetworkMigration(); 1304 1305 mLooper.startAutoDispatch(); 1306 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1307 mLooper.stopAutoDispatch(); 1308 1309 assertEquals("DisconnectedState", getCurrentState().getName()); 1310 } 1311 1312 /** 1313 * Verify failure in starting Wps PBC network connection. 1314 */ 1315 @Test 1316 public void wpsPbcConnectFailure() throws Exception { 1317 loadComponentsInStaMode(); 1318 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1319 mLooper.dispatchAll(); 1320 1321 when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(false); 1322 WpsInfo wpsInfo = new WpsInfo(); 1323 wpsInfo.setup = WpsInfo.PBC; 1324 wpsInfo.BSSID = sBSSID; 1325 1326 mLooper.startAutoDispatch(); 1327 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1328 mLooper.stopAutoDispatch(); 1329 verify(mWifiNative).startWpsPbc(eq(sBSSID)); 1330 1331 assertFalse("WpsRunningState".equals(getCurrentState().getName())); 1332 } 1333 1334 /** 1335 * Verify successful Wps Pin Display network connection. 1336 */ 1337 @Test 1338 public void wpsPinDisplayConnectSuccess() throws Exception { 1339 loadComponentsInStaMode(); 1340 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1341 mLooper.dispatchAll(); 1342 1343 when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn("34545434"); 1344 WpsInfo wpsInfo = new WpsInfo(); 1345 wpsInfo.setup = WpsInfo.DISPLAY; 1346 wpsInfo.BSSID = sBSSID; 1347 1348 mLooper.startAutoDispatch(); 1349 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1350 mLooper.stopAutoDispatch(); 1351 verify(mWifiNative).startWpsPinDisplay(eq(sBSSID)); 1352 1353 assertEquals("WpsRunningState", getCurrentState().getName()); 1354 1355 setupMocksForWpsNetworkMigration(); 1356 1357 mLooper.startAutoDispatch(); 1358 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1359 mLooper.stopAutoDispatch(); 1360 1361 assertEquals("DisconnectedState", getCurrentState().getName()); 1362 } 1363 1364 /** 1365 * Verify failure in Wps Pin Display network connection. 1366 */ 1367 @Test 1368 public void wpsPinDisplayConnectFailure() throws Exception { 1369 loadComponentsInStaMode(); 1370 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1371 mLooper.dispatchAll(); 1372 1373 when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn(null); 1374 WpsInfo wpsInfo = new WpsInfo(); 1375 wpsInfo.setup = WpsInfo.DISPLAY; 1376 wpsInfo.BSSID = sBSSID; 1377 1378 mLooper.startAutoDispatch(); 1379 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1380 mLooper.stopAutoDispatch(); 1381 verify(mWifiNative).startWpsPinDisplay(eq(sBSSID)); 1382 1383 assertFalse("WpsRunningState".equals(getCurrentState().getName())); 1384 } 1385 1386 @Test 1387 public void handleVendorHalDeath() throws Exception { 1388 ArgumentCaptor<WifiNative.VendorHalDeathEventHandler> deathHandlerCapturer = 1389 ArgumentCaptor.forClass(WifiNative.VendorHalDeathEventHandler.class); 1390 when(mWifiNative.initializeVendorHal(deathHandlerCapturer.capture())).thenReturn(true); 1391 1392 // Trigger initialize to capture the death handler registration. 1393 mLooper.startAutoDispatch(); 1394 assertTrue(mWsm.syncInitialize(mWsmAsyncChannel)); 1395 mLooper.stopAutoDispatch(); 1396 1397 verify(mWifiNative).initializeVendorHal(any(WifiNative.VendorHalDeathEventHandler.class)); 1398 WifiNative.VendorHalDeathEventHandler deathHandler = deathHandlerCapturer.getValue(); 1399 1400 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1401 mLooper.dispatchAll(); 1402 1403 // We should not be in initial state now. 1404 assertFalse("InitialState".equals(getCurrentState().getName())); 1405 1406 // Now trigger the death notification. 1407 mLooper.startAutoDispatch(); 1408 deathHandler.onDeath(); 1409 mLooper.stopAutoDispatch(); 1410 1411 // We should back to initial state after vendor HAL death. 1412 assertTrue("InitialState".equals(getCurrentState().getName())); 1413 } 1414 1415 private void setupMocksForWpsNetworkMigration() { 1416 int newNetworkId = 5; 1417 // Now trigger the network connection event for adding the WPS network. 1418 doAnswer(new AnswerWithArguments() { 1419 public boolean answer(Map<String, WifiConfiguration> configs, 1420 SparseArray<Map<String, String>> networkExtras) throws Exception { 1421 configs.put("dummy", new WifiConfiguration()); 1422 return true; 1423 } 1424 }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class)); 1425 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) 1426 .thenReturn(new NetworkUpdateResult(newNetworkId)); 1427 when(mWifiConfigManager.enableNetwork(eq(newNetworkId), anyBoolean(), anyInt())) 1428 .thenReturn(true); 1429 } 1430} 1431