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