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