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