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