WifiStateMachineTest.java revision d27716a747d9cf2d86153aa9ec1b55b663808b28
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.assertNotEquals; 34import static org.junit.Assert.assertNotNull; 35import static org.junit.Assert.assertNull; 36import static org.junit.Assert.assertTrue; 37import static org.mockito.Mockito.*; 38 39import android.app.ActivityManager; 40import android.app.test.MockAnswerUtil.AnswerWithArguments; 41import android.app.test.TestAlarmManager; 42import android.content.Context; 43import android.content.Intent; 44import android.content.pm.PackageManager; 45import android.content.pm.UserInfo; 46import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; 47import android.net.ConnectivityManager; 48import android.net.DhcpResults; 49import android.net.LinkProperties; 50import android.net.dhcp.DhcpClient; 51import android.net.ip.IpManager; 52import android.net.wifi.IApInterface; 53import android.net.wifi.IClientInterface; 54import android.net.wifi.IWificond; 55import android.net.wifi.ScanResult; 56import android.net.wifi.SupplicantState; 57import android.net.wifi.WifiConfiguration; 58import android.net.wifi.WifiInfo; 59import android.net.wifi.WifiManager; 60import android.net.wifi.WifiScanner; 61import android.net.wifi.WifiSsid; 62import android.net.wifi.WpsInfo; 63import android.net.wifi.hotspot2.PasspointConfiguration; 64import android.net.wifi.hotspot2.pps.HomeSp; 65import android.net.wifi.p2p.IWifiP2pManager; 66import android.os.BatteryStats; 67import android.os.Binder; 68import android.os.Bundle; 69import android.os.Handler; 70import android.os.HandlerThread; 71import android.os.IBinder; 72import android.os.IInterface; 73import android.os.INetworkManagementService; 74import android.os.IPowerManager; 75import android.os.Looper; 76import android.os.Message; 77import android.os.Messenger; 78import android.os.PowerManager; 79import android.os.Process; 80import android.os.RemoteException; 81import android.os.UserHandle; 82import android.os.UserManager; 83import android.os.test.TestLooper; 84import android.provider.Settings; 85import android.security.KeyStore; 86import android.telephony.PhoneStateListener; 87import android.telephony.TelephonyManager; 88import android.test.mock.MockContentProvider; 89import android.test.mock.MockContentResolver; 90import android.test.suitebuilder.annotation.SmallTest; 91import android.util.Log; 92import android.util.Pair; 93import android.util.SparseArray; 94 95import com.android.internal.R; 96import com.android.internal.app.IBatteryStats; 97import com.android.internal.util.AsyncChannel; 98import com.android.internal.util.IState; 99import com.android.internal.util.StateMachine; 100import com.android.server.wifi.hotspot2.NetworkDetail; 101import com.android.server.wifi.hotspot2.PasspointManager; 102import com.android.server.wifi.p2p.WifiP2pServiceImpl; 103import com.android.server.wifi.util.WifiPermissionsUtil; 104 105import org.junit.After; 106import org.junit.Before; 107import org.junit.Test; 108import org.mockito.ArgumentCaptor; 109import org.mockito.ArgumentMatcher; 110import org.mockito.InOrder; 111import org.mockito.Mock; 112import org.mockito.MockitoAnnotations; 113 114import java.io.ByteArrayOutputStream; 115import java.io.PrintWriter; 116import java.lang.reflect.Field; 117import java.lang.reflect.InvocationTargetException; 118import java.lang.reflect.Method; 119import java.util.ArrayList; 120import java.util.Arrays; 121import java.util.HashSet; 122import java.util.List; 123import java.util.Map; 124import java.util.Set; 125import java.util.concurrent.CountDownLatch; 126 127/** 128 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}. 129 */ 130@SmallTest 131public class WifiStateMachineTest { 132 public static final String TAG = "WifiStateMachineTest"; 133 134 private static final int MANAGED_PROFILE_UID = 1100000; 135 private static final int OTHER_USER_UID = 1200000; 136 private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE = 137 (ActivityManager.isLowRamDeviceStatic() 138 ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY 139 : WifiStateMachine.NUM_LOG_RECS_VERBOSE); 140 private static final int WPS_SUPPLICANT_NETWORK_ID = 5; 141 private static final int WPS_FRAMEWORK_NETWORK_ID = 10; 142 private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\""; 143 private static final String OP_PACKAGE_NAME = "com.xxx"; 144 145 private long mBinderToken; 146 147 private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) { 148 return mock(class1, withSettings().extraInterfaces(interfaces)); 149 } 150 151 private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) { 152 T tImpl = mockWithInterfaces(class1, iface); 153 IBinder binder = mock(IBinder.class); 154 when(((IInterface) tImpl).asBinder()).thenReturn(binder); 155 when(binder.queryLocalInterface(iface.getCanonicalName())) 156 .thenReturn((IInterface) tImpl); 157 return binder; 158 } 159 160 private void enableDebugLogs() { 161 mWsm.enableVerboseLogging(1); 162 } 163 164 private FrameworkFacade getFrameworkFacade() throws Exception { 165 FrameworkFacade facade = mock(FrameworkFacade.class); 166 167 when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn( 168 mockWithInterfaces(IBinder.class, INetworkManagementService.class)); 169 170 IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class); 171 when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder); 172 173 WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface( 174 IWifiP2pManager.class.getCanonicalName()); 175 176 final CountDownLatch untilDone = new CountDownLatch(1); 177 mP2pThread = new HandlerThread("WifiP2pMockThread") { 178 @Override 179 protected void onLooperPrepared() { 180 untilDone.countDown(); 181 } 182 }; 183 184 mP2pThread.start(); 185 untilDone.await(); 186 187 Handler handler = new Handler(mP2pThread.getLooper()); 188 when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler)); 189 190 IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class); 191 when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder); 192 193 when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class))) 194 .then(new AnswerWithArguments() { 195 public IpManager answer( 196 Context context, String ifname, IpManager.Callback callback) { 197 mIpManagerCallback = callback; 198 return mIpManager; 199 } 200 }); 201 202 return facade; 203 } 204 205 private Context getContext() throws Exception { 206 PackageManager pkgMgr = mock(PackageManager.class); 207 when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true); 208 209 Context context = mock(Context.class); 210 when(context.getPackageManager()).thenReturn(pkgMgr); 211 212 MockContentResolver mockContentResolver = new MockContentResolver(); 213 mockContentResolver.addProvider(Settings.AUTHORITY, 214 new MockContentProvider(context) { 215 @Override 216 public Bundle call(String method, String arg, Bundle extras) { 217 return new Bundle(); 218 } 219 }); 220 when(context.getContentResolver()).thenReturn(mockContentResolver); 221 222 when(context.getSystemService(Context.POWER_SERVICE)).thenReturn( 223 new PowerManager(context, mock(IPowerManager.class), new Handler())); 224 225 mAlarmManager = new TestAlarmManager(); 226 when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( 227 mAlarmManager.getAlarmManager()); 228 229 when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( 230 mock(ConnectivityManager.class)); 231 232 when(context.getOpPackageName()).thenReturn(OP_PACKAGE_NAME); 233 234 return context; 235 } 236 237 private MockResources getMockResources() { 238 MockResources resources = new MockResources(); 239 resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false); 240 resources.setBoolean( 241 R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, 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 private void injectDhcpSuccess(DhcpResults dhcpResults) { 297 mIpManagerCallback.onNewDhcpResults(dhcpResults); 298 mIpManagerCallback.onProvisioningSuccess(new LinkProperties()); 299 } 300 301 private void injectDhcpFailure() { 302 mIpManagerCallback.onNewDhcpResults(null); 303 mIpManagerCallback.onProvisioningFailure(new LinkProperties()); 304 } 305 306 static final String sSSID = "\"GoogleGuest\""; 307 static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); 308 static final String sBSSID = "01:02:03:04:05:06"; 309 static final int sFreq = 2437; 310 static final String WIFI_IFACE_NAME = "mockWlan"; 311 312 WifiStateMachine mWsm; 313 HandlerThread mWsmThread; 314 HandlerThread mP2pThread; 315 HandlerThread mSyncThread; 316 AsyncChannel mWsmAsyncChannel; 317 TestAlarmManager mAlarmManager; 318 MockWifiMonitor mWifiMonitor; 319 TestLooper mLooper; 320 Context mContext; 321 MockResources mResources; 322 FrameworkFacade mFrameworkFacade; 323 IpManager.Callback mIpManagerCallback; 324 PhoneStateListener mPhoneStateListener; 325 326 final ArgumentCaptor<SoftApManager.Listener> mSoftApManagerListenerCaptor = 327 ArgumentCaptor.forClass(SoftApManager.Listener.class); 328 329 @Mock WifiScanner mWifiScanner; 330 @Mock SupplicantStateTracker mSupplicantStateTracker; 331 @Mock WifiMetrics mWifiMetrics; 332 @Mock UserManager mUserManager; 333 @Mock WifiApConfigStore mApConfigStore; 334 @Mock BackupManagerProxy mBackupManagerProxy; 335 @Mock WifiCountryCode mCountryCode; 336 @Mock WifiInjector mWifiInjector; 337 @Mock WifiLastResortWatchdog mWifiLastResortWatchdog; 338 @Mock PropertyService mPropertyService; 339 @Mock BuildProperties mBuildProperties; 340 @Mock IWificond mWificond; 341 @Mock IApInterface mApInterface; 342 @Mock IClientInterface mClientInterface; 343 @Mock IBinder mApInterfaceBinder; 344 @Mock IBinder mClientInterfaceBinder; 345 @Mock IBinder mPackageManagerBinder; 346 @Mock WifiConfigManager mWifiConfigManager; 347 @Mock WifiNative mWifiNative; 348 @Mock WifiConnectivityManager mWifiConnectivityManager; 349 @Mock SoftApManager mSoftApManager; 350 @Mock WifiStateTracker mWifiStateTracker; 351 @Mock PasspointManager mPasspointManager; 352 @Mock SelfRecovery mSelfRecovery; 353 @Mock WifiPermissionsUtil mWifiPermissionsUtil; 354 @Mock IpManager mIpManager; 355 @Mock TelephonyManager mTelephonyManager; 356 @Mock WrongPasswordNotifier mWrongPasswordNotifier; 357 @Mock Clock mClock; 358 359 public WifiStateMachineTest() throws Exception { 360 } 361 362 @Before 363 public void setUp() throws Exception { 364 Log.d(TAG, "Setting up ..."); 365 366 // Ensure looper exists 367 mLooper = new TestLooper(); 368 369 MockitoAnnotations.initMocks(this); 370 371 /** uncomment this to enable logs from WifiStateMachines */ 372 // enableDebugLogs(); 373 374 mWifiMonitor = new MockWifiMonitor(); 375 when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 376 when(mWifiInjector.getClock()).thenReturn(new Clock()); 377 when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); 378 when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService); 379 when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties); 380 when(mWifiInjector.getKeyStore()).thenReturn(mock(KeyStore.class)); 381 when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class)); 382 when(mWifiInjector.makeWifiDiagnostics(anyObject())).thenReturn( 383 mock(BaseWifiDiagnostics.class)); 384 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 385 when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); 386 when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner); 387 when(mWifiInjector.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean())) 388 .thenReturn(mWifiConnectivityManager); 389 when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class), 390 mSoftApManagerListenerCaptor.capture(), any(IApInterface.class), 391 any(WifiConfiguration.class))) 392 .thenReturn(mSoftApManager); 393 when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager); 394 when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker); 395 when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor); 396 when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative); 397 when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); 398 when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil); 399 when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager); 400 when(mWifiInjector.getClock()).thenReturn(mClock); 401 402 when(mWifiNative.setupForClientMode()) 403 .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mClientInterface)); 404 when(mWifiNative.setupForSoftApMode()) 405 .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface)); 406 when(mApInterface.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); 407 when(mWifiNative.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); 408 when(mWifiNative.enableSupplicant()).thenReturn(true); 409 when(mWifiNative.disableSupplicant()).thenReturn(true); 410 when(mWifiNative.getFrameworkNetworkId(anyInt())).thenReturn(0); 411 412 413 mFrameworkFacade = getFrameworkFacade(); 414 mContext = getContext(); 415 416 mResources = getMockResources(); 417 when(mContext.getResources()).thenReturn(mResources); 418 419 when(mFrameworkFacade.getIntegerSetting(mContext, 420 Settings.Global.WIFI_FREQUENCY_BAND, 421 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn( 422 WifiManager.WIFI_FREQUENCY_BAND_AUTO); 423 424 when(mFrameworkFacade.makeApConfigStore(eq(mContext), eq(mBackupManagerProxy))) 425 .thenReturn(mApConfigStore); 426 427 when(mFrameworkFacade.makeSupplicantStateTracker( 428 any(Context.class), any(WifiConfigManager.class), 429 any(Handler.class))).thenReturn(mSupplicantStateTracker); 430 431 when(mUserManager.getProfileParent(11)) 432 .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0)); 433 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList( 434 new UserInfo(UserHandle.USER_SYSTEM, "owner", 0), 435 new UserInfo(11, "managed profile", 0))); 436 437 when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder); 438 when(mClientInterface.asBinder()).thenReturn(mClientInterfaceBinder); 439 440 doAnswer(new AnswerWithArguments() { 441 public void answer(PhoneStateListener phoneStateListener, int events) 442 throws Exception { 443 mPhoneStateListener = phoneStateListener; 444 } 445 }).when(mTelephonyManager).listen(any(PhoneStateListener.class), anyInt()); 446 447 initializeWsm(); 448 } 449 450 private void initializeWsm() throws Exception { 451 mWsm = new WifiStateMachine(mContext, mFrameworkFacade, mLooper.getLooper(), 452 mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative, 453 mWrongPasswordNotifier); 454 mWsmThread = getWsmHandlerThread(mWsm); 455 456 final AsyncChannel channel = new AsyncChannel(); 457 Handler handler = new Handler(mLooper.getLooper()) { 458 @Override 459 public void handleMessage(Message msg) { 460 switch (msg.what) { 461 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 462 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 463 mWsmAsyncChannel = channel; 464 } else { 465 Log.d(TAG, "Failed to connect Command channel " + this); 466 } 467 break; 468 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 469 Log.d(TAG, "Command channel disconnected" + this); 470 break; 471 } 472 } 473 }; 474 475 channel.connect(mContext, handler, mWsm.getMessenger()); 476 mLooper.dispatchAll(); 477 /* Now channel is supposed to be connected */ 478 479 mBinderToken = Binder.clearCallingIdentity(); 480 481 /* Send the BOOT_COMPLETED message to setup some WSM state. */ 482 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 483 mLooper.dispatchAll(); 484 } 485 486 @After 487 public void cleanUp() throws Exception { 488 Binder.restoreCallingIdentity(mBinderToken); 489 490 if (mSyncThread != null) stopLooper(mSyncThread.getLooper()); 491 if (mWsmThread != null) stopLooper(mWsmThread.getLooper()); 492 if (mP2pThread != null) stopLooper(mP2pThread.getLooper()); 493 494 mWsmThread = null; 495 mP2pThread = null; 496 mSyncThread = null; 497 mWsmAsyncChannel = null; 498 mWsm = null; 499 } 500 501 @Test 502 public void createNew() throws Exception { 503 assertEquals("InitialState", getCurrentState().getName()); 504 505 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 506 mLooper.dispatchAll(); 507 assertEquals("InitialState", getCurrentState().getName()); 508 } 509 510 @Test 511 public void loadComponentsInStaMode() throws Exception { 512 startSupplicantAndDispatchMessages(); 513 514 verify(mContext).sendStickyBroadcastAsUser( 515 (Intent) argThat(new WifiEnablingStateIntentMatcher()), eq(UserHandle.ALL)); 516 517 assertEquals("DisconnectedState", getCurrentState().getName()); 518 } 519 520 private void checkApStateChangedBroadcast(Intent intent, int expectedCurrentState, 521 int expectedPrevState, int expectedErrorCode, String expectedIfaceName, 522 int expectedMode) { 523 int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); 524 int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); 525 int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON, HOTSPOT_NO_ERROR); 526 String ifaceName = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME); 527 int mode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, WifiManager.IFACE_IP_MODE_UNSPECIFIED); 528 assertEquals(expectedCurrentState, currentState); 529 assertEquals(expectedPrevState, prevState); 530 assertEquals(expectedErrorCode, errorCode); 531 assertEquals(expectedIfaceName, ifaceName); 532 assertEquals(expectedMode, mode); 533 } 534 535 private void loadComponentsInApMode(int mode) throws Exception { 536 SoftApModeConfiguration config = new SoftApModeConfiguration(mode, new WifiConfiguration()); 537 mWsm.setHostApRunning(config, true); 538 mLooper.dispatchAll(); 539 540 assertEquals("SoftApState", getCurrentState().getName()); 541 542 verify(mWifiNative).setupForSoftApMode(); 543 verify(mSoftApManager).start(); 544 545 // reset expectations for mContext due to previously sent AP broadcast 546 reset(mContext); 547 548 // get the SoftApManager.Listener and trigger some updates 549 SoftApManager.Listener listener = mSoftApManagerListenerCaptor.getValue(); 550 listener.onStateChanged(WIFI_AP_STATE_ENABLING, 0); 551 listener.onStateChanged(WIFI_AP_STATE_ENABLED, 0); 552 listener.onStateChanged(WIFI_AP_STATE_DISABLING, 0); 553 // note, this will trigger a mode change when TestLooper is dispatched 554 listener.onStateChanged(WIFI_AP_STATE_DISABLED, 0); 555 556 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 557 verify(mContext, times(4)) 558 .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL)); 559 560 List<Intent> capturedIntents = intentCaptor.getAllValues(); 561 checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING, 562 WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode); 563 checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_ENABLED, 564 WIFI_AP_STATE_ENABLING, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode); 565 checkApStateChangedBroadcast(capturedIntents.get(2), WIFI_AP_STATE_DISABLING, 566 WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode); 567 checkApStateChangedBroadcast(capturedIntents.get(3), WIFI_AP_STATE_DISABLED, 568 WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode); 569 } 570 571 @Test 572 public void loadComponentsInApModeForTethering() throws Exception { 573 loadComponentsInApMode(WifiManager.IFACE_IP_MODE_TETHERED); 574 } 575 576 @Test 577 public void loadComponentsInApModeForLOHS() throws Exception { 578 loadComponentsInApMode(WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 579 } 580 581 @Test 582 public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception { 583 when(mWifiNative.enableSupplicant()).thenReturn(false); 584 mWsm.setSupplicantRunning(true); 585 mLooper.dispatchAll(); 586 assertEquals("InitialState", getCurrentState().getName()); 587 // we should not be sending a wifi enabling update 588 verify(mContext, never()).sendStickyBroadcastAsUser( 589 (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); 590 } 591 592 @Test 593 public void shouldRequireWificondToLeaveInitialState() throws Exception { 594 // We start out with valid default values, break them going backwards so that 595 // we test all the bailout cases. 596 597 // ClientInterface dies after creation. 598 doThrow(new RemoteException()).when(mClientInterfaceBinder).linkToDeath(any(), anyInt()); 599 mWsm.setSupplicantRunning(true); 600 mLooper.dispatchAll(); 601 assertEquals("InitialState", getCurrentState().getName()); 602 603 // Failed to even create the client interface. 604 when(mWificond.createClientInterface()).thenReturn(null); 605 mWsm.setSupplicantRunning(true); 606 mLooper.dispatchAll(); 607 assertEquals("InitialState", getCurrentState().getName()); 608 609 // Failed to get wificond proxy. 610 when(mWifiInjector.makeWificond()).thenReturn(null); 611 mWsm.setSupplicantRunning(true); 612 mLooper.dispatchAll(); 613 assertEquals("InitialState", getCurrentState().getName()); 614 } 615 616 @Test 617 public void loadComponentsFailure() throws Exception { 618 when(mWifiNative.enableSupplicant()).thenReturn(false); 619 620 mWsm.setSupplicantRunning(true); 621 mLooper.dispatchAll(); 622 assertEquals("InitialState", getCurrentState().getName()); 623 624 mWsm.setSupplicantRunning(true); 625 mLooper.dispatchAll(); 626 assertEquals("InitialState", getCurrentState().getName()); 627 } 628 629 @Test 630 public void checkInitialStateStickyWhenDisabledMode() throws Exception { 631 mLooper.dispatchAll(); 632 assertEquals("InitialState", getCurrentState().getName()); 633 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 634 635 mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE); 636 mLooper.dispatchAll(); 637 assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest()); 638 assertEquals("InitialState", getCurrentState().getName()); 639 } 640 641 @Test 642 public void shouldStartSupplicantWhenConnectModeRequested() throws Exception { 643 // The first time we start out in InitialState, we sit around here. 644 mLooper.dispatchAll(); 645 assertEquals("InitialState", getCurrentState().getName()); 646 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 647 648 // But if someone tells us to enter connect mode, we start up supplicant 649 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 650 mLooper.dispatchAll(); 651 assertEquals("SupplicantStartingState", getCurrentState().getName()); 652 } 653 654 /** 655 * Test that mode changes accurately reflect the value for isWifiEnabled. 656 */ 657 @Test 658 public void checkIsWifiEnabledForModeChanges() throws Exception { 659 // Check initial state 660 mLooper.dispatchAll(); 661 assertEquals("InitialState", getCurrentState().getName()); 662 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 663 664 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); 665 startSupplicantAndDispatchMessages(); 666 mWsm.setSupplicantRunning(true); 667 mLooper.dispatchAll(); 668 assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); 669 assertEquals("ScanModeState", getCurrentState().getName()); 670 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 671 verify(mContext, never()).sendStickyBroadcastAsUser( 672 (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); 673 674 675 // switch to connect mode and verify wifi is reported as enabled 676 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 677 mLooper.dispatchAll(); 678 assertEquals("DisconnectedState", getCurrentState().getName()); 679 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 680 assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); 681 verify(mContext).sendStickyBroadcastAsUser( 682 (Intent) argThat(new WifiEnablingStateIntentMatcher()), eq(UserHandle.ALL)); 683 684 // reset the expectations on mContext since we did get an expected broadcast, but we should 685 // not on the next transition 686 reset(mContext); 687 688 // now go back to scan mode with "wifi disabled" to verify the reported wifi state. 689 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE); 690 mLooper.dispatchAll(); 691 assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE, 692 mWsm.getOperationalModeForTest()); 693 assertEquals("ScanModeState", getCurrentState().getName()); 694 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 695 verify(mContext, never()).sendStickyBroadcastAsUser( 696 (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); 697 698 // now go to AP mode 699 mWsm.setSupplicantRunning(false); 700 mWsm.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP); 701 mWsm.sendMessage(WifiMonitor.SUP_DISCONNECTION_EVENT); 702 SoftApModeConfiguration config = new SoftApModeConfiguration( 703 WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration()); 704 mWsm.setHostApRunning(config, true); 705 mLooper.dispatchAll(); 706 assertEquals("SoftApState", getCurrentState().getName()); 707 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 708 verify(mContext, never()).sendStickyBroadcastAsUser( 709 (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); 710 } 711 712 private class WifiEnablingStateIntentMatcher implements ArgumentMatcher<Intent> { 713 @Override 714 public boolean matches(Intent intent) { 715 if (WifiManager.WIFI_STATE_CHANGED_ACTION != intent.getAction()) { 716 // not the correct type 717 return false; 718 } 719 return WifiManager.WIFI_STATE_ENABLING 720 == intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 721 WifiManager.WIFI_STATE_DISABLED); 722 } 723 } 724 725 /** 726 * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant 727 * is started. 728 */ 729 @Test 730 public void checkStartInCorrectStateAfterChangingInitialState() throws Exception { 731 // Check initial state 732 mLooper.dispatchAll(); 733 assertEquals("InitialState", getCurrentState().getName()); 734 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 735 736 // Update the mode 737 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); 738 mLooper.dispatchAll(); 739 assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); 740 741 // Start supplicant so we move to the next state 742 startSupplicantAndDispatchMessages(); 743 744 assertEquals("ScanModeState", getCurrentState().getName()); 745 verify(mContext, never()).sendStickyBroadcastAsUser( 746 (Intent) argThat(new WifiEnablingStateIntentMatcher()), any()); 747 } 748 749 /** 750 * Verifies that configs can be removed when in client mode. 751 */ 752 @Test 753 public void canRemoveNetworkConfigInClientMode() throws Exception { 754 boolean result; 755 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 756 initializeAndAddNetworkAndVerifySuccess(); 757 mLooper.startAutoDispatch(); 758 result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0); 759 mLooper.stopAutoDispatch(); 760 assertTrue(result); 761 } 762 763 /** 764 * Verifies that configs can be removed when not in client mode. 765 */ 766 @Test 767 public void canRemoveNetworkConfigWhenWifiDisabled() { 768 boolean result; 769 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 770 mLooper.startAutoDispatch(); 771 result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0); 772 mLooper.stopAutoDispatch(); 773 774 assertTrue(result); 775 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 776 } 777 778 /** 779 * Verifies that configs can be forgotten when in client mode. 780 */ 781 @Test 782 public void canForgetNetworkConfigInClientMode() throws Exception { 783 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 784 initializeAndAddNetworkAndVerifySuccess(); 785 mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID); 786 mLooper.dispatchAll(); 787 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 788 } 789 790 /** 791 * Verifies that configs can be removed when not in client mode. 792 */ 793 @Test 794 public void canForgetNetworkConfigWhenWifiDisabled() throws Exception { 795 when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true); 796 mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID); 797 mLooper.dispatchAll(); 798 verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt()); 799 } 800 801 /** 802 * Helper method to move through SupplicantStarting and SupplicantStarted states. 803 */ 804 private void startSupplicantAndDispatchMessages() throws Exception { 805 mWsm.setSupplicantRunning(true); 806 mLooper.dispatchAll(); 807 808 assertEquals("SupplicantStartingState", getCurrentState().getName()); 809 810 when(mWifiNative.setDeviceName(anyString())).thenReturn(true); 811 when(mWifiNative.setManufacturer(anyString())).thenReturn(true); 812 when(mWifiNative.setModelName(anyString())).thenReturn(true); 813 when(mWifiNative.setModelNumber(anyString())).thenReturn(true); 814 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 815 when(mWifiNative.setConfigMethods(anyString())).thenReturn(true); 816 when(mWifiNative.setDeviceType(anyString())).thenReturn(true); 817 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 818 when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true); 819 820 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 821 mLooper.dispatchAll(); 822 823 verify(mWifiNative).setupForClientMode(); 824 verify(mWifiLastResortWatchdog).clearAllFailureCounts(); 825 } 826 827 private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception { 828 WifiConfiguration config = new WifiConfiguration(); 829 config.SSID = sSSID; 830 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 831 config.hiddenSSID = isHidden; 832 833 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) 834 .thenReturn(new NetworkUpdateResult(0)); 835 when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config)); 836 when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config); 837 when(mWifiConfigManager.getConfiguredNetworkWithPassword(0)).thenReturn(config); 838 839 mLooper.startAutoDispatch(); 840 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 841 mLooper.stopAutoDispatch(); 842 843 verify(mWifiConfigManager).addOrUpdateNetwork(eq(config), anyInt()); 844 845 mLooper.startAutoDispatch(); 846 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 847 mLooper.stopAutoDispatch(); 848 assertEquals(1, configs.size()); 849 850 WifiConfiguration config2 = configs.get(0); 851 assertEquals("\"GoogleGuest\"", config2.SSID); 852 assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); 853 } 854 855 private void initializeAndAddNetworkAndVerifySuccess() throws Exception { 856 initializeAndAddNetworkAndVerifySuccess(false); 857 } 858 859 private void initializeAndAddNetworkAndVerifySuccess(boolean isHidden) throws Exception { 860 loadComponentsInStaMode(); 861 addNetworkAndVerifySuccess(isHidden); 862 } 863 864 /** 865 * Helper method to retrieve WifiConfiguration by SSID. 866 * 867 * Returns the associated WifiConfiguration if it is found, null otherwise. 868 */ 869 private WifiConfiguration getWifiConfigurationForNetwork(String ssid) { 870 mLooper.startAutoDispatch(); 871 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 872 mLooper.stopAutoDispatch(); 873 874 for (WifiConfiguration checkConfig : configs) { 875 if (checkConfig.SSID.equals(ssid)) { 876 return checkConfig; 877 } 878 } 879 return null; 880 } 881 882 private void verifyScan(int band, int reportEvents, Set<String> hiddenNetworkSSIDSet) { 883 ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor = 884 ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); 885 ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor = 886 ArgumentCaptor.forClass(WifiScanner.ScanListener.class); 887 verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(), 888 eq(null)); 889 WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue(); 890 assertEquals("band", band, actualSettings.band); 891 assertEquals("reportEvents", reportEvents, actualSettings.reportEvents); 892 893 if (hiddenNetworkSSIDSet == null) { 894 hiddenNetworkSSIDSet = new HashSet<>(); 895 } 896 Set<String> actualHiddenNetworkSSIDSet = new HashSet<>(); 897 if (actualSettings.hiddenNetworks != null) { 898 for (int i = 0; i < actualSettings.hiddenNetworks.length; ++i) { 899 actualHiddenNetworkSSIDSet.add(actualSettings.hiddenNetworks[i].ssid); 900 } 901 } 902 assertEquals("hidden networks", hiddenNetworkSSIDSet, actualHiddenNetworkSSIDSet); 903 904 when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); 905 mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); 906 907 mLooper.dispatchAll(); 908 909 List<ScanResult> reportedResults = mWsm.syncGetScanResultsList(); 910 assertEquals(8, reportedResults.size()); 911 } 912 913 @Test 914 public void scan() throws Exception { 915 initializeAndAddNetworkAndVerifySuccess(); 916 917 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 918 mWsm.startScan(-1, 0, null, null); 919 mLooper.dispatchAll(); 920 921 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 922 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 923 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null); 924 } 925 926 @Test 927 public void scanWithHiddenNetwork() throws Exception { 928 initializeAndAddNetworkAndVerifySuccess(true); 929 930 Set<String> hiddenNetworkSet = new HashSet<>(); 931 hiddenNetworkSet.add(sSSID); 932 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList = new ArrayList<>(); 933 hiddenNetworkList.add(new WifiScanner.ScanSettings.HiddenNetwork(sSSID)); 934 when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(hiddenNetworkList); 935 936 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 937 mWsm.startScan(-1, 0, null, null); 938 mLooper.dispatchAll(); 939 940 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 941 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 942 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 943 hiddenNetworkSet); 944 } 945 946 @Test 947 public void connect() throws Exception { 948 initializeAndAddNetworkAndVerifySuccess(); 949 when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(true); 950 when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(true); 951 952 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 953 mLooper.dispatchAll(); 954 verify(mWifiNative).removeAllNetworks(); 955 956 mLooper.startAutoDispatch(); 957 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 958 mLooper.stopAutoDispatch(); 959 960 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 961 verify(mWifiConnectivityManager).setUserConnectChoice(eq(0)); 962 963 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 964 mLooper.dispatchAll(); 965 966 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 967 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 968 mLooper.dispatchAll(); 969 970 assertEquals("ObtainingIpState", getCurrentState().getName()); 971 972 DhcpResults dhcpResults = new DhcpResults(); 973 dhcpResults.setGateway("1.2.3.4"); 974 dhcpResults.setIpAddress("192.168.1.100", 0); 975 dhcpResults.addDns("8.8.8.8"); 976 dhcpResults.setLeaseDuration(3600); 977 978 injectDhcpSuccess(dhcpResults); 979 mLooper.dispatchAll(); 980 981 assertEquals("ConnectedState", getCurrentState().getName()); 982 } 983 984 @Test 985 public void connectWithNoEnablePermission() throws Exception { 986 initializeAndAddNetworkAndVerifySuccess(); 987 when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(false); 988 when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(false); 989 990 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 991 mLooper.dispatchAll(); 992 verify(mWifiNative).removeAllNetworks(); 993 994 mLooper.startAutoDispatch(); 995 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 996 mLooper.stopAutoDispatch(); 997 998 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 999 verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0)); 1000 1001 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 1002 mLooper.dispatchAll(); 1003 1004 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1005 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 1006 mLooper.dispatchAll(); 1007 1008 assertEquals("ObtainingIpState", getCurrentState().getName()); 1009 1010 DhcpResults dhcpResults = new DhcpResults(); 1011 dhcpResults.setGateway("1.2.3.4"); 1012 dhcpResults.setIpAddress("192.168.1.100", 0); 1013 dhcpResults.addDns("8.8.8.8"); 1014 dhcpResults.setLeaseDuration(3600); 1015 1016 injectDhcpSuccess(dhcpResults); 1017 mLooper.dispatchAll(); 1018 1019 assertEquals("ConnectedState", getCurrentState().getName()); 1020 } 1021 1022 @Test 1023 public void enableWithInvalidNetworkId() throws Exception { 1024 initializeAndAddNetworkAndVerifySuccess(); 1025 when(mWifiConfigManager.getConfiguredNetwork(eq(0))).thenReturn(null); 1026 1027 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1028 mLooper.dispatchAll(); 1029 verify(mWifiNative).removeAllNetworks(); 1030 1031 mLooper.startAutoDispatch(); 1032 assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 1033 mLooper.stopAutoDispatch(); 1034 1035 verify(mWifiConfigManager, never()).enableNetwork(eq(0), eq(true), anyInt()); 1036 verify(mWifiConfigManager, never()).checkAndUpdateLastConnectUid(eq(0), anyInt()); 1037 } 1038 1039 /** 1040 * If caller tries to connect to a network that is already connected, the connection request 1041 * should succeed. 1042 * 1043 * Test: Create and connect to a network, then try to reconnect to the same network. Verify 1044 * that connection request returns with CONNECT_NETWORK_SUCCEEDED. 1045 */ 1046 @Test 1047 public void reconnectToConnectedNetwork() throws Exception { 1048 initializeAndAddNetworkAndVerifySuccess(); 1049 1050 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1051 mLooper.dispatchAll(); 1052 verify(mWifiNative).removeAllNetworks(); 1053 1054 mLooper.startAutoDispatch(); 1055 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 1056 mLooper.stopAutoDispatch(); 1057 1058 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 1059 1060 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 1061 mLooper.dispatchAll(); 1062 1063 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1064 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 1065 mLooper.dispatchAll(); 1066 1067 assertEquals("ObtainingIpState", getCurrentState().getName()); 1068 1069 // try to reconnect 1070 mLooper.startAutoDispatch(); 1071 Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.CONNECT_NETWORK, 0); 1072 mLooper.stopAutoDispatch(); 1073 1074 assertEquals(WifiManager.CONNECT_NETWORK_SUCCEEDED, reply.what); 1075 } 1076 1077 @Test 1078 public void testDhcpFailure() throws Exception { 1079 initializeAndAddNetworkAndVerifySuccess(); 1080 1081 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1082 mLooper.dispatchAll(); 1083 1084 mLooper.startAutoDispatch(); 1085 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 1086 mLooper.stopAutoDispatch(); 1087 1088 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 1089 1090 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 1091 mLooper.dispatchAll(); 1092 1093 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1094 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 1095 mLooper.dispatchAll(); 1096 1097 assertEquals("ObtainingIpState", getCurrentState().getName()); 1098 1099 injectDhcpFailure(); 1100 mLooper.dispatchAll(); 1101 1102 assertEquals("DisconnectingState", getCurrentState().getName()); 1103 } 1104 1105 /** 1106 * Verify that the network selection status will be updated with DISABLED_AUTHENTICATION_FAILURE 1107 * when wrong password authentication failure is detected and the network had been 1108 * connected previously. 1109 */ 1110 @Test 1111 public void testWrongPasswordWithPreviouslyConnected() throws Exception { 1112 initializeAndAddNetworkAndVerifySuccess(); 1113 1114 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1115 mLooper.dispatchAll(); 1116 1117 mLooper.startAutoDispatch(); 1118 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 1119 mLooper.stopAutoDispatch(); 1120 1121 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 1122 1123 WifiConfiguration config = new WifiConfiguration(); 1124 config.getNetworkSelectionStatus().setHasEverConnected(true); 1125 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); 1126 1127 mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, 1128 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); 1129 mLooper.dispatchAll(); 1130 1131 verify(mWrongPasswordNotifier, never()).onWrongPasswordError(anyString()); 1132 verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(), 1133 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE)); 1134 1135 assertEquals("DisconnectedState", getCurrentState().getName()); 1136 } 1137 1138 /** 1139 * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD 1140 * when wrong password authentication failure is detected and the network has never been 1141 * connected. 1142 */ 1143 @Test 1144 public void testWrongPasswordWithNeverConnected() throws Exception { 1145 initializeAndAddNetworkAndVerifySuccess(); 1146 1147 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1148 mLooper.dispatchAll(); 1149 1150 mLooper.startAutoDispatch(); 1151 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 1152 mLooper.stopAutoDispatch(); 1153 1154 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 1155 1156 WifiConfiguration config = new WifiConfiguration(); 1157 config.SSID = sSSID; 1158 config.getNetworkSelectionStatus().setHasEverConnected(false); 1159 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config); 1160 1161 mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, 1162 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); 1163 mLooper.dispatchAll(); 1164 1165 verify(mWrongPasswordNotifier).onWrongPasswordError(eq(sSSID)); 1166 verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(), 1167 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD)); 1168 1169 assertEquals("DisconnectedState", getCurrentState().getName()); 1170 } 1171 1172 /** 1173 * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD 1174 * when wrong password authentication failure is detected and the network is unknown. 1175 */ 1176 @Test 1177 public void testWrongPasswordWithNullNetwork() throws Exception { 1178 initializeAndAddNetworkAndVerifySuccess(); 1179 1180 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1181 mLooper.dispatchAll(); 1182 1183 mLooper.startAutoDispatch(); 1184 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 1185 mLooper.stopAutoDispatch(); 1186 1187 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 1188 1189 when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null); 1190 1191 mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, 1192 WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD); 1193 mLooper.dispatchAll(); 1194 1195 verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(), 1196 eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD)); 1197 1198 assertEquals("DisconnectedState", getCurrentState().getName()); 1199 } 1200 1201 @Test 1202 public void testBadNetworkEvent() throws Exception { 1203 initializeAndAddNetworkAndVerifySuccess(); 1204 1205 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1206 mLooper.dispatchAll(); 1207 1208 mLooper.startAutoDispatch(); 1209 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 1210 mLooper.stopAutoDispatch(); 1211 1212 verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt()); 1213 1214 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); 1215 mLooper.dispatchAll(); 1216 1217 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1218 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 1219 mLooper.dispatchAll(); 1220 1221 assertEquals("DisconnectedState", getCurrentState().getName()); 1222 } 1223 1224 1225 @Test 1226 public void smToString() throws Exception { 1227 assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString( 1228 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED)); 1229 assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString( 1230 DhcpClient.CMD_PRE_DHCP_ACTION)); 1231 assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString( 1232 WifiStateMachine.CMD_IP_REACHABILITY_LOST)); 1233 } 1234 1235 @Test 1236 public void disconnect() throws Exception { 1237 connect(); 1238 1239 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06"); 1240 mLooper.dispatchAll(); 1241 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1242 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); 1243 mLooper.dispatchAll(); 1244 1245 assertEquals("DisconnectedState", getCurrentState().getName()); 1246 } 1247 1248 /** 1249 * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected 1250 * to true. 1251 * 1252 * Test: Successfully create and connect to a network. Check the config and verify 1253 * WifiConfiguration.getHasEverConnected() is true. 1254 */ 1255 @Test 1256 public void setHasEverConnectedTrueOnConnect() throws Exception { 1257 connect(); 1258 verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0); 1259 } 1260 1261 /** 1262 * Fail network connection attempt and verify HasEverConnected remains false. 1263 * 1264 * Test: Successfully create a network but fail when connecting. Check the config and verify 1265 * WifiConfiguration.getHasEverConnected() is false. 1266 */ 1267 @Test 1268 public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception { 1269 testDhcpFailure(); 1270 verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0); 1271 } 1272 1273 @Test 1274 public void iconQueryTest() throws Exception { 1275 // TODO(b/31065385): Passpoint config management. 1276 } 1277 1278 @Test 1279 public void verboseLogRecSizeIsGreaterThanNormalSize() { 1280 assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL); 1281 } 1282 1283 /** 1284 * Verifies that, by default, we allow only the "normal" number of log records. 1285 */ 1286 @Test 1287 public void normalLogRecSizeIsUsedByDefault() { 1288 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize()); 1289 } 1290 1291 /** 1292 * Verifies that, in verbose mode, we allow a larger number of log records. 1293 */ 1294 @Test 1295 public void enablingVerboseLoggingUpdatesLogRecSize() { 1296 mWsm.enableVerboseLogging(1); 1297 assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecMaxSize()); 1298 } 1299 1300 @Test 1301 public void disablingVerboseLoggingClearsRecords() { 1302 mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT); 1303 mLooper.dispatchAll(); 1304 assertTrue(mWsm.getLogRecSize() >= 1); 1305 1306 mWsm.enableVerboseLogging(0); 1307 assertEquals(0, mWsm.getLogRecSize()); 1308 } 1309 1310 @Test 1311 public void disablingVerboseLoggingUpdatesLogRecSize() { 1312 mWsm.enableVerboseLogging(1); 1313 mWsm.enableVerboseLogging(0); 1314 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize()); 1315 } 1316 1317 @Test 1318 public void logRecsIncludeDisconnectCommand() { 1319 // There's nothing special about the DISCONNECT command. It's just representative of 1320 // "normal" commands. 1321 mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT); 1322 mLooper.dispatchAll(); 1323 assertEquals(1, mWsm.copyLogRecs() 1324 .stream() 1325 .filter(logRec -> logRec.getWhat() == WifiStateMachine.CMD_DISCONNECT) 1326 .count()); 1327 } 1328 1329 @Test 1330 public void logRecsExcludeRssiPollCommandByDefault() { 1331 mWsm.sendMessage(WifiStateMachine.CMD_RSSI_POLL); 1332 mLooper.dispatchAll(); 1333 assertEquals(0, mWsm.copyLogRecs() 1334 .stream() 1335 .filter(logRec -> logRec.getWhat() == WifiStateMachine.CMD_RSSI_POLL) 1336 .count()); 1337 } 1338 1339 @Test 1340 public void logRecsIncludeRssiPollCommandWhenVerboseLoggingIsEnabled() { 1341 mWsm.enableVerboseLogging(1); 1342 mWsm.sendMessage(WifiStateMachine.CMD_RSSI_POLL); 1343 mLooper.dispatchAll(); 1344 assertEquals(1, mWsm.copyLogRecs() 1345 .stream() 1346 .filter(logRec -> logRec.getWhat() == WifiStateMachine.CMD_RSSI_POLL) 1347 .count()); 1348 } 1349 1350 /** Verifies that enabling verbose logging sets the hal log property in eng builds. */ 1351 @Test 1352 public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() { 1353 reset(mPropertyService); // Ignore calls made in setUp() 1354 when(mBuildProperties.isEngBuild()).thenReturn(true); 1355 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 1356 when(mBuildProperties.isUserBuild()).thenReturn(false); 1357 mWsm.enableVerboseLogging(1); 1358 verify(mPropertyService).set("log.tag.WifiHAL", "V"); 1359 } 1360 1361 /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */ 1362 @Test 1363 public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() { 1364 reset(mPropertyService); // Ignore calls made in setUp() 1365 when(mBuildProperties.isUserdebugBuild()).thenReturn(true); 1366 when(mBuildProperties.isEngBuild()).thenReturn(false); 1367 when(mBuildProperties.isUserBuild()).thenReturn(false); 1368 mWsm.enableVerboseLogging(1); 1369 verify(mPropertyService).set("log.tag.WifiHAL", "V"); 1370 } 1371 1372 /** Verifies that enabling verbose logging does NOT set the hal log property in user builds. */ 1373 @Test 1374 public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() { 1375 reset(mPropertyService); // Ignore calls made in setUp() 1376 when(mBuildProperties.isUserBuild()).thenReturn(true); 1377 when(mBuildProperties.isEngBuild()).thenReturn(false); 1378 when(mBuildProperties.isUserdebugBuild()).thenReturn(false); 1379 mWsm.enableVerboseLogging(1); 1380 verify(mPropertyService, never()).set(anyString(), anyString()); 1381 } 1382 1383 private int testGetSupportedFeaturesCase(int supportedFeatures, boolean rttConfigured) { 1384 AsyncChannel channel = mock(AsyncChannel.class); 1385 Message reply = Message.obtain(); 1386 reply.arg1 = supportedFeatures; 1387 reset(mPropertyService); // Ignore calls made in setUp() 1388 when(channel.sendMessageSynchronously(WifiStateMachine.CMD_GET_SUPPORTED_FEATURES)) 1389 .thenReturn(reply); 1390 when(mPropertyService.getBoolean("config.disable_rtt", false)) 1391 .thenReturn(rttConfigured); 1392 return mWsm.syncGetSupportedFeatures(channel); 1393 } 1394 1395 /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ 1396 @Test 1397 public void syncGetSupportedFeatures() { 1398 final int featureAware = WifiManager.WIFI_FEATURE_AWARE; 1399 final int featureInfra = WifiManager.WIFI_FEATURE_INFRA; 1400 final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; 1401 final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; 1402 1403 assertEquals(0, testGetSupportedFeaturesCase(0, false)); 1404 assertEquals(0, testGetSupportedFeaturesCase(0, true)); 1405 assertEquals(featureAware | featureInfra, 1406 testGetSupportedFeaturesCase(featureAware | featureInfra, false)); 1407 assertEquals(featureAware | featureInfra, 1408 testGetSupportedFeaturesCase(featureAware | featureInfra, true)); 1409 assertEquals(featureInfra | featureD2dRtt, 1410 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, false)); 1411 assertEquals(featureInfra, 1412 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, true)); 1413 assertEquals(featureInfra | featureD2apRtt, 1414 testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, false)); 1415 assertEquals(featureInfra, 1416 testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, true)); 1417 assertEquals(featureInfra | featureD2dRtt | featureD2apRtt, 1418 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, false)); 1419 assertEquals(featureInfra, 1420 testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, true)); 1421 } 1422 1423 /** 1424 * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager} 1425 * and returning the result that's returned from {@link PasspointManager}. 1426 */ 1427 @Test 1428 public void syncAddOrUpdatePasspointConfig() throws Exception { 1429 PasspointConfiguration config = new PasspointConfiguration(); 1430 HomeSp homeSp = new HomeSp(); 1431 homeSp.setFqdn("test.com"); 1432 config.setHomeSp(homeSp); 1433 1434 when(mPasspointManager.addOrUpdateProvider(config, MANAGED_PROFILE_UID)).thenReturn(true); 1435 mLooper.startAutoDispatch(); 1436 assertTrue(mWsm.syncAddOrUpdatePasspointConfig( 1437 mWsmAsyncChannel, config, MANAGED_PROFILE_UID)); 1438 mLooper.stopAutoDispatch(); 1439 reset(mPasspointManager); 1440 1441 when(mPasspointManager.addOrUpdateProvider(config, MANAGED_PROFILE_UID)).thenReturn(false); 1442 mLooper.startAutoDispatch(); 1443 assertFalse(mWsm.syncAddOrUpdatePasspointConfig( 1444 mWsmAsyncChannel, config, MANAGED_PROFILE_UID)); 1445 mLooper.stopAutoDispatch(); 1446 } 1447 1448 /** 1449 * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager} 1450 * and returning the result that's returned from {@link PasspointManager} when in client mode. 1451 */ 1452 @Test 1453 public void syncAddOrUpdatePasspointConfigInClientMode() throws Exception { 1454 loadComponentsInStaMode(); 1455 syncAddOrUpdatePasspointConfig(); 1456 } 1457 1458 /** 1459 * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager} 1460 * and returning the result that's returned from {@link PasspointManager}. 1461 */ 1462 @Test 1463 public void syncRemovePasspointConfig() throws Exception { 1464 String fqdn = "test.com"; 1465 when(mPasspointManager.removeProvider(fqdn)).thenReturn(true); 1466 mLooper.startAutoDispatch(); 1467 assertTrue(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn)); 1468 mLooper.stopAutoDispatch(); 1469 reset(mPasspointManager); 1470 1471 when(mPasspointManager.removeProvider(fqdn)).thenReturn(false); 1472 mLooper.startAutoDispatch(); 1473 assertFalse(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn)); 1474 mLooper.stopAutoDispatch(); 1475 } 1476 1477 /** 1478 * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager} 1479 * and returning the result that's returned from {@link PasspointManager} when in client mode. 1480 */ 1481 @Test 1482 public void syncRemovePasspointConfigInClientMode() throws Exception { 1483 loadComponentsInStaMode(); 1484 syncRemovePasspointConfig(); 1485 } 1486 1487 /** 1488 * Verify that syncGetPasspointConfigs will redirect calls to {@link PasspointManager} 1489 * and returning the result that's returned from {@link PasspointManager}. 1490 */ 1491 @Test 1492 public void syncGetPasspointConfigs() throws Exception { 1493 // Setup expected configs. 1494 List<PasspointConfiguration> expectedConfigs = new ArrayList<>(); 1495 PasspointConfiguration config = new PasspointConfiguration(); 1496 HomeSp homeSp = new HomeSp(); 1497 homeSp.setFqdn("test.com"); 1498 config.setHomeSp(homeSp); 1499 expectedConfigs.add(config); 1500 1501 when(mPasspointManager.getProviderConfigs()).thenReturn(expectedConfigs); 1502 mLooper.startAutoDispatch(); 1503 assertEquals(expectedConfigs, mWsm.syncGetPasspointConfigs(mWsmAsyncChannel)); 1504 mLooper.stopAutoDispatch(); 1505 reset(mPasspointManager); 1506 1507 when(mPasspointManager.getProviderConfigs()) 1508 .thenReturn(new ArrayList<PasspointConfiguration>()); 1509 mLooper.startAutoDispatch(); 1510 assertTrue(mWsm.syncGetPasspointConfigs(mWsmAsyncChannel).isEmpty()); 1511 mLooper.stopAutoDispatch(); 1512 } 1513 1514 /** 1515 * Verify that syncGetMatchingWifiConfig will redirect calls to {@link PasspointManager} 1516 * with expected {@link WifiConfiguration} being returned when in client mode. 1517 * 1518 * @throws Exception 1519 */ 1520 @Test 1521 public void syncGetMatchingWifiConfigInClientMode() throws Exception { 1522 loadComponentsInStaMode(); 1523 1524 when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))).thenReturn(null); 1525 mLooper.startAutoDispatch(); 1526 assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel)); 1527 mLooper.stopAutoDispatch(); 1528 reset(mPasspointManager); 1529 1530 WifiConfiguration expectedConfig = new WifiConfiguration(); 1531 expectedConfig.SSID = "TestSSID"; 1532 when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))) 1533 .thenReturn(expectedConfig); 1534 mLooper.startAutoDispatch(); 1535 WifiConfiguration actualConfig = mWsm.syncGetMatchingWifiConfig(new ScanResult(), 1536 mWsmAsyncChannel); 1537 mLooper.stopAutoDispatch(); 1538 assertEquals(expectedConfig.SSID, actualConfig.SSID); 1539 } 1540 1541 /** 1542 * Verify that syncGetMatchingWifiConfig will be a no-op and return {@code null} when not in 1543 * client mode. 1544 * 1545 * @throws Exception 1546 */ 1547 @Test 1548 public void syncGetMatchingWifiConfigInNonClientMode() throws Exception { 1549 mLooper.startAutoDispatch(); 1550 assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel)); 1551 mLooper.stopAutoDispatch(); 1552 verify(mPasspointManager, never()).getMatchingWifiConfig(any(ScanResult.class)); 1553 } 1554 1555 /** 1556 * Sunny-day scenario for WPS connections. Verifies that after a START_WPS and 1557 * NETWORK_CONNECTION_EVENT command, WifiStateMachine will have transitioned to ObtainingIpState 1558 */ 1559 @Test 1560 public void wpsPbcConnectSuccess() throws Exception { 1561 loadComponentsInStaMode(); 1562 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1563 mLooper.dispatchAll(); 1564 assertEquals("DisconnectedState", getCurrentState().getName()); 1565 1566 WpsInfo wpsInfo = new WpsInfo(); 1567 wpsInfo.setup = WpsInfo.PBC; 1568 wpsInfo.BSSID = sBSSID; 1569 when(mWifiNative.removeAllNetworks()).thenReturn(true); 1570 when(mWifiNative.startWpsPbc(anyString())).thenReturn(true); 1571 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1572 mLooper.dispatchAll(); 1573 assertEquals("WpsRunningState", getCurrentState().getName()); 1574 1575 setupMocksForWpsNetworkMigration(); 1576 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1577 mLooper.dispatchAll(); 1578 assertEquals("ObtainingIpState", getCurrentState().getName()); 1579 verifyMocksForWpsNetworkMigration(); 1580 } 1581 1582 /** 1583 * Verify failure in starting Wps PBC network connection. 1584 */ 1585 @Test 1586 public void wpsPbcConnectFailure() throws Exception { 1587 loadComponentsInStaMode(); 1588 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1589 mLooper.dispatchAll(); 1590 1591 when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(false); 1592 WpsInfo wpsInfo = new WpsInfo(); 1593 wpsInfo.setup = WpsInfo.PBC; 1594 wpsInfo.BSSID = sBSSID; 1595 1596 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1597 mLooper.dispatchAll(); 1598 verify(mWifiNative).startWpsPbc(eq(sBSSID)); 1599 1600 assertFalse("WpsRunningState".equals(getCurrentState().getName())); 1601 } 1602 1603 /** 1604 * Verify that if Supplicant generates multiple networks for a WPS configuration, 1605 * WifiStateMachine cycles into DisconnectedState 1606 */ 1607 @Test 1608 public void wpsPbcConnectFailure_tooManyConfigs() throws Exception { 1609 loadComponentsInStaMode(); 1610 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1611 mLooper.dispatchAll(); 1612 assertEquals("DisconnectedState", getCurrentState().getName()); 1613 1614 WpsInfo wpsInfo = new WpsInfo(); 1615 wpsInfo.setup = WpsInfo.PBC; 1616 wpsInfo.BSSID = sBSSID; 1617 when(mWifiNative.removeAllNetworks()).thenReturn(true); 1618 when(mWifiNative.startWpsPbc(anyString())).thenReturn(true); 1619 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1620 mLooper.dispatchAll(); 1621 assertEquals("WpsRunningState", getCurrentState().getName()); 1622 1623 setupMocksForWpsNetworkMigration(); 1624 doAnswer(new AnswerWithArguments() { 1625 public boolean answer(Map<String, WifiConfiguration> configs, 1626 SparseArray<Map<String, String>> networkExtras) throws Exception { 1627 configs.put("dummy1", new WifiConfiguration()); 1628 configs.put("dummy2", new WifiConfiguration()); 1629 return true; 1630 } 1631 }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class)); 1632 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1633 mLooper.dispatchAll(); 1634 assertTrue("DisconnectedState".equals(getCurrentState().getName())); 1635 } 1636 1637 /** 1638 * Verify that when supplicant fails to load networks during WPS, WifiStateMachine cycles into 1639 * DisconnectedState 1640 */ 1641 @Test 1642 public void wpsPbcConnectFailure_migrateNetworksFailure() throws Exception { 1643 loadComponentsInStaMode(); 1644 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1645 mLooper.dispatchAll(); 1646 assertEquals("DisconnectedState", getCurrentState().getName()); 1647 1648 WpsInfo wpsInfo = new WpsInfo(); 1649 wpsInfo.setup = WpsInfo.PBC; 1650 wpsInfo.BSSID = sBSSID; 1651 when(mWifiNative.removeAllNetworks()).thenReturn(true); 1652 when(mWifiNative.startWpsPbc(anyString())).thenReturn(true); 1653 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1654 mLooper.dispatchAll(); 1655 assertEquals("WpsRunningState", getCurrentState().getName()); 1656 1657 setupMocksForWpsNetworkMigration(); 1658 when(mWifiNative.migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class))) 1659 .thenReturn(false); 1660 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1661 mLooper.dispatchAll(); 1662 assertEquals("DisconnectedState", getCurrentState().getName()); 1663 } 1664 1665 /** 1666 * Verify successful Wps Pin Display network connection. 1667 */ 1668 @Test 1669 public void wpsPinDisplayConnectSuccess() throws Exception { 1670 loadComponentsInStaMode(); 1671 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1672 mLooper.dispatchAll(); 1673 1674 when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn("34545434"); 1675 WpsInfo wpsInfo = new WpsInfo(); 1676 wpsInfo.setup = WpsInfo.DISPLAY; 1677 wpsInfo.BSSID = sBSSID; 1678 1679 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1680 mLooper.dispatchAll(); 1681 verify(mWifiNative).startWpsPinDisplay(eq(sBSSID)); 1682 1683 assertEquals("WpsRunningState", getCurrentState().getName()); 1684 1685 setupMocksForWpsNetworkMigration(); 1686 1687 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 1688 mLooper.dispatchAll(); 1689 1690 assertEquals("ObtainingIpState", getCurrentState().getName()); 1691 verifyMocksForWpsNetworkMigration(); 1692 } 1693 1694 /** 1695 * Verify failure in Wps Pin Display network connection. 1696 */ 1697 @Test 1698 public void wpsPinDisplayConnectFailure() throws Exception { 1699 loadComponentsInStaMode(); 1700 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1701 mLooper.dispatchAll(); 1702 1703 when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn(null); 1704 WpsInfo wpsInfo = new WpsInfo(); 1705 wpsInfo.setup = WpsInfo.DISPLAY; 1706 wpsInfo.BSSID = sBSSID; 1707 1708 mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo); 1709 mLooper.dispatchAll(); 1710 verify(mWifiNative).startWpsPinDisplay(eq(sBSSID)); 1711 1712 assertFalse("WpsRunningState".equals(getCurrentState().getName())); 1713 } 1714 1715 @Test 1716 public void handleVendorHalDeath() throws Exception { 1717 ArgumentCaptor<WifiNative.VendorHalDeathEventHandler> deathHandlerCapturer = 1718 ArgumentCaptor.forClass(WifiNative.VendorHalDeathEventHandler.class); 1719 when(mWifiNative.initializeVendorHal(deathHandlerCapturer.capture())).thenReturn(true); 1720 1721 // Trigger initialize to capture the death handler registration. 1722 mLooper.startAutoDispatch(); 1723 assertTrue(mWsm.syncInitialize(mWsmAsyncChannel)); 1724 mLooper.stopAutoDispatch(); 1725 1726 verify(mWifiNative).initializeVendorHal(any(WifiNative.VendorHalDeathEventHandler.class)); 1727 WifiNative.VendorHalDeathEventHandler deathHandler = deathHandlerCapturer.getValue(); 1728 1729 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1730 mLooper.dispatchAll(); 1731 1732 // Now trigger the death notification. 1733 deathHandler.onDeath(); 1734 mLooper.dispatchAll(); 1735 1736 verify(mWifiMetrics).incrementNumHalCrashes(); 1737 verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_HAL_CRASH)); 1738 } 1739 1740 @Test 1741 public void handleWificondDeath() throws Exception { 1742 ArgumentCaptor<StateMachineDeathRecipient> deathHandlerCapturer = 1743 ArgumentCaptor.forClass(StateMachineDeathRecipient.class); 1744 1745 // Trigger initialize to capture the death handler registration. 1746 loadComponentsInStaMode(); 1747 1748 verify(mClientInterfaceBinder).linkToDeath(deathHandlerCapturer.capture(), anyInt()); 1749 StateMachineDeathRecipient deathHandler = deathHandlerCapturer.getValue(); 1750 1751 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1752 mLooper.dispatchAll(); 1753 1754 // Now trigger the death notification. 1755 deathHandler.binderDied(); 1756 mLooper.dispatchAll(); 1757 1758 verify(mWifiMetrics).incrementNumWificondCrashes(); 1759 verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_WIFICOND_CRASH)); 1760 } 1761 1762 private void setupMocksForWpsNetworkMigration() { 1763 WifiConfiguration config = new WifiConfiguration(); 1764 config.networkId = WPS_SUPPLICANT_NETWORK_ID; 1765 config.SSID = DEFAULT_TEST_SSID; 1766 doAnswer(new AnswerWithArguments() { 1767 public boolean answer(Map<String, WifiConfiguration> configs, 1768 SparseArray<Map<String, String>> networkExtras) throws Exception { 1769 configs.put("dummy", config); 1770 return true; 1771 } 1772 }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class)); 1773 when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt())) 1774 .thenReturn(new NetworkUpdateResult(WPS_FRAMEWORK_NETWORK_ID)); 1775 when(mWifiConfigManager.enableNetwork(eq(WPS_FRAMEWORK_NETWORK_ID), anyBoolean(), anyInt())) 1776 .thenReturn(true); 1777 when(mWifiNative.getFrameworkNetworkId(eq(WPS_FRAMEWORK_NETWORK_ID))).thenReturn( 1778 WPS_FRAMEWORK_NETWORK_ID); 1779 when(mWifiConfigManager.getConfiguredNetwork(eq(WPS_FRAMEWORK_NETWORK_ID))).thenReturn( 1780 config); 1781 } 1782 1783 private void verifyMocksForWpsNetworkMigration() { 1784 // Network Ids should be reset so that it is treated as addition. 1785 ArgumentCaptor<WifiConfiguration> wifiConfigCaptor = 1786 ArgumentCaptor.forClass(WifiConfiguration.class); 1787 verify(mWifiConfigManager).addOrUpdateNetwork(wifiConfigCaptor.capture(), anyInt()); 1788 assertEquals(WifiConfiguration.INVALID_NETWORK_ID, wifiConfigCaptor.getValue().networkId); 1789 assertEquals(DEFAULT_TEST_SSID, wifiConfigCaptor.getValue().SSID); 1790 verify(mWifiConfigManager).enableNetwork(eq(WPS_FRAMEWORK_NETWORK_ID), anyBoolean(), 1791 anyInt()); 1792 } 1793 1794 /** 1795 * Verifies that WifiInfo is cleared upon exiting and entering WifiInfo, and that it is not 1796 * updated by SUPPLICAN_STATE_CHANGE_EVENTs in ScanModeState. 1797 * This protects WifiStateMachine from getting into a bad state where WifiInfo says wifi is 1798 * already Connected or Connecting, (when it is in-fact Disconnected), so 1799 * WifiConnectivityManager does not attempt any new Connections, freezing wifi. 1800 */ 1801 @Test 1802 public void testWifiInfoCleanedUpEnteringExitingConnectModeState() throws Exception { 1803 InOrder inOrder = inOrder(mWifiConnectivityManager); 1804 Log.i(TAG, mWsm.getCurrentState().getName()); 1805 String initialBSSID = "aa:bb:cc:dd:ee:ff"; 1806 WifiInfo wifiInfo = mWsm.getWifiInfo(); 1807 wifiInfo.setBSSID(initialBSSID); 1808 1809 // Set WSM to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager 1810 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1811 startSupplicantAndDispatchMessages(); 1812 mWsm.setSupplicantRunning(true); 1813 mLooper.dispatchAll(); 1814 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 1815 assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); 1816 inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true)); 1817 assertNull(wifiInfo.getBSSID()); 1818 1819 // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated 1820 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1821 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 1822 mLooper.dispatchAll(); 1823 assertEquals(sBSSID, wifiInfo.getBSSID()); 1824 assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState()); 1825 1826 // Set WSM to SCAN_ONLY_MODE, verify state and wifi disabled in ConnectivityManager, and 1827 // WifiInfo is reset() and state set to DISCONNECTED 1828 mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE); 1829 mLooper.dispatchAll(); 1830 assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest()); 1831 assertEquals("ScanModeState", getCurrentState().getName()); 1832 assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState()); 1833 inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false)); 1834 assertNull(wifiInfo.getBSSID()); 1835 assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); 1836 1837 // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated 1838 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 1839 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 1840 mLooper.dispatchAll(); 1841 assertNull(wifiInfo.getBSSID()); 1842 assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); 1843 1844 // Set the bssid to something, so we can verify it is cleared (just in case) 1845 wifiInfo.setBSSID(initialBSSID); 1846 1847 // Set WSM to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager, 1848 // and WifiInfo has been reset 1849 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1850 mLooper.dispatchAll(); 1851 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 1852 assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState()); 1853 inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true)); 1854 assertEquals("DisconnectedState", getCurrentState().getName()); 1855 assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState()); 1856 assertNull(wifiInfo.getBSSID()); 1857 } 1858 1859 /** 1860 * Test that the process uid has full wifiInfo access. 1861 * Also tests that {@link WifiStateMachine#syncRequestConnectionInfo(String)} always 1862 * returns a copy of WifiInfo. 1863 */ 1864 @Test 1865 public void testConnectedIdsAreVisibleFromOwnUid() throws Exception { 1866 assertEquals(Process.myUid(), Binder.getCallingUid()); 1867 WifiInfo wifiInfo = mWsm.getWifiInfo(); 1868 wifiInfo.setBSSID(sBSSID); 1869 wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(sSSID)); 1870 1871 connect(); 1872 WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo(mContext.getOpPackageName()); 1873 1874 assertNotEquals(wifiInfo, connectionInfo); 1875 assertEquals(wifiInfo.getSSID(), connectionInfo.getSSID()); 1876 assertEquals(wifiInfo.getBSSID(), connectionInfo.getBSSID()); 1877 } 1878 1879 /** 1880 * Test that connected SSID and BSSID are not exposed to an app that does not have the 1881 * appropriate permissions. 1882 * Also tests that {@link WifiStateMachine#syncRequestConnectionInfo(String)} always 1883 * returns a copy of WifiInfo. 1884 */ 1885 @Test 1886 public void testConnectedIdsAreHiddenFromRandomApp() throws Exception { 1887 int actualUid = Binder.getCallingUid(); 1888 int fakeUid = Process.myUid() + 100000; 1889 assertNotEquals(actualUid, fakeUid); 1890 BinderUtil.setUid(fakeUid); 1891 try { 1892 WifiInfo wifiInfo = mWsm.getWifiInfo(); 1893 1894 // Get into a connected state, with known BSSID and SSID 1895 connect(); 1896 assertEquals(sBSSID, wifiInfo.getBSSID()); 1897 assertEquals(sWifiSsid, wifiInfo.getWifiSsid()); 1898 1899 when(mWifiPermissionsUtil.canAccessScanResults(anyString(), eq(fakeUid), anyInt())) 1900 .thenReturn(false); 1901 1902 WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo(mContext.getOpPackageName()); 1903 1904 assertNotEquals(wifiInfo, connectionInfo); 1905 assertEquals(WifiSsid.NONE, connectionInfo.getSSID()); 1906 assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID()); 1907 } finally { 1908 BinderUtil.setUid(actualUid); 1909 } 1910 } 1911 1912 /** 1913 * Test that connected SSID and BSSID are not exposed to an app that does not have the 1914 * appropriate permissions, when canAccessScanResults raises a SecurityException. 1915 * Also tests that {@link WifiStateMachine#syncRequestConnectionInfo(String)} always 1916 * returns a copy of WifiInfo. 1917 */ 1918 @Test 1919 public void testConnectedIdsAreHiddenOnSecurityException() throws Exception { 1920 int actualUid = Binder.getCallingUid(); 1921 int fakeUid = Process.myUid() + 100000; 1922 assertNotEquals(actualUid, fakeUid); 1923 BinderUtil.setUid(fakeUid); 1924 try { 1925 WifiInfo wifiInfo = mWsm.getWifiInfo(); 1926 1927 // Get into a connected state, with known BSSID and SSID 1928 connect(); 1929 assertEquals(sBSSID, wifiInfo.getBSSID()); 1930 assertEquals(sWifiSsid, wifiInfo.getWifiSsid()); 1931 1932 when(mWifiPermissionsUtil.canAccessScanResults(anyString(), eq(fakeUid), anyInt())) 1933 .thenThrow(new SecurityException()); 1934 1935 WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo(mContext.getOpPackageName()); 1936 1937 assertNotEquals(wifiInfo, connectionInfo); 1938 assertEquals(WifiSsid.NONE, connectionInfo.getSSID()); 1939 assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID()); 1940 } finally { 1941 BinderUtil.setUid(actualUid); 1942 } 1943 } 1944 1945 /** 1946 * Test that connected SSID and BSSID are exposed to an app that does have the 1947 * appropriate permissions. 1948 */ 1949 @Test 1950 public void testConnectedIdsAreVisibleFromPermittedApp() throws Exception { 1951 int actualUid = Binder.getCallingUid(); 1952 int fakeUid = Process.myUid() + 100000; 1953 BinderUtil.setUid(fakeUid); 1954 try { 1955 WifiInfo wifiInfo = mWsm.getWifiInfo(); 1956 1957 // Get into a connected state, with known BSSID and SSID 1958 connect(); 1959 assertEquals(sBSSID, wifiInfo.getBSSID()); 1960 assertEquals(sWifiSsid, wifiInfo.getWifiSsid()); 1961 1962 when(mWifiPermissionsUtil.canAccessScanResults(anyString(), eq(fakeUid), anyInt())) 1963 .thenReturn(true); 1964 1965 WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo(mContext.getOpPackageName()); 1966 1967 assertNotEquals(wifiInfo, connectionInfo); 1968 assertEquals(wifiInfo.getSSID(), connectionInfo.getSSID()); 1969 assertEquals(wifiInfo.getBSSID(), connectionInfo.getBSSID()); 1970 // Access to our MAC address uses a different permission, make sure it is not granted 1971 assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getMacAddress()); 1972 } finally { 1973 BinderUtil.setUid(actualUid); 1974 } 1975 } 1976 1977 /** 1978 * Adds the network without putting WifiStateMachine into ConnectMode. 1979 */ 1980 @Test 1981 public void addNetworkInInitialState() throws Exception { 1982 // We should not be in initial state now. 1983 assertTrue("InitialState".equals(getCurrentState().getName())); 1984 addNetworkAndVerifySuccess(false); 1985 verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0)); 1986 } 1987 1988 /** 1989 * Test START_WPS with a null wpsInfo object fails gracefully (No NPE) 1990 */ 1991 @Test 1992 public void testStartWps_nullWpsInfo() throws Exception { 1993 loadComponentsInStaMode(); 1994 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 1995 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 1996 assertEquals("DisconnectedState", getCurrentState().getName()); 1997 mLooper.startAutoDispatch(); 1998 Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.START_WPS, 0, 0, 1999 null); 2000 mLooper.stopAutoDispatch(); 2001 assertEquals(WifiManager.WPS_FAILED, reply.what); 2002 } 2003 2004 /** 2005 * Test that DISABLE_NETWORK returns failure to public API when WifiConfigManager returns 2006 * failure. 2007 */ 2008 @Test 2009 public void testSyncDisableNetwork_failure() throws Exception { 2010 loadComponentsInStaMode(); 2011 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 2012 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 2013 assertEquals("DisconnectedState", getCurrentState().getName()); 2014 when(mWifiConfigManager.disableNetwork(anyInt(), anyInt())).thenReturn(false); 2015 2016 mLooper.startAutoDispatch(); 2017 boolean succeeded = mWsm.syncDisableNetwork(mWsmAsyncChannel, 0); 2018 mLooper.stopAutoDispatch(); 2019 assertFalse(succeeded); 2020 } 2021 2022 /** 2023 * Test that failure to start HAL in AP mode increments the corresponding metrics. 2024 */ 2025 @Test 2026 public void testSetupForSoftApModeHalFailureIncrementsMetrics() throws Exception { 2027 when(mWifiNative.setupForSoftApMode()) 2028 .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_HAL, null)); 2029 2030 SoftApModeConfiguration config = new SoftApModeConfiguration( 2031 WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration()); 2032 mWsm.setHostApRunning(config, true); 2033 mLooper.dispatchAll(); 2034 2035 verify(mWifiNative).setupForSoftApMode(); 2036 verify(mWifiMetrics).incrementNumWifiOnFailureDueToHal(); 2037 } 2038 2039 /** 2040 * Test that failure to start HAL in AP mode increments the corresponding metrics. 2041 */ 2042 @Test 2043 public void testSetupForSoftApModeWificondFailureIncrementsMetrics() throws Exception { 2044 when(mWifiNative.setupForSoftApMode()) 2045 .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_WIFICOND, null)); 2046 2047 SoftApModeConfiguration config = new SoftApModeConfiguration( 2048 WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration()); 2049 mWsm.setHostApRunning(config, true); 2050 mLooper.dispatchAll(); 2051 2052 verify(mWifiNative).setupForSoftApMode(); 2053 verify(mWifiMetrics).incrementNumWifiOnFailureDueToWificond(); 2054 } 2055 2056 /** 2057 * Test that failure to start HAL in client mode increments the corresponding metrics. 2058 */ 2059 @Test 2060 public void testSetupForClientModeHalFailureIncrementsMetrics() throws Exception { 2061 when(mWifiNative.setupForClientMode()) 2062 .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_HAL, null)); 2063 2064 mWsm.setSupplicantRunning(true); 2065 mLooper.dispatchAll(); 2066 2067 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 2068 mLooper.dispatchAll(); 2069 2070 verify(mWifiNative).setupForClientMode(); 2071 verify(mWifiMetrics).incrementNumWifiOnFailureDueToHal(); 2072 } 2073 2074 /** 2075 * Test that failure to start HAL in client mode increments the corresponding metrics. 2076 */ 2077 @Test 2078 public void testSetupForClientModeWificondFailureIncrementsMetrics() throws Exception { 2079 when(mWifiNative.setupForClientMode()) 2080 .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_WIFICOND, null)); 2081 2082 mWsm.setSupplicantRunning(true); 2083 mLooper.dispatchAll(); 2084 2085 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 2086 mLooper.dispatchAll(); 2087 2088 verify(mWifiNative).setupForClientMode(); 2089 verify(mWifiMetrics).incrementNumWifiOnFailureDueToWificond(); 2090 } 2091 2092 /** 2093 * Test that we don't register the telephony call state listener on devices which do not support 2094 * setting/resetting Tx power limit. 2095 */ 2096 @Test 2097 public void testVoiceCallSar_disabledTxPowerScenario_WifiOn() throws Exception { 2098 loadComponentsInStaMode(); 2099 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 2100 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 2101 assertEquals("DisconnectedState", getCurrentState().getName()); 2102 assertNull(mPhoneStateListener); 2103 } 2104 2105 /** 2106 * Test that we do register the telephony call state listener on devices which do support 2107 * setting/resetting Tx power limit. 2108 */ 2109 @Test 2110 public void testVoiceCallSar_enabledTxPowerScenario_WifiOn() throws Exception { 2111 mResources.setBoolean( 2112 R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); 2113 initializeWsm(); 2114 2115 loadComponentsInStaMode(); 2116 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 2117 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 2118 assertEquals("DisconnectedState", getCurrentState().getName()); 2119 assertNotNull(mPhoneStateListener); 2120 } 2121 2122 /** 2123 * Test that we do register the telephony call state listener on devices which do support 2124 * setting/resetting Tx power limit and set the tx power level if we're in state 2125 * {@link TelephonyManager#CALL_STATE_OFFHOOK}. 2126 */ 2127 @Test 2128 public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiTurnedOn() 2129 throws Exception { 2130 mResources.setBoolean( 2131 R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); 2132 initializeWsm(); 2133 2134 when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); 2135 when(mTelephonyManager.isOffhook()).thenReturn(true); 2136 2137 loadComponentsInStaMode(); 2138 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 2139 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 2140 assertEquals("DisconnectedState", getCurrentState().getName()); 2141 assertNotNull(mPhoneStateListener); 2142 verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); 2143 } 2144 2145 /** 2146 * Test that we do register the telephony call state listener on devices which do support 2147 * setting/resetting Tx power limit and set the tx power level if we're in state 2148 * {@link TelephonyManager#CALL_STATE_IDLE}. 2149 */ 2150 @Test 2151 public void testVoiceCallSar_enabledTxPowerScenarioCallStateIdle_WhenWifiTurnedOn() 2152 throws Exception { 2153 mResources.setBoolean( 2154 R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); 2155 initializeWsm(); 2156 2157 when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); 2158 when(mTelephonyManager.isIdle()).thenReturn(true); 2159 2160 loadComponentsInStaMode(); 2161 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 2162 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 2163 assertEquals("DisconnectedState", getCurrentState().getName()); 2164 assertNotNull(mPhoneStateListener); 2165 } 2166 2167 /** 2168 * Test that we do register the telephony call state listener on devices which do support 2169 * setting/resetting Tx power limit and set the tx power level if we're in state 2170 * {@link TelephonyManager#CALL_STATE_OFFHOOK}. This test checks if the 2171 * {@link WifiNative#selectTxPowerScenario(int)} failure is handled correctly. 2172 */ 2173 @Test 2174 public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiTurnedOn_Fails() 2175 throws Exception { 2176 mResources.setBoolean( 2177 R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); 2178 initializeWsm(); 2179 2180 when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(false); 2181 when(mTelephonyManager.isOffhook()).thenReturn(true); 2182 2183 loadComponentsInStaMode(); 2184 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 2185 assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest()); 2186 assertEquals("DisconnectedState", getCurrentState().getName()); 2187 assertNotNull(mPhoneStateListener); 2188 verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); 2189 } 2190 2191 /** 2192 * Test that we invoke the corresponding WifiNative method when 2193 * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state 2194 * {@link TelephonyManager#CALL_STATE_OFFHOOK}. 2195 */ 2196 @Test 2197 public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiOn() 2198 throws Exception { 2199 when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); 2200 testVoiceCallSar_enabledTxPowerScenario_WifiOn(); 2201 2202 mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, ""); 2203 mLooper.dispatchAll(); 2204 verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); 2205 } 2206 2207 /** 2208 * Test that we invoke the corresponding WifiNative method when 2209 * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state 2210 * {@link TelephonyManager#CALL_STATE_IDLE}. 2211 */ 2212 @Test 2213 public void testVoiceCallSar_enabledTxPowerScenarioCallStateIdle_WhenWifiOn() throws Exception { 2214 when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(true); 2215 testVoiceCallSar_enabledTxPowerScenario_WifiOn(); 2216 2217 mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE, ""); 2218 mLooper.dispatchAll(); 2219 verify(mWifiNative, atLeastOnce()) 2220 .selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_NORMAL)); 2221 } 2222 2223 /** 2224 * Test that we invoke the corresponding WifiNative method when 2225 * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state 2226 * {@link TelephonyManager#CALL_STATE_OFFHOOK}. This test checks if the 2227 * {@link WifiNative#selectTxPowerScenario(int)} failure is handled correctly. 2228 */ 2229 @Test 2230 public void testVoiceCallSar_enabledTxPowerScenarioCallStateOffHook_WhenWifiOn_Fails() 2231 throws Exception { 2232 when(mWifiNative.selectTxPowerScenario(anyInt())).thenReturn(false); 2233 testVoiceCallSar_enabledTxPowerScenario_WifiOn(); 2234 2235 mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, ""); 2236 mLooper.dispatchAll(); 2237 verify(mWifiNative).selectTxPowerScenario(eq(WifiNative.TX_POWER_SCENARIO_VOICE_CALL)); 2238 } 2239 2240 /** 2241 * Test that we don't invoke the corresponding WifiNative method when 2242 * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state 2243 * {@link TelephonyManager#CALL_STATE_IDLE} or {@link TelephonyManager#CALL_STATE_OFFHOOK} when 2244 * wifi is off (state machine is not in SupplicantStarted state). 2245 */ 2246 @Test 2247 public void testVoiceCallSar_enabledTxPowerScenarioCallState_WhenWifiOff() throws Exception { 2248 mResources.setBoolean( 2249 R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true); 2250 initializeWsm(); 2251 2252 mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, ""); 2253 mLooper.dispatchAll(); 2254 verify(mWifiNative, never()).selectTxPowerScenario(anyInt()); 2255 2256 mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE, ""); 2257 mLooper.dispatchAll(); 2258 verify(mWifiNative, never()).selectTxPowerScenario(anyInt()); 2259 } 2260 2261 /** 2262 * Verifies that a network disconnection event will result in WifiStateMachine invoking 2263 * {@link WifiConfigManager#removeAllEphemeralOrPasspointConfiguredNetworks()} to remove 2264 * any ephemeral or passpoint networks from it's internal database. 2265 */ 2266 @Test 2267 public void testDisconnectionRemovesEphemeralAndPasspointNetworks() throws Exception { 2268 disconnect(); 2269 verify(mWifiConfigManager).removeAllEphemeralOrPasspointConfiguredNetworks(); 2270 } 2271 2272 /** 2273 * Verifies that WifiStateMachine sets and unsets appropriate 'RecentFailureReason' values 2274 * on a WifiConfiguration when it fails association, authentication, or successfully connects 2275 */ 2276 @Test 2277 public void testExtraFailureReason_ApIsBusy() throws Exception { 2278 // Setup CONNECT_MODE & a WifiConfiguration 2279 initializeAndAddNetworkAndVerifySuccess(); 2280 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 2281 mLooper.dispatchAll(); 2282 // Trigger a connection to this (CMD_START_CONNECT will actually fail, but it sets up 2283 // targetNetworkId state) 2284 mWsm.sendMessage(WifiStateMachine.CMD_START_CONNECT, 0, 0, sBSSID); 2285 mLooper.dispatchAll(); 2286 // Simulate an ASSOCIATION_REJECTION_EVENT, due to the AP being busy 2287 mWsm.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0, 2288 ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID); 2289 mLooper.dispatchAll(); 2290 verify(mWifiConfigManager).setRecentFailureAssociationStatus(eq(0), 2291 eq(WifiConfiguration.RecentFailure.STATUS_AP_UNABLE_TO_HANDLE_NEW_STA)); 2292 assertEquals("DisconnectedState", getCurrentState().getName()); 2293 2294 // Simulate an AUTHENTICATION_FAILURE_EVENT, which should clear the ExtraFailureReason 2295 reset(mWifiConfigManager); 2296 mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, 0, null); 2297 mLooper.dispatchAll(); 2298 verify(mWifiConfigManager).clearRecentFailureReason(eq(0)); 2299 verify(mWifiConfigManager, never()).setRecentFailureAssociationStatus(anyInt(), anyInt()); 2300 2301 // Simulate a NETWORK_CONNECTION_EVENT which should clear the ExtraFailureReason 2302 reset(mWifiConfigManager); 2303 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null); 2304 mLooper.dispatchAll(); 2305 verify(mWifiConfigManager).clearRecentFailureReason(eq(0)); 2306 verify(mWifiConfigManager, never()).setRecentFailureAssociationStatus(anyInt(), anyInt()); 2307 } 2308 2309 /** 2310 * Test that the helper method 2311 * {@link WifiStateMachine#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)} 2312 * returns true when we connect to the last selected network before expiration of 2313 * {@link WifiStateMachine#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}. 2314 */ 2315 @Test 2316 public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkNotExpired() { 2317 long lastSelectedTimestamp = 45666743454L; 2318 int lastSelectedNetworkId = 5; 2319 2320 when(mClock.getElapsedSinceBootMillis()).thenReturn( 2321 lastSelectedTimestamp 2322 + WifiStateMachine.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1); 2323 when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp); 2324 when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId); 2325 2326 WifiConfiguration currentConfig = new WifiConfiguration(); 2327 currentConfig.networkId = lastSelectedNetworkId; 2328 assertTrue(mWsm.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig)); 2329 } 2330 2331 /** 2332 * Test that the helper method 2333 * {@link WifiStateMachine#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)} 2334 * returns false when we connect to the last selected network after expiration of 2335 * {@link WifiStateMachine#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}. 2336 */ 2337 @Test 2338 public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkExpired() { 2339 long lastSelectedTimestamp = 45666743454L; 2340 int lastSelectedNetworkId = 5; 2341 2342 when(mClock.getElapsedSinceBootMillis()).thenReturn( 2343 lastSelectedTimestamp 2344 + WifiStateMachine.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1); 2345 when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp); 2346 when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId); 2347 2348 WifiConfiguration currentConfig = new WifiConfiguration(); 2349 currentConfig.networkId = lastSelectedNetworkId; 2350 assertFalse(mWsm.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig)); 2351 } 2352 2353 /** 2354 * Test that the helper method 2355 * {@link WifiStateMachine#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)} 2356 * returns false when we connect to a different network to the last selected network. 2357 */ 2358 @Test 2359 public void testShouldEvaluateWhetherToSendExplicitlySelected_DifferentNetwork() { 2360 long lastSelectedTimestamp = 45666743454L; 2361 int lastSelectedNetworkId = 5; 2362 2363 when(mClock.getElapsedSinceBootMillis()).thenReturn( 2364 lastSelectedTimestamp 2365 + WifiStateMachine.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1); 2366 when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp); 2367 when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId); 2368 2369 WifiConfiguration currentConfig = new WifiConfiguration(); 2370 currentConfig.networkId = lastSelectedNetworkId - 1; 2371 assertFalse(mWsm.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig)); 2372 } 2373} 2374