1 /* 2 * Copyright (C) 2016 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 android.net.wifi; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.mockito.ArgumentMatchers.eq; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.spy; 28 import static org.mockito.Mockito.times; 29 import static org.mockito.Mockito.validateMockitoUsage; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.content.Context; 34 import android.net.wifi.WifiScanner.PnoSettings; 35 import android.net.wifi.WifiScanner.PnoSettings.PnoNetwork; 36 import android.net.wifi.WifiScanner.ScanData; 37 import android.net.wifi.WifiScanner.ScanSettings; 38 import android.os.Bundle; 39 import android.os.Handler; 40 import android.os.Message; 41 import android.os.Messenger; 42 import android.os.Parcel; 43 import android.os.test.TestLooper; 44 45 import androidx.test.filters.SmallTest; 46 47 import com.android.internal.util.test.BidirectionalAsyncChannelServer; 48 49 import org.junit.After; 50 import org.junit.Before; 51 import org.junit.Test; 52 import org.mockito.ArgumentCaptor; 53 import org.mockito.Mock; 54 import org.mockito.MockitoAnnotations; 55 56 import java.util.Arrays; 57 58 /** 59 * Unit tests for {@link android.net.wifi.WifiScanner}. 60 */ 61 @SmallTest 62 public class WifiScannerTest { 63 @Mock 64 private Context mContext; 65 @Mock 66 private IWifiScanner mService; 67 68 private static final boolean TEST_PNOSETTINGS_IS_CONNECTED = false; 69 private static final int TEST_PNOSETTINGS_MIN_5GHZ_RSSI = -60; 70 private static final int TEST_PNOSETTINGS_MIN_2GHZ_RSSI = -70; 71 private static final int TEST_PNOSETTINGS_INITIAL_SCORE_MAX = 50; 72 private static final int TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS = 10; 73 private static final int TEST_PNOSETTINGS_SAME_NETWORK_BONUS = 11; 74 private static final int TEST_PNOSETTINGS_SECURE_BONUS = 12; 75 private static final int TEST_PNOSETTINGS_BAND_5GHZ_BONUS = 13; 76 private static final String TEST_SSID_1 = "TEST1"; 77 private static final String TEST_SSID_2 = "TEST2"; 78 private static final int[] TEST_FREQUENCIES_1 = {}; 79 private static final int[] TEST_FREQUENCIES_2 = {2500, 5124}; 80 81 private WifiScanner mWifiScanner; 82 private TestLooper mLooper; 83 private Handler mHandler; 84 private BidirectionalAsyncChannelServer mBidirectionalAsyncChannelServer; 85 86 /** 87 * Setup before tests. 88 */ 89 @Before setUp()90 public void setUp() throws Exception { 91 MockitoAnnotations.initMocks(this); 92 mLooper = new TestLooper(); 93 mHandler = spy(new Handler(mLooper.getLooper())); 94 mBidirectionalAsyncChannelServer = new BidirectionalAsyncChannelServer( 95 mContext, mLooper.getLooper(), mHandler); 96 when(mService.getMessenger()).thenReturn(mBidirectionalAsyncChannelServer.getMessenger()); 97 mWifiScanner = new WifiScanner(mContext, mService, mLooper.getLooper()); 98 mLooper.dispatchAll(); 99 } 100 101 /** 102 * Clean up after tests. 103 */ 104 @After cleanup()105 public void cleanup() { 106 validateMockitoUsage(); 107 } 108 109 /** 110 * Verify parcel read/write for ScanSettings. 111 */ 112 @Test verifyScanSettingsParcelWithBand()113 public void verifyScanSettingsParcelWithBand() throws Exception { 114 ScanSettings writeSettings = new ScanSettings(); 115 writeSettings.type = WifiScanner.TYPE_LOW_POWER; 116 writeSettings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS; 117 118 ScanSettings readSettings = parcelWriteRead(writeSettings); 119 assertEquals(readSettings.type, writeSettings.type); 120 assertEquals(readSettings.band, writeSettings.band); 121 assertEquals(0, readSettings.channels.length); 122 } 123 124 /** 125 * Verify parcel read/write for ScanSettings. 126 */ 127 @Test verifyScanSettingsParcelWithChannels()128 public void verifyScanSettingsParcelWithChannels() throws Exception { 129 ScanSettings writeSettings = new ScanSettings(); 130 writeSettings.type = WifiScanner.TYPE_HIGH_ACCURACY; 131 writeSettings.band = WifiScanner.WIFI_BAND_UNSPECIFIED; 132 writeSettings.channels = new WifiScanner.ChannelSpec[] { 133 new WifiScanner.ChannelSpec(5), 134 new WifiScanner.ChannelSpec(7) 135 }; 136 137 ScanSettings readSettings = parcelWriteRead(writeSettings); 138 assertEquals(writeSettings.type, readSettings.type); 139 assertEquals(writeSettings.band, readSettings.band); 140 assertEquals(2, readSettings.channels.length); 141 assertEquals(5, readSettings.channels[0].frequency); 142 assertEquals(7, readSettings.channels[1].frequency); 143 } 144 145 /** 146 * Write the provided {@link ScanSettings} to a parcel and deserialize it. 147 */ parcelWriteRead(ScanSettings writeSettings)148 private static ScanSettings parcelWriteRead(ScanSettings writeSettings) throws Exception { 149 Parcel parcel = Parcel.obtain(); 150 writeSettings.writeToParcel(parcel, 0); 151 parcel.setDataPosition(0); // Rewind data position back to the beginning for read. 152 return ScanSettings.CREATOR.createFromParcel(parcel); 153 } 154 155 /** 156 * PnoSettings object can be serialized and deserialized, while keeping the 157 * values unchanged. 158 */ 159 @Test canSerializeAndDeserializePnoSettings()160 public void canSerializeAndDeserializePnoSettings() throws Exception { 161 162 PnoSettings pnoSettings = new PnoSettings(); 163 164 PnoNetwork pnoNetwork1 = new PnoNetwork(TEST_SSID_1); 165 PnoNetwork pnoNetwork2 = new PnoNetwork(TEST_SSID_2); 166 pnoNetwork1.frequencies = TEST_FREQUENCIES_1; 167 pnoNetwork2.frequencies = TEST_FREQUENCIES_2; 168 169 pnoSettings.networkList = new PnoNetwork[]{pnoNetwork1, pnoNetwork2}; 170 pnoSettings.isConnected = TEST_PNOSETTINGS_IS_CONNECTED; 171 pnoSettings.min5GHzRssi = TEST_PNOSETTINGS_MIN_5GHZ_RSSI; 172 pnoSettings.min24GHzRssi = TEST_PNOSETTINGS_MIN_2GHZ_RSSI; 173 pnoSettings.initialScoreMax = TEST_PNOSETTINGS_INITIAL_SCORE_MAX; 174 pnoSettings.currentConnectionBonus = TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS; 175 pnoSettings.sameNetworkBonus = TEST_PNOSETTINGS_SAME_NETWORK_BONUS; 176 pnoSettings.secureBonus = TEST_PNOSETTINGS_SECURE_BONUS; 177 pnoSettings.band5GHzBonus = TEST_PNOSETTINGS_BAND_5GHZ_BONUS; 178 179 Parcel parcel = Parcel.obtain(); 180 pnoSettings.writeToParcel(parcel, 0); 181 // Rewind the pointer to the head of the parcel. 182 parcel.setDataPosition(0); 183 PnoSettings pnoSettingsDeserialized = 184 pnoSettings.CREATOR.createFromParcel(parcel); 185 186 assertNotNull(pnoSettingsDeserialized); 187 assertEquals(TEST_PNOSETTINGS_IS_CONNECTED, pnoSettingsDeserialized.isConnected); 188 assertEquals(TEST_PNOSETTINGS_MIN_5GHZ_RSSI, pnoSettingsDeserialized.min5GHzRssi); 189 assertEquals(TEST_PNOSETTINGS_MIN_2GHZ_RSSI, pnoSettingsDeserialized.min24GHzRssi); 190 assertEquals(TEST_PNOSETTINGS_INITIAL_SCORE_MAX, pnoSettingsDeserialized.initialScoreMax); 191 assertEquals(TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS, 192 pnoSettingsDeserialized.currentConnectionBonus); 193 assertEquals(TEST_PNOSETTINGS_SAME_NETWORK_BONUS, 194 pnoSettingsDeserialized.sameNetworkBonus); 195 assertEquals(TEST_PNOSETTINGS_SECURE_BONUS, pnoSettingsDeserialized.secureBonus); 196 assertEquals(TEST_PNOSETTINGS_BAND_5GHZ_BONUS, pnoSettingsDeserialized.band5GHzBonus); 197 198 // Test parsing of PnoNetwork 199 assertEquals(pnoSettings.networkList.length, pnoSettingsDeserialized.networkList.length); 200 for (int i = 0; i < pnoSettings.networkList.length; i++) { 201 PnoNetwork expected = pnoSettings.networkList[i]; 202 PnoNetwork actual = pnoSettingsDeserialized.networkList[i]; 203 assertEquals(expected.ssid, actual.ssid); 204 assertEquals(expected.flags, actual.flags); 205 assertEquals(expected.authBitField, actual.authBitField); 206 assertTrue(Arrays.equals(expected.frequencies, actual.frequencies)); 207 } 208 } 209 210 /** 211 * Make sure that frequencies is not null by default. 212 */ 213 @Test pnoNetworkFrequencyIsNotNull()214 public void pnoNetworkFrequencyIsNotNull() throws Exception { 215 PnoNetwork pnoNetwork = new PnoNetwork(TEST_SSID_1); 216 assertNotNull(pnoNetwork.frequencies); 217 } 218 219 /** 220 * Verify parcel read/write for ScanData. 221 */ 222 @Test verifyScanDataParcel()223 public void verifyScanDataParcel() throws Exception { 224 ScanData writeScanData = new ScanData(2, 0, 3, 225 WifiScanner.WIFI_BAND_BOTH_WITH_DFS, new ScanResult[0]); 226 227 ScanData readScanData = parcelWriteRead(writeScanData); 228 assertEquals(writeScanData.getId(), readScanData.getId()); 229 assertEquals(writeScanData.getFlags(), readScanData.getFlags()); 230 assertEquals(writeScanData.getBucketsScanned(), readScanData.getBucketsScanned()); 231 assertEquals(writeScanData.getBandScanned(), readScanData.getBandScanned()); 232 assertArrayEquals(writeScanData.getResults(), readScanData.getResults()); 233 } 234 235 /** 236 * Write the provided {@link ScanData} to a parcel and deserialize it. 237 */ parcelWriteRead(ScanData writeScanData)238 private static ScanData parcelWriteRead(ScanData writeScanData) throws Exception { 239 Parcel parcel = Parcel.obtain(); 240 writeScanData.writeToParcel(parcel, 0); 241 parcel.setDataPosition(0); // Rewind data position back to the beginning for read. 242 return ScanData.CREATOR.createFromParcel(parcel); 243 } 244 245 246 /** 247 * Test behavior of {@link WifiScanner#startScan(ScanSettings, WifiScanner.ScanListener)} 248 * @throws Exception 249 */ 250 @Test testStartScan()251 public void testStartScan() throws Exception { 252 ScanSettings scanSettings = new ScanSettings(); 253 WifiScanner.ScanListener scanListener = mock(WifiScanner.ScanListener.class); 254 255 mWifiScanner.startScan(scanSettings, scanListener); 256 mLooper.dispatchAll(); 257 258 ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 259 verify(mHandler).handleMessage(messageArgumentCaptor.capture()); 260 Message message = messageArgumentCaptor.getValue(); 261 assertNotNull(message); 262 263 assertEquals(WifiScanner.CMD_START_SINGLE_SCAN, message.what); 264 assertTrue(message.obj instanceof Bundle); 265 Bundle messageBundle = (Bundle) message.obj; 266 assertEquals(scanSettings, 267 messageBundle.getParcelable(WifiScanner.SCAN_PARAMS_SCAN_SETTINGS_KEY)); 268 assertNull(messageBundle.getParcelable(WifiScanner.SCAN_PARAMS_WORK_SOURCE_KEY)); 269 assertEquals(mContext.getOpPackageName(), 270 messageBundle.getParcelable(WifiScanner.REQUEST_PACKAGE_NAME_KEY)); 271 272 } 273 274 /** 275 * Test behavior of {@link WifiScanner#stopScan(WifiScanner.ScanListener)} 276 * @throws Exception 277 */ 278 @Test testStopScan()279 public void testStopScan() throws Exception { 280 ScanSettings scanSettings = new ScanSettings(); 281 WifiScanner.ScanListener scanListener = mock(WifiScanner.ScanListener.class); 282 283 mWifiScanner.startScan(scanSettings, scanListener); 284 mLooper.dispatchAll(); 285 286 mWifiScanner.stopScan(scanListener); 287 mLooper.dispatchAll(); 288 289 ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 290 verify(mHandler, times(2)).handleMessage(messageArgumentCaptor.capture()); 291 Message message = messageArgumentCaptor.getValue(); 292 assertNotNull(message); 293 294 assertEquals(WifiScanner.CMD_STOP_SINGLE_SCAN, message.what); 295 assertTrue(message.obj instanceof Bundle); 296 Bundle messageBundle = (Bundle) message.obj; 297 assertEquals(mContext.getOpPackageName(), 298 messageBundle.getParcelable(WifiScanner.REQUEST_PACKAGE_NAME_KEY)); 299 300 } 301 302 /** 303 * Test behavior of {@link WifiScanner#startScan(ScanSettings, WifiScanner.ScanListener)} 304 * @throws Exception 305 */ 306 @Test testStartScanListenerOnSuccess()307 public void testStartScanListenerOnSuccess() throws Exception { 308 ScanSettings scanSettings = new ScanSettings(); 309 WifiScanner.ScanListener scanListener = mock(WifiScanner.ScanListener.class); 310 311 mWifiScanner.startScan(scanSettings, scanListener); 312 mLooper.dispatchAll(); 313 314 ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 315 verify(mHandler).handleMessage(messageArgumentCaptor.capture()); 316 Message sentMessage = messageArgumentCaptor.getValue(); 317 assertNotNull(sentMessage); 318 319 assertEquals(1, mBidirectionalAsyncChannelServer.getClientMessengers().size()); 320 Messenger scannerMessenger = 321 mBidirectionalAsyncChannelServer.getClientMessengers().iterator().next(); 322 323 Message responseMessage = Message.obtain(); 324 responseMessage.what = WifiScanner.CMD_OP_SUCCEEDED; 325 responseMessage.arg2 = sentMessage.arg2; 326 scannerMessenger.send(responseMessage); 327 mLooper.dispatchAll(); 328 329 verify(scanListener).onSuccess(); 330 } 331 332 /** 333 * Test behavior of {@link WifiScanner#startScan(ScanSettings, WifiScanner.ScanListener)} 334 * @throws Exception 335 */ 336 @Test testStartScanListenerOnResults()337 public void testStartScanListenerOnResults() throws Exception { 338 ScanSettings scanSettings = new ScanSettings(); 339 WifiScanner.ScanListener scanListener = mock(WifiScanner.ScanListener.class); 340 341 mWifiScanner.startScan(scanSettings, scanListener); 342 mLooper.dispatchAll(); 343 344 ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 345 verify(mHandler).handleMessage(messageArgumentCaptor.capture()); 346 Message sentMessage = messageArgumentCaptor.getValue(); 347 assertNotNull(sentMessage); 348 349 assertEquals(1, mBidirectionalAsyncChannelServer.getClientMessengers().size()); 350 Messenger scannerMessenger = 351 mBidirectionalAsyncChannelServer.getClientMessengers().iterator().next(); 352 353 ScanResult scanResult = new ScanResult(); 354 ScanData scanDatas[] = new ScanData[]{new ScanData(0, 0 , new ScanResult[] {scanResult})}; 355 Message responseMessage = Message.obtain(); 356 responseMessage.what = WifiScanner.CMD_SCAN_RESULT; 357 responseMessage.arg2 = sentMessage.arg2; 358 responseMessage.obj = new WifiScanner.ParcelableScanData(scanDatas); 359 scannerMessenger.send(responseMessage); 360 mLooper.dispatchAll(); 361 362 verify(scanListener).onResults(scanDatas); 363 } 364 365 /** 366 * Test behavior of {@link WifiScanner#startDisconnectedPnoScan(ScanSettings, PnoSettings, 367 * WifiScanner.PnoScanListener)} 368 * @throws Exception 369 */ 370 @Test testStartDisconnectedPnoScan()371 public void testStartDisconnectedPnoScan() throws Exception { 372 ScanSettings scanSettings = new ScanSettings(); 373 PnoSettings pnoSettings = new PnoSettings(); 374 WifiScanner.PnoScanListener pnoScanListener = mock(WifiScanner.PnoScanListener.class); 375 376 mWifiScanner.startDisconnectedPnoScan(scanSettings, pnoSettings, pnoScanListener); 377 mLooper.dispatchAll(); 378 379 ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 380 verify(mHandler).handleMessage(messageArgumentCaptor.capture()); 381 Message message = messageArgumentCaptor.getValue(); 382 assertNotNull(message); 383 384 assertEquals(WifiScanner.CMD_START_PNO_SCAN, message.what); 385 assertTrue(message.obj instanceof Bundle); 386 Bundle messageBundle = (Bundle) message.obj; 387 assertEquals(scanSettings, 388 messageBundle.getParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY)); 389 assertTrue(scanSettings.isPnoScan); 390 assertFalse(pnoSettings.isConnected); 391 assertEquals(pnoSettings, 392 messageBundle.getParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY)); 393 } 394 395 /** 396 * Test behavior of {@link WifiScanner#startConnectedPnoScan(ScanSettings, PnoSettings, 397 * WifiScanner.PnoScanListener)} 398 * @throws Exception 399 */ 400 @Test testStartConnectedPnoScan()401 public void testStartConnectedPnoScan() throws Exception { 402 ScanSettings scanSettings = new ScanSettings(); 403 PnoSettings pnoSettings = new PnoSettings(); 404 WifiScanner.PnoScanListener pnoScanListener = mock(WifiScanner.PnoScanListener.class); 405 406 mWifiScanner.startConnectedPnoScan(scanSettings, pnoSettings, pnoScanListener); 407 mLooper.dispatchAll(); 408 409 ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 410 verify(mHandler).handleMessage(messageArgumentCaptor.capture()); 411 Message message = messageArgumentCaptor.getValue(); 412 assertNotNull(message); 413 414 assertEquals(WifiScanner.CMD_START_PNO_SCAN, message.what); 415 assertTrue(message.obj instanceof Bundle); 416 Bundle messageBundle = (Bundle) message.obj; 417 assertEquals(scanSettings, 418 messageBundle.getParcelable(WifiScanner.PNO_PARAMS_SCAN_SETTINGS_KEY)); 419 assertTrue(scanSettings.isPnoScan); 420 assertTrue(pnoSettings.isConnected); 421 assertEquals(pnoSettings, 422 messageBundle.getParcelable(WifiScanner.PNO_PARAMS_PNO_SETTINGS_KEY)); 423 } 424 425 /** 426 * Test behavior of {@link WifiScanner#stopPnoScan(WifiScanner.ScanListener)} 427 * WifiScanner.PnoScanListener)} 428 * @throws Exception 429 */ 430 @Test testStopPnoScan()431 public void testStopPnoScan() throws Exception { 432 ScanSettings scanSettings = new ScanSettings(); 433 PnoSettings pnoSettings = new PnoSettings(); 434 WifiScanner.PnoScanListener pnoScanListener = mock(WifiScanner.PnoScanListener.class); 435 436 mWifiScanner.startDisconnectedPnoScan(scanSettings, pnoSettings, pnoScanListener); 437 mLooper.dispatchAll(); 438 mWifiScanner.stopPnoScan(pnoScanListener); 439 mLooper.dispatchAll(); 440 441 ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 442 verify(mHandler, times(2)).handleMessage(messageArgumentCaptor.capture()); 443 Message message = messageArgumentCaptor.getValue(); 444 assertNotNull(message); 445 446 assertEquals(WifiScanner.CMD_STOP_PNO_SCAN, message.what); 447 } 448 } 449