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