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 17 package com.android.server.wifi.scanner; 18 19 import static com.android.server.wifi.ScanTestUtil.NativeScanSettingsBuilder; 20 import static com.android.server.wifi.ScanTestUtil.assertScanDataEquals; 21 import static com.android.server.wifi.ScanTestUtil.createFreqSet; 22 23 import static org.junit.Assert.*; 24 import static org.mockito.Mockito.*; 25 26 import android.app.test.TestAlarmManager; 27 import android.content.Context; 28 import android.net.wifi.ScanResult; 29 import android.net.wifi.WifiScanner; 30 import android.net.wifi.WifiScanner.ScanData; 31 import android.net.wifi.WifiSsid; 32 import android.os.SystemClock; 33 import android.os.test.TestLooper; 34 35 import com.android.server.wifi.Clock; 36 import com.android.server.wifi.MockResources; 37 import com.android.server.wifi.MockWifiMonitor; 38 import com.android.server.wifi.ScanDetail; 39 import com.android.server.wifi.ScanResults; 40 import com.android.server.wifi.WifiMonitor; 41 import com.android.server.wifi.WifiNative; 42 import com.android.server.wifi.scanner.ChannelHelper.ChannelCollection; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.mockito.InOrder; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 50 import java.util.ArrayList; 51 import java.util.Arrays; 52 import java.util.Collections; 53 import java.util.HashSet; 54 import java.util.Set; 55 56 /** 57 * Base unit tests that should pass for all implementations of 58 * {@link com.android.server.wifi.scanner.WifiScannerImpl}. 59 */ 60 public abstract class BaseWifiScannerImplTest { 61 @Mock Context mContext; 62 TestAlarmManager mAlarmManager; 63 MockWifiMonitor mWifiMonitor; 64 TestLooper mLooper; 65 @Mock WifiNative mWifiNative; 66 MockResources mResources; 67 @Mock Clock mClock; 68 69 /** 70 * mScanner implementation should be filled in by derived test class 71 */ 72 WifiScannerImpl mScanner; 73 74 @Before 75 public void setUpBase() throws Exception { 76 MockitoAnnotations.initMocks(this); 77 78 mLooper = new TestLooper(); 79 mAlarmManager = new TestAlarmManager(); 80 mWifiMonitor = new MockWifiMonitor(); 81 mResources = new MockResources(); 82 83 when(mWifiNative.getInterfaceName()).thenReturn("a_test_interface_name"); 84 85 when(mContext.getSystemService(Context.ALARM_SERVICE)) 86 .thenReturn(mAlarmManager.getAlarmManager()); 87 88 when(mContext.getResources()).thenReturn(mResources); 89 when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()); 90 } 91 92 protected boolean isAllChannelsScanned(int band) { 93 ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection(); 94 collection.addBand(band); 95 return collection.isAllChannels(); 96 } 97 98 protected Set<Integer> expectedBandScanFreqs(int band) { 99 ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection(); 100 collection.addBand(band); 101 return collection.getScanFreqs(); 102 } 103 104 protected Set<Integer> expectedBandAndChannelScanFreqs(int band, int... channels) { 105 ChannelCollection collection = mScanner.getChannelHelper().createChannelCollection(); 106 collection.addBand(band); 107 for (int channel : channels) { 108 collection.addChannel(channel); 109 } 110 return collection.getScanFreqs(); 111 } 112 113 @Test 114 public void singleScanSuccess() { 115 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 116 .withBasePeriod(10000) // ms 117 .withMaxApPerScan(10) 118 .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 119 WifiScanner.WIFI_BAND_24_GHZ) 120 .build(); 121 122 doSuccessfulSingleScanTest(settings, expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), 123 new HashSet<String>(), 124 ScanResults.create(0, isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ), 125 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), false); 126 } 127 128 @Test 129 public void singleScanSuccessWithChannels() { 130 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 131 .withBasePeriod(10000) 132 .withMaxApPerScan(10) 133 .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5650) 134 .build(); 135 136 doSuccessfulSingleScanTest(settings, createFreqSet(5650), 137 new HashSet<String>(), 138 ScanResults.create(0, 5650, 5650, 5650, 5650, 5650, 5650, 5650, 5650), false); 139 } 140 141 @Test 142 public void singleScanSuccessWithFullResults() { 143 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 144 .withBasePeriod(10000) 145 .withMaxApPerScan(10) 146 .addBucketWithBand(10000, 147 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 148 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 149 WifiScanner.WIFI_BAND_24_GHZ) 150 .build(); 151 152 doSuccessfulSingleScanTest(settings, expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), 153 new HashSet<String>(), 154 ScanResults.create(0, isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ), 155 2400, 2450, 2450, 2400, 2450, 2450, 2400, 2450, 2450), true); 156 } 157 158 /** 159 * Tests whether the provided hidden networkId's in scan settings is correctly passed along 160 * when invoking native scan. 161 */ 162 @Test 163 public void singleScanSuccessWithHiddenNetworkIds() { 164 String[] hiddenNetworkSSIDs = {"test_ssid_1", "test_ssid_2"}; 165 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 166 .withBasePeriod(10000) 167 .withMaxApPerScan(10) 168 .withHiddenNetworkSSIDs(hiddenNetworkSSIDs) 169 .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5650) 170 .build(); 171 172 Set<String> hiddenNetworkSSIDSet = new HashSet<>(); 173 for (int i = 0; i < hiddenNetworkSSIDs.length; i++) { 174 hiddenNetworkSSIDSet.add(hiddenNetworkSSIDs[i]); 175 } 176 doSuccessfulSingleScanTest(settings, createFreqSet(5650), 177 hiddenNetworkSSIDSet, 178 ScanResults.create(0, 5650, 5650, 5650, 5650, 5650, 5650, 5650, 5650), false); 179 } 180 181 /** 182 * Tests whether the provided hidden networkId's in scan settings is truncated to max size 183 * supported by wificond when invoking native scan. 184 */ 185 @Test 186 public void singleScanSuccessWithTruncatedHiddenNetworkIds() { 187 String[] hiddenNetworkSSIDs = { 188 "test_ssid_0", "test_ssid_1", "test_ssid_2", "test_ssid_3", "test_ssid_4", 189 "test_ssid_5", "test_ssid_6", "test_ssid_7", "test_ssid_8", "test_ssid_9", 190 "test_ssid_10", "test_ssid_11", "test_ssid_12", "test_ssid_13", "test_ssid_14", 191 "test_ssid_15", "test_ssid_16", "test_ssid_17", "test_ssid_18", "test_ssid_19" 192 }; 193 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 194 .withBasePeriod(10000) 195 .withMaxApPerScan(10) 196 .withHiddenNetworkSSIDs(hiddenNetworkSSIDs) 197 .addBucketWithChannels(20000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 5650) 198 .build(); 199 200 Set<String> hiddenNetworkSSIDSet = new HashSet<>(); 201 for (int i = 0; i < WificondScannerImpl.MAX_HIDDEN_NETWORK_IDS_PER_SCAN; i++) { 202 hiddenNetworkSSIDSet.add(hiddenNetworkSSIDs[i]); 203 } 204 doSuccessfulSingleScanTest(settings, createFreqSet(5650), 205 hiddenNetworkSSIDSet, 206 ScanResults.create(0, 5650, 5650, 5650, 5650, 5650, 5650, 5650, 5650), false); 207 } 208 209 @Test 210 public void overlappingSingleScanFails() { 211 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 212 .withBasePeriod(10000) // ms 213 .withMaxApPerScan(10) 214 .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 215 WifiScanner.WIFI_BAND_24_GHZ) 216 .build(); 217 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 218 219 WifiNative.ScanSettings settings2 = new NativeScanSettingsBuilder() 220 .withBasePeriod(10000) // ms 221 .withMaxApPerScan(10) 222 .addBucketWithBand(10000 /* ms */, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 223 WifiScanner.WIFI_BAND_5_GHZ) 224 .build(); 225 WifiNative.ScanEventHandler eventHandler2 = mock(WifiNative.ScanEventHandler.class); 226 227 // scan start succeeds 228 when(mWifiNative.scan(any(), any(Set.class))).thenReturn(true); 229 230 assertTrue(mScanner.startSingleScan(settings, eventHandler)); 231 assertFalse("second scan while first scan running should fail immediately", 232 mScanner.startSingleScan(settings2, eventHandler2)); 233 } 234 235 @Test 236 public void singleScanFailOnExecute() { 237 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 238 .withBasePeriod(10000) 239 .withMaxApPerScan(10) 240 .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 241 WifiScanner.WIFI_BAND_24_GHZ) 242 .build(); 243 244 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 245 246 ScanResults results = ScanResults.create(0, 2400, 2450, 2450); 247 248 InOrder order = inOrder(eventHandler, mWifiNative); 249 250 // scan fails 251 when(mWifiNative.scan(any(), any(Set.class))).thenReturn(false); 252 253 // start scan 254 assertTrue(mScanner.startSingleScan(settings, eventHandler)); 255 256 mLooper.dispatchAll(); 257 order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); 258 259 verifyNoMoreInteractions(eventHandler); 260 } 261 262 /** 263 * Test that a scan failure is reported if a scan times out 264 */ 265 @Test 266 public void singleScanFailOnTimeout() { 267 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 268 .withBasePeriod(10000) 269 .withMaxApPerScan(10) 270 .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 271 WifiScanner.WIFI_BAND_24_GHZ) 272 .build(); 273 274 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 275 276 ScanResults results = ScanResults.create(0, 2400, 2450, 2450); 277 278 InOrder order = inOrder(eventHandler, mWifiNative); 279 280 // scan succeeds 281 when(mWifiNative.scan(any(), any(Set.class))).thenReturn(true); 282 283 // start scan 284 assertTrue(mScanner.startSingleScan(settings, eventHandler)); 285 mLooper.dispatchAll(); 286 287 // Fire timeout 288 mAlarmManager.dispatch(WificondScannerImpl.TIMEOUT_ALARM_TAG); 289 mLooper.dispatchAll(); 290 291 order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); 292 293 verifyNoMoreInteractions(eventHandler); 294 } 295 296 /** 297 * Test that a scan failure is reported if wificond sends a scan failed event 298 */ 299 @Test 300 public void singleScanFailOnFailedEvent() { 301 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 302 .withBasePeriod(10000) 303 .withMaxApPerScan(10) 304 .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 305 WifiScanner.WIFI_BAND_24_GHZ) 306 .build(); 307 308 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 309 310 ScanResults results = ScanResults.create(0, 2400, 2450, 2450); 311 312 InOrder order = inOrder(eventHandler, mWifiNative); 313 314 // scan succeeds 315 when(mWifiNative.scan(any(), any(Set.class))).thenReturn(true); 316 317 // start scan 318 assertTrue(mScanner.startSingleScan(settings, eventHandler)); 319 mLooper.dispatchAll(); 320 321 // Fire failed event 322 mWifiMonitor.sendMessage(mWifiNative.getInterfaceName(), WifiMonitor.SCAN_FAILED_EVENT); 323 mLooper.dispatchAll(); 324 325 order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED); 326 327 verifyNoMoreInteractions(eventHandler); 328 } 329 330 @Test 331 public void singleScanNullEventHandler() { 332 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 333 .withBasePeriod(10000) 334 .withMaxApPerScan(10) 335 .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 336 WifiScanner.WIFI_BAND_24_GHZ) 337 .build(); 338 assertFalse(mScanner.startSingleScan(settings, null)); 339 } 340 341 @Test 342 public void singleScanNullSettings() { 343 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 344 345 assertFalse(mScanner.startSingleScan(null, eventHandler)); 346 347 verifyNoMoreInteractions(eventHandler); 348 } 349 350 @Test 351 public void multipleSingleScanSuccess() { 352 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 353 .withBasePeriod(10000) 354 .withMaxApPerScan(10) 355 .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 356 WifiScanner.WIFI_BAND_24_GHZ) 357 .build(); 358 WifiNative.ScanSettings settings2 = new NativeScanSettingsBuilder() 359 .withBasePeriod(10000) 360 .withMaxApPerScan(10) 361 .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 362 WifiScanner.WIFI_BAND_BOTH_WITH_DFS) 363 .build(); 364 365 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 366 InOrder order = inOrder(eventHandler, mWifiNative); 367 368 // scans succeed 369 when(mWifiNative.scan(any(), any(Set.class))).thenReturn(true); 370 371 // start first scan 372 assertTrue(mScanner.startSingleScan(settings, eventHandler)); 373 374 expectSuccessfulSingleScan(order, eventHandler, 375 expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ), 376 new HashSet<String>(), 377 ScanResults.create(0, isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ), 378 2400, 2450, 2450), false); 379 380 // start second scan 381 assertTrue(mScanner.startSingleScan(settings2, eventHandler)); 382 383 expectSuccessfulSingleScan(order, eventHandler, 384 expectedBandScanFreqs(WifiScanner.WIFI_BAND_BOTH_WITH_DFS), 385 new HashSet<String>(), 386 ScanResults.create(0, true, 387 5150, 5175), false); 388 389 verifyNoMoreInteractions(eventHandler); 390 } 391 392 /** 393 * Validate that scan results that are returned from wificond, which are timestamped prior to 394 * the start of the scan, are ignored. 395 */ 396 @Test 397 public void singleScanWhereSupplicantReturnsSomeOldResults() { 398 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 399 .withBasePeriod(10000) 400 .withMaxApPerScan(2) 401 .addBucketWithBand(10000, 402 WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN 403 | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, 404 WifiScanner.WIFI_BAND_24_GHZ) 405 .build(); 406 407 long approxScanStartUs = mClock.getElapsedSinceBootMillis() * 1000; 408 ArrayList<ScanDetail> rawResults = new ArrayList<>(Arrays.asList( 409 new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 1"), 410 "00:00:00:00:00:00", "", -70, 2450, 411 approxScanStartUs + 2000 * 1000, 0), 412 new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 2"), 413 "AA:BB:CC:DD:EE:FF", "", -66, 2400, 414 approxScanStartUs + 2500 * 1000, 0), 415 new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 3"), 416 "00:00:00:00:00:00", "", -80, 2450, 417 approxScanStartUs - 2000 * 1000, 0), // old result will be filtered 418 new ScanDetail(WifiSsid.createFromAsciiEncoded("TEST AP 4"), 419 "AA:BB:CC:11:22:33", "", -65, 2450, 420 approxScanStartUs + 4000 * 1000, 0))); 421 422 ArrayList<ScanResult> fullResults = new ArrayList<>(); 423 for (ScanDetail detail : rawResults) { 424 if (detail.getScanResult().timestamp > approxScanStartUs) { 425 fullResults.add(detail.getScanResult()); 426 } 427 } 428 ArrayList<ScanResult> scanDataResults = new ArrayList<>(fullResults); 429 Collections.sort(scanDataResults, ScanResults.SCAN_RESULT_RSSI_COMPARATOR); 430 ScanData scanData = new ScanData(0, 0, 0, 431 isAllChannelsScanned(WifiScanner.WIFI_BAND_24_GHZ), 432 scanDataResults.toArray(new ScanResult[scanDataResults.size()])); 433 Set<Integer> expectedScan = expectedBandScanFreqs(WifiScanner.WIFI_BAND_24_GHZ); 434 435 // Actual test 436 437 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 438 439 InOrder order = inOrder(eventHandler, mWifiNative); 440 441 // scan succeeds 442 when(mWifiNative.scan(any(), any(Set.class))).thenReturn(true); 443 444 // start scan 445 assertTrue(mScanner.startSingleScan(settings, eventHandler)); 446 447 order.verify(mWifiNative).scan(eq(expectedScan), any(Set.class)); 448 449 when(mWifiNative.getScanResults()).thenReturn(rawResults); 450 451 // Notify scan has finished 452 mWifiMonitor.sendMessage(mWifiNative.getInterfaceName(), WifiMonitor.SCAN_RESULTS_EVENT); 453 454 mLooper.dispatchAll(); 455 456 for (ScanResult result : fullResults) { 457 order.verify(eventHandler).onFullScanResult(eq(result), eq(0)); 458 } 459 460 order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); 461 assertScanDataEquals(scanData, mScanner.getLatestSingleScanResults()); 462 463 verifyNoMoreInteractions(eventHandler); 464 } 465 466 @Test 467 public void backgroundScanNullEventHandler() { 468 WifiNative.ScanSettings settings = new NativeScanSettingsBuilder() 469 .withBasePeriod(10000) 470 .withMaxApPerScan(10) 471 .addBucketWithBand(10000, WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN, 472 WifiScanner.WIFI_BAND_24_GHZ) 473 .build(); 474 assertFalse(mScanner.startBatchedScan(settings, null)); 475 } 476 477 @Test 478 public void backgroundScanNullSettings() { 479 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 480 481 assertFalse(mScanner.startBatchedScan(null, eventHandler)); 482 483 verifyNoMoreInteractions(eventHandler); 484 } 485 486 protected void doSuccessfulSingleScanTest(WifiNative.ScanSettings settings, 487 Set<Integer> expectedScan, Set<String> expectedHiddenNetSSIDs, ScanResults results, 488 boolean expectFullResults) { 489 WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class); 490 491 InOrder order = inOrder(eventHandler, mWifiNative); 492 493 // scan succeeds 494 when(mWifiNative.scan(any(), any(Set.class))).thenReturn(true); 495 496 // start scan 497 assertTrue(mScanner.startSingleScan(settings, eventHandler)); 498 499 expectSuccessfulSingleScan(order, eventHandler, expectedScan, expectedHiddenNetSSIDs, 500 results, expectFullResults); 501 502 verifyNoMoreInteractions(eventHandler); 503 } 504 505 protected void expectSuccessfulSingleScan(InOrder order, 506 WifiNative.ScanEventHandler eventHandler, Set<Integer> expectedScan, 507 Set<String> expectedHiddenNetSSIDs, ScanResults results, boolean expectFullResults) { 508 order.verify(mWifiNative).scan(eq(expectedScan), eq(expectedHiddenNetSSIDs)); 509 510 when(mWifiNative.getScanResults()).thenReturn(results.getScanDetailArrayList()); 511 512 // Notify scan has finished 513 mWifiMonitor.sendMessage(mWifiNative.getInterfaceName(), WifiMonitor.SCAN_RESULTS_EVENT); 514 515 mLooper.dispatchAll(); 516 517 if (expectFullResults) { 518 for (ScanResult result : results.getRawScanResults()) { 519 order.verify(eventHandler).onFullScanResult(eq(result), eq(0)); 520 } 521 } 522 523 order.verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE); 524 assertScanDataEquals(results.getScanData(), mScanner.getLatestSingleScanResults()); 525 } 526 } 527