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 com.google.common.truth.Truth.assertThat; 22 import static com.google.common.truth.Truth.assertWithMessage; 23 24 import static org.junit.Assert.fail; 25 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.content.pm.PackageInfo; 31 import android.content.pm.PackageManager; 32 import android.location.LocationManager; 33 import android.os.AsyncTask; 34 import android.os.Handler; 35 import android.os.HandlerThread; 36 import android.os.Message; 37 import android.os.Parcel; 38 import android.os.Process; 39 import android.os.UserHandle; 40 import android.telephony.AccessNetworkConstants; 41 import android.telephony.CellInfo; 42 import android.telephony.CellInfoGsm; 43 import android.telephony.CellInfoLte; 44 import android.telephony.CellInfoWcdma; 45 import android.telephony.NetworkScan; 46 import android.telephony.NetworkScanRequest; 47 import android.telephony.RadioAccessSpecifier; 48 import android.telephony.TelephonyManager; 49 import android.telephony.TelephonyScanManager; 50 import android.util.Log; 51 52 import androidx.test.InstrumentationRegistry; 53 import androidx.test.runner.AndroidJUnit4; 54 55 import org.junit.After; 56 import org.junit.Before; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 60 import java.util.ArrayList; 61 import java.util.Arrays; 62 import java.util.List; 63 import java.util.concurrent.CountDownLatch; 64 import java.util.concurrent.TimeUnit; 65 import java.util.stream.Collectors; 66 67 /** 68 * Unit tests for {@link TelephonyManager}'s network scan APIs. 69 * 70 * <p>Test using `atest CtsCarrierApiTestCases:NetworkScanApiTest` or `make cts -j64 && cts-tradefed 71 * run cts -m CtsCarrierApiTestCases --test android.carrierapi.cts.NetworkScanApiTest` 72 */ 73 @RunWith(AndroidJUnit4.class) 74 public class NetworkScanApiTest extends BaseCarrierApiTest { 75 private static final String TAG = "NetworkScanApiTest"; 76 77 private TelephonyManager mTelephonyManager; 78 private int mNetworkScanStatus; 79 private static final int EVENT_NETWORK_SCAN_START = 100; 80 private static final int EVENT_NETWORK_SCAN_RENOUNCE_START = 101; 81 private static final int EVENT_NETWORK_SCAN_RESULTS = 200; 82 private static final int EVENT_NETWORK_SCAN_RESTRICTED_RESULTS = 201; 83 private static final int EVENT_NETWORK_SCAN_ERROR = 300; 84 private static final int EVENT_NETWORK_SCAN_COMPLETED = 400; 85 private static final int EVENT_SCAN_DENIED = 500; 86 private List<CellInfo> mScanResults = null; 87 private HandlerThread mTestHandlerThread; 88 private Handler mHandler; 89 private NetworkScan mNetworkScan; 90 private NetworkScanRequest mNetworkScanRequest; 91 private NetworkScanCallbackImpl mNetworkScanCallback; 92 private static final int LOCATION_SETTING_CHANGE_WAIT_MS = 1000; 93 private static final int MAX_CELLINFO_WAIT_MILLIS = 5000; // 5 seconds 94 private static final int SCAN_SEARCH_TIME_SECONDS = 60; 95 // Wait one second longer than the max scan search time to give the test time to receive the 96 // results. 97 private static final int MAX_INIT_WAIT_MS = (SCAN_SEARCH_TIME_SECONDS + 1) * 1000; 98 private Object mLock = new Object(); 99 private boolean mReady; 100 private int mErrorCode; 101 /* All the following constants are used to construct NetworkScanRequest*/ 102 private static final int SCAN_TYPE = NetworkScanRequest.SCAN_TYPE_ONE_SHOT; 103 private static final boolean INCREMENTAL_RESULTS = true; 104 private static final int SEARCH_PERIODICITY_SEC = 5; 105 private static final int MAX_SEARCH_TIME_SEC = 300; 106 private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3; 107 private static final ArrayList<String> MCC_MNC = new ArrayList<>(); 108 private static final RadioAccessSpecifier[] RADIO_ACCESS_SPECIFIERS = { 109 new RadioAccessSpecifier( 110 AccessNetworkConstants.AccessNetworkType.GERAN, 111 null /* bands */, 112 null /* channels */), 113 new RadioAccessSpecifier( 114 AccessNetworkConstants.AccessNetworkType.EUTRAN, 115 null /* bands */, 116 null /* channels */), 117 new RadioAccessSpecifier( 118 AccessNetworkConstants.AccessNetworkType.UTRAN, 119 null /* bands */, 120 null /* channels */) 121 }; 122 123 // Needed because NETWORK_SCAN_PERMISSION is a systemapi 124 public static final String NETWORK_SCAN_PERMISSION = "android.permission.NETWORK_SCAN"; 125 126 @Before setUp()127 public void setUp() throws Exception { 128 mTelephonyManager = getContext().getSystemService(TelephonyManager.class); 129 String selfPackageName = getContext().getPackageName(); 130 InstrumentationRegistry.getInstrumentation() 131 .getUiAutomation() 132 .grantRuntimePermission(selfPackageName, ACCESS_FINE_LOCATION); 133 InstrumentationRegistry.getInstrumentation() 134 .getUiAutomation() 135 .grantRuntimePermission(selfPackageName, ACCESS_BACKGROUND_LOCATION); 136 mTestHandlerThread = new HandlerThread(TAG); 137 mTestHandlerThread.start(); 138 /* create a custom handler for the Handler Thread */ 139 mHandler = 140 new Handler(mTestHandlerThread.getLooper()) { 141 @Override 142 public void handleMessage(Message msg) { 143 switch (msg.what) { 144 case EVENT_NETWORK_SCAN_START: { 145 Log.d(TAG, "request network scan"); 146 boolean useShellIdentity = (Boolean) msg.obj; 147 if (useShellIdentity) { 148 InstrumentationRegistry.getInstrumentation() 149 .getUiAutomation() 150 .adoptShellPermissionIdentity(); 151 } 152 try { 153 mNetworkScan = 154 mTelephonyManager.requestNetworkScan( 155 mNetworkScanRequest, 156 AsyncTask.SERIAL_EXECUTOR, 157 mNetworkScanCallback); 158 if (mNetworkScan == null) { 159 mNetworkScanStatus = EVENT_SCAN_DENIED; 160 setReady(true); 161 } 162 } catch (SecurityException e) { 163 mNetworkScanStatus = EVENT_SCAN_DENIED; 164 setReady(true); 165 } finally { 166 if (useShellIdentity) { 167 InstrumentationRegistry.getInstrumentation() 168 .getUiAutomation() 169 .dropShellPermissionIdentity(); 170 } 171 } 172 break; 173 } 174 case EVENT_NETWORK_SCAN_RENOUNCE_START: { 175 Log.d(TAG, "request network scan with renounce"); 176 boolean useShellIdentity = (Boolean) msg.obj; 177 if (useShellIdentity) { 178 InstrumentationRegistry.getInstrumentation() 179 .getUiAutomation() 180 .adoptShellPermissionIdentity(); 181 } 182 try { 183 mNetworkScan = mTelephonyManager.requestNetworkScan( 184 TelephonyManager.INCLUDE_LOCATION_DATA_NONE, 185 mNetworkScanRequest, 186 AsyncTask.SERIAL_EXECUTOR, 187 mNetworkScanCallback); 188 if (mNetworkScan == null) { 189 mNetworkScanStatus = EVENT_SCAN_DENIED; 190 setReady(true); 191 } 192 } catch (SecurityException e) { 193 mNetworkScanStatus = EVENT_SCAN_DENIED; 194 setReady(true); 195 } finally { 196 if (useShellIdentity) { 197 InstrumentationRegistry.getInstrumentation() 198 .getUiAutomation() 199 .dropShellPermissionIdentity(); 200 } 201 } 202 break; 203 } 204 default: 205 Log.d(TAG, "Unknown Event " + msg.what); 206 } 207 } 208 }; 209 } 210 211 @After tearDown()212 public void tearDown() throws Exception { 213 if (!werePreconditionsSatisfied()) return; 214 215 // Revoking runtime permissions makes ActivityManager kill our process, so we don't do it, 216 // as the test harness will eventually uninstall this APK after testing completes anyway, so 217 // we aren't really leaking anything long-term. 218 mTestHandlerThread.quit(); 219 } 220 waitUntilReady()221 private void waitUntilReady() { 222 synchronized (mLock) { 223 try { 224 mLock.wait(MAX_INIT_WAIT_MS); 225 } catch (InterruptedException ie) { 226 } 227 228 assertWithMessage("NetworkScanApiTest failed to initialize").that(mReady).isTrue(); 229 } 230 } 231 setReady(boolean ready)232 private void setReady(boolean ready) { 233 synchronized (mLock) { 234 mReady = ready; 235 mLock.notifyAll(); 236 } 237 } 238 239 private class NetworkScanCallbackImpl extends TelephonyScanManager.NetworkScanCallback { 240 @Override onResults(List<CellInfo> results)241 public void onResults(List<CellInfo> results) { 242 Log.d(TAG, "onResults: " + results.toString()); 243 mNetworkScanStatus = EVENT_NETWORK_SCAN_RESULTS; 244 mScanResults = results; 245 } 246 247 @Override onComplete()248 public void onComplete() { 249 Log.d(TAG, "onComplete"); 250 mNetworkScanStatus = EVENT_NETWORK_SCAN_COMPLETED; 251 setReady(true); 252 } 253 254 @Override onError(int error)255 public void onError(int error) { 256 Log.d(TAG, "onError: " + String.valueOf(error)); 257 mNetworkScanStatus = EVENT_NETWORK_SCAN_ERROR; 258 mErrorCode = error; 259 setReady(true); 260 } 261 } 262 263 private class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback { 264 public List<CellInfo> cellInfo; 265 266 @Override onCellInfo(List<CellInfo> cellInfo)267 public synchronized void onCellInfo(List<CellInfo> cellInfo) { 268 this.cellInfo = cellInfo; 269 notifyAll(); 270 } 271 wait(int millis)272 public synchronized void wait(int millis) throws InterruptedException { 273 if (cellInfo == null) { 274 super.wait(millis); 275 } 276 } 277 } 278 getRadioAccessSpecifier(List<CellInfo> allCellInfo)279 private List<RadioAccessSpecifier> getRadioAccessSpecifier(List<CellInfo> allCellInfo) { 280 List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>(); 281 List<Integer> lteChannels = new ArrayList<>(); 282 List<Integer> wcdmaChannels = new ArrayList<>(); 283 List<Integer> gsmChannels = new ArrayList<>(); 284 for (int i = 0; i < allCellInfo.size(); i++) { 285 CellInfo cellInfo = allCellInfo.get(i); 286 if (cellInfo instanceof CellInfoLte) { 287 lteChannels.add(((CellInfoLte) cellInfo).getCellIdentity().getEarfcn()); 288 } else if (cellInfo instanceof CellInfoWcdma) { 289 wcdmaChannels.add(((CellInfoWcdma) cellInfo).getCellIdentity().getUarfcn()); 290 } else if (cellInfo instanceof CellInfoGsm) { 291 gsmChannels.add(((CellInfoGsm) cellInfo).getCellIdentity().getArfcn()); 292 } 293 } 294 if (!lteChannels.isEmpty()) { 295 Log.d(TAG, "lte channels" + lteChannels.toString()); 296 int ranLte = AccessNetworkConstants.AccessNetworkType.EUTRAN; 297 radioAccessSpecifier.add( 298 new RadioAccessSpecifier( 299 ranLte, 300 null /* bands */, 301 lteChannels.stream().mapToInt(i -> i).toArray())); 302 } 303 if (!wcdmaChannels.isEmpty()) { 304 Log.d(TAG, "wcdma channels" + wcdmaChannels.toString()); 305 int ranWcdma = AccessNetworkConstants.AccessNetworkType.UTRAN; 306 radioAccessSpecifier.add( 307 new RadioAccessSpecifier( 308 ranWcdma, 309 null /* bands */, 310 wcdmaChannels.stream().mapToInt(i -> i).toArray())); 311 } 312 if (!gsmChannels.isEmpty()) { 313 Log.d(TAG, "gsm channels" + gsmChannels.toString()); 314 int ranGsm = AccessNetworkConstants.AccessNetworkType.GERAN; 315 radioAccessSpecifier.add( 316 new RadioAccessSpecifier( 317 ranGsm, 318 null /* bands */, 319 gsmChannels.stream().mapToInt(i -> i).toArray())); 320 } 321 return radioAccessSpecifier; 322 } 323 324 /** Tests that the device properly requests a network scan. */ 325 @Test testRequestNetworkScan()326 public void testRequestNetworkScan() { 327 boolean isLocationSwitchOn = getAndSetLocationSwitch(true); 328 try { 329 mNetworkScanRequest = buildNetworkScanRequest(true); 330 mNetworkScanCallback = new NetworkScanCallbackImpl(); 331 Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_START, false); 332 setReady(false); 333 startNetworkScan.sendToTarget(); 334 waitUntilReady(); 335 336 Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus); 337 assertWithMessage( 338 "The final scan status is " 339 + mNetworkScanStatus 340 + " with error code " 341 + mErrorCode 342 + ", not ScanCompleted" 343 + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or" 344 + " ERROR_UNSUPPORTED") 345 .that(isScanStatusValid()) 346 .isTrue(); 347 } finally { 348 getAndSetLocationSwitch(isLocationSwitchOn); 349 } 350 } 351 352 /** Tests that the device properly requests a network scan. */ 353 @Test testRequestNetworkScanWithRenounce()354 public void testRequestNetworkScanWithRenounce() { 355 boolean isLocationSwitchOn = getAndSetLocationSwitch(true); 356 try { 357 mNetworkScanRequest = buildNetworkScanRequest(true); 358 mNetworkScanCallback = new NetworkScanCallbackImpl(); 359 Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RENOUNCE_START, 360 false); 361 setReady(false); 362 startNetworkScan.sendToTarget(); 363 waitUntilReady(); 364 365 Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus); 366 assertWithMessage( 367 "The final scan status is " 368 + mNetworkScanStatus 369 + " with error code " 370 + mErrorCode 371 + ", not ScanCompleted" 372 + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or" 373 + " ERROR_UNSUPPORTED") 374 .that(mNetworkScanStatus) 375 .isEqualTo(EVENT_SCAN_DENIED); 376 } finally { 377 getAndSetLocationSwitch(isLocationSwitchOn); 378 } 379 } 380 381 @Test testRequestNetworkScanWithRenounceWithoutChannels()382 public void testRequestNetworkScanWithRenounceWithoutChannels() { 383 boolean isLocationSwitchOn = getAndSetLocationSwitch(true); 384 try { 385 mNetworkScanRequest = buildNetworkScanRequest(/*includeBandsAndChannels=*/false); 386 mNetworkScanCallback = new NetworkScanCallbackImpl(); 387 Message startNetworkScan = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RENOUNCE_START, 388 false); 389 setReady(false); 390 startNetworkScan.sendToTarget(); 391 waitUntilReady(); 392 393 Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus); 394 assertWithMessage( 395 "The final scan status is " 396 + mNetworkScanStatus 397 + " with error code " 398 + mErrorCode 399 + ", not ScanCompleted" 400 + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or" 401 + " ERROR_UNSUPPORTED") 402 .that(isScanStatusValid()) 403 .isTrue(); 404 } finally { 405 getAndSetLocationSwitch(isLocationSwitchOn); 406 } 407 } 408 409 @Test testRequestNetworkScanLocationOffPass()410 public void testRequestNetworkScanLocationOffPass() { 411 requestNetworkScanLocationOffHelper(false, true); 412 } 413 414 @Test testRequestNetworkScanLocationOffFail()415 public void testRequestNetworkScanLocationOffFail() { 416 requestNetworkScanLocationOffHelper(true, true); 417 } 418 requestNetworkScanLocationOffHelper( boolean includeBandsAndChannels, boolean useSpecialScanPermission)419 public void requestNetworkScanLocationOffHelper( 420 boolean includeBandsAndChannels, boolean useSpecialScanPermission) { 421 mNetworkScanRequest = buildNetworkScanRequest(includeBandsAndChannels); 422 423 boolean isLocationSwitchOn = getAndSetLocationSwitch(false); 424 try { 425 mNetworkScanCallback = new NetworkScanCallbackImpl(); 426 Message startNetworkScan = 427 mHandler.obtainMessage(EVENT_NETWORK_SCAN_START, useSpecialScanPermission); 428 setReady(false); 429 startNetworkScan.sendToTarget(); 430 waitUntilReady(); 431 if (includeBandsAndChannels) { 432 // If we included the bands when location is off, expect a security error and 433 // nothing else. 434 assertThat(mNetworkScanStatus).isEqualTo(EVENT_SCAN_DENIED); 435 return; 436 } 437 438 Log.d(TAG, "mNetworkScanStatus: " + mNetworkScanStatus); 439 assertWithMessage( 440 "The final scan status is " 441 + mNetworkScanStatus 442 + " with error code " 443 + mErrorCode 444 + ", not ScanCompleted" 445 + " or ScanError with an error code ERROR_MODEM_UNAVAILABLE or" 446 + " ERROR_UNSUPPORTED") 447 .that(isScanStatusValid()) 448 .isTrue(); 449 } finally { 450 getAndSetLocationSwitch(isLocationSwitchOn); 451 } 452 } 453 buildNetworkScanRequest(boolean includeBandsAndChannels)454 private NetworkScanRequest buildNetworkScanRequest(boolean includeBandsAndChannels) { 455 // Make sure that there should be at least one entry. 456 List<CellInfo> allCellInfo = getCellInfo(); 457 List<RadioAccessSpecifier> radioAccessSpecifier = new ArrayList<>(); 458 459 if (allCellInfo != null && allCellInfo.size() != 0) { 460 // Construct a NetworkScanRequest 461 radioAccessSpecifier = getRadioAccessSpecifier(allCellInfo); 462 if (!includeBandsAndChannels) { 463 radioAccessSpecifier = 464 radioAccessSpecifier.stream() 465 .map( 466 spec -> 467 new RadioAccessSpecifier( 468 spec.getRadioAccessNetwork(), null, null)) 469 .collect(Collectors.toList()); 470 } 471 } 472 473 Log.d(TAG, "number of radioAccessSpecifier: " + radioAccessSpecifier.size()); 474 if (radioAccessSpecifier.isEmpty()) { 475 // Put in some arbitrary bands and channels so that we trip the location check if needed 476 int[] fakeBands = 477 includeBandsAndChannels 478 ? new int[] {AccessNetworkConstants.EutranBand.BAND_5} 479 : null; 480 int[] fakeChannels = includeBandsAndChannels ? new int[] {2400} : null; 481 482 RadioAccessSpecifier gsm = 483 new RadioAccessSpecifier( 484 AccessNetworkConstants.AccessNetworkType.GERAN, 485 null /* bands */, 486 null /* channels */); 487 RadioAccessSpecifier lte = 488 new RadioAccessSpecifier( 489 AccessNetworkConstants.AccessNetworkType.EUTRAN, 490 fakeBands /* bands */, 491 fakeChannels /* channels */); 492 RadioAccessSpecifier wcdma = 493 new RadioAccessSpecifier( 494 AccessNetworkConstants.AccessNetworkType.UTRAN, 495 null /* bands */, 496 null /* channels */); 497 radioAccessSpecifier.add(gsm); 498 radioAccessSpecifier.add(lte); 499 radioAccessSpecifier.add(wcdma); 500 } 501 RadioAccessSpecifier[] radioAccessSpecifierArray = 502 new RadioAccessSpecifier[radioAccessSpecifier.size()]; 503 return new NetworkScanRequest( 504 NetworkScanRequest.SCAN_TYPE_ONE_SHOT /* scan type */, 505 radioAccessSpecifier.toArray(radioAccessSpecifierArray), 506 5 /* search periodicity */, 507 SCAN_SEARCH_TIME_SECONDS /* max search time */, 508 true /*enable incremental results*/, 509 5 /* incremental results periodicity */, 510 null /* List of PLMN ids (MCC-MNC) */); 511 } 512 getCellInfo()513 private List<CellInfo> getCellInfo() { 514 CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback(); 515 mTelephonyManager.requestCellInfoUpdate(r -> r.run(), resultsCallback); 516 try { 517 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 518 } catch (InterruptedException ex) { 519 fail("CellInfoCallback was interrupted: " + ex); 520 } 521 return resultsCallback.cellInfo; 522 } 523 524 @Test testNetworkScanPermission()525 public void testNetworkScanPermission() { 526 PackageManager pm = getContext().getPackageManager(); 527 528 List<Integer> specialUids = 529 Arrays.asList(Process.SYSTEM_UID, Process.PHONE_UID, Process.SHELL_UID); 530 531 List<PackageInfo> holding = 532 pm.getPackagesHoldingPermissions( 533 new String[] {NETWORK_SCAN_PERMISSION}, 534 PackageManager.MATCH_DISABLED_COMPONENTS); 535 536 List<Integer> nonSpecialPackages = 537 holding.stream() 538 .map( 539 pi -> { 540 try { 541 return pm.getPackageUid(pi.packageName, 0); 542 } catch (PackageManager.NameNotFoundException e) { 543 return Process.INVALID_UID; 544 } 545 }) 546 .filter(uid -> !specialUids.contains(UserHandle.getAppId(uid))) 547 .collect(Collectors.toList()); 548 549 assertWithMessage( 550 "Only one app on the device is allowed to hold the NETWORK_SCAN" 551 + " permission.") 552 .that(nonSpecialPackages.size()) 553 .isAtMost(1); 554 } 555 getAndSetLocationSwitch(boolean enabled)556 private boolean getAndSetLocationSwitch(boolean enabled) { 557 CountDownLatch locationChangeLatch = new CountDownLatch(1); 558 BroadcastReceiver locationModeChangeReceiver = new BroadcastReceiver() { 559 @Override 560 public void onReceive(Context context, Intent intent) { 561 if (LocationManager.MODE_CHANGED_ACTION.equals(intent.getAction()) 562 && intent.getBooleanExtra(LocationManager.EXTRA_LOCATION_ENABLED, !enabled) 563 == enabled) { 564 locationChangeLatch.countDown(); 565 } 566 } 567 }; 568 569 InstrumentationRegistry.getInstrumentation().getUiAutomation() 570 .adoptShellPermissionIdentity(); 571 try { 572 Context context = InstrumentationRegistry.getContext(); 573 LocationManager lm = context.getSystemService( 574 LocationManager.class); 575 boolean oldLocationOn = lm.isLocationEnabledForUser( 576 UserHandle.of(UserHandle.myUserId())); 577 578 if (enabled != oldLocationOn) { 579 context.registerReceiver(locationModeChangeReceiver, 580 new IntentFilter(LocationManager.MODE_CHANGED_ACTION)); 581 lm.setLocationEnabledForUser(enabled, UserHandle.of(UserHandle.myUserId())); 582 try { 583 assertThat(locationChangeLatch.await(LOCATION_SETTING_CHANGE_WAIT_MS, 584 TimeUnit.MILLISECONDS)).isTrue(); 585 } catch (InterruptedException e) { 586 Log.w(NetworkScanApiTest.class.getSimpleName(), 587 "Interrupted while waiting for location settings change. Test results" 588 + " may not be accurate."); 589 } finally { 590 context.unregisterReceiver(locationModeChangeReceiver); 591 } 592 } 593 return oldLocationOn; 594 } finally { 595 InstrumentationRegistry.getInstrumentation().getUiAutomation() 596 .dropShellPermissionIdentity(); 597 } 598 } 599 isScanStatusValid()600 private boolean isScanStatusValid() { 601 // TODO(b/72162885): test the size of ScanResults is not zero after the blocking bug fixed. 602 if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_COMPLETED) && (mScanResults != null)) { 603 // Scan complete. 604 return true; 605 } 606 if ((mNetworkScanStatus == EVENT_NETWORK_SCAN_ERROR) 607 && ((mErrorCode == NetworkScan.ERROR_MODEM_UNAVAILABLE) 608 || (mErrorCode == NetworkScan.ERROR_UNSUPPORTED))) { 609 // Scan error but the error type is allowed. 610 return true; 611 } 612 return false; 613 } 614 getPlmns()615 private ArrayList<String> getPlmns() { 616 ArrayList<String> mccMncs = new ArrayList<>(); 617 mccMncs.add("310260"); 618 mccMncs.add("310120"); 619 return mccMncs; 620 } 621 622 /** To test its constructor and getters. */ 623 @Test testNetworkScanRequest_constructorAndGetters()624 public void testNetworkScanRequest_constructorAndGetters() { 625 NetworkScanRequest networkScanRequest = 626 new NetworkScanRequest( 627 SCAN_TYPE, 628 RADIO_ACCESS_SPECIFIERS, 629 SEARCH_PERIODICITY_SEC, 630 MAX_SEARCH_TIME_SEC, 631 INCREMENTAL_RESULTS, 632 INCREMENTAL_RESULTS_PERIODICITY_SEC, 633 getPlmns()); 634 635 assertWithMessage("getScanType() returns wrong value") 636 .that(networkScanRequest.getScanType()) 637 .isEqualTo(SCAN_TYPE); 638 assertWithMessage("getSpecifiers() returns wrong value") 639 .that(networkScanRequest.getSpecifiers()) 640 .isEqualTo(RADIO_ACCESS_SPECIFIERS); 641 assertWithMessage("getSearchPeriodicity() returns wrong value") 642 .that(networkScanRequest.getSearchPeriodicity()) 643 .isEqualTo(SEARCH_PERIODICITY_SEC); 644 assertWithMessage("getMaxSearchTime() returns wrong value") 645 .that(networkScanRequest.getMaxSearchTime()) 646 .isEqualTo(MAX_SEARCH_TIME_SEC); 647 assertWithMessage("getIncrementalResults() returns wrong value") 648 .that(networkScanRequest.getIncrementalResults()) 649 .isEqualTo(INCREMENTAL_RESULTS); 650 assertWithMessage("getIncrementalResultsPeriodicity() returns wrong value") 651 .that(networkScanRequest.getIncrementalResultsPeriodicity()) 652 .isEqualTo(INCREMENTAL_RESULTS_PERIODICITY_SEC); 653 assertWithMessage("getPlmns() returns wrong value") 654 .that(networkScanRequest.getPlmns()) 655 .isEqualTo(getPlmns()); 656 assertWithMessage("describeContents() returns wrong value") 657 .that(networkScanRequest.describeContents()) 658 .isEqualTo(0); 659 } 660 661 /** To test its hashCode method. */ 662 @Test testNetworkScanRequestParcel_hashCode()663 public void testNetworkScanRequestParcel_hashCode() { 664 NetworkScanRequest networkScanRequest1 = 665 new NetworkScanRequest( 666 SCAN_TYPE, 667 RADIO_ACCESS_SPECIFIERS, 668 SEARCH_PERIODICITY_SEC, 669 MAX_SEARCH_TIME_SEC, 670 INCREMENTAL_RESULTS, 671 INCREMENTAL_RESULTS_PERIODICITY_SEC, 672 getPlmns()); 673 674 NetworkScanRequest networkScanRequest2 = 675 new NetworkScanRequest( 676 SCAN_TYPE, 677 RADIO_ACCESS_SPECIFIERS, 678 SEARCH_PERIODICITY_SEC, 679 MAX_SEARCH_TIME_SEC, 680 INCREMENTAL_RESULTS, 681 INCREMENTAL_RESULTS_PERIODICITY_SEC, 682 getPlmns()); 683 684 NetworkScanRequest networkScanRequest3 = 685 new NetworkScanRequest( 686 SCAN_TYPE, 687 null, 688 SEARCH_PERIODICITY_SEC, 689 MAX_SEARCH_TIME_SEC, 690 false, 691 0, 692 getPlmns()); 693 694 assertWithMessage("hashCode() returns different hash code for same objects") 695 .that(networkScanRequest1.hashCode()) 696 .isEqualTo(networkScanRequest2.hashCode()); 697 assertWithMessage("hashCode() returns same hash code for different objects") 698 .that(networkScanRequest1.hashCode()) 699 .isNotEqualTo(networkScanRequest3.hashCode()); 700 } 701 702 /** To test its comparison method. */ 703 @Test testNetworkScanRequestParcel_equals()704 public void testNetworkScanRequestParcel_equals() { 705 NetworkScanRequest networkScanRequest1 = 706 new NetworkScanRequest( 707 SCAN_TYPE, 708 RADIO_ACCESS_SPECIFIERS, 709 SEARCH_PERIODICITY_SEC, 710 MAX_SEARCH_TIME_SEC, 711 INCREMENTAL_RESULTS, 712 INCREMENTAL_RESULTS_PERIODICITY_SEC, 713 getPlmns()); 714 715 NetworkScanRequest networkScanRequest2 = 716 new NetworkScanRequest( 717 SCAN_TYPE, 718 RADIO_ACCESS_SPECIFIERS, 719 SEARCH_PERIODICITY_SEC, 720 MAX_SEARCH_TIME_SEC, 721 INCREMENTAL_RESULTS, 722 INCREMENTAL_RESULTS_PERIODICITY_SEC, 723 getPlmns()); 724 725 assertThat(networkScanRequest1).isEqualTo(networkScanRequest2); 726 727 networkScanRequest2 = 728 new NetworkScanRequest( 729 SCAN_TYPE, 730 RADIO_ACCESS_SPECIFIERS, 731 SEARCH_PERIODICITY_SEC, 732 MAX_SEARCH_TIME_SEC, 733 INCREMENTAL_RESULTS, 734 INCREMENTAL_RESULTS_PERIODICITY_SEC, 735 null /* List of PLMN ids (MCC-MNC) */); 736 assertThat(networkScanRequest1).isNotEqualTo(networkScanRequest2); 737 } 738 739 /** To test its writeToParcel and createFromParcel methods. */ 740 @Test testNetworkScanRequestParcel_parcel()741 public void testNetworkScanRequestParcel_parcel() { 742 NetworkScanRequest networkScanRequest = 743 new NetworkScanRequest( 744 SCAN_TYPE, 745 null /* Radio Access Specifier */, 746 SEARCH_PERIODICITY_SEC, 747 MAX_SEARCH_TIME_SEC, 748 INCREMENTAL_RESULTS, 749 INCREMENTAL_RESULTS_PERIODICITY_SEC, 750 getPlmns()); 751 752 Parcel p = Parcel.obtain(); 753 networkScanRequest.writeToParcel(p, 0); 754 p.setDataPosition(0); 755 NetworkScanRequest newnsr = NetworkScanRequest.CREATOR.createFromParcel(p); 756 assertThat(networkScanRequest).isEqualTo(newnsr); 757 } 758 } 759