WifiStateMachineTest.java revision 8fe3e3497daf08b71ffc8c33cb7b139df6667448
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 @Mock WifiInjector mWifiInjector; 335 @Mock WifiLastResortWatchdog mWifiLastResortWatchdog; 336 337 public WifiStateMachineTest() throws Exception { 338 } 339 340 @Before 341 public void setUp() throws Exception { 342 Log.d(TAG, "Setting up ..."); 343 344 // Ensure looper exists 345 mLooper = new MockLooper(); 346 347 MockitoAnnotations.initMocks(this); 348 349 /** uncomment this to enable logs from WifiStateMachines */ 350 // enableDebugLogs(); 351 352 TestUtil.installWlanWifiNative(mWifiNative); 353 mWifiMonitor = new MockWifiMonitor(); 354 when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 355 when(mWifiInjector.getClock()).thenReturn(mock(Clock.class)); 356 when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); 357 FrameworkFacade factory = getFrameworkFacade(); 358 Context context = getContext(); 359 360 Resources resources = getMockResources(); 361 when(context.getResources()).thenReturn(resources); 362 363 when(factory.getIntegerSetting(context, 364 Settings.Global.WIFI_FREQUENCY_BAND, 365 WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn( 366 WifiManager.WIFI_FREQUENCY_BAND_AUTO); 367 368 when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy))) 369 .thenReturn(mApConfigStore); 370 371 when(factory.makeSupplicantStateTracker( 372 any(Context.class), any(WifiConfigManager.class), 373 any(Handler.class))).thenReturn(mSupplicantStateTracker); 374 375 when(mUserManager.getProfileParent(11)) 376 .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0)); 377 when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList( 378 new UserInfo(UserHandle.USER_SYSTEM, "owner", 0), 379 new UserInfo(11, "managed profile", 0))); 380 381 mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(), 382 mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode); 383 mWsmThread = getWsmHandlerThread(mWsm); 384 385 final AsyncChannel channel = new AsyncChannel(); 386 Handler handler = new Handler(mLooper.getLooper()) { 387 @Override 388 public void handleMessage(Message msg) { 389 switch (msg.what) { 390 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 391 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 392 mWsmAsyncChannel = channel; 393 } else { 394 Log.d(TAG, "Failed to connect Command channel " + this); 395 } 396 break; 397 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 398 Log.d(TAG, "Command channel disconnected" + this); 399 break; 400 } 401 } 402 }; 403 404 channel.connect(context, handler, mWsm.getMessenger()); 405 mLooper.dispatchAll(); 406 /* Now channel is supposed to be connected */ 407 408 mBinderToken = Binder.clearCallingIdentity(); 409 } 410 411 @After 412 public void cleanUp() throws Exception { 413 Binder.restoreCallingIdentity(mBinderToken); 414 415 if (mSyncThread != null) stopLooper(mSyncThread.getLooper()); 416 if (mWsmThread != null) stopLooper(mWsmThread.getLooper()); 417 if (mP2pThread != null) stopLooper(mP2pThread.getLooper()); 418 419 mWsmThread = null; 420 mP2pThread = null; 421 mSyncThread = null; 422 mWsmAsyncChannel = null; 423 mWsm = null; 424 } 425 426 @Test 427 public void createNew() throws Exception { 428 assertEquals("InitialState", getCurrentState().getName()); 429 430 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 431 mLooper.dispatchAll(); 432 assertEquals("InitialState", getCurrentState().getName()); 433 } 434 435 @Test 436 public void loadComponents() throws Exception { 437 when(mWifiNative.loadDriver()).thenReturn(true); 438 when(mWifiNative.startHal()).thenReturn(true); 439 when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true); 440 mWsm.setSupplicantRunning(true); 441 mLooper.dispatchAll(); 442 443 assertEquals("SupplicantStartingState", getCurrentState().getName()); 444 445 when(mWifiNative.setBand(anyInt())).thenReturn(true); 446 when(mWifiNative.setDeviceName(anyString())).thenReturn(true); 447 when(mWifiNative.setManufacturer(anyString())).thenReturn(true); 448 when(mWifiNative.setModelName(anyString())).thenReturn(true); 449 when(mWifiNative.setModelNumber(anyString())).thenReturn(true); 450 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 451 when(mWifiNative.setConfigMethods(anyString())).thenReturn(true); 452 when(mWifiNative.setDeviceType(anyString())).thenReturn(true); 453 when(mWifiNative.setSerialNumber(anyString())).thenReturn(true); 454 when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true); 455 456 mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT); 457 mLooper.dispatchAll(); 458 459 assertEquals("DisconnectedState", getCurrentState().getName()); 460 } 461 462 @Test 463 public void loadComponentsFailure() throws Exception { 464 when(mWifiNative.loadDriver()).thenReturn(false); 465 when(mWifiNative.startHal()).thenReturn(false); 466 when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(false); 467 468 mWsm.setSupplicantRunning(true); 469 mLooper.dispatchAll(); 470 assertEquals("InitialState", getCurrentState().getName()); 471 472 when(mWifiNative.loadDriver()).thenReturn(true); 473 mWsm.setSupplicantRunning(true); 474 mLooper.dispatchAll(); 475 assertEquals("InitialState", getCurrentState().getName()); 476 477 when(mWifiNative.startHal()).thenReturn(true); 478 mWsm.setSupplicantRunning(true); 479 mLooper.dispatchAll(); 480 assertEquals("InitialState", getCurrentState().getName()); 481 } 482 483 private void addNetworkAndVerifySuccess() throws Exception { 484 addNetworkAndVerifySuccess(false); 485 } 486 487 private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception { 488 loadComponents(); 489 490 final HashMap<String, String> nameToValue = new HashMap<String, String>(); 491 492 when(mWifiNative.addNetwork()).thenReturn(0); 493 when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString())) 494 .then(new AnswerWithArguments() { 495 public boolean answer(int netId, String name, String value) { 496 if (netId != 0) { 497 Log.d(TAG, "Can't set var " + name + " for " + netId); 498 return false; 499 } 500 501 Log.d(TAG, "Setting var " + name + " to " + value + " for " + netId); 502 nameToValue.put(name, value); 503 return true; 504 } 505 }); 506 507 when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject())) 508 .then(new AnswerWithArguments() { 509 public boolean answer(int netId, String name, Map<String, String> values) { 510 if (netId != 0) { 511 Log.d(TAG, "Can't set extra " + name + " for " + netId); 512 return false; 513 } 514 515 Log.d(TAG, "Setting extra for " + netId); 516 return true; 517 } 518 }); 519 520 when(mWifiNative.getNetworkVariable(anyInt(), anyString())) 521 .then(new AnswerWithArguments() { 522 public String answer(int netId, String name) throws Throwable { 523 if (netId != 0) { 524 Log.d(TAG, "Can't find var " + name + " for " + netId); 525 return null; 526 } 527 String value = nameToValue.get(name); 528 if (value != null) { 529 Log.d(TAG, "Returning var " + name + " to " + value + " for " + netId); 530 } else { 531 Log.d(TAG, "Can't find var " + name + " for " + netId); 532 } 533 return value; 534 } 535 }); 536 537 WifiConfiguration config = new WifiConfiguration(); 538 config.SSID = sSSID; 539 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 540 config.hiddenSSID = isHidden; 541 mLooper.startAutoDispatch(); 542 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 543 mLooper.stopAutoDispatch(); 544 545 verify(mWifiNative).addNetwork(); 546 verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID); 547 if (isHidden) { 548 verify(mWifiNative).setNetworkVariable(0, "scan_ssid", Integer.toString(1)); 549 } 550 551 mLooper.startAutoDispatch(); 552 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 553 mLooper.stopAutoDispatch(); 554 assertEquals(1, configs.size()); 555 556 WifiConfiguration config2 = configs.get(0); 557 assertEquals("\"GoogleGuest\"", config2.SSID); 558 assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)); 559 } 560 561 private void addNetworkAndVerifyFailure() throws Exception { 562 loadComponents(); 563 564 final WifiConfiguration config = new WifiConfiguration(); 565 config.SSID = sSSID; 566 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 567 568 mLooper.startAutoDispatch(); 569 mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config); 570 mLooper.stopAutoDispatch(); 571 572 verify(mWifiNative, never()).addNetwork(); 573 verify(mWifiNative, never()).setNetworkVariable(anyInt(), anyString(), anyString()); 574 575 mLooper.startAutoDispatch(); 576 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 577 mLooper.stopAutoDispatch(); 578 } 579 580 /** 581 * Verifies that the current foreground user is allowed to add a network. 582 */ 583 @Test 584 public void addNetworkAsCurrentUser() throws Exception { 585 addNetworkAndVerifySuccess(); 586 } 587 588 /** 589 * Verifies that a managed profile of the current foreground user is allowed to add a network. 590 */ 591 @Test 592 public void addNetworkAsCurrentUsersManagedProfile() throws Exception { 593 BinderUtil.setUid(MANAGED_PROFILE_UID); 594 addNetworkAndVerifySuccess(); 595 } 596 597 /** 598 * Verifies that a background user is not allowed to add a network. 599 */ 600 @Test 601 public void addNetworkAsOtherUser() throws Exception { 602 BinderUtil.setUid(OTHER_USER_UID); 603 addNetworkAndVerifyFailure(); 604 } 605 606 private void removeNetworkAndVerifySuccess() throws Exception { 607 when(mWifiNative.removeNetwork(0)).thenReturn(true); 608 mLooper.startAutoDispatch(); 609 assertTrue(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0)); 610 mLooper.stopAutoDispatch(); 611 612 mLooper.startAutoDispatch(); 613 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 614 mLooper.stopAutoDispatch(); 615 } 616 617 private void removeNetworkAndVerifyFailure() throws Exception { 618 mLooper.startAutoDispatch(); 619 assertFalse(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0)); 620 mLooper.stopAutoDispatch(); 621 622 mLooper.startAutoDispatch(); 623 assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size()); 624 mLooper.stopAutoDispatch(); 625 verify(mWifiNative, never()).removeNetwork(anyInt()); 626 } 627 628 /** 629 * Verifies that the current foreground user is allowed to remove a network. 630 */ 631 @Test 632 public void removeNetworkAsCurrentUser() throws Exception { 633 addNetworkAndVerifySuccess(); 634 removeNetworkAndVerifySuccess(); 635 } 636 637 /** 638 * Verifies that a managed profile of the current foreground user is allowed to remove a 639 * network. 640 */ 641 @Test 642 public void removeNetworkAsCurrentUsersManagedProfile() throws Exception { 643 addNetworkAndVerifySuccess(); 644 BinderUtil.setUid(MANAGED_PROFILE_UID); 645 removeNetworkAndVerifySuccess(); 646 } 647 648 /** 649 * Verifies that a background user is not allowed to remove a network. 650 */ 651 @Test 652 public void removeNetworkAsOtherUser() throws Exception { 653 addNetworkAndVerifySuccess(); 654 BinderUtil.setUid(OTHER_USER_UID); 655 removeNetworkAndVerifyFailure(); 656 } 657 658 private void enableNetworkAndVerifySuccess() throws Exception { 659 when(mWifiNative.selectNetwork(0)).thenReturn(true); 660 661 mLooper.startAutoDispatch(); 662 assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 663 mLooper.stopAutoDispatch(); 664 665 verify(mWifiNative).selectNetwork(0); 666 } 667 668 private void enableNetworkAndVerifyFailure() throws Exception { 669 mLooper.startAutoDispatch(); 670 assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true)); 671 mLooper.stopAutoDispatch(); 672 673 verify(mWifiNative, never()).selectNetwork(anyInt()); 674 } 675 676 /** 677 * Verifies that the current foreground user is allowed to enable a network. 678 */ 679 @Test 680 public void enableNetworkAsCurrentUser() throws Exception { 681 addNetworkAndVerifySuccess(); 682 enableNetworkAndVerifySuccess(); 683 } 684 685 /** 686 * Verifies that a managed profile of the current foreground user is allowed to enable a 687 * network. 688 */ 689 @Test 690 public void enableNetworkAsCurrentUsersManagedProfile() throws Exception { 691 addNetworkAndVerifySuccess(); 692 BinderUtil.setUid(MANAGED_PROFILE_UID); 693 enableNetworkAndVerifySuccess(); 694 } 695 696 /** 697 * Verifies that a background user is not allowed to enable a network. 698 */ 699 @Test 700 public void enableNetworkAsOtherUser() throws Exception { 701 addNetworkAndVerifySuccess(); 702 BinderUtil.setUid(OTHER_USER_UID); 703 enableNetworkAndVerifyFailure(); 704 } 705 706 private void forgetNetworkAndVerifySuccess() throws Exception { 707 when(mWifiNative.removeNetwork(0)).thenReturn(true); 708 mLooper.startAutoDispatch(); 709 final Message result = 710 mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0); 711 mLooper.stopAutoDispatch(); 712 assertEquals(WifiManager.FORGET_NETWORK_SUCCEEDED, result.what); 713 result.recycle(); 714 mLooper.startAutoDispatch(); 715 assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty()); 716 mLooper.stopAutoDispatch(); 717 } 718 719 private void forgetNetworkAndVerifyFailure() throws Exception { 720 mLooper.startAutoDispatch(); 721 final Message result = 722 mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0); 723 mLooper.stopAutoDispatch(); 724 assertEquals(WifiManager.FORGET_NETWORK_FAILED, result.what); 725 result.recycle(); 726 mLooper.startAutoDispatch(); 727 assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size()); 728 mLooper.stopAutoDispatch(); 729 verify(mWifiNative, never()).removeNetwork(anyInt()); 730 } 731 732 /** 733 * Helper method to retrieve WifiConfiguration by SSID. 734 * 735 * Returns the associated WifiConfiguration if it is found, null otherwise. 736 */ 737 private WifiConfiguration getWifiConfigurationForNetwork(String ssid) { 738 mLooper.startAutoDispatch(); 739 List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel); 740 mLooper.stopAutoDispatch(); 741 742 for (WifiConfiguration checkConfig : configs) { 743 if (checkConfig.SSID.equals(ssid)) { 744 return checkConfig; 745 } 746 } 747 return null; 748 } 749 750 /** 751 * Verifies that the current foreground user is allowed to forget a network. 752 */ 753 @Test 754 public void forgetNetworkAsCurrentUser() throws Exception { 755 addNetworkAndVerifySuccess(); 756 forgetNetworkAndVerifySuccess(); 757 } 758 759 /** 760 * Verifies that a managed profile of the current foreground user is allowed to forget a 761 * network. 762 */ 763 @Test 764 public void forgetNetworkAsCurrentUsersManagedProfile() throws Exception { 765 addNetworkAndVerifySuccess(); 766 BinderUtil.setUid(MANAGED_PROFILE_UID); 767 forgetNetworkAndVerifySuccess(); 768 } 769 770 /** 771 * Verifies that a background user is not allowed to forget a network. 772 */ 773 @Test 774 public void forgetNetworkAsOtherUser() throws Exception { 775 addNetworkAndVerifySuccess(); 776 BinderUtil.setUid(OTHER_USER_UID); 777 forgetNetworkAndVerifyFailure(); 778 } 779 780 private void verifyScan(int band, int reportEvents, Set<Integer> configuredNetworkIds) { 781 ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor = 782 ArgumentCaptor.forClass(WifiScanner.ScanSettings.class); 783 ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor = 784 ArgumentCaptor.forClass(WifiScanner.ScanListener.class); 785 verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(), 786 eq(null)); 787 WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue(); 788 assertEquals("band", band, actualSettings.band); 789 assertEquals("reportEvents", reportEvents, actualSettings.reportEvents); 790 791 if (configuredNetworkIds == null) { 792 configuredNetworkIds = new HashSet<>(); 793 } 794 Set<Integer> actualConfiguredNetworkIds = new HashSet<>(); 795 if (actualSettings.hiddenNetworkIds != null) { 796 for (int i = 0; i < actualSettings.hiddenNetworkIds.length; ++i) { 797 actualConfiguredNetworkIds.add(actualSettings.hiddenNetworkIds[i]); 798 } 799 } 800 assertEquals("configured networks", configuredNetworkIds, actualConfiguredNetworkIds); 801 802 when(mWifiNative.getScanResults()).thenReturn(getMockScanResults()); 803 mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT); 804 805 mLooper.dispatchAll(); 806 807 List<ScanResult> reportedResults = mWsm.syncGetScanResultsList(); 808 assertEquals(8, reportedResults.size()); 809 } 810 811 @Test 812 public void scan() throws Exception { 813 addNetworkAndVerifySuccess(); 814 815 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 816 mWsm.startScan(-1, 0, null, null); 817 mLooper.dispatchAll(); 818 819 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 820 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 821 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null); 822 } 823 824 @Test 825 public void scanWithHiddenNetwork() throws Exception { 826 addNetworkAndVerifySuccess(true); 827 828 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 829 mWsm.startScan(-1, 0, null, null); 830 mLooper.dispatchAll(); 831 832 verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS, 833 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 834 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 835 mWifiConfigManager.getHiddenConfiguredNetworkIds()); 836 } 837 838 @Test 839 public void connect() throws Exception { 840 addNetworkAndVerifySuccess(); 841 842 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 843 mLooper.dispatchAll(); 844 845 mLooper.startAutoDispatch(); 846 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 847 mLooper.stopAutoDispatch(); 848 849 verify(mWifiNative).selectNetwork(0); 850 851 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 852 mLooper.dispatchAll(); 853 854 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 855 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 856 mLooper.dispatchAll(); 857 858 assertEquals("ObtainingIpState", getCurrentState().getName()); 859 860 DhcpResults dhcpResults = new DhcpResults(); 861 dhcpResults.setGateway("1.2.3.4"); 862 dhcpResults.setIpAddress("192.168.1.100", 0); 863 dhcpResults.addDns("8.8.8.8"); 864 dhcpResults.setLeaseDuration(3600); 865 866 mTestIpManager.injectDhcpSuccess(dhcpResults); 867 mLooper.dispatchAll(); 868 869 assertEquals("ConnectedState", getCurrentState().getName()); 870 } 871 872 @Test 873 public void testDhcpFailure() throws Exception { 874 addNetworkAndVerifySuccess(); 875 876 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 877 mLooper.dispatchAll(); 878 879 mLooper.startAutoDispatch(); 880 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 881 mLooper.stopAutoDispatch(); 882 883 verify(mWifiNative).selectNetwork(0); 884 885 mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID); 886 mLooper.dispatchAll(); 887 888 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 889 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 890 mLooper.dispatchAll(); 891 892 assertEquals("ObtainingIpState", getCurrentState().getName()); 893 894 mTestIpManager.injectDhcpFailure(); 895 mLooper.dispatchAll(); 896 897 assertEquals("DisconnectingState", getCurrentState().getName()); 898 } 899 900 @Test 901 public void testBadNetworkEvent() throws Exception { 902 addNetworkAndVerifySuccess(); 903 904 mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE); 905 mLooper.dispatchAll(); 906 907 mLooper.startAutoDispatch(); 908 mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true); 909 mLooper.stopAutoDispatch(); 910 911 verify(mWifiNative).selectNetwork(0); 912 913 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID); 914 mLooper.dispatchAll(); 915 916 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 917 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED)); 918 mLooper.dispatchAll(); 919 920 assertEquals("DisconnectedState", getCurrentState().getName()); 921 } 922 923 924 @Test 925 public void smToString() throws Exception { 926 assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString( 927 AsyncChannel.CMD_CHANNEL_HALF_CONNECTED)); 928 assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString( 929 DhcpClient.CMD_PRE_DHCP_ACTION)); 930 assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString( 931 WifiStateMachine.CMD_IP_REACHABILITY_LOST)); 932 } 933 934 @Test 935 public void disconnect() throws Exception { 936 connect(); 937 938 mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06"); 939 mLooper.dispatchAll(); 940 mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0, 941 new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED)); 942 mLooper.dispatchAll(); 943 944 assertEquals("DisconnectedState", getCurrentState().getName()); 945 } 946 947 /** 948 * WifiConfigurations default to HasEverConnected to false, creating and adding a config should 949 * not update this value to true. 950 * 951 * Test: Successfully add a network. Check the config and verify 952 * WifiConfiguration.getHasEverConnected() is false. 953 */ 954 @Test 955 public void addNetworkDoesNotSetHasEverConnectedTrue() throws Exception { 956 addNetworkAndVerifySuccess(); 957 958 WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); 959 assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 960 } 961 962 /** 963 * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected 964 * to true. 965 * 966 * Test: Successfully create and connect to a network. Check the config and verify 967 * WifiConfiguration.getHasEverConnected() is true. 968 */ 969 @Test 970 public void setHasEverConnectedTrueOnConnect() throws Exception { 971 connect(); 972 973 WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); 974 assertTrue(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 975 } 976 977 /** 978 * Fail network connection attempt and verify HasEverConnected remains false. 979 * 980 * Test: Successfully create a network but fail when connecting. Check the config and verify 981 * WifiConfiguration.getHasEverConnected() is false. 982 */ 983 @Test 984 public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception { 985 testDhcpFailure(); 986 987 WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID); 988 assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected()); 989 } 990 991 @Test 992 public void handleUserSwitch() throws Exception { 993 assertEquals(UserHandle.USER_SYSTEM, mWifiConfigManager.getCurrentUserId()); 994 995 mWsm.handleUserSwitch(10); 996 mLooper.dispatchAll(); 997 998 assertEquals(10, mWifiConfigManager.getCurrentUserId()); 999 } 1000 1001 @Test 1002 public void iconQueryTest() throws Exception { 1003 /* enable wi-fi */ 1004 addNetworkAndVerifySuccess(); 1005 1006 long bssid = 0x1234567800FFL; 1007 String filename = "iconFileName.png"; 1008 String command = "REQ_HS20_ICON " + Utils.macToString(bssid) + " " + filename; 1009 1010 when(mWifiNative.doCustomSupplicantCommand(command)).thenReturn("OK"); 1011 1012 mLooper.startAutoDispatch(); 1013 boolean result = mWsm.syncQueryPasspointIcon(mWsmAsyncChannel, bssid, filename); 1014 mLooper.stopAutoDispatch(); 1015 1016 verify(mWifiNative).doCustomSupplicantCommand(command); 1017 assertEquals(true, result); 1018 } 1019 1020 private String createSimChallengeRequest(byte[] challengeValue) { 1021 // Produce a base64 encoded length byte + data. 1022 byte[] challengeLengthAndValue = new byte[challengeValue.length + 1]; 1023 challengeLengthAndValue[0] = (byte) challengeValue.length; 1024 for (int i = 0; i < challengeValue.length; ++i) { 1025 challengeLengthAndValue[i + 1] = challengeValue[i]; 1026 } 1027 return Base64.encodeToString(challengeLengthAndValue, android.util.Base64.NO_WRAP); 1028 } 1029 1030 private String createSimAuthResponse(byte[] sresValue, byte[] kcValue) { 1031 // Produce a base64 encoded sres length byte + sres + kc length byte + kc. 1032 int overallLength = sresValue.length + kcValue.length + 2; 1033 byte[] result = new byte[sresValue.length + kcValue.length + 2]; 1034 int idx = 0; 1035 result[idx++] = (byte) sresValue.length; 1036 for (int i = 0; i < sresValue.length; ++i) { 1037 result[idx++] = sresValue[i]; 1038 } 1039 result[idx++] = (byte) kcValue.length; 1040 for (int i = 0; i < kcValue.length; ++i) { 1041 result[idx++] = kcValue[i]; 1042 } 1043 return Base64.encodeToString(result, Base64.NO_WRAP); 1044 } 1045 1046 /** Verifies function getGsmSimAuthResponse method. */ 1047 @Test 1048 public void getGsmSimAuthResponseTest() throws Exception { 1049 TelephonyManager tm = mock(TelephonyManager.class); 1050 final String[] invalidRequests = { null, "", "XXXX" }; 1051 assertEquals("", mWsm.getGsmSimAuthResponse(invalidRequests, tm)); 1052 1053 final String[] failedRequests = { "5E5F" }; 1054 when(tm.getIccAuthentication(anyInt(), anyInt(), 1055 eq(createSimChallengeRequest(new byte[] { 0x5e, 0x5f })))).thenReturn(null); 1056 assertEquals(null, mWsm.getGsmSimAuthResponse(failedRequests, tm)); 1057 1058 when(tm.getIccAuthentication(2, tm.AUTHTYPE_EAP_SIM, 1059 createSimChallengeRequest(new byte[] { 0x1a, 0x2b }))) 1060 .thenReturn(null); 1061 when(tm.getIccAuthentication(1, tm.AUTHTYPE_EAP_SIM, 1062 createSimChallengeRequest(new byte[] { 0x1a, 0x2b }))) 1063 .thenReturn(createSimAuthResponse(new byte[] { 0x1D, 0x2C }, 1064 new byte[] { 0x3B, 0x4A })); 1065 when(tm.getIccAuthentication(1, tm.AUTHTYPE_EAP_SIM, 1066 createSimChallengeRequest(new byte[] { 0x01, 0x23 }))) 1067 .thenReturn(createSimAuthResponse(new byte[] { 0x33, 0x22 }, 1068 new byte[] { 0x11, 0x00 })); 1069 assertEquals(":3b4a:1d2c:1100:3322", mWsm.getGsmSimAuthResponse( 1070 new String[] { "1A2B", "0123" }, tm)); 1071 } 1072 1073 /** 1074 * Verifies that, by default, we allow only the "normal" number of log records. 1075 */ 1076 @Test 1077 public void normalLogRecSizeIsUsedByDefault() { 1078 for (int i = 0; i < WifiStateMachine.NUM_LOG_RECS_NORMAL * 2; i++) { 1079 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1080 } 1081 mLooper.dispatchAll(); 1082 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize()); 1083 } 1084 1085 /** 1086 * Verifies that, in verbose mode, we allow a larger number of log records. 1087 */ 1088 @Test 1089 public void enablingVerboseLoggingIncreasesLogRecSize() { 1090 assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL); 1091 mWsm.enableVerboseLogging(1); 1092 for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE * 2; i++) { 1093 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1094 } 1095 mLooper.dispatchAll(); 1096 assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize()); 1097 } 1098 1099 /** 1100 * Verifies that moving from verbose mode to normal mode resets the buffer, and limits new 1101 * records to a small number of entries. 1102 */ 1103 @Test 1104 public void disablingVerboseLoggingClearsRecordsAndDecreasesLogRecSize() { 1105 mWsm.enableVerboseLogging(1); 1106 for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) { 1107 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1108 } 1109 mLooper.dispatchAll(); 1110 assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize()); 1111 1112 mWsm.enableVerboseLogging(0); 1113 assertEquals(0, mWsm.getLogRecSize()); 1114 for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) { 1115 mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED); 1116 } 1117 mLooper.dispatchAll(); 1118 assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize()); 1119 } 1120 1121} 1122