1 /* 2 * Copyright (C) 2018 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 package android.carrierapi.cts; 17 18 import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION; 19 import static android.Manifest.permission.ACCESS_FINE_LOCATION; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertNotSame; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 27 import android.content.Context; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageManager; 30 import android.os.AsyncTask; 31 import android.os.Handler; 32 import android.os.HandlerThread; 33 import android.os.Message; 34 import android.os.Parcel; 35 import android.os.Process; 36 import android.provider.Settings; 37 import android.telephony.AccessNetworkConstants; 38 import android.telephony.CellInfo; 39 import android.telephony.CellInfoGsm; 40 import android.telephony.CellInfoLte; 41 import android.telephony.CellInfoWcdma; 42 import android.telephony.NetworkScan; 43 import android.telephony.NetworkScanRequest; 44 import android.telephony.RadioAccessSpecifier; 45 import android.telephony.TelephonyManager; 46 import android.telephony.TelephonyScanManager; 47 import android.util.Log; 48 49 import androidx.test.InstrumentationRegistry; 50 import androidx.test.runner.AndroidJUnit4; 51 52 import org.junit.After; 53 import org.junit.Before; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 57 import java.util.ArrayList; 58 import java.util.Arrays; 59 import java.util.List; 60 import java.util.stream.Collectors; 61 62 /** 63 * Build, install and run the tests by running the commands below: 64 * make cts -j64 65 * cts-tradefed run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.NetworkScanApiTest 66 */ 67 @RunWith(AndroidJUnit4.class) 68 public class NetworkScanApiTest { 69 private TelephonyManager mTelephonyManager; 70 private PackageManager mPackageManager; 71 private static final String TAG = "NetworkScanApiTest"; 72 private int mNetworkScanStatus; 73 private static final int EVENT_NETWORK_SCAN_START = 100; 74 private static final int EVENT_NETWORK_SCAN_RESULTS = 200; 75 private static final int EVENT_NETWORK_SCAN_RESTRICTED_RESULTS = 201; 76 private static final int EVENT_NETWORK_SCAN_ERROR = 300; 77 private static final int EVENT_NETWORK_SCAN_COMPLETED = 400; 78 private static final int EVENT_SCAN_DENIED = 500; 79 private List<CellInfo> mScanResults = null; 80 private NetworkScanHandlerThread mTestHandlerThread; 81 private Handler mHandler; 82 private NetworkScan mNetworkScan; 83 private NetworkScanRequest mNetworkScanRequest; 84 private NetworkScanCallbackImpl mNetworkScanCallback; 85 private static final int MAX_CELLINFO_WAIT_MILLIS = 5000; // 5 seconds 86 private static final int SCAN_SEARCH_TIME_SECONDS = 60; 87 // Wait one second longer than the max scan search time to give the test time to receive the 88 // results. 89 private static final int MAX_INIT_WAIT_MS = (SCAN_SEARCH_TIME_SECONDS + 1) * 1000; 90 private Object mLock = new Object(); 91 private boolean mReady; 92 private int mErrorCode; 93 /* All the following constants are used to construct NetworkScanRequest*/ 94 private static final int SCAN_TYPE = NetworkScanRequest.SCAN_TYPE_ONE_SHOT; 95 private static final boolean INCREMENTAL_RESULTS = true; 96 private static final int SEARCH_PERIODICITY_SEC = 5; 97 private static final int MAX_SEARCH_TIME_SEC = 300; 98 private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3; 99 private static final ArrayList<String> MCC_MNC = new ArrayList<>(); 100 private static final RadioAccessSpecifier[] RADIO_ACCESS_SPECIFIERS = { 101 new RadioAccessSpecifier( 102 AccessNetworkConstants.AccessNetworkType.GERAN, 103 null /* bands */, 104 null /* channels */), 105 new RadioAccessSpecifier( 106 AccessNetworkConstants.AccessNetworkType.EUTRAN, 107 null /* bands */, 108 null /* channels */), 109 new RadioAccessSpecifier( 110 AccessNetworkConstants.AccessNetworkType.UTRAN, 111 null /* bands */, 112 null /* channels */) 113 }; 114 115 // Needed because NETWORK_SCAN_PERMISSION is a systemapi 116 public static final String NETWORK_SCAN_PERMISSION = "android.permission.NETWORK_SCAN"; 117 118 @Before setUp()119 public void setUp() throws Exception { 120 Context context = InstrumentationRegistry.getContext(); 121 mTelephonyManager = (TelephonyManager) 122 context.getSystemService(Context.TELEPHONY_SERVICE); 123 mPackageManager = context.getPackageManager(); 124 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 125 context.getPackageName(), ACCESS_FINE_LOCATION); 126 InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission( 127 context.getPackageName(), ACCESS_BACKGROUND_LOCATION); 128 mTestHandlerThread = new NetworkScanHandlerThread(TAG); 129 mTestHandlerThread.start(); 130 } 131 132 @After tearDown()133 public void tearDown() throws Exception { 134 mTestHandlerThread.quit(); 135 } 136 waitUntilReady()137 private void waitUntilReady() { 138 synchronized (mLock) { 139 try { 140 mLock.wait(MAX_INIT_WAIT_MS); 141 } catch (InterruptedException ie) { 142 } 143 144 if (!mReady) { 145 fail("NetworkScanApiTest failed to initialize"); 146 } 147 } 148 } 149 setReady(boolean ready)150 private void setReady(boolean ready) { 151 synchronized (mLock) { 152 mReady = ready; 153 mLock.notifyAll(); 154 } 155 } 156 157 private class NetworkScanHandlerThread extends HandlerThread { 158 NetworkScanHandlerThread(String name)159 public NetworkScanHandlerThread(String name) { 160 super(name); 161 } 162 163 @Override onLooperPrepared()164 public void onLooperPrepared() { 165 /* create a custom handler for the Handler Thread */ 166 mHandler = new Handler(mTestHandlerThread.getLooper()) { 167 @Override 168 public void handleMessage(Message msg) { 169 switch (msg.what) { 170 case EVENT_NETWORK_SCAN_START: 171 Log.d(TAG, "request network scan"); 172 boolean useShellIdentity = (Boolean) msg.obj; 173 if (useShellIdentity) { 174 InstrumentationRegistry.getInstrumentation().getUiAutomation() 175 .adoptShellPermissionIdentity(); 176 } 177 try { 178 mNetworkScan = mTelephonyManager.requestNetworkScan( 179 mNetworkScanRequest, 180 AsyncTask.SERIAL_EXECUTOR, 181 mNetworkScanCallback); 182 if (mNetworkScan == null) { 183 mNetworkScanStatus = EVENT_SCAN_DENIED; 184 setReady(true); 185 } 186 } catch (SecurityException e) { 187 mNetworkScanStatus = EVENT_SCAN_DENIED; 188 setReady(true); 189 } finally { 190 if (useShellIdentity) { 191 InstrumentationRegistry.getInstrumentation().getUiAutomation() 192 .dropShellPermissionIdentity(); 193 } 194 } 195 break; 196 default: 197 Log.d(TAG, "Unknown Event " + msg.what); 198 } 199 } 200 }; 201 } 202 } 203 204 private class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback { 205 @Override onResults(List<CellInfo> results)206 public void onResults(List<CellInfo> results) { 207 Log.d(TAG, "onResults: " + results.toString()); 208 mNetworkScanStatus = EVENT_NETWORK_SCAN_RESULTS; 209 mScanResults = results; 210 } 211 212 @Override onComplete()213 public void onComplete() { 214 Log.d(TAG, "onComplete"); 215 mNetworkScanStatus = EVENT_NETWORK_SCAN_COMPLETED; 216 setReady(true); 217 } 218 219 @Override onError(int error)220 public void onError(int error) { 221 Log.d(TAG, "onError: " + String.valueOf(error)); 222 mNetworkScanStatus = EVENT_NETWORK_SCAN_ERROR; 223 mErrorCode = error; 224 setReady(true); 225 } 226 } 227 228 private class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback { 229 public List<CellInfo> cellInfo; 230 231 @Override onCellInfo(List<CellInfo> cellInfo)232 public synchronized void onCellInfo(List<CellInfo> cellInfo) { 233 this.cellInfo = cellInfo; 234 notifyAll(); 235 } 236 wait(int millis)237 public synchronized void wait(int millis) throws InterruptedException { 238 if (cellInfo == null) { 239 super.wait(millis); 240 } 241 } 242 } 243 getRadioAccessSpecifier(List<CellInfo> allCellInfo)244 private List<RadioAccessSpecifier> getRadioAccessSpecifier(List<CellInfo> allCellInfo) { 245 List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>(); 246 List<Integer> lteChannels = new ArrayList<>(); 247 List<Integer> wcdmaChannels = new ArrayList<>(); 248 List<Integer> gsmChannels = new ArrayList<>(); 249 for (int i = 0; i < allCellInfo.size(); i++) { 250 CellInfo cellInfo = allCellInfo.get(i); 251 if (cellInfo instanceof CellInfoLte) { 252 lteChannels.add(((CellInfoLte) cellInfo).getCellIdentity().getEarfcn()); 253 } else if (cellInfo instanceof CellInfoWcdma) { 254 wcdmaChannels.add(((CellInfoWcdma) cellInfo).getCellIdentity().getUarfcn()); 255 } else if (cellInfo instanceof CellInfoGsm) { 256 gsmChannels.add(((CellInfoGsm) cellInfo).getCellIdentity().getArfcn()); 257 } 258 } 259 if (!lteChannels.isEmpty()) { 260 Log.d(TAG, "lte channels" + lteChannels.toString()); 261 int ranLte = AccessNetworkConstants.AccessNetworkType.EUTRAN; 262 radioAccessSpecifier.add( 263 new RadioAccessSpecifier(ranLte, null /* bands */, 264 lteChannels.stream().mapToInt(i->i).toArray())); 265 } 266 if (!wcdmaChannels.isEmpty()) { 267 Log.d(TAG, "wcdma channels" + wcdmaChannels.toString()); 268 int ranWcdma = AccessNetworkConstants.AccessNetworkType.UTRAN; 269 radioAccessSpecifier.add( 270 new RadioAccessSpecifier(ranWcdma, null /* bands */, 271 wcdmaChannels.stream().mapToInt(i->i).toArray())); 272 } 273 if (!gsmChannels.isEmpty()) { 274 Log.d(TAG, "gsm channels" + gsmChannels.toString()); 275 int ranGsm = AccessNetworkConstants.AccessNetworkType.GERAN; 276 radioAccessSpecifier.add( 277 new RadioAccessSpecifier(ranGsm, null /* bands */, 278 gsmChannels.stream().mapToInt(i->i).toArray())); 279 } 280 return radioAccessSpecifier; 281 } 282 283 /** 284 * Tests that the device properly requests a network scan. 285 */ 286 @Test testRequestNetworkScan()287 public void testRequestNetworkScan() { 288 if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { 289 // Checks whether the cellular stack should be running on this device. 290 Log.e(TAG, "No cellular support, the test will be skipped."); 291 return; 292 } 293 if (!mTelephonyManager.hasCarrierPrivileges()) { 294 fail("This test requires a SIM card with carrier privilege rule on it."); 295 } 296 boolean isLocationSwitchOn = getAndSetLocationSwitch(true); 297 try { 298 mNetworkScanRequest = buildNetworkScanRequest(true); 299 mNetworkScanCallback = new NetworkScanCallbackImpl(); 300 Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_START, false); 301 setReady(false); 302 startNetworkScan.sendToTarget(); 303 waitUntilReady(); 304 305 Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus); 306 assertTrue("The final scan status is " + mNetworkScanStatus + " with error code " 307 + mErrorCode + ", not ScanCompleted" 308 + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or" 309 + " ERROR_UNSUPPORTED", 310 isScanStatusValid()); 311 } finally { 312 getAndSetLocationSwitch(isLocationSwitchOn); 313 } 314 } 315 316 @Test testRequestNetworkScanLocationOffPass()317 public void testRequestNetworkScanLocationOffPass() { 318 requestNetworkScanLocationOffHelper(false, true); 319 } 320 321 @Test testRequestNetworkScanLocationOffFail()322 public void testRequestNetworkScanLocationOffFail() { 323 requestNetworkScanLocationOffHelper(true, true); 324 } 325 requestNetworkScanLocationOffHelper(boolean includeBandsAndChannels, boolean useSpecialScanPermission)326 public void requestNetworkScanLocationOffHelper(boolean includeBandsAndChannels, 327 boolean useSpecialScanPermission) { 328 if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { 329 // Checks whether the cellular stack should be running on this device. 330 Log.e(TAG, "No cellular support, the test will be skipped."); 331 return; 332 } 333 if (!mTelephonyManager.hasCarrierPrivileges()) { 334 fail("This test requires a SIM card with carrier privilege rule on it."); 335 } 336 337 mNetworkScanRequest = buildNetworkScanRequest(includeBandsAndChannels); 338 339 boolean isLocationSwitchOn = getAndSetLocationSwitch(false); 340 try { 341 mNetworkScanCallback = new NetworkScanCallbackImpl(); 342 Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_START, 343 useSpecialScanPermission); 344 setReady(false); 345 startNetworkScan.sendToTarget(); 346 waitUntilReady(); 347 if (includeBandsAndChannels) { 348 // If we included the bands when location is off, expect a security error and 349 // nothing else. 350 assertEquals(EVENT_SCAN_DENIED, mNetworkScanStatus); 351 return; 352 } 353 354 Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus); 355 assertTrue("The final scan status is " + mNetworkScanStatus + " with error code " 356 + mErrorCode + ", not ScanCompleted" 357 + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or" 358 + " ERROR_UNSUPPORTED", 359 isScanStatusValid()); 360 } finally { 361 getAndSetLocationSwitch(isLocationSwitchOn); 362 } 363 } 364 buildNetworkScanRequest(boolean includeBandsAndChannels)365 private NetworkScanRequest buildNetworkScanRequest(boolean includeBandsAndChannels) { 366 // Make sure that there should be at least one entry. 367 List<CellInfo> allCellInfo = getCellInfo(); 368 List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>(); 369 370 if (allCellInfo != null && allCellInfo.size() != 0) { 371 // Construct a NetworkScanRequest 372 radioAccessSpecifier = getRadioAccessSpecifier(allCellInfo); 373 if (!includeBandsAndChannels) { 374 radioAccessSpecifier = radioAccessSpecifier.stream().map(spec -> 375 new RadioAccessSpecifier(spec.getRadioAccessNetwork(), null, null)) 376 .collect(Collectors.toList()); 377 } 378 } 379 380 Log.d(TAG, "number of radioAccessSpecifier: " + radioAccessSpecifier.size()); 381 if (radioAccessSpecifier.isEmpty()) { 382 // Put in some arbitrary bands and channels so that we trip the location check if needed 383 int[] fakeBands = includeBandsAndChannels 384 ? new int[] { AccessNetworkConstants.EutranBand.BAND_5 } 385 : null; 386 int[] fakeChannels = includeBandsAndChannels ? new int[] { 2400 } : null; 387 388 RadioAccessSpecifier gsm = new RadioAccessSpecifier( 389 AccessNetworkConstants.AccessNetworkType.GERAN, 390 null /* bands */, 391 null /* channels */); 392 RadioAccessSpecifier lte = new RadioAccessSpecifier( 393 AccessNetworkConstants.AccessNetworkType.EUTRAN, 394 fakeBands /* bands */, 395 fakeChannels /* channels */); 396 RadioAccessSpecifier wcdma = new RadioAccessSpecifier( 397 AccessNetworkConstants.AccessNetworkType.UTRAN, 398 null /* bands */, 399 null /* channels */); 400 radioAccessSpecifier.add(gsm); 401 radioAccessSpecifier.add(lte); 402 radioAccessSpecifier.add(wcdma); 403 } 404 RadioAccessSpecifier[] radioAccessSpecifierArray = 405 new RadioAccessSpecifier[radioAccessSpecifier.size()]; 406 return new NetworkScanRequest( 407 NetworkScanRequest.SCAN_TYPE_ONE_SHOT /* scan type */, 408 radioAccessSpecifier.toArray(radioAccessSpecifierArray), 409 5 /* search periodicity */, 410 SCAN_SEARCH_TIME_SECONDS /* max search time */, 411 true /*enable incremental results*/, 412 5 /* incremental results periodicity */, 413 null /* List of PLMN ids (MCC-MNC) */); 414 415 } 416 getCellInfo()417 private List<CellInfo> getCellInfo() { 418 CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback(); 419 mTelephonyManager.requestCellInfoUpdate(r -> r.run(), resultsCallback); 420 try { 421 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 422 } catch (InterruptedException ex) { 423 fail("CellInfoCallback was interrupted: " + ex); 424 } 425 return resultsCallback.cellInfo; 426 } 427 428 @Test testNetworkScanPermission()429 public void testNetworkScanPermission() { 430 PackageManager pm = InstrumentationRegistry.getContext().getPackageManager(); 431 432 List<Integer> specialUids = Arrays.asList(Process.SYSTEM_UID, 433 Process.PHONE_UID, Process.SHELL_UID); 434 435 List<PackageInfo> holding = pm.getPackagesHoldingPermissions( 436 new String[] { NETWORK_SCAN_PERMISSION }, 437 PackageManager.MATCH_DISABLED_COMPONENTS); 438 439 List<Integer> nonSpecialPackages = holding.stream() 440 .map(pi -> { 441 try { 442 return pm.getPackageUid(pi.packageName, 0); 443 } catch (PackageManager.NameNotFoundException e) { 444 return Process.INVALID_UID; 445 } 446 }) 447 .filter(uid -> !specialUids.contains(uid)) 448 .collect(Collectors.toList()); 449 450 if (nonSpecialPackages.size() > 1) { 451 fail("Only one app on the device is allowed to hold the NETWORK_SCAN permission."); 452 } 453 } 454 getAndSetLocationSwitch(boolean enabled)455 private boolean getAndSetLocationSwitch(boolean enabled) { 456 InstrumentationRegistry.getInstrumentation().getUiAutomation() 457 .adoptShellPermissionIdentity(); 458 try { 459 int oldLocationMode = Settings.Secure.getInt( 460 InstrumentationRegistry.getContext().getContentResolver(), 461 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 462 463 int locationMode = enabled ? Settings.Secure.LOCATION_MODE_HIGH_ACCURACY 464 : Settings.Secure.LOCATION_MODE_OFF; 465 if (locationMode != oldLocationMode) { 466 Settings.Secure.putInt(InstrumentationRegistry.getContext().getContentResolver(), 467 Settings.Secure.LOCATION_MODE, locationMode); 468 } 469 return oldLocationMode == Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 470 } finally { 471 InstrumentationRegistry.getInstrumentation().getUiAutomation() 472 .dropShellPermissionIdentity(); 473 } 474 } 475 isScanStatusValid()476 private boolean isScanStatusValid() { 477 // TODO(b/72162885): test the size of ScanResults is not zero after the blocking bug fixed. 478 if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_COMPLETED) && (mScanResults != null)) { 479 // Scan complete. 480 return true; 481 } 482 if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_ERROR) 483 && ((mErrorCode == NetworkScan.ERROR_MODEM_UNAVAILABLE) 484 || (mErrorCode == NetworkScan.ERROR_UNSUPPORTED))) { 485 // Scan error but the error type is allowed. 486 return true; 487 } 488 return false; 489 } 490 getPlmns()491 private ArrayList<String> getPlmns() { 492 ArrayList<String> mccMncs = new ArrayList<>(); 493 mccMncs.add("310260"); 494 mccMncs.add("310120"); 495 return mccMncs; 496 } 497 498 /** 499 * To test its constructor and getters. 500 */ 501 @Test testNetworkScanRequest_ConstructorAndGetters()502 public void testNetworkScanRequest_ConstructorAndGetters() { 503 NetworkScanRequest networkScanRequest = new NetworkScanRequest( 504 SCAN_TYPE, 505 RADIO_ACCESS_SPECIFIERS, 506 SEARCH_PERIODICITY_SEC, 507 MAX_SEARCH_TIME_SEC, 508 INCREMENTAL_RESULTS, 509 INCREMENTAL_RESULTS_PERIODICITY_SEC, 510 getPlmns()); 511 512 assertEquals("getScanType() returns wrong value", 513 SCAN_TYPE, networkScanRequest.getScanType()); 514 assertEquals("getSpecifiers() returns wrong value", 515 RADIO_ACCESS_SPECIFIERS, networkScanRequest.getSpecifiers()); 516 assertEquals("getSearchPeriodicity() returns wrong value", 517 SEARCH_PERIODICITY_SEC, networkScanRequest.getSearchPeriodicity()); 518 assertEquals("getMaxSearchTime() returns wrong value", 519 MAX_SEARCH_TIME_SEC, networkScanRequest.getMaxSearchTime()); 520 assertEquals("getIncrementalResults() returns wrong value", 521 INCREMENTAL_RESULTS, networkScanRequest.getIncrementalResults()); 522 assertEquals("getIncrementalResultsPeriodicity() returns wrong value", 523 INCREMENTAL_RESULTS_PERIODICITY_SEC, 524 networkScanRequest.getIncrementalResultsPeriodicity()); 525 assertEquals("getPlmns() returns wrong value", getPlmns(), networkScanRequest.getPlmns()); 526 assertEquals("describeContents() returns wrong value", 527 0, networkScanRequest.describeContents()); 528 } 529 530 /** 531 * To test its hashCode method. 532 */ 533 @Test testNetworkScanRequestParcel_Hashcode()534 public void testNetworkScanRequestParcel_Hashcode() { 535 NetworkScanRequest networkScanRequest1 = new NetworkScanRequest( 536 SCAN_TYPE, 537 RADIO_ACCESS_SPECIFIERS, 538 SEARCH_PERIODICITY_SEC, 539 MAX_SEARCH_TIME_SEC, 540 INCREMENTAL_RESULTS, 541 INCREMENTAL_RESULTS_PERIODICITY_SEC, 542 getPlmns()); 543 544 NetworkScanRequest networkScanRequest2 = new NetworkScanRequest( 545 SCAN_TYPE, 546 RADIO_ACCESS_SPECIFIERS, 547 SEARCH_PERIODICITY_SEC, 548 MAX_SEARCH_TIME_SEC, 549 INCREMENTAL_RESULTS, 550 INCREMENTAL_RESULTS_PERIODICITY_SEC, 551 getPlmns()); 552 553 NetworkScanRequest networkScanRequest3 = new NetworkScanRequest( 554 SCAN_TYPE, 555 null, 556 SEARCH_PERIODICITY_SEC, 557 MAX_SEARCH_TIME_SEC, 558 false, 559 0, 560 getPlmns()); 561 562 assertEquals("hashCode() returns different hash code for same objects", 563 networkScanRequest1.hashCode(), networkScanRequest2.hashCode()); 564 assertNotSame("hashCode() returns same hash code for different objects", 565 networkScanRequest1.hashCode(), networkScanRequest3.hashCode()); 566 } 567 568 /** 569 * To test its comparision method. 570 */ 571 @Test testNetworkScanRequestParcel_Equals()572 public void testNetworkScanRequestParcel_Equals() { 573 NetworkScanRequest networkScanRequest1 = new NetworkScanRequest( 574 SCAN_TYPE, 575 RADIO_ACCESS_SPECIFIERS, 576 SEARCH_PERIODICITY_SEC, 577 MAX_SEARCH_TIME_SEC, 578 INCREMENTAL_RESULTS, 579 INCREMENTAL_RESULTS_PERIODICITY_SEC, 580 getPlmns()); 581 582 NetworkScanRequest networkScanRequest2 = new NetworkScanRequest( 583 SCAN_TYPE, 584 RADIO_ACCESS_SPECIFIERS, 585 SEARCH_PERIODICITY_SEC, 586 MAX_SEARCH_TIME_SEC, 587 INCREMENTAL_RESULTS, 588 INCREMENTAL_RESULTS_PERIODICITY_SEC, 589 getPlmns()); 590 591 assertTrue(networkScanRequest1.equals(networkScanRequest2)); 592 593 networkScanRequest2 = new NetworkScanRequest( 594 SCAN_TYPE, 595 RADIO_ACCESS_SPECIFIERS, 596 SEARCH_PERIODICITY_SEC, 597 MAX_SEARCH_TIME_SEC, 598 INCREMENTAL_RESULTS, 599 INCREMENTAL_RESULTS_PERIODICITY_SEC, 600 null /* List of PLMN ids (MCC-MNC) */); 601 assertFalse(networkScanRequest1.equals(networkScanRequest2)); 602 } 603 604 /** 605 * To test its writeToParcel and createFromParcel methods. 606 */ 607 @Test testNetworkScanRequestParcel_Parcel()608 public void testNetworkScanRequestParcel_Parcel() { 609 NetworkScanRequest networkScanRequest = new NetworkScanRequest( 610 SCAN_TYPE, 611 null /* Radio Access Specifier */, 612 SEARCH_PERIODICITY_SEC, 613 MAX_SEARCH_TIME_SEC, 614 INCREMENTAL_RESULTS, 615 INCREMENTAL_RESULTS_PERIODICITY_SEC, 616 getPlmns()); 617 618 Parcel p = Parcel.obtain(); 619 networkScanRequest.writeToParcel(p, 0); 620 p.setDataPosition(0); 621 NetworkScanRequest newnsr = NetworkScanRequest.CREATOR.createFromParcel(p); 622 assertTrue(networkScanRequest.equals(newnsr)); 623 } 624 } 625