WifiStateMachineTest.java revision 5ccc0a429dfea8ef452f8f63454b013983eb87fe
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertFalse; 21import static org.junit.Assert.assertTrue; 22import static org.mockito.Mockito.any; 23import static org.mockito.Mockito.anyBoolean; 24import static org.mockito.Mockito.anyInt; 25import static org.mockito.Mockito.anyObject; 26import static org.mockito.Mockito.anyString; 27import static org.mockito.Mockito.eq; 28import static org.mockito.Mockito.mock; 29import static org.mockito.Mockito.never; 30import static org.mockito.Mockito.verify; 31import static org.mockito.Mockito.when; 32import static org.mockito.Mockito.withSettings; 33 34import android.app.ActivityManager; 35import android.content.ContentResolver; 36import android.content.Context; 37import android.content.pm.PackageManager; 38import android.content.pm.UserInfo; 39import android.content.res.Resources; 40import android.net.ConnectivityManager; 41import android.net.DhcpResults; 42import android.net.LinkProperties; 43import android.net.dhcp.DhcpClient; 44import android.net.ip.IpManager; 45import android.net.wifi.ScanResult; 46import android.net.wifi.SupplicantState; 47import android.net.wifi.WifiConfiguration; 48import android.net.wifi.WifiManager; 49import android.net.wifi.WifiScanner; 50import android.net.wifi.WifiSsid; 51import android.net.wifi.p2p.IWifiP2pManager; 52import android.os.BatteryStats; 53import android.os.Binder; 54import android.os.Handler; 55import android.os.HandlerThread; 56import android.os.IBinder; 57import android.os.IInterface; 58import android.os.INetworkManagementService; 59import android.os.IPowerManager; 60import android.os.Looper; 61import android.os.Message; 62import android.os.Messenger; 63import android.os.PowerManager; 64import android.os.UserHandle; 65import android.os.UserManager; 66import android.provider.Settings; 67import android.security.KeyStore; 68import android.telephony.TelephonyManager; 69import android.test.suitebuilder.annotation.SmallTest; 70import android.util.Base64; 71import android.util.Log; 72 73import com.android.internal.R; 74import com.android.internal.app.IBatteryStats; 75import com.android.internal.util.AsyncChannel; 76import com.android.internal.util.IState; 77import com.android.internal.util.StateMachine; 78import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 79import com.android.server.wifi.hotspot2.NetworkDetail; 80import com.android.server.wifi.hotspot2.Utils; 81import com.android.server.wifi.p2p.WifiP2pServiceImpl; 82 83import org.junit.After; 84import org.junit.Before; 85import org.junit.Test; 86import org.mockito.ArgumentCaptor; 87import org.mockito.Mock; 88import org.mockito.MockitoAnnotations; 89 90import java.io.ByteArrayOutputStream; 91import java.io.PrintWriter; 92import java.lang.reflect.Field; 93import java.lang.reflect.InvocationTargetException; 94import java.lang.reflect.Method; 95import java.util.ArrayList; 96import java.util.Arrays; 97import java.util.HashMap; 98import java.util.HashSet; 99import java.util.List; 100import java.util.Map; 101import java.util.Set; 102 103/** 104 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}. 105 */ 106@SmallTest 107public class WifiStateMachineTest { 108 public static final String TAG = "WifiStateMachineTest"; 109 110 private static final int MANAGED_PROFILE_UID = 1100000; 111 private static final int OTHER_USER_UID = 1200000; 112 private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE = 113 (ActivityManager.isLowRamDeviceStatic() 114 ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY 115 : WifiStateMachine.NUM_LOG_RECS_VERBOSE); 116 private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\""; 117 118 private long mBinderToken; 119 120 private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) { 121 return mock(class1, withSettings().extraInterfaces(interfaces)); 122 } 123 124 private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) { 125 T tImpl = mockWithInterfaces(class1, iface); 126 IBinder binder = mock(IBinder.class); 127 when(((IInterface) tImpl).asBinder()).thenReturn(binder); 128 when(binder.queryLocalInterface(iface.getCanonicalName())) 129 .thenReturn((IInterface) tImpl); 130 return binder; 131 } 132 133 private void enableDebugLogs() { 134 mWsm.enableVerboseLogging(1); 135 } 136 137 private class TestIpManager extends IpManager { 138 TestIpManager(Context context, String ifname, IpManager.Callback callback) { 139 // Call dependency-injection superclass constructor. 140 super(context, ifname, callback, mock(INetworkManagementService.class)); 141 } 142 143 @Override 144 public void startProvisioning(IpManager.ProvisioningConfiguration config) {} 145 146 @Override 147 public void stop() {} 148 149 @Override 150 public void confirmConfiguration() {} 151 152 void injectDhcpSuccess(DhcpResults dhcpResults) { 153 mCallback.onNewDhcpResults(dhcpResults); 154 mCallback.onProvisioningSuccess(new LinkProperties()); 155 } 156 157 void injectDhcpFailure() { 158 mCallback.onNewDhcpResults(null); 159 mCallback.onProvisioningFailure(new LinkProperties()); 160 } 161 } 162 163 private FrameworkFacade getFrameworkFacade() throws Exception { 164 FrameworkFacade facade = mock(FrameworkFacade.class); 165 166 when(facade.makeWifiScanner(any(Context.class), any(Looper.class))) 167 .thenReturn(mWifiScanner); 168 when(facade.makeBaseLogger()).thenReturn(mock(BaseWifiLogger.class)); 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 Object sync = new Object(); 179 synchronized (sync) { 180 mP2pThread = new HandlerThread("WifiP2pMockThread") { 181 @Override 182 protected void onLooperPrepared() { 183 synchronized (sync) { 184 sync.notifyAll(); 185 } 186 } 187 }; 188 189 mP2pThread.start(); 190 sync.wait(); 191 } 192 193 Handler handler = new Handler(mP2pThread.getLooper()); 194 when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler)); 195 196 IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class); 197 when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder); 198 199 when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class))) 200 .then(new AnswerWithArguments() { 201 public IpManager answer( 202 Context context, String ifname, IpManager.Callback callback) { 203 mTestIpManager = new TestIpManager(context, ifname, callback); 204 return mTestIpManager; 205 } 206 }); 207 208 when(facade.checkUidPermission(eq(android.Manifest.permission.OVERRIDE_WIFI_CONFIG), 209 anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED); 210 211 when(facade.makeWifiConfigManager(any(Context.class), any(WifiNative.class), 212 any(FrameworkFacade.class), any(Clock.class), 213 any(UserManager.class), any(KeyStore.class))).then(new AnswerWithArguments() { 214 public WifiConfigManager answer(Context context, WifiNative wifiNative, 215 FrameworkFacade frameworkFacade, Clock clock, 216 UserManager userManager, KeyStore keyStore){ 217 mWifiConfigManager = new WifiConfigManager(context, wifiNative, frameworkFacade, 218 clock, userManager, keyStore); 219 return mWifiConfigManager; 220 } 221 }); 222 return facade; 223 } 224 225 private Context getContext() throws Exception { 226 PackageManager pkgMgr = mock(PackageManager.class); 227 when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true); 228 229 Context context = mock(Context.class); 230 when(context.getPackageManager()).thenReturn(pkgMgr); 231 when(context.getContentResolver()).thenReturn(mock(ContentResolver.class)); 232 233 MockResources resources = new com.android.server.wifi.MockResources(); 234 when(context.getResources()).thenReturn(resources); 235 236 ContentResolver cr = mock(ContentResolver.class); 237 when(context.getContentResolver()).thenReturn(cr); 238 239 when(context.getSystemService(Context.POWER_SERVICE)).thenReturn( 240 new PowerManager(context, mock(IPowerManager.class), new Handler())); 241 242 mAlarmManager = new MockAlarmManager(); 243 when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( 244 mAlarmManager.getAlarmManager()); 245 246 when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn( 247 mock(ConnectivityManager.class)); 248 249 return context; 250 } 251 252 private Resources getMockResources() { 253 MockResources resources = new MockResources(); 254 resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false); 255 return resources; 256 } 257 258 private IState getCurrentState() throws 259 NoSuchMethodException, InvocationTargetException, IllegalAccessException { 260 Method method = StateMachine.class.getDeclaredMethod("getCurrentState"); 261 method.setAccessible(true); 262 return (IState) method.invoke(mWsm); 263 } 264 265 private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws 266 NoSuchFieldException, InvocationTargetException, IllegalAccessException { 267 Field field = StateMachine.class.getDeclaredField("mSmThread"); 268 field.setAccessible(true); 269 return (HandlerThread) field.get(wsm); 270 } 271 272 private static void stopLooper(final Looper looper) throws Exception { 273 new Handler(looper).post(new Runnable() { 274 @Override 275 public void run() { 276 looper.quitSafely(); 277 } 278 }); 279 } 280 281 private void dumpState() { 282 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 283 PrintWriter writer = new PrintWriter(stream); 284 mWsm.dump(null, writer, null); 285 writer.flush(); 286 Log.d(TAG, "WifiStateMachine state -" + stream.toString()); 287 } 288 289 private static ScanDetail getGoogleGuestScanDetail(int rssi) { 290 ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1]; 291 ie[0] = ScanResults.generateSsidIe(sSSID); 292 NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq); 293 ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq, 294 Long.MAX_VALUE, /* needed so that scan results aren't rejected because 295 there older than scan start */ 296 ie, new ArrayList<String>()); 297 return detail; 298 } 299 300 private ArrayList<ScanDetail> getMockScanResults() { 301 ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825); 302 ArrayList<ScanDetail> list = sr.getScanDetailArrayList(); 303 304 int rssi = -65; 305 list.add(getGoogleGuestScanDetail(rssi)); 306 return list; 307 } 308 309 static final String sSSID = "\"GoogleGuest\""; 310 static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID); 311 static final String sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", ""); 312 static final String sBSSID = "01:02:03:04:05:06"; 313 static final int sFreq = 2437; 314 315 WifiStateMachine mWsm; 316 HandlerThread mWsmThread; 317 HandlerThread mP2pThread; 318 HandlerThread mSyncThread; 319 AsyncChannel mWsmAsyncChannel; 320 MockAlarmManager mAlarmManager; 321 MockWifiMonitor mWifiMonitor; 322 TestIpManager mTestIpManager; 323 MockLooper mLooper; 324 WifiConfigManager mWifiConfigManager; 325 326 @Mock WifiNative mWifiNative; 327 @Mock WifiScanner mWifiScanner; 328 @Mock SupplicantStateTracker mSupplicantStateTracker; 329 @Mock WifiMetrics mWifiMetrics; 330 @Mock UserManager mUserManager; 331 @Mock WifiApConfigStore mApConfigStore; 332 @Mock BackupManagerProxy mBackupManagerProxy; 333 @Mock WifiCountryCode mCountryCode; 334 335 public WifiStateMachineTest() throws Exception { 336 } 337 338 @Before 339 public void setUp() throws Exception { 340 Log.d(TAG, "Setting up ..."); 341 342 // Ensure looper exists 343 mLooper = new MockLooper(); 344 345 MockitoAnnotations.initMocks(this); 346 347 /** uncomment this to enable logs from WifiStateMachines */ 348 // enableDebugLogs(); 349 350 TestUtil.installWlanWifiNative(mWifiNative); 351 mWifiMonitor = new MockWifiMonitor(); 352 mWifiMetrics = mock(WifiMetrics.class); 353 WifiInjector wifiInjector = mock(WifiInjector.class); 354 when(wifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 355 FrameworkFacade factory = getFrameworkFacade(); 356 Context context = getContext(); 357 358 Resources resources = getMockResources(); 359 when(context.getResources()).thenReturn(resources); 360 361 when(factory.getIntegerSetting(context, 362 Settings.Global.WIFI_FREQUENCY_BAND, 363 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn( 364 WifiManager.WIFI_FREQUENCY_BAND_AUTO); 365 366 when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy))) 367 .thenReturn(mApConfigStore); 368 369 when(factory.makeSupplicantStateTracker( 370 any(Context.class), any(WifiConfigManager.class), 371 any(Handler.class))).thenReturn(mSupplicantStateTracker); 372 373 when(mUserManager.getProfileParent(11)) 374 .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0)); 375 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList( 376 new UserInfo(UserHandle.USER_SYSTEM, "owner", 0), 377 new UserInfo(11, "managed profile", 0))); 378 379 mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(), 380 mUserManager, wifiInjector, mBackupManagerProxy, mCountryCode); 381 mWsmThread = getWsmHandlerThread(mWsm); 382 383 final AsyncChannel channel = new AsyncChannel(); 384 Handler handler = new Handler(mLooper.getLooper()) { 385 @Override 386 public void handleMessage(Message msg) { 387 switch (msg.what) { 388 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 389 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 390 mWsmAsyncChannel = channel; 391 } else { 392 Log.d(TAG, "Failed to connect Command channel " + this); 393 } 394 break; 395 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 396 Log.d(TAG, "Command channel disconnected" + this); 397 break; 398 } 399 } 400 }; 401 402 channel.connect(context, handler, mWsm.getMessenger()); 403 mLooper.dispatchAll(); 404 /* Now channel is supposed to be connected */ 405 406 mBinderToken = Binder.clearCallingIdentity(); 407 } 408 409 @After 410 public void cleanUp() throws Exception { 411 Binder.restoreCallingIdentity(mBinderToken); 412 413 if (mSyncThread != null) stopLooper(mSyncThread.getLooper()); 414 if (mWsmThread != null) stopLooper(mWsmThread.getLooper()); 415 if (mP2pThread != null) stopLooper(mP2pThread.getLooper()); 416 417 mWsmThread = null; 418 mP2pThread = null; 419 mSyncThread = null; 420 mWsmAsyncChannel = null; 421 mWsm = null; 422 } 423 424 @Test 425 public void createNew() throws Exception { 426 assertEquals("InitialState", getCurrentState().getName()); 427 428 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 429 mLooper.dispatchAll(); 430 assertEquals("InitialState", getCurrentState().getName()); 431 } 432 433 @Test 434 public void loadComponents() throws Exception { 435 when(mWifiNative.loadDriver()).thenReturn(true); 436 when(mWifiNative.startHal()).thenReturn(true); 437 when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true); 438 mWsm.setSupplicantRunning(true); 439 mLooper.dispatchAll(); 440 441 assertEquals("SupplicantStartingState", getCurrentState().getName()); 442 443 when(mWifiNative.setBand(anyInt())).thenReturn(true); 444 when(mWifiNative.setDeviceName(anyString())).thenReturn(true); 445 when(mWifiNative.setManufacturer(anyString())).thenReturn(true); 446 when(mWifiNative.setModelName(anyString())).thenReturn(true); 447 when(mWifiNative.setModelNumber(anyString())).thenReturn(true); 448 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 449 when(mWifiNative.setConfigMethods(anyString())).thenReturn(true); 450 when(mWifiNative.setDeviceType(anyString())).thenReturn(true); 451 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 452 when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true); 453 454 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 455 mLooper.dispatchAll(); 456 457 assertEquals("DisconnectedState", getCurrentState().getName()); 458 } 459 460 @Test 461 public void loadComponentsFailure() throws Exception { 462 when(mWifiNative.loadDriver()).thenReturn(false); 463 when(mWifiNative.startHal()).thenReturn(false); 464 when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(false); 465 466 mWsm.setSupplicantRunning(true); 467 mLooper.dispatchAll(); 468 assertEquals("InitialState", getCurrentState().getName()); 469 470 when(mWifiNative.loadDriver()).thenReturn(true); 471 mWsm.setSupplicantRunning(true); 472 mLooper.dispatchAll(); 473 assertEquals("InitialState", getCurrentState().getName()); 474 475 when(mWifiNative.startHal()).thenReturn(true); 476 mWsm.setSupplicantRunning(true); 477 mLooper.dispatchAll(); 478 assertEquals("InitialState", getCurrentState().getName()); 479 } 480 481 private void addNetworkAndVerifySuccess() throws Exception { 482 addNetworkAndVerifySuccess(false); 483 } 484 485 private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception { 486 loadComponents(); 487 488 final HashMap<String, String> nameToValue = new HashMap<String, String>(); 489 490 when(mWifiNative.addNetwork()).thenReturn(0); 491 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())) 492 .then(new AnswerWithArguments() { 493 public boolean answer(int netId, String name, String value) { 494 if (netId != 0) { 495 Log.d(TAG, "Can't set var " + name + " for " + netId); 496 return false; 497 } 498 499 Log.d(TAG, "Setting var " + name + " to " + value + " for " + netId); 500 nameToValue.put(name, value); 501 return true; 502 } 503 }); 504 505 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 506 .then(new AnswerWithArguments() { 507 public boolean answer(int netId, String name, Map<String, String> values) { 508 if (netId != 0) { 509 Log.d(TAG, "Can't set extra " + name + " for " + netId); 510 return false; 511 } 512 513 Log.d(TAG, "Setting extra for " + netId); 514 return true; 515 } 516 }); 517 518 when(mWifiNative.getNetworkVariable(anyInt(), anyString())) 519 .then(new AnswerWithArguments() { 520 public String answer(int netId, String name) throws Throwable { 521 if (netId != 0) { 522 Log.d(TAG, "Can't find var " + name + " for " + netId); 523 return null; 524 } 525 String value = nameToValue.get(name); 526 if (value != null) { 527 Log.d(TAG, "Returning var " + name + " to " + value + " for " + netId); 528 } else { 529 Log.d(TAG, "Can't find var " + name + " for " + netId); 530 } 531 return value; 532 } 533 }); 534 535 WifiConfiguration config = new WifiConfiguration(); 536 config.SSID = sSSID; 537 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 538 config.hiddenSSID = isHidden; 539 mLooper.startAutoDispatch(); 540 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 541 mLooper.stopAutoDispatch(); 542 543 verify(mWifiNative).addNetwork(); 544 verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID); 545 if (isHidden) { 546 verify(mWifiNative).setNetworkVariable(0, "scan_ssid", Integer.toString(1)); 547 } 548 549 mLooper.startAutoDispatch(); 550 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 551 mLooper.stopAutoDispatch(); 552 assertEquals(1, configs.size()); 553 554 WifiConfiguration config2 = configs.get(0); 555 assertEquals("\"GoogleGuest\"", config2.SSID); 556 assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); 557 } 558 559 private void addNetworkAndVerifyFailure() throws Exception { 560 loadComponents(); 561 562 final WifiConfiguration config = new WifiConfiguration(); 563 config.SSID = sSSID; 564 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 565 566 mLooper.startAutoDispatch(); 567 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 568 mLooper.stopAutoDispatch(); 569 570 verify(mWifiNative, never()).addNetwork(); 571 verify(mWifiNative, never()).setNetworkVariable(anyInt(), anyString(), anyString()); 572 573 mLooper.startAutoDispatch(); 574 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 575 mLooper.stopAutoDispatch(); 576 } 577 578 /** 579 * Verifies that the current foreground user is allowed to add a network. 580 */ 581 @Test 582 public void addNetworkAsCurrentUser() throws Exception { 583 addNetworkAndVerifySuccess(); 584 } 585 586 /** 587 * Verifies that a managed profile of the current foreground user is allowed to add a network. 588 */ 589 @Test 590 public void addNetworkAsCurrentUsersManagedProfile() throws Exception { 591 BinderUtil.setUid(MANAGED_PROFILE_UID); 592 addNetworkAndVerifySuccess(); 593 } 594 595 /** 596 * Verifies that a background user is not allowed to add a network. 597 */ 598 @Test 599 public void addNetworkAsOtherUser() throws Exception { 600 BinderUtil.setUid(OTHER_USER_UID); 601 addNetworkAndVerifyFailure(); 602 } 603 604 private void removeNetworkAndVerifySuccess() throws Exception { 605 when(mWifiNative.removeNetwork(0)).thenReturn(true); 606 mLooper.startAutoDispatch(); 607 assertTrue(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0)); 608 mLooper.stopAutoDispatch(); 609 610 mLooper.startAutoDispatch(); 611 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 612 mLooper.stopAutoDispatch(); 613 } 614 615 private void removeNetworkAndVerifyFailure() throws Exception { 616 mLooper.startAutoDispatch(); 617 assertFalse(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0)); 618 mLooper.stopAutoDispatch(); 619 620 mLooper.startAutoDispatch(); 621 assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size()); 622 mLooper.stopAutoDispatch(); 623 verify(mWifiNative, never()).removeNetwork(anyInt()); 624 } 625 626 /** 627 * Verifies that the current foreground user is allowed to remove a network. 628 */ 629 @Test 630 public void removeNetworkAsCurrentUser() throws Exception { 631 addNetworkAndVerifySuccess(); 632 removeNetworkAndVerifySuccess(); 633 } 634 635 /** 636 * Verifies that a managed profile of the current foreground user is allowed to remove a 637 * network. 638 */ 639 @Test 640 public void removeNetworkAsCurrentUsersManagedProfile() throws Exception { 641 addNetworkAndVerifySuccess(); 642 BinderUtil.setUid(MANAGED_PROFILE_UID); 643 removeNetworkAndVerifySuccess(); 644 } 645 646 /** 647 * Verifies that a background user is not allowed to remove a network. 648 */ 649 @Test 650 public void removeNetworkAsOtherUser() throws Exception { 651 addNetworkAndVerifySuccess(); 652 BinderUtil.setUid(OTHER_USER_UID); 653 removeNetworkAndVerifyFailure(); 654 } 655 656 private void enableNetworkAndVerifySuccess() throws Exception { 657 when(mWifiNative.selectNetwork(0)).thenReturn(true); 658 659 mLooper.startAutoDispatch(); 660 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 661 mLooper.stopAutoDispatch(); 662 663 verify(mWifiNative).selectNetwork(0); 664 } 665 666 private void enableNetworkAndVerifyFailure() throws Exception { 667 mLooper.startAutoDispatch(); 668 assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 669 mLooper.stopAutoDispatch(); 670 671 verify(mWifiNative, never()).selectNetwork(anyInt()); 672 } 673 674 /** 675 * Verifies that the current foreground user is allowed to enable a network. 676 */ 677 @Test 678 public void enableNetworkAsCurrentUser() throws Exception { 679 addNetworkAndVerifySuccess(); 680 enableNetworkAndVerifySuccess(); 681 } 682 683 /** 684 * Verifies that a managed profile of the current foreground user is allowed to enable a 685 * network. 686 */ 687 @Test 688 public void enableNetworkAsCurrentUsersManagedProfile() throws Exception { 689 addNetworkAndVerifySuccess(); 690 BinderUtil.setUid(MANAGED_PROFILE_UID); 691 enableNetworkAndVerifySuccess(); 692 } 693 694 /** 695 * Verifies that a background user is not allowed to enable a network. 696 */ 697 @Test 698 public void enableNetworkAsOtherUser() throws Exception { 699 addNetworkAndVerifySuccess(); 700 BinderUtil.setUid(OTHER_USER_UID); 701 enableNetworkAndVerifyFailure(); 702 } 703 704 private void forgetNetworkAndVerifySuccess() throws Exception { 705 when(mWifiNative.removeNetwork(0)).thenReturn(true); 706 mLooper.startAutoDispatch(); 707 final Message result = 708 mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0); 709 mLooper.stopAutoDispatch(); 710 assertEquals(WifiManager.FORGET_NETWORK_SUCCEEDED, result.what); 711 result.recycle(); 712 mLooper.startAutoDispatch(); 713 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 714 mLooper.stopAutoDispatch(); 715 } 716 717 private void forgetNetworkAndVerifyFailure() throws Exception { 718 mLooper.startAutoDispatch(); 719 final Message result = 720 mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0); 721 mLooper.stopAutoDispatch(); 722 assertEquals(WifiManager.FORGET_NETWORK_FAILED, result.what); 723 result.recycle(); 724 mLooper.startAutoDispatch(); 725 assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size()); 726 mLooper.stopAutoDispatch(); 727 verify(mWifiNative, never()).removeNetwork(anyInt()); 728 } 729 730 /** 731 * Helper method to retrieve WifiConfiguration by SSID. 732 * 733 * Returns the associated WifiConfiguration if it is found, null otherwise. 734 */ 735 private WifiConfiguration getWifiConfigurationForNetwork(String ssid) { 736 mLooper.startAutoDispatch(); 737 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 738 mLooper.stopAutoDispatch(); 739 740 for (WifiConfiguration checkConfig : configs) { 741 if (checkConfig.SSID.equals(ssid)) { 742 return checkConfig; 743 } 744 } 745 return null; 746 } 747 748 /** 749 * Verifies that the current foreground user is allowed to forget a network. 750 */ 751 @Test 752 public void forgetNetworkAsCurrentUser() throws Exception { 753 addNetworkAndVerifySuccess(); 754 forgetNetworkAndVerifySuccess(); 755 } 756 757 /** 758 * Verifies that a managed profile of the current foreground user is allowed to forget a 759 * network. 760 */ 761 @Test 762 public void forgetNetworkAsCurrentUsersManagedProfile() throws Exception { 763 addNetworkAndVerifySuccess(); 764 BinderUtil.setUid(MANAGED_PROFILE_UID); 765 forgetNetworkAndVerifySuccess(); 766 } 767 768 /** 769 * Verifies that a background user is not allowed to forget a network. 770 */ 771 @Test 772 public void forgetNetworkAsOtherUser() throws Exception { 773 addNetworkAndVerifySuccess(); 774 BinderUtil.setUid(OTHER_USER_UID); 775 forgetNetworkAndVerifyFailure(); 776 } 777 778 private void verifyScan(int band, int reportEvents, Set<Integer> configuredNetworkIds) { 779 ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor = 780 ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); 781 ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor = 782 ArgumentCaptor.forClass(WifiScanner.ScanListener.class); 783 verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(), 784 eq(null)); 785 WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue(); 786 assertEquals("band", band, actualSettings.band); 787 assertEquals("reportEvents", reportEvents, actualSettings.reportEvents); 788 789 if (configuredNetworkIds == null) { 790 configuredNetworkIds = new HashSet<>(); 791 } 792 Set<Integer> actualConfiguredNetworkIds = new HashSet<>(); 793 if (actualSettings.hiddenNetworkIds != null) { 794 for (int i = 0; i < actualSettings.hiddenNetworkIds.length; ++i) { 795 actualConfiguredNetworkIds.add(actualSettings.hiddenNetworkIds[i]); 796 } 797 } 798 assertEquals("configured networks", configuredNetworkIds, actualConfiguredNetworkIds); 799 800 when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); 801 mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); 802 803 mLooper.dispatchAll(); 804 805 List<ScanResult> reportedResults = mWsm.syncGetScanResultsList(); 806 assertEquals(8, reportedResults.size()); 807 } 808 809 @Test 810 public void scan() throws Exception { 811 addNetworkAndVerifySuccess(); 812 813 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 814 mWsm.startScan(-1, 0, null, null); 815 mLooper.dispatchAll(); 816 817 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 818 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 819 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null); 820 } 821 822 @Test 823 public void scanWithHiddenNetwork() throws Exception { 824 addNetworkAndVerifySuccess(true); 825 826 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 827 mWsm.startScan(-1, 0, null, null); 828 mLooper.dispatchAll(); 829 830 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 831 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 832 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 833 mWifiConfigManager.getHiddenConfiguredNetworkIds()); 834 } 835 836 @Test 837 public void connect() throws Exception { 838 addNetworkAndVerifySuccess(); 839 840 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 841 mLooper.dispatchAll(); 842 843 mLooper.startAutoDispatch(); 844 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 845 mLooper.stopAutoDispatch(); 846 847 verify(mWifiNative).selectNetwork(0); 848 849 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 850 mLooper.dispatchAll(); 851 852 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 853 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 854 mLooper.dispatchAll(); 855 856 assertEquals("ObtainingIpState", getCurrentState().getName()); 857 858 DhcpResults dhcpResults = new DhcpResults(); 859 dhcpResults.setGateway("1.2.3.4"); 860 dhcpResults.setIpAddress("192.168.1.100", 0); 861 dhcpResults.addDns("8.8.8.8"); 862 dhcpResults.setLeaseDuration(3600); 863 864 mTestIpManager.injectDhcpSuccess(dhcpResults); 865 mLooper.dispatchAll(); 866 867 assertEquals("ConnectedState", getCurrentState().getName()); 868 } 869 870 @Test 871 public void testDhcpFailure() throws Exception { 872 addNetworkAndVerifySuccess(); 873 874 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 875 mLooper.dispatchAll(); 876 877 mLooper.startAutoDispatch(); 878 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 879 mLooper.stopAutoDispatch(); 880 881 verify(mWifiNative).selectNetwork(0); 882 883 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 884 mLooper.dispatchAll(); 885 886 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 887 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 888 mLooper.dispatchAll(); 889 890 assertEquals("ObtainingIpState", getCurrentState().getName()); 891 892 mTestIpManager.injectDhcpFailure(); 893 mLooper.dispatchAll(); 894 895 assertEquals("DisconnectingState", getCurrentState().getName()); 896 } 897 898 @Test 899 public void testBadNetworkEvent() throws Exception { 900 addNetworkAndVerifySuccess(); 901 902 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 903 mLooper.dispatchAll(); 904 905 mLooper.startAutoDispatch(); 906 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 907 mLooper.stopAutoDispatch(); 908 909 verify(mWifiNative).selectNetwork(0); 910 911 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); 912 mLooper.dispatchAll(); 913 914 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 915 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 916 mLooper.dispatchAll(); 917 918 assertEquals("DisconnectedState", getCurrentState().getName()); 919 } 920 921 922 @Test 923 public void smToString() throws Exception { 924 assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString( 925 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED)); 926 assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString( 927 DhcpClient.CMD_PRE_DHCP_ACTION)); 928 assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString( 929 WifiStateMachine.CMD_IP_REACHABILITY_LOST)); 930 } 931 932 @Test 933 public void disconnect() throws Exception { 934 connect(); 935 936 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06"); 937 mLooper.dispatchAll(); 938 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 939 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); 940 mLooper.dispatchAll(); 941 942 assertEquals("DisconnectedState", getCurrentState().getName()); 943 } 944 945 /** 946 * WifiConfigurations default to HasEverConnected to false, creating and adding a config should 947 * not update this value to true. 948 * 949 * Test: Successfully add a network. Check the config and verify 950 * WifiConfiguration.getHasEverConnected() is false. 951 */ 952 @Test 953 public void addNetworkDoesNotSetHasEverConnectedTrue() throws Exception { 954 addNetworkAndVerifySuccess(); 955 956 WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); 957 assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 958 } 959 960 /** 961 * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected 962 * to true. 963 * 964 * Test: Successfully create and connect to a network. Check the config and verify 965 * WifiConfiguration.getHasEverConnected() is true. 966 */ 967 @Test 968 public void setHasEverConnectedTrueOnConnect() throws Exception { 969 connect(); 970 971 WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); 972 assertTrue(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 973 } 974 975 /** 976 * Fail network connection attempt and verify HasEverConnected remains false. 977 * 978 * Test: Successfully create a network but fail when connecting. Check the config and verify 979 * WifiConfiguration.getHasEverConnected() is false. 980 */ 981 @Test 982 public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception { 983 testDhcpFailure(); 984 985 WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); 986 assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 987 } 988 989 @Test 990 public void handleUserSwitch() throws Exception { 991 assertEquals(UserHandle.USER_SYSTEM, mWifiConfigManager.getCurrentUserId()); 992 993 mWsm.handleUserSwitch(10); 994 mLooper.dispatchAll(); 995 996 assertEquals(10, mWifiConfigManager.getCurrentUserId()); 997 } 998 999 @Test 1000 public void iconQueryTest() throws Exception { 1001 /* enable wi-fi */ 1002 addNetworkAndVerifySuccess(); 1003 1004 long bssid = 0x1234567800FFL; 1005 String filename = "iconFileName.png"; 1006 String command = "REQ_HS20_ICON " + Utils.macToString(bssid) + " " + filename; 1007 1008 when(mWifiNative.doCustomSupplicantCommand(command)).thenReturn("OK"); 1009 1010 mLooper.startAutoDispatch(); 1011 boolean result = mWsm.syncQueryPasspointIcon(mWsmAsyncChannel, bssid, filename); 1012 mLooper.stopAutoDispatch(); 1013 1014 verify(mWifiNative).doCustomSupplicantCommand(command); 1015 assertEquals(true, result); 1016 } 1017 1018 private String createSimChallengeRequest(byte[] challengeValue) { 1019 // Produce a base64 encoded length byte + data. 1020 byte[] challengeLengthAndValue = new byte[challengeValue.length + 1]; 1021 challengeLengthAndValue[0] = (byte) challengeValue.length; 1022 for (int i = 0; i < challengeValue.length; ++i) { 1023 challengeLengthAndValue[i + 1] = challengeValue[i]; 1024 } 1025 return Base64.encodeToString(challengeLengthAndValue, android.util.Base64.NO_WRAP); 1026 } 1027 1028 private String createSimAuthResponse(byte[] sresValue, byte[] kcValue) { 1029 // Produce a base64 encoded sres length byte + sres + kc length byte + kc. 1030 int overallLength = sresValue.length + kcValue.length + 2; 1031 byte[] result = new byte[sresValue.length + kcValue.length + 2]; 1032 int idx = 0; 1033 result[idx++] = (byte) sresValue.length; 1034 for (int i = 0; i < sresValue.length; ++i) { 1035 result[idx++] = sresValue[i]; 1036 } 1037 result[idx++] = (byte) kcValue.length; 1038 for (int i = 0; i < kcValue.length; ++i) { 1039 result[idx++] = kcValue[i]; 1040 } 1041 return Base64.encodeToString(result, Base64.NO_WRAP); 1042 } 1043 1044 /** Verifies function getGsmSimAuthResponse method. */ 1045 @Test 1046 public void getGsmSimAuthResponseTest() throws Exception { 1047 TelephonyManager tm = mock(TelephonyManager.class); 1048 final String[] invalidRequests = { null, "", "XXXX" }; 1049 assertEquals("", mWsm.getGsmSimAuthResponse(invalidRequests, tm)); 1050 1051 final String[] failedRequests = { "5E5F" }; 1052 when(tm.getIccAuthentication(anyInt(), anyInt(), 1053 eq(createSimChallengeRequest(new byte[] { 0x5e, 0x5f })))).thenReturn(null); 1054 assertEquals(null, mWsm.getGsmSimAuthResponse(failedRequests, tm)); 1055 1056 when(tm.getIccAuthentication(2, tm.AUTHTYPE_EAP_SIM, 1057 createSimChallengeRequest(new byte[] { 0x1a, 0x2b }))) 1058 .thenReturn(null); 1059 when(tm.getIccAuthentication(1, tm.AUTHTYPE_EAP_SIM, 1060 createSimChallengeRequest(new byte[] { 0x1a, 0x2b }))) 1061 .thenReturn(createSimAuthResponse(new byte[] { 0x1D, 0x2C }, 1062 new byte[] { 0x3B, 0x4A })); 1063 when(tm.getIccAuthentication(1, tm.AUTHTYPE_EAP_SIM, 1064 createSimChallengeRequest(new byte[] { 0x01, 0x23 }))) 1065 .thenReturn(createSimAuthResponse(new byte[] { 0x33, 0x22 }, 1066 new byte[] { 0x11, 0x00 })); 1067 assertEquals(":3b4a:1d2c:1100:3322", mWsm.getGsmSimAuthResponse( 1068 new String[] { "1A2B", "0123" }, tm)); 1069 } 1070 1071 /** 1072 * Verifies that, by default, we allow only the "normal" number of log records. 1073 */ 1074 @Test 1075 public void normalLogRecSizeIsUsedByDefault() { 1076 for (int i = 0; i < WifiStateMachine.NUM_LOG_RECS_NORMAL * 2; i++) { 1077 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1078 } 1079 mLooper.dispatchAll(); 1080 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize()); 1081 } 1082 1083 /** 1084 * Verifies that, in verbose mode, we allow a larger number of log records. 1085 */ 1086 @Test 1087 public void enablingVerboseLoggingIncreasesLogRecSize() { 1088 assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL); 1089 mWsm.enableVerboseLogging(1); 1090 for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE * 2; i++) { 1091 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1092 } 1093 mLooper.dispatchAll(); 1094 assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize()); 1095 } 1096 1097 /** 1098 * Verifies that moving from verbose mode to normal mode resets the buffer, and limits new 1099 * records to a small number of entries. 1100 */ 1101 @Test 1102 public void disablingVerboseLoggingClearsRecordsAndDecreasesLogRecSize() { 1103 mWsm.enableVerboseLogging(1); 1104 for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) { 1105 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1106 } 1107 mLooper.dispatchAll(); 1108 assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize()); 1109 1110 mWsm.enableVerboseLogging(0); 1111 assertEquals(0, mWsm.getLogRecSize()); 1112 for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) { 1113 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1114 } 1115 mLooper.dispatchAll(); 1116 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize()); 1117 } 1118 1119} 1120