WifiStateMachineTest.java revision 17c2a7b30e5680b11fc0073ce322ee7bc14ef2c5
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.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean())) 364 .thenReturn(mWifiConnectivityManager); 365 when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class), 366 any(SoftApManager.Listener.class), any(IApInterface.class), 367 any(WifiConfiguration.class))) 368 .thenReturn(mSoftApManager); 369 when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager); 370 when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker); 371 when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor); 372 when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); 373 374 when(mWifiNative.setupForClientMode()).thenReturn(mClientInterface); 375 when(mWifiNative.setupForSoftApMode()).thenReturn(mApInterface); 376 when(mWifiNative.getInterfaceName()).thenReturn("mockWlan"); 377 when(mWifiNative.enableSupplicant()).thenReturn(true); 378 when(mWifiNative.disableSupplicant()).thenReturn(true); 379 when(mWifiNative.getFrameworkNetworkId(anyInt())).thenReturn(0); 380 381 382 FrameworkFacade factory = getFrameworkFacade(); 383 Context context = getContext(); 384 385 Resources resources = getMockResources(); 386 when(context.getResources()).thenReturn(resources); 387 388 when(factory.getIntegerSetting(context, 389 Settings.Global.WIFI_FREQUENCY_BAND, 390 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn( 391 WifiManager.WIFI_FREQUENCY_BAND_AUTO); 392 393 when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy))) 394 .thenReturn(mApConfigStore); 395 396 when(factory.makeSupplicantStateTracker( 397 any(Context.class), any(WifiConfigManager.class), 398 any(Handler.class))).thenReturn(mSupplicantStateTracker); 399 400 when(mUserManager.getProfileParent(11)) 401 .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0)); 402 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList( 403 new UserInfo(UserHandle.USER_SYSTEM, "owner", 0), 404 new UserInfo(11, "managed profile", 0))); 405 406 when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder); 407 when(mClientInterface.asBinder()).thenReturn(mClientInterfaceBinder); 408 409 mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(), 410 mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative); 411 mWsmThread = getWsmHandlerThread(mWsm); 412 413 final AsyncChannel channel = new AsyncChannel(); 414 Handler handler = new Handler(mLooper.getLooper()) { 415 @Override 416 public void handleMessage(Message msg) { 417 switch (msg.what) { 418 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 419 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 420 mWsmAsyncChannel = channel; 421 } else { 422 Log.d(TAG, "Failed to connect Command channel " + this); 423 } 424 break; 425 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 426 Log.d(TAG, "Command channel disconnected" + this); 427 break; 428 } 429 } 430 }; 431 432 channel.connect(context, handler, mWsm.getMessenger()); 433 mLooper.dispatchAll(); 434 /* Now channel is supposed to be connected */ 435 436 mBinderToken = Binder.clearCallingIdentity(); 437 } 438 439 @After 440 public void cleanUp() throws Exception { 441 Binder.restoreCallingIdentity(mBinderToken); 442 443 if (mSyncThread != null) stopLooper(mSyncThread.getLooper()); 444 if (mWsmThread != null) stopLooper(mWsmThread.getLooper()); 445 if (mP2pThread != null) stopLooper(mP2pThread.getLooper()); 446 447 mWsmThread = null; 448 mP2pThread = null; 449 mSyncThread = null; 450 mWsmAsyncChannel = null; 451 mWsm = null; 452 } 453 454 @Test 455 public void createNew() throws Exception { 456 assertEquals("InitialState", getCurrentState().getName()); 457 458 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 459 mLooper.dispatchAll(); 460 assertEquals("InitialState", getCurrentState().getName()); 461 } 462 463 @Test 464 public void loadComponentsInStaMode() throws Exception { 465 startSupplicantAndDispatchMessages(); 466 467 assertEquals("DisconnectedState", getCurrentState().getName()); 468 } 469 470 @Test 471 public void loadComponentsInApMode() throws Exception { 472 mWsm.setHostApRunning(new WifiConfiguration(), true); 473 mLooper.dispatchAll(); 474 475 assertEquals("SoftApState", getCurrentState().getName()); 476 477 verify(mSoftApManager).start(); 478 } 479 480 @Test 481 public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception { 482 when(mWifiNative.enableSupplicant()).thenReturn(false); 483 mWsm.setSupplicantRunning(true); 484 mLooper.dispatchAll(); 485 assertEquals("InitialState", getCurrentState().getName()); 486 } 487 488 @Test 489 public void shouldRequireWificondToLeaveInitialState() throws Exception { 490 // We start out with valid default values, break them going backwards so that 491 // we test all the bailout cases. 492 493 // ClientInterface dies after creation. 494 doThrow(new RemoteException()).when(mClientInterfaceBinder).linkToDeath(any(), anyInt()); 495 mWsm.setSupplicantRunning(true); 496 mLooper.dispatchAll(); 497 assertEquals("InitialState", getCurrentState().getName()); 498 499 // Failed to even create the client interface. 500 when(mWificond.createClientInterface()).thenReturn(null); 501 mWsm.setSupplicantRunning(true); 502 mLooper.dispatchAll(); 503 assertEquals("InitialState", getCurrentState().getName()); 504 505 // Failed to get wificond proxy. 506 when(mWifiInjector.makeWificond()).thenReturn(null); 507 mWsm.setSupplicantRunning(true); 508 mLooper.dispatchAll(); 509 assertEquals("InitialState", getCurrentState().getName()); 510 } 511 512 @Test 513 public void loadComponentsFailure() throws Exception { 514 when(mWifiNative.startHal(anyBoolean())).thenReturn(false); 515 when(mWifiNative.enableSupplicant()).thenReturn(false); 516 517 mWsm.setSupplicantRunning(true); 518 mLooper.dispatchAll(); 519 assertEquals("InitialState", getCurrentState().getName()); 520 521 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 522 mWsm.setSupplicantRunning(true); 523 mLooper.dispatchAll(); 524 assertEquals("InitialState", getCurrentState().getName()); 525 } 526 527 @Test 528 public void checkInitialStateStickyWhenDisabledMode() throws Exception { 529 mLooper.dispatchAll(); 530 assertEquals("InitialState", getCurrentState().getName()); 531 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 532 533 mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE); 534 mLooper.dispatchAll(); 535 assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); 536 assertEquals("InitialState", getCurrentState().getName()); 537 } 538 539 @Test 540 public void shouldStartSupplicantWhenConnectModeRequested() throws Exception { 541 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 542 543 // The first time we start out in InitialState, we sit around here. 544 mLooper.dispatchAll(); 545 assertEquals("InitialState", getCurrentState().getName()); 546 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 547 548 // But if someone tells us to enter connect mode, we start up supplicant 549 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 550 mLooper.dispatchAll(); 551 assertEquals("SupplicantStartingState", getCurrentState().getName()); 552 } 553 554 /** 555 * Test that mode changes accurately reflect the value for isWifiEnabled. 556 */ 557 @Test 558 public void checkIsWifiEnabledForModeChanges() throws Exception { 559 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 560 561 // Check initial state 562 mLooper.dispatchAll(); 563 assertEquals("InitialState", getCurrentState().getName()); 564 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 565 566 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); 567 startSupplicantAndDispatchMessages(); 568 mWsm.setSupplicantRunning(true); 569 mLooper.dispatchAll(); 570 assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); 571 assertEquals("ScanModeState", getCurrentState().getName()); 572 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 573 574 // switch to connect mode and verify wifi is reported as enabled 575 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 576 mLooper.dispatchAll(); 577 assertEquals("DisconnectedState", getCurrentState().getName()); 578 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 579 assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); 580 581 // now go back to scan mode with "wifi disabled" to verify the reported wifi state. 582 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE); 583 mLooper.dispatchAll(); 584 assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE, 585 mWsm.getOperationalModeForTest()); 586 assertEquals("ScanModeState", getCurrentState().getName()); 587 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 588 589 // now go to AP mode 590 mWsm.setSupplicantRunning(false); 591 mWsm.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP); 592 mWsm.sendMessage(WifiMonitor.SUP_DISCONNECTION_EVENT); 593 mWsm.setHostApRunning(new WifiConfiguration(), true); 594 mLooper.dispatchAll(); 595 assertEquals("SoftApState", getCurrentState().getName()); 596 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 597 } 598 599 600 /** 601 * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant 602 * is started. 603 */ 604 @Test 605 public void checkStartInCorrectStateAfterChangingInitialState() throws Exception { 606 when(mWifiNative.startHal(anyBoolean())).thenReturn(true); 607 608 // Check initial state 609 mLooper.dispatchAll(); 610 assertEquals("InitialState", getCurrentState().getName()); 611 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 612 613 // Update the mode 614 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); 615 mLooper.dispatchAll(); 616 assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); 617 618 // Start supplicant so we move to the next state 619 startSupplicantAndDispatchMessages(); 620 621 assertEquals("ScanModeState", getCurrentState().getName()); 622 } 623 624 /** 625 * Verifies that configs can be removed when in client mode. 626 */ 627 @Test 628 public void canRemoveNetworkConfigInClientMode() throws Exception { 629 boolean result; 630 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 631 addNetworkAndVerifySuccess(); 632 mLooper.startAutoDispatch(); 633 result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0); 634 mLooper.stopAutoDispatch(); 635 assertTrue(result); 636 } 637 638 /** 639 * Verifies that configs can be removed when not in client mode. 640 */ 641 @Test 642 public void canRemoveNetworkConfigWhenWifiDisabled() { 643 boolean result; 644 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 645 mLooper.startAutoDispatch(); 646 result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0); 647 mLooper.stopAutoDispatch(); 648 649 assertTrue(result); 650 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 651 } 652 653 /** 654 * Verifies that configs can be forgotten when in client mode. 655 */ 656 @Test 657 public void canForgetNetworkConfigInClientMode() throws Exception { 658 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 659 addNetworkAndVerifySuccess(); 660 mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID); 661 mLooper.dispatchAll(); 662 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 663 } 664 665 /** 666 * Verifies that configs can be removed when not in client mode. 667 */ 668 @Test 669 public void canForgetNetworkConfigWhenWifiDisabled() throws Exception { 670 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 671 mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID); 672 mLooper.dispatchAll(); 673 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 674 } 675 676 /** 677 * Helper method to move through SupplicantStarting and SupplicantStarted states. 678 */ 679 private void startSupplicantAndDispatchMessages() throws Exception { 680 mWsm.setSupplicantRunning(true); 681 mLooper.dispatchAll(); 682 683 assertEquals("SupplicantStartingState", getCurrentState().getName()); 684 685 when(mWifiNative.setDeviceName(anyString())).thenReturn(true); 686 when(mWifiNative.setManufacturer(anyString())).thenReturn(true); 687 when(mWifiNative.setModelName(anyString())).thenReturn(true); 688 when(mWifiNative.setModelNumber(anyString())).thenReturn(true); 689 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 690 when(mWifiNative.setConfigMethods(anyString())).thenReturn(true); 691 when(mWifiNative.setDeviceType(anyString())).thenReturn(true); 692 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 693 when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true); 694 695 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 696 mLooper.dispatchAll(); 697 } 698 699 private void addNetworkAndVerifySuccess() throws Exception { 700 addNetworkAndVerifySuccess(false); 701 } 702 703 private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception { 704 loadComponentsInStaMode(); 705 706 WifiConfiguration config = new WifiConfiguration(); 707 config.SSID = sSSID; 708 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 709 config.hiddenSSID = isHidden; 710 711 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) 712 .thenReturn(new NetworkUpdateResult(0)); 713 when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config)); 714 when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config); 715 716 mLooper.startAutoDispatch(); 717 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 718 mLooper.stopAutoDispatch(); 719 720 verify(mWifiConfigManager).addOrUpdateNetwork(eq(config), anyInt()); 721 722 mLooper.startAutoDispatch(); 723 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 724 mLooper.stopAutoDispatch(); 725 assertEquals(1, configs.size()); 726 727 WifiConfiguration config2 = configs.get(0); 728 assertEquals("\"GoogleGuest\"", config2.SSID); 729 assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); 730 } 731 732 /** 733 * Helper method to retrieve WifiConfiguration by SSID. 734 * 735 * Returns the associated WifiConfiguration if it is found, null otherwise. 736 */ 737 private WifiConfiguration getWifiConfigurationForNetwork(String ssid) { 738 mLooper.startAutoDispatch(); 739 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 740 mLooper.stopAutoDispatch(); 741 742 for (WifiConfiguration checkConfig : configs) { 743 if (checkConfig.SSID.equals(ssid)) { 744 return checkConfig; 745 } 746 } 747 return null; 748 } 749 750 private void verifyScan(int band, int reportEvents, Set<String> hiddenNetworkSSIDSet) { 751 ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor = 752 ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); 753 ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor = 754 ArgumentCaptor.forClass(WifiScanner.ScanListener.class); 755 verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(), 756 eq(null)); 757 WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue(); 758 assertEquals("band", band, actualSettings.band); 759 assertEquals("reportEvents", reportEvents, actualSettings.reportEvents); 760 761 if (hiddenNetworkSSIDSet == null) { 762 hiddenNetworkSSIDSet = new HashSet<>(); 763 } 764 Set<String> actualHiddenNetworkSSIDSet = new HashSet<>(); 765 if (actualSettings.hiddenNetworks != null) { 766 for (int i = 0; i < actualSettings.hiddenNetworks.length; ++i) { 767 actualHiddenNetworkSSIDSet.add(actualSettings.hiddenNetworks[i].ssid); 768 } 769 } 770 assertEquals("hidden networks", hiddenNetworkSSIDSet, actualHiddenNetworkSSIDSet); 771 772 when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); 773 mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); 774 775 mLooper.dispatchAll(); 776 777 List<ScanResult> reportedResults = mWsm.syncGetScanResultsList(); 778 assertEquals(8, reportedResults.size()); 779 } 780 781 @Test 782 public void scan() throws Exception { 783 addNetworkAndVerifySuccess(); 784 785 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 786 mWsm.startScan(-1, 0, null, null); 787 mLooper.dispatchAll(); 788 789 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 790 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 791 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null); 792 } 793 794 @Test 795 public void scanWithHiddenNetwork() throws Exception { 796 addNetworkAndVerifySuccess(true); 797 798 Set<String> hiddenNetworkSet = new HashSet<>(); 799 hiddenNetworkSet.add(sSSID); 800 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList = new ArrayList<>(); 801 hiddenNetworkList.add(new WifiScanner.ScanSettings.HiddenNetwork(sSSID)); 802 when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(hiddenNetworkList); 803 804 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 805 mWsm.startScan(-1, 0, null, null); 806 mLooper.dispatchAll(); 807 808 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 809 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 810 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 811 hiddenNetworkSet); 812 } 813 814 @Test 815 public void connect() throws Exception { 816 addNetworkAndVerifySuccess(); 817 when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(true); 818 when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(true); 819 820 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 821 mLooper.dispatchAll(); 822 verify(mWifiNative).removeAllNetworks(); 823 824 mLooper.startAutoDispatch(); 825 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 826 mLooper.stopAutoDispatch(); 827 828 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 829 verify(mWifiConnectivityManager).setUserConnectChoice(eq(0)); 830 831 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 832 mLooper.dispatchAll(); 833 834 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 835 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 836 mLooper.dispatchAll(); 837 838 assertEquals("ObtainingIpState", getCurrentState().getName()); 839 840 DhcpResults dhcpResults = new DhcpResults(); 841 dhcpResults.setGateway("1.2.3.4"); 842 dhcpResults.setIpAddress("192.168.1.100", 0); 843 dhcpResults.addDns("8.8.8.8"); 844 dhcpResults.setLeaseDuration(3600); 845 846 mTestIpManager.injectDhcpSuccess(dhcpResults); 847 mLooper.dispatchAll(); 848 849 assertEquals("ConnectedState", getCurrentState().getName()); 850 } 851 852 @Test 853 public void connectWithNoEnablePermission() throws Exception { 854 addNetworkAndVerifySuccess(); 855 when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(false); 856 when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(false); 857 858 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 859 mLooper.dispatchAll(); 860 verify(mWifiNative).removeAllNetworks(); 861 862 mLooper.startAutoDispatch(); 863 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 864 mLooper.stopAutoDispatch(); 865 866 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 867 verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0)); 868 869 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 870 mLooper.dispatchAll(); 871 872 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 873 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 874 mLooper.dispatchAll(); 875 876 assertEquals("ObtainingIpState", getCurrentState().getName()); 877 878 DhcpResults dhcpResults = new DhcpResults(); 879 dhcpResults.setGateway("1.2.3.4"); 880 dhcpResults.setIpAddress("192.168.1.100", 0); 881 dhcpResults.addDns("8.8.8.8"); 882 dhcpResults.setLeaseDuration(3600); 883 884 mTestIpManager.injectDhcpSuccess(dhcpResults); 885 mLooper.dispatchAll(); 886 887 assertEquals("ConnectedState", getCurrentState().getName()); 888 } 889 890 @Test 891 public void enableWithInvalidNetworkId() throws Exception { 892 addNetworkAndVerifySuccess(); 893 when(mWifiConfigManager.getConfiguredNetwork(eq(0))).thenReturn(null); 894 895 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 896 mLooper.dispatchAll(); 897 verify(mWifiNative).removeAllNetworks(); 898 899 mLooper.startAutoDispatch(); 900 assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 901 mLooper.stopAutoDispatch(); 902 903 verify(mWifiConfigManager, never()).enableNetwork(eq(0), eq(true), anyInt()); 904 verify(mWifiConfigManager, never()).checkAndUpdateLastConnectUid(eq(0), anyInt()); 905 } 906 907 /** 908 * If caller tries to connect to a network that is already connected, the connection request 909 * should succeed. 910 * 911 * Test: Create and connect to a network, then try to reconnect to the same network. Verify 912 * that connection request returns with CONNECT_NETWORK_SUCCEEDED. 913 */ 914 @Test 915 public void reconnectToConnectedNetwork() throws Exception { 916 addNetworkAndVerifySuccess(); 917 918 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 919 mLooper.dispatchAll(); 920 verify(mWifiNative).removeAllNetworks(); 921 922 mLooper.startAutoDispatch(); 923 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 924 mLooper.stopAutoDispatch(); 925 926 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 927 928 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 929 mLooper.dispatchAll(); 930 931 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 932 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 933 mLooper.dispatchAll(); 934 935 assertEquals("ObtainingIpState", getCurrentState().getName()); 936 937 // try to reconnect 938 mLooper.startAutoDispatch(); 939 Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.CONNECT_NETWORK, 0); 940 mLooper.stopAutoDispatch(); 941 942 assertEquals(WifiManager.CONNECT_NETWORK_SUCCEEDED, reply.what); 943 } 944 945 @Test 946 public void testDhcpFailure() throws Exception { 947 addNetworkAndVerifySuccess(); 948 949 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 950 mLooper.dispatchAll(); 951 952 mLooper.startAutoDispatch(); 953 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 954 mLooper.stopAutoDispatch(); 955 956 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 957 958 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 959 mLooper.dispatchAll(); 960 961 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 962 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 963 mLooper.dispatchAll(); 964 965 assertEquals("ObtainingIpState", getCurrentState().getName()); 966 967 mTestIpManager.injectDhcpFailure(); 968 mLooper.dispatchAll(); 969 970 assertEquals("DisconnectingState", getCurrentState().getName()); 971 } 972 973 @Test 974 public void testBadNetworkEvent() throws Exception { 975 addNetworkAndVerifySuccess(); 976 977 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 978 mLooper.dispatchAll(); 979 980 mLooper.startAutoDispatch(); 981 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 982 mLooper.stopAutoDispatch(); 983 984 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 985 986 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); 987 mLooper.dispatchAll(); 988 989 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 990 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 991 mLooper.dispatchAll(); 992 993 assertEquals("DisconnectedState", getCurrentState().getName()); 994 } 995 996 997 @Test 998 public void smToString() throws Exception { 999 assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString( 1000 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED)); 1001 assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString( 1002 DhcpClient.CMD_PRE_DHCP_ACTION)); 1003 assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString( 1004 WifiStateMachine.CMD_IP_REACHABILITY_LOST)); 1005 } 1006 1007 @Test 1008 public void disconnect() throws Exception { 1009 connect(); 1010 1011 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06"); 1012 mLooper.dispatchAll(); 1013 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1014 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); 1015 mLooper.dispatchAll(); 1016 1017 assertEquals("DisconnectedState", getCurrentState().getName()); 1018 } 1019 1020 /** 1021 * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected 1022 * to true. 1023 * 1024 * Test: Successfully create and connect to a network. Check the config and verify 1025 * WifiConfiguration.getHasEverConnected() is true. 1026 */ 1027 @Test 1028 public void setHasEverConnectedTrueOnConnect() throws Exception { 1029 connect(); 1030 verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0); 1031 } 1032 1033 /** 1034 * Fail network connection attempt and verify HasEverConnected remains false. 1035 * 1036 * Test: Successfully create a network but fail when connecting. Check the config and verify 1037 * WifiConfiguration.getHasEverConnected() is false. 1038 */ 1039 @Test 1040 public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception { 1041 testDhcpFailure(); 1042 verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0); 1043 } 1044 1045 @Test 1046 public void iconQueryTest() throws Exception { 1047 // TODO(b/31065385): Passpoint config management. 1048 } 1049 1050 @Test 1051 public void verboseLogRecSizeIsGreaterThanNormalSize() { 1052 assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL); 1053 } 1054 1055 /** 1056 * Verifies that, by default, we allow only the "normal" number of log records. 1057 */ 1058 @Test 1059 public void normalLogRecSizeIsUsedByDefault() { 1060 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize()); 1061 } 1062 1063 /** 1064 * Verifies that, in verbose mode, we allow a larger number of log records. 1065 */ 1066 @Test 1067 public void enablingVerboseLoggingUpdatesLogRecSize() { 1068 mWsm.enableVerboseLogging(1); 1069 assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecMaxSize()); 1070 } 1071 1072 @Test 1073 public void disablingVerboseLoggingClearsRecords() { 1074 mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT); 1075 mLooper.dispatchAll(); 1076 assertTrue(mWsm.getLogRecSize() >= 1); 1077 1078 mWsm.enableVerboseLogging(0); 1079 assertEquals(0, mWsm.getLogRecSize()); 1080 } 1081 1082 @Test 1083 public void disablingVerboseLoggingUpdatesLogRecSize() { 1084 mWsm.enableVerboseLogging(1); 1085 mWsm.enableVerboseLogging(0); 1086 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize()); 1087 } 1088 1089 /** Verifies that enabling verbose logging sets the hal log property in eng builds. */ 1090 @Test 1091 public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() { 1092 reset(mPropertyService); // Ignore calls made in setUp() 1093 when(mBuildProperties.isEngBuild()).thenReturn(true); 1094 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 1095 when(mBuildProperties.isUserBuild()).thenReturn(false); 1096 mWsm.enableVerboseLogging(1); 1097 verify(mPropertyService).set("log.tag.WifiHAL", "V"); 1098 } 1099 1100 /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */ 1101 @Test 1102 public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() { 1103 reset(mPropertyService); // Ignore calls made in setUp() 1104 when(mBuildProperties.isUserdebugBuild()).thenReturn(true); 1105 when(mBuildProperties.isEngBuild()).thenReturn(false); 1106 when(mBuildProperties.isUserBuild()).thenReturn(false); 1107 mWsm.enableVerboseLogging(1); 1108 verify(mPropertyService).set("log.tag.WifiHAL", "V"); 1109 } 1110 1111 /** Verifies that enabling verbose logging does NOT set the hal log property in user builds. */ 1112 @Test 1113 public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() { 1114 reset(mPropertyService); // Ignore calls made in setUp() 1115 when(mBuildProperties.isUserBuild()).thenReturn(true); 1116 when(mBuildProperties.isEngBuild()).thenReturn(false); 1117 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 1118 mWsm.enableVerboseLogging(1); 1119 verify(mPropertyService, never()).set(anyString(), anyString()); 1120 } 1121 1122 private int testGetSupportedFeaturesCase(int supportedFeatures, boolean rttConfigured) { 1123 AsyncChannel channel = mock(AsyncChannel.class); 1124 Message reply = Message.obtain(); 1125 reply.arg1 = supportedFeatures; 1126 reset(mPropertyService); // Ignore calls made in setUp() 1127 when(channel.sendMessageSynchronously(WifiStateMachine.CMD_GET_SUPPORTED_FEATURES)) 1128 .thenReturn(reply); 1129 when(mPropertyService.getBoolean("config.disable_rtt", false)) 1130 .thenReturn(rttConfigured); 1131 return mWsm.syncGetSupportedFeatures(channel); 1132 } 1133 1134 /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ 1135 @Test 1136 public void syncGetSupportedFeatures() { 1137 final int featureAware = WifiManager.WIFI_FEATURE_AWARE; 1138 final int featureInfra = WifiManager.WIFI_FEATURE_INFRA; 1139 final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; 1140 final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; 1141 1142 assertEquals(0, testGetSupportedFeaturesCase(0, false)); 1143 assertEquals(0, testGetSupportedFeaturesCase(0, true)); 1144 assertEquals(featureAware | featureInfra, 1145 testGetSupportedFeaturesCase(featureAware | featureInfra, false)); 1146 assertEquals(featureAware | featureInfra, 1147 testGetSupportedFeaturesCase(featureAware | featureInfra, true)); 1148 assertEquals(featureInfra | featureD2dRtt, 1149 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, false)); 1150 assertEquals(featureInfra, 1151 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, true)); 1152 assertEquals(featureInfra | featureD2apRtt, 1153 testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, false)); 1154 assertEquals(featureInfra, 1155 testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, true)); 1156 assertEquals(featureInfra | featureD2dRtt | featureD2apRtt, 1157 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, false)); 1158 assertEquals(featureInfra, 1159 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, true)); 1160 } 1161 1162 /** 1163 * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager} 1164 * and returning the result that's returned from {@link PasspointManager}. 1165 */ 1166 @Test 1167 public void syncAddOrUpdatePasspointConfig() throws Exception { 1168 when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class))) 1169 .thenReturn(true); 1170 mLooper.startAutoDispatch(); 1171 assertTrue(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel, 1172 new PasspointConfiguration())); 1173 mLooper.stopAutoDispatch(); 1174 reset(mPasspointManager); 1175 1176 when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class))) 1177 .thenReturn(false); 1178 mLooper.startAutoDispatch(); 1179 assertFalse(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel, 1180 new PasspointConfiguration())); 1181 mLooper.stopAutoDispatch(); 1182 } 1183 1184 /** 1185 * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager} 1186 * and returning the result that's returned from {@link PasspointManager}. 1187 */ 1188 @Test 1189 public void syncRemovePasspointConfig() throws Exception { 1190 String fqdn = "test.com"; 1191 when(mPasspointManager.removeProvider(fqdn)).thenReturn(true); 1192 mLooper.startAutoDispatch(); 1193 assertTrue(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn)); 1194 mLooper.stopAutoDispatch(); 1195 reset(mPasspointManager); 1196 1197 when(mPasspointManager.removeProvider(fqdn)).thenReturn(false); 1198 mLooper.startAutoDispatch(); 1199 assertFalse(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn)); 1200 mLooper.stopAutoDispatch(); 1201 } 1202 1203 /** 1204 * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager} 1205 * and returning the result that's returned from {@link PasspointManager} when in client mode. 1206 */ 1207 @Test 1208 public void syncRemovePasspointConfigInClientMode() throws Exception { 1209 loadComponentsInStaMode(); 1210 syncRemovePasspointConfig(); 1211 } 1212 1213 /** 1214 * Verify that syncGetPasspointConfigs will redirect calls to {@link PasspointManager} 1215 * and returning the result that's returned from {@link PasspointManager}. 1216 */ 1217 @Test 1218 public void syncGetPasspointConfigs() throws Exception { 1219 // Setup expected configs. 1220 List<PasspointConfiguration> expectedConfigs = new ArrayList<>(); 1221 PasspointConfiguration config = new PasspointConfiguration(); 1222 HomeSp homeSp = new HomeSp(); 1223 homeSp.setFqdn("test.com"); 1224 config.setHomeSp(homeSp); 1225 expectedConfigs.add(config); 1226 1227 when(mPasspointManager.getProviderConfigs()).thenReturn(expectedConfigs); 1228 mLooper.startAutoDispatch(); 1229 assertEquals(expectedConfigs, mWsm.syncGetPasspointConfigs(mWsmAsyncChannel)); 1230 mLooper.stopAutoDispatch(); 1231 reset(mPasspointManager); 1232 1233 when(mPasspointManager.getProviderConfigs()) 1234 .thenReturn(new ArrayList<PasspointConfiguration>()); 1235 mLooper.startAutoDispatch(); 1236 assertTrue(mWsm.syncGetPasspointConfigs(mWsmAsyncChannel).isEmpty()); 1237 mLooper.stopAutoDispatch(); 1238 } 1239 1240 /** 1241 * Verify that syncGetMatchingWifiConfig will redirect calls to {@link PasspointManager} 1242 * with expected {@link WifiConfiguration} being returned when in client mode. 1243 * 1244 * @throws Exception 1245 */ 1246 @Test 1247 public void syncGetMatchingWifiConfigInClientMode() throws Exception { 1248 loadComponentsInStaMode(); 1249 1250 when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))).thenReturn(null); 1251 mLooper.startAutoDispatch(); 1252 assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel)); 1253 mLooper.stopAutoDispatch(); 1254 reset(mPasspointManager); 1255 1256 WifiConfiguration expectedConfig = new WifiConfiguration(); 1257 expectedConfig.SSID = "TestSSID"; 1258 when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))) 1259 .thenReturn(expectedConfig); 1260 mLooper.startAutoDispatch(); 1261 WifiConfiguration actualConfig = mWsm.syncGetMatchingWifiConfig(new ScanResult(), 1262 mWsmAsyncChannel); 1263 mLooper.stopAutoDispatch(); 1264 assertEquals(expectedConfig.SSID, actualConfig.SSID); 1265 } 1266 1267 /** 1268 * Verify that syncGetMatchingWifiConfig will be a no-op and return {@code null} when not in 1269 * client mode. 1270 * 1271 * @throws Exception 1272 */ 1273 @Test 1274 public void syncGetMatchingWifiConfigInNonClientMode() throws Exception { 1275 mLooper.startAutoDispatch(); 1276 assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel)); 1277 mLooper.stopAutoDispatch(); 1278 verify(mPasspointManager, never()).getMatchingWifiConfig(any(ScanResult.class)); 1279 } 1280 1281 /** 1282 * Verify successful Wps PBC network connection. 1283 */ 1284 @Test 1285 public void wpsPbcConnectSuccess() throws Exception { 1286 loadComponentsInStaMode(); 1287 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1288 mLooper.dispatchAll(); 1289 1290 when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(true); 1291 WpsInfo wpsInfo = new WpsInfo(); 1292 wpsInfo.setup = WpsInfo.PBC; 1293 wpsInfo.BSSID = sBSSID; 1294 1295 mLooper.startAutoDispatch(); 1296 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1297 mLooper.stopAutoDispatch(); 1298 verify(mWifiNative).startWpsPbc(eq(sBSSID)); 1299 1300 assertEquals("WpsRunningState", getCurrentState().getName()); 1301 1302 setupMocksForWpsNetworkMigration(); 1303 1304 mLooper.startAutoDispatch(); 1305 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1306 mLooper.stopAutoDispatch(); 1307 1308 assertEquals("DisconnectedState", getCurrentState().getName()); 1309 } 1310 1311 /** 1312 * Verify failure in starting Wps PBC network connection. 1313 */ 1314 @Test 1315 public void wpsPbcConnectFailure() throws Exception { 1316 loadComponentsInStaMode(); 1317 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1318 mLooper.dispatchAll(); 1319 1320 when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(false); 1321 WpsInfo wpsInfo = new WpsInfo(); 1322 wpsInfo.setup = WpsInfo.PBC; 1323 wpsInfo.BSSID = sBSSID; 1324 1325 mLooper.startAutoDispatch(); 1326 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1327 mLooper.stopAutoDispatch(); 1328 verify(mWifiNative).startWpsPbc(eq(sBSSID)); 1329 1330 assertFalse("WpsRunningState".equals(getCurrentState().getName())); 1331 } 1332 1333 /** 1334 * Verify successful Wps Pin Display network connection. 1335 */ 1336 @Test 1337 public void wpsPinDisplayConnectSuccess() throws Exception { 1338 loadComponentsInStaMode(); 1339 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1340 mLooper.dispatchAll(); 1341 1342 when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn("34545434"); 1343 WpsInfo wpsInfo = new WpsInfo(); 1344 wpsInfo.setup = WpsInfo.DISPLAY; 1345 wpsInfo.BSSID = sBSSID; 1346 1347 mLooper.startAutoDispatch(); 1348 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1349 mLooper.stopAutoDispatch(); 1350 verify(mWifiNative).startWpsPinDisplay(eq(sBSSID)); 1351 1352 assertEquals("WpsRunningState", getCurrentState().getName()); 1353 1354 setupMocksForWpsNetworkMigration(); 1355 1356 mLooper.startAutoDispatch(); 1357 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1358 mLooper.stopAutoDispatch(); 1359 1360 assertEquals("DisconnectedState", getCurrentState().getName()); 1361 } 1362 1363 /** 1364 * Verify failure in Wps Pin Display network connection. 1365 */ 1366 @Test 1367 public void wpsPinDisplayConnectFailure() throws Exception { 1368 loadComponentsInStaMode(); 1369 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1370 mLooper.dispatchAll(); 1371 1372 when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn(null); 1373 WpsInfo wpsInfo = new WpsInfo(); 1374 wpsInfo.setup = WpsInfo.DISPLAY; 1375 wpsInfo.BSSID = sBSSID; 1376 1377 mLooper.startAutoDispatch(); 1378 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1379 mLooper.stopAutoDispatch(); 1380 verify(mWifiNative).startWpsPinDisplay(eq(sBSSID)); 1381 1382 assertFalse("WpsRunningState".equals(getCurrentState().getName())); 1383 } 1384 1385 @Test 1386 public void handleVendorHalDeath() throws Exception { 1387 ArgumentCaptor<WifiNative.VendorHalDeathEventHandler> deathHandlerCapturer = 1388 ArgumentCaptor.forClass(WifiNative.VendorHalDeathEventHandler.class); 1389 when(mWifiNative.initializeVendorHal(deathHandlerCapturer.capture())).thenReturn(true); 1390 1391 // Trigger initialize to capture the death handler registration. 1392 mLooper.startAutoDispatch(); 1393 assertTrue(mWsm.syncInitialize(mWsmAsyncChannel)); 1394 mLooper.stopAutoDispatch(); 1395 1396 verify(mWifiNative).initializeVendorHal(any(WifiNative.VendorHalDeathEventHandler.class)); 1397 WifiNative.VendorHalDeathEventHandler deathHandler = deathHandlerCapturer.getValue(); 1398 1399 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1400 mLooper.dispatchAll(); 1401 1402 // We should not be in initial state now. 1403 assertFalse("InitialState".equals(getCurrentState().getName())); 1404 1405 // Now trigger the death notification. 1406 mLooper.startAutoDispatch(); 1407 deathHandler.onDeath(); 1408 mLooper.stopAutoDispatch(); 1409 1410 // We should back to initial state after vendor HAL death. 1411 assertTrue("InitialState".equals(getCurrentState().getName())); 1412 } 1413 1414 private void setupMocksForWpsNetworkMigration() { 1415 int newNetworkId = 5; 1416 // Now trigger the network connection event for adding the WPS network. 1417 doAnswer(new AnswerWithArguments() { 1418 public boolean answer(Map<String, WifiConfiguration> configs, 1419 SparseArray<Map<String, String>> networkExtras) throws Exception { 1420 configs.put("dummy", new WifiConfiguration()); 1421 return true; 1422 } 1423 }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class)); 1424 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) 1425 .thenReturn(new NetworkUpdateResult(newNetworkId)); 1426 when(mWifiConfigManager.enableNetwork(eq(newNetworkId), anyBoolean(), anyInt())) 1427 .thenReturn(true); 1428 } 1429} 1430