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