1 /* 2 * Copyright (C) 2014 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.telephony.cts; 17 18 import static androidx.test.InstrumentationRegistry.getContext; 19 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 import static org.junit.Assume.assumeTrue; 27 28 import android.annotation.Nullable; 29 import android.content.Context; 30 import android.content.pm.PackageManager; 31 import android.os.Parcel; 32 import android.os.SystemClock; 33 import android.platform.test.annotations.AppModeNonSdkSandbox; 34 import android.platform.test.flag.junit.CheckFlagsRule; 35 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 36 import android.telephony.AccessNetworkConstants; 37 import android.telephony.CellIdentity; 38 import android.telephony.CellIdentityGsm; 39 import android.telephony.CellIdentityLte; 40 import android.telephony.CellIdentityNr; 41 import android.telephony.CellIdentityTdscdma; 42 import android.telephony.CellIdentityWcdma; 43 import android.telephony.CellInfo; 44 import android.telephony.CellInfoGsm; 45 import android.telephony.CellInfoLte; 46 import android.telephony.CellInfoNr; 47 import android.telephony.CellInfoTdscdma; 48 import android.telephony.CellInfoWcdma; 49 import android.telephony.CellSignalStrengthGsm; 50 import android.telephony.CellSignalStrengthLte; 51 import android.telephony.CellSignalStrengthNr; 52 import android.telephony.CellSignalStrengthTdscdma; 53 import android.telephony.CellSignalStrengthWcdma; 54 import android.telephony.ClosedSubscriberGroupInfo; 55 import android.telephony.NetworkRegistrationInfo; 56 import android.telephony.PhoneStateListener; 57 import android.telephony.ServiceState; 58 import android.telephony.TelephonyManager; 59 import android.text.TextUtils; 60 import android.util.Pair; 61 62 import androidx.test.InstrumentationRegistry; 63 64 import org.junit.After; 65 import org.junit.Before; 66 import org.junit.Rule; 67 import org.junit.Test; 68 69 import java.util.Arrays; 70 import java.util.List; 71 import java.util.concurrent.Executor; 72 73 /** 74 * Test TelephonyManager.getAllCellInfo() 75 * <p> 76 * 77 * Test that the Cellular Location APIs return proper and complete information. 78 * <ul> 79 * <li>At least one cell must be reported as the registered cell. 80 * <li>Registered cells must report the technology-specific fields consisting of a globally 81 * unique cell identifier. 82 * <li>All cells must report a technology-specific physical cell identifier, such as a tuple 83 * of the frequency and a phyisical cell ID that allows them to be uniquely identified 84 * given a known global cell. 85 * <li>All cells must report at least one valid power measurement. 86 * </ul> 87 * 88 */ 89 @AppModeNonSdkSandbox( 90 reason = "SDK sandboxes are not allowed to access cell info - no location permission") 91 public class CellInfoTest { 92 @Rule 93 public final CheckFlagsRule mCheckFlagsRule = 94 DeviceFlagsValueProvider.createCheckFlagsRule(); 95 96 private static final String TAG = "android.telephony.cts.CellInfoTest"; 97 98 // Maximum and minimum possible RSSI values(in dbm). 99 private static final int MAX_RSSI = -10; 100 private static final int MIN_RSSI = -150; 101 // Maximum and minimum possible RSRP values(in dbm). 102 private static final int MAX_RSRP = -44; 103 private static final int MIN_RSRP = -140; 104 // Maximum and minimum possible RSRQ values. 105 private static final int MAX_RSRQ = -3; 106 private static final int MIN_RSRQ = -35; 107 // Maximum and minimum possible RSSNR values. 108 private static final int MAX_RSSNR = 30; 109 private static final int MIN_RSSNR = -20; 110 // Maximum and minimum possible CQI values. 111 private static final int MAX_CQI = 15; 112 private static final int MIN_CQI = 0; 113 114 /** 115 * Maximum and minimum valid LTE RSSI values in dBm 116 * 117 * The valid RSSI ASU range from current HAL is [0,31]. 118 * Convert RSSI ASU to dBm: dBm = -113 + 2 * ASU, which is [-113, -51] 119 * 120 * Reference: TS 27.007 8.5 - Signal quality +CSQ 121 */ 122 private static final int MAX_LTE_RSSI = -51; 123 private static final int MIN_LTE_RSSI = -113; 124 125 // The followings are parameters for testing CellIdentityLte 126 private static final int CI = 268435456; 127 // Physical cell id ranges from 0 to 503. 128 private static final int PCI = 503; 129 // Tracking area code ranges from 0 to 65535. 130 private static final int TAC = 65535; 131 // Absolute RF Channel Number ranges from 0 to 262143. 132 private static final int EARFCN_MAX = 262143; 133 private static final int BANDWIDTH_LOW = 1400; // kHz 134 private static final int BANDWIDTH_HIGH = 20000; // kHz 135 // 3GPP TS 36.101 136 private static final int BAND_MIN_LTE = 1; 137 private static final int BAND_MAX_LTE = 88; 138 //3GPP TS 136.213 section 7.2.3 139 private static final int CQI_TABLE_INDEX_MIN_LTE = 1; 140 private static final int CQI_TABLE_INDEX_MAX_LTE = 6; 141 142 // The followings are parameters for testing CellIdentityWcdma 143 // Location Area Code ranges from 0 to 65535. 144 private static final int LAC = 65535; 145 // UMTS Cell Identity ranges from 0 to 268435455. 146 private static final int CID_UMTS = 268435455; 147 // Primary Scrambling Code ranges from 0 to 511. 148 private static final int PSC = 511; 149 // Cell Parameters Index rangest from 0-127. 150 private static final int CPID = 127; 151 152 // The followings are parameters for testing CellIdentityGsm 153 // GSM Cell Identity ranges from 0 to 65535. 154 private static final int CID_GSM = 65535; 155 // GSM Absolute RF Channel Number ranges from 0 to 65535. 156 private static final int ARFCN = 1024; 157 158 // The followings are parameters for testing CellIdentityNr 159 // 3GPP TS 38.101-1 and 38.101-2 160 private static final int BAND_FR1_MIN_NR = 1; 161 private static final int BAND_FR1_MAX_NR = 95; 162 private static final int BAND_FR2_MIN_NR = 257; 163 private static final int BAND_FR2_MAX_NR = 261; 164 //3GPP TS 138.214 section 5.2.2.1 165 private static final int CQI_TABLE_INDEX_MIN_NR = 1; 166 private static final int CQI_TABLE_INDEX_MAX_NR = 3; 167 168 // 3gpp 36.101 Sec 5.7.2 169 private static final int CHANNEL_RASTER_EUTRAN = 100; //kHz 170 171 private static final int MAX_CELLINFO_WAIT_MILLIS = 5000; 172 private static final int MAX_LISTENER_WAIT_MILLIS = 1000; // usually much less 173 // The maximum interval between CellInfo updates from the modem. In the AOSP code it varies 174 // between 2 and 10 seconds, and there is an allowable modem delay of 3 seconds, so if we 175 // cannot get a seconds CellInfo update within 15 seconds, then something is broken. 176 // See DeviceStateMonitor#CELL_INFO_INTERVAL_* 177 private static final int MAX_CELLINFO_INTERVAL_MILLIS = 15000; // in AOSP the max is 10s 178 private static final int RADIO_HAL_VERSION_1_2 = makeRadioVersion(1, 2); 179 private static final int RADIO_HAL_VERSION_1_5 = makeRadioVersion(1, 5); 180 181 private PackageManager mPm; 182 private TelephonyManager mTm; 183 184 private int mNetworkHalVersion; 185 private Boolean mWasLocationEnabled; 186 makeRadioVersion(int major, int minor)187 private static final int makeRadioVersion(int major, int minor) { 188 if (major < 0 || minor < 0) return 0; 189 return major * 100 + minor; 190 } 191 192 private Executor mSimpleExecutor = new Executor() { 193 @Override 194 public void execute(Runnable r) { 195 r.run(); 196 } 197 }; 198 199 private static class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback { 200 List<CellInfo> cellInfo; 201 202 @Override onCellInfo(List<CellInfo> cellInfo)203 public synchronized void onCellInfo(List<CellInfo> cellInfo) { 204 this.cellInfo = cellInfo; 205 notifyAll(); 206 } 207 wait(int millis)208 public synchronized void wait(int millis) throws InterruptedException { 209 if (cellInfo == null) { 210 super.wait(millis); 211 } 212 } 213 } 214 215 private static class CellInfoListener extends PhoneStateListener { 216 List<CellInfo> cellInfo; 217 CellInfoListener(Executor e)218 public CellInfoListener(Executor e) { 219 super(e); 220 } 221 222 @Override onCellInfoChanged(List<CellInfo> cellInfo)223 public synchronized void onCellInfoChanged(List<CellInfo> cellInfo) { 224 this.cellInfo = cellInfo; 225 notifyAll(); 226 } 227 wait(int millis)228 public synchronized void wait(int millis) throws InterruptedException { 229 if (cellInfo == null) { 230 super.wait(millis); 231 } 232 } 233 } 234 isCamped()235 private boolean isCamped() { 236 InstrumentationRegistry.getInstrumentation().getUiAutomation() 237 .adoptShellPermissionIdentity("android.permission.READ_PHONE_STATE"); 238 239 ServiceState ss = mTm.getServiceState(); 240 if (ss == null) return false; 241 if (ss.getState() == ServiceState.STATE_EMERGENCY_ONLY) return true; 242 List<NetworkRegistrationInfo> nris = ss.getNetworkRegistrationInfoList(); 243 for (NetworkRegistrationInfo nri : nris) { 244 if (nri.getTransportType() != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) continue; 245 if (nri.isRegistered()) return true; 246 } 247 return false; 248 } 249 250 @Before setUp()251 public void setUp() throws Exception { 252 mPm = getContext().getPackageManager(); 253 assumeTrue(mPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS)); 254 255 mTm = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); 256 Pair<Integer, Integer> verPair = 257 mTm.getHalVersion(TelephonyManager.HAL_SERVICE_NETWORK); 258 mNetworkHalVersion = makeRadioVersion(verPair.first, verPair.second); 259 TelephonyManagerTest.grantLocationPermissions(); 260 mWasLocationEnabled = TelephonyManagerTest.setLocationEnabled(true); 261 } 262 263 @After tearDown()264 public void tearDown() { 265 if (mWasLocationEnabled != null) { 266 TelephonyManagerTest.setLocationEnabled(mWasLocationEnabled); 267 mWasLocationEnabled = null; 268 } 269 } 270 271 /** 272 * Test to ensure that the PhoneStateListener receives callbacks every time that new CellInfo 273 * is received and not otherwise. 274 */ 275 @Test testPhoneStateListenerCallback()276 public void testPhoneStateListenerCallback() throws Throwable { 277 CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback(); 278 // Prime the system by requesting a CellInfoUpdate 279 mTm.requestCellInfoUpdate(mSimpleExecutor, resultsCallback); 280 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 281 // Register a new PhoneStateListener for CellInfo 282 CellInfoListener listener = new CellInfoListener(mSimpleExecutor); 283 mTm.listen(listener, PhoneStateListener.LISTEN_CELL_INFO); 284 // Expect a callback immediately upon registration 285 listener.wait(MAX_LISTENER_WAIT_MILLIS); 286 assertNotNull("CellInfo Listener Never Fired on Registration", listener.cellInfo); 287 // Save the initial listener result as a baseline 288 List<CellInfo> referenceList = listener.cellInfo; 289 assertFalse("CellInfo does not contain valid results", referenceList.isEmpty()); 290 assertTrue("Listener Didn't Receive the Right Data", 291 referenceList.containsAll(resultsCallback.cellInfo)); 292 listener.cellInfo = null; 293 resultsCallback.cellInfo = null; 294 long timeoutTime = SystemClock.elapsedRealtime() + MAX_CELLINFO_INTERVAL_MILLIS; 295 while (timeoutTime > SystemClock.elapsedRealtime()) { 296 // Request a CellInfo update to try and coax an update from the listener 297 mTm.requestCellInfoUpdate(mSimpleExecutor, resultsCallback); 298 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 299 assertNotNull("CellInfoCallback should return valid data", resultsCallback.cellInfo); 300 if (referenceList.containsAll(resultsCallback.cellInfo)) { 301 // Check the a call to getAllCellInfo doesn't trigger the listener. 302 mTm.getAllCellInfo(); 303 // Wait for the listener to fire; it shouldn't. 304 listener.wait(MAX_LISTENER_WAIT_MILLIS); 305 // Check to ensure the listener didn't fire for stale data. 306 assertNull("PhoneStateListener Fired For Old CellInfo Data", listener.cellInfo); 307 } else { 308 // If there is new CellInfo data, then the listener should fire 309 listener.wait(MAX_LISTENER_WAIT_MILLIS); 310 assertNotNull("Listener did not receive updated CellInfo Data", 311 listener.cellInfo); 312 assertFalse("CellInfo data should be different from the old listener data." 313 + referenceList + " : " + listener.cellInfo, 314 referenceList.containsAll(listener.cellInfo)); 315 return; // pass the test 316 } 317 // Reset the resultsCallback for the next iteration 318 resultsCallback.cellInfo = null; 319 } 320 } 321 322 @Test testCellInfo()323 public void testCellInfo() throws Throwable { 324 if (!isCamped()) fail("Device is not camped to a cell"); 325 326 // Make a blocking call to requestCellInfoUpdate for results (for simplicity of test). 327 CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback(); 328 mTm.requestCellInfoUpdate(mSimpleExecutor, resultsCallback); 329 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 330 List<CellInfo> allCellInfo = resultsCallback.cellInfo; 331 332 assertNotNull("TelephonyManager.getAllCellInfo() returned NULL!", allCellInfo); 333 assertTrue("TelephonyManager.getAllCellInfo() returned zero-length list!", 334 allCellInfo.size() > 0); 335 336 int numRegisteredCells = 0; 337 for (CellInfo cellInfo : allCellInfo) { 338 if (cellInfo.isRegistered()) { 339 ++numRegisteredCells; 340 } 341 verifyBaseCellInfo(cellInfo); 342 verifyBaseCellIdentity(cellInfo.getCellIdentity(), cellInfo.isRegistered()); 343 if (cellInfo instanceof CellInfoLte) { 344 verifyLteInfo((CellInfoLte) cellInfo); 345 } else if (cellInfo instanceof CellInfoWcdma) { 346 verifyWcdmaInfo((CellInfoWcdma) cellInfo); 347 } else if (cellInfo instanceof CellInfoGsm) { 348 verifyGsmInfo((CellInfoGsm) cellInfo); 349 } else if (cellInfo instanceof CellInfoTdscdma) { 350 verifyTdscdmaInfo((CellInfoTdscdma) cellInfo); 351 } else if (cellInfo instanceof CellInfoNr) { 352 verifyNrInfo((CellInfoNr) cellInfo); 353 } else { 354 fail("Unknown CellInfo Type reported."); 355 } 356 } 357 358 //FIXME: The maximum needs to be calculated based on the number of 359 // radios and the technologies used (ex SRLTE); however, we have 360 // not hit any of these cases yet. 361 assertTrue("None or too many registered cells : " + numRegisteredCells, 362 numRegisteredCells > 0 && numRegisteredCells <= 2); 363 } 364 verifyBaseCellInfo(CellInfo info)365 private void verifyBaseCellInfo(CellInfo info) { 366 assertTrue("Invalid timestamp in CellInfo: " + info.getTimeStamp(), 367 info.getTimeStamp() > 0 && info.getTimeStamp() < Long.MAX_VALUE); 368 369 long curTime = SystemClock.elapsedRealtime(); 370 assertTrue("Invalid timestamp in CellInfo: " + info.getTimestampMillis(), 371 info.getTimestampMillis() > 0 && info.getTimestampMillis() <= curTime); 372 373 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_2) { 374 // In HAL 1.2 or greater, the connection status must be reported 375 assertTrue(info.getCellConnectionStatus() != CellInfo.CONNECTION_UNKNOWN); 376 } 377 } 378 verifyBaseCellIdentity(CellIdentity id, boolean isRegistered)379 private void verifyBaseCellIdentity(CellIdentity id, boolean isRegistered) { 380 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_2) { 381 if (isRegistered) { 382 String alphaLong = (String) id.getOperatorAlphaLong(); 383 assertNotNull("getOperatorAlphaLong() returns NULL!", alphaLong); 384 385 String alphaShort = (String) id.getOperatorAlphaShort(); 386 assertNotNull("getOperatorAlphaShort() returns NULL!", alphaShort); 387 } 388 } 389 } 390 verifyPlmnInfo(String mccStr, String mncStr, int mcc, int mnc)391 private static void verifyPlmnInfo(String mccStr, String mncStr, int mcc, int mnc) { 392 // If either int value is invalid, all values must be invalid 393 if (mcc == CellInfo.UNAVAILABLE) { 394 assertTrue("MNC and MNC must always be reported together.", 395 mnc == CellInfo.UNAVAILABLE && mccStr == null && mncStr == null); 396 return; 397 } 398 399 assertTrue("getMcc() out of range [0, 999], mcc=" + mcc, (mcc >= 0 && mcc <= 999)); 400 assertTrue("getMnc() out of range [0, 999], mnc=" + mnc, (mnc >= 0 && mnc <= 999)); 401 assertTrue("MCC and MNC Strings must always be reported together.", 402 (mccStr == null) == (mncStr == null)); 403 404 // For legacy compatibility, it's possible to have int values without valid string values 405 // but not the other way around. 406 // mccStr is set as NULL if empty, unknown or invalid. 407 assertTrue("getMccString() out of range [0, 999], mcc=" + mccStr, 408 mccStr == null || mccStr.matches("^[0-9]{3}$")); 409 // mccStr must either be null or match mcc integer. 410 assertTrue("MccString must match Mcc Integer, str=" + mccStr + " int=" + mcc, 411 mccStr == null || mcc == Integer.parseInt(mccStr)); 412 413 // mncStr is set as NULL if empty, unknown or invalid. 414 assertTrue("getMncString() out of range [0, 999], mnc=" + mncStr, 415 mncStr == null || mncStr.matches("^[0-9]{2,3}$")); 416 // mncStr must either be null or match mnc integer. 417 assertTrue("MncString must match Mnc Integer, str=" + mncStr + " int=" + mnc, 418 mncStr == null || mnc == Integer.parseInt(mncStr)); 419 } 420 421 // Verify lte cell information is within correct range. verifyLteInfo(CellInfoLte lte)422 private void verifyLteInfo(CellInfoLte lte) { 423 verifyCellConnectionStatus(lte.getCellConnectionStatus()); 424 verifyCellInfoLteParcelandHashcode(lte); 425 verifyCellIdentityLte(lte.getCellIdentity(), lte.isRegistered()); 426 verifyCellIdentityLteParcel(lte.getCellIdentity()); 427 verifyCellSignalStrengthLte(lte.getCellSignalStrength()); 428 verifyCellSignalStrengthLteParcel(lte.getCellSignalStrength()); 429 } 430 431 // Verify NR 5G cell information is within correct range. verifyNrInfo(CellInfoNr nr)432 private void verifyNrInfo(CellInfoNr nr) { 433 verifyCellConnectionStatus(nr.getCellConnectionStatus()); 434 verifyCellIdentityNr((CellIdentityNr) nr.getCellIdentity(), nr.isRegistered()); 435 verifyCellIdentityNrParcel((CellIdentityNr) nr.getCellIdentity()); 436 verifyCellSignalStrengthNr((CellSignalStrengthNr) nr.getCellSignalStrength()); 437 verifyCellSignalStrengthNrParcel((CellSignalStrengthNr) nr.getCellSignalStrength()); 438 } 439 verifyCellSignalStrengthNrParcel(CellSignalStrengthNr nr)440 private void verifyCellSignalStrengthNrParcel(CellSignalStrengthNr nr) { 441 Parcel p = Parcel.obtain(); 442 nr.writeToParcel(p, 0); 443 p.setDataPosition(0); 444 445 CellSignalStrengthNr newCss = CellSignalStrengthNr.CREATOR.createFromParcel(p); 446 assertEquals(nr, newCss); 447 } 448 verifyCellIdentityNrParcel(CellIdentityNr nr)449 private void verifyCellIdentityNrParcel(CellIdentityNr nr) { 450 Parcel p = Parcel.obtain(); 451 nr.writeToParcel(p, 0); 452 p.setDataPosition(0); 453 454 CellIdentityNr newCi = CellIdentityNr.CREATOR.createFromParcel(p); 455 assertEquals(nr, newCi); 456 } 457 verifyCellIdentityNr(CellIdentityNr nr, boolean isRegistered)458 private void verifyCellIdentityNr(CellIdentityNr nr, boolean isRegistered) { 459 // This class was added after numeric mcc/mncs were no longer provided, so it lacks the 460 // basic getMcc() and getMnc() - empty out those checks. 461 String mccStr = nr.getMccString(); 462 String mncStr = nr.getMncString(); 463 verifyPlmnInfo(mccStr, mncStr, 464 mccStr != null ? Integer.parseInt(mccStr) : CellInfo.UNAVAILABLE, 465 mncStr != null ? Integer.parseInt(mncStr) : CellInfo.UNAVAILABLE); 466 467 int pci = nr.getPci(); 468 assertTrue("getPci() out of range [0, 1007], pci = " + pci, 0 <= pci && pci <= 1007); 469 470 int tac = nr.getTac(); 471 assertTrue("getTac() out of range [0, 16777215], tac = " + tac, 472 (tac == Integer.MAX_VALUE) || (0 <= tac && tac <= 16777215)); 473 474 int nrArfcn = nr.getNrarfcn(); 475 assertTrue("getNrarfcn() out of range [0, 3279165], nrarfcn = " + nrArfcn, 476 0 <= nrArfcn && nrArfcn <= 3279165); 477 478 for (String plmnId : nr.getAdditionalPlmns()) { 479 verifyPlmnId(plmnId); 480 } 481 482 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_5) { 483 int[] bands = nr.getBands(); 484 485 for (int band: bands) { 486 assertTrue("getBand out of range [1, 95] or [257, 261], band = " + band, 487 (band >= BAND_FR1_MIN_NR && band <= BAND_FR1_MAX_NR) 488 || (band >= BAND_FR2_MIN_NR && band <= BAND_FR2_MAX_NR)); 489 490 verifyCellIdentityNrBands(bands); 491 } 492 } 493 494 // If the cell is reported as registered, then all the logical cell info must be reported 495 if (isRegistered) { 496 assertTrue("TAC is required for registered cells", tac != CellInfo.UNAVAILABLE); 497 assertTrue("MCC is required for registered cells", nr.getMccString() != null); 498 assertTrue("MNC is required for registered cells", nr.getMncString() != null); 499 } 500 501 verifyCellIdentityNrLocationSanitation(nr); 502 } 503 verifyCellIdentityNrLocationSanitation(CellIdentityNr nr)504 private void verifyCellIdentityNrLocationSanitation(CellIdentityNr nr) { 505 CellIdentityNr sanitized = nr.sanitizeLocationInfo(); 506 assertEquals(CellInfo.UNAVAILABLE, sanitized.getPci()); 507 assertEquals(CellInfo.UNAVAILABLE, sanitized.getTac()); 508 assertEquals(CellInfo.UNAVAILABLE_LONG, sanitized.getNci()); 509 } 510 verifyCellSignalStrengthNr(CellSignalStrengthNr nr)511 private void verifyCellSignalStrengthNr(CellSignalStrengthNr nr) { 512 int csiRsrp = nr.getCsiRsrp(); 513 int csiRsrq = nr.getCsiRsrq(); 514 int csiSinr = nr.getSsSinr(); 515 int csiCqiTableIndex = nr.getCsiCqiTableIndex(); 516 List<Integer> csiCqiReport = nr.getCsiCqiReport(); 517 int ssRsrp = nr.getSsRsrp(); 518 int ssRsrq = nr.getSsRsrq(); 519 int ssSinr = nr.getSsSinr(); 520 int timingAdvance = nr.getTimingAdvanceMicros(); 521 522 assertTrue("getCsiRsrp() out of range [-140, -44] | Integer.MAX_INTEGER, csiRsrp = " 523 + csiRsrp, -140 <= csiRsrp && csiRsrp <= -44 524 || csiRsrp == CellInfo.UNAVAILABLE); 525 assertTrue("getCsiRsrq() out of range [-20, -3] | Integer.MAX_INTEGER, csiRsrq = " 526 + csiRsrq, -20 <= csiRsrq && csiRsrq <= -3 || csiRsrq == CellInfo.UNAVAILABLE); 527 assertTrue("getCsiSinr() out of range [-23, 40] | Integer.MAX_INTEGER, csiSinr = " 528 + csiSinr, -23 <= csiSinr && csiSinr <= 40 || csiSinr == CellInfo.UNAVAILABLE); 529 assertTrue("getCsiCqiTableIndex() out of range | CellInfo.UNAVAILABLE, csiCqiTableIndex=" 530 + csiCqiTableIndex, csiCqiTableIndex == CellInfo.UNAVAILABLE 531 || (csiCqiTableIndex >= CQI_TABLE_INDEX_MIN_NR 532 && csiCqiTableIndex <= CQI_TABLE_INDEX_MAX_NR)); 533 assertTrue("cqi in getCsiCqiReport() out of range | CellInfo.UNAVAILABLE, csiCqiReport=" 534 + csiCqiReport, csiCqiReport.stream().allMatch( 535 cqi -> cqi == CellInfo.UNAVAILABLE || (cqi >= MIN_CQI && cqi <= MAX_CQI))); 536 assertTrue("getSsRsrp() out of range [-140, -44] | Integer.MAX_INTEGER, ssRsrp = " 537 + ssRsrp, -140 <= ssRsrp && ssRsrp <= -44 538 || ssRsrp == CellInfo.UNAVAILABLE); 539 assertTrue("getSsRsrq() out of range [-20, -3] | Integer.MAX_INTEGER, ssRsrq = " 540 + ssRsrq, -20 <= ssRsrq && ssRsrq <= -3 || ssRsrq == CellInfo.UNAVAILABLE); 541 assertTrue("getSsSinr() out of range [-23, 40] | Integer.MAX_INTEGER, ssSinr = " 542 + ssSinr, -23 <= ssSinr && ssSinr <= 40 || ssSinr == CellInfo.UNAVAILABLE); 543 assertTrue("getTimingAdvanceMicros() out of range [0, 1282] | Integer.MAX_INTEGER, " 544 + "timingAdvance = " + timingAdvance, 0 <= timingAdvance && timingAdvance <= 1282 545 || timingAdvance == CellInfo.UNAVAILABLE); 546 } 547 verifyCellIdentityNrBands(int[] nrBands)548 private void verifyCellIdentityNrBands(int[] nrBands) { 549 //Verify the registered cell reports non-null band. 550 assertTrue(nrBands != null); 551 552 //Verify the registered cell reports at least one band. 553 assertTrue(Arrays.stream(nrBands).anyMatch(band -> band > 0)); 554 } 555 verifyCellInfoLteParcelandHashcode(CellInfoLte lte)556 private void verifyCellInfoLteParcelandHashcode(CellInfoLte lte) { 557 Parcel p = Parcel.obtain(); 558 lte.writeToParcel(p, 0); 559 p.setDataPosition(0); 560 561 CellInfoLte newCi = CellInfoLte.CREATOR.createFromParcel(p); 562 assertTrue(lte.equals(newCi)); 563 assertEquals("hashCode() did not get right hashCode", lte.hashCode(), newCi.hashCode()); 564 } 565 verifyCellIdentityLte(CellIdentityLte lte, boolean isRegistered)566 private void verifyCellIdentityLte(CellIdentityLte lte, boolean isRegistered) { 567 verifyPlmnInfo(lte.getMccString(), lte.getMncString(), lte.getMcc(), lte.getMnc()); 568 569 // Cell identity ranges from 0 to 268435456. 570 int ci = lte.getCi(); 571 assertTrue("getCi() out of range [0,268435456], ci=" + ci, 572 (ci == CellInfo.UNAVAILABLE) || (ci >= 0 && ci <= CI)); 573 574 // Verify LTE physical cell id information. 575 // Only physical cell id is available for LTE neighbor. 576 int pci = lte.getPci(); 577 // Physical cell id should be within [0, 503]. 578 assertTrue("getPci() out of range [0, 503], pci=" + pci, (pci >= 0 && pci <= PCI)); 579 580 // Tracking area code ranges from 0 to 65535. 581 int tac = lte.getTac(); 582 assertTrue("getTac() out of range [0,65535], tac=" + tac, 583 (tac == CellInfo.UNAVAILABLE) || (tac >= 0 && tac <= TAC)); 584 585 // Bandwidth ranges from 1400 to 20000 586 int bw = lte.getBandwidth(); 587 assertTrue("getBandwidth out of range [1400, 20000] | Integer.Max_Value, bw=" + bw, 588 bw == CellInfo.UNAVAILABLE || bw >= BANDWIDTH_LOW && bw <= BANDWIDTH_HIGH); 589 590 int earfcn = lte.getEarfcn(); 591 // Reference 3GPP 36.101 Table 5.7.3-1 592 // As per NOTE 1 in the table, although 0-6 are valid channel numbers for 593 // LTE, the reported EARFCN is the center frequency, rendering these channels 594 // out of the range of the narrowest 1.4Mhz deployment. 595 int minEarfcn = 7; 596 int maxEarfcn = EARFCN_MAX - 7; 597 if (bw != CellInfo.UNAVAILABLE) { 598 // The number of channels used by a cell is equal to the cell bandwidth divided 599 // by the channel raster (bandwidth of a channel). The center channel is the channel 600 // the n/2-th channel where n is the number of channels, and since it is the center 601 // channel that is reported as the channel number for a cell, we can exclude any channel 602 // numbers within a band that would place the bottom of a cell's bandwidth below the 603 // edge of the band. For channel numbers in Band 1, the EARFCN numbering starts from 604 // channel 0, which means that we can exclude from the valid range channels starting 605 // from 0 and numbered less than half the total number of channels occupied by a cell. 606 minEarfcn = bw / CHANNEL_RASTER_EUTRAN / 2; 607 maxEarfcn = EARFCN_MAX - (bw / CHANNEL_RASTER_EUTRAN / 2); 608 } 609 assertTrue( 610 "getEarfcn() out of range [" + minEarfcn + "," + maxEarfcn + "], earfcn=" + earfcn, 611 (earfcn >= minEarfcn && earfcn <= maxEarfcn)); 612 613 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_5) { 614 int[] bands = lte.getBands(); 615 616 for (int band: bands) { 617 assertTrue("getBand out of range [1, 88], band = " + band, 618 band >= BAND_MIN_LTE && band <= BAND_MAX_LTE); 619 620 verifyCellIdentityLteBands(bands); 621 } 622 } 623 624 verifyPlmnId(lte.getMobileNetworkOperator()); 625 626 for (String plmnId : lte.getAdditionalPlmns()) { 627 verifyPlmnId(plmnId); 628 } 629 630 verifyCsgInfo(lte.getClosedSubscriberGroupInfo()); 631 632 verifyCellIdentityLteLocationSanitation(lte); 633 634 // If the cell is reported as registered, then all the logical cell info must be reported 635 if (isRegistered) { 636 assertTrue("TAC is required for registered cells", tac != CellInfo.UNAVAILABLE); 637 assertTrue("CID is required for registered cells", ci != CellInfo.UNAVAILABLE); 638 assertTrue("MCC is required for registered cells", 639 lte.getMccString() != null || lte.getMcc() != CellInfo.UNAVAILABLE); 640 assertTrue("MNC is required for registered cells", 641 lte.getMncString() != null || lte.getMnc() != CellInfo.UNAVAILABLE); 642 assertFalse("PLMN-ID is required for registered cells", 643 TextUtils.isEmpty(lte.getMobileNetworkOperator())); 644 } 645 } 646 verifyCellIdentityLteLocationSanitation(CellIdentityLte lte)647 private void verifyCellIdentityLteLocationSanitation(CellIdentityLte lte) { 648 CellIdentityLte sanitized = lte.sanitizeLocationInfo(); 649 assertEquals(CellInfo.UNAVAILABLE, sanitized.getCi()); 650 assertEquals(CellInfo.UNAVAILABLE, sanitized.getEarfcn()); 651 assertEquals(CellInfo.UNAVAILABLE, sanitized.getPci()); 652 assertEquals(CellInfo.UNAVAILABLE, sanitized.getTac()); 653 } 654 verifyCellIdentityLteParcel(CellIdentityLte lte)655 private void verifyCellIdentityLteParcel(CellIdentityLte lte) { 656 Parcel p = Parcel.obtain(); 657 lte.writeToParcel(p, 0); 658 p.setDataPosition(0); 659 660 CellIdentityLte newci = CellIdentityLte.CREATOR.createFromParcel(p); 661 assertEquals(lte, newci); 662 } 663 verifyCellSignalStrengthLte(CellSignalStrengthLte cellSignalStrengthLte)664 private void verifyCellSignalStrengthLte(CellSignalStrengthLte cellSignalStrengthLte) { 665 verifyRssiDbm(cellSignalStrengthLte.getDbm()); 666 667 //ICellInfo.UNAVAILABLE indicates an unavailable field 668 int rsrp = cellSignalStrengthLte.getRsrp(); 669 // RSRP is being treated as RSSI in LTE (they are similar but not quite right) 670 // so reusing the constants here. 671 assertTrue("getRsrp() out of range, rsrp=" + rsrp, rsrp >= MIN_RSRP && rsrp <= MAX_RSRP); 672 673 int rsrq = cellSignalStrengthLte.getRsrq(); 674 assertTrue("getRsrq() out of range | CellInfo.UNAVAILABLE, rsrq=" + rsrq, 675 rsrq == CellInfo.UNAVAILABLE || (rsrq >= MIN_RSRQ && rsrq <= MAX_RSRQ)); 676 677 int rssi = cellSignalStrengthLte.getRssi(); 678 assertTrue("getRssi() out of range [-113, -51] or CellInfo.UNAVAILABLE if unknown, rssi=" 679 + rssi, rssi == CellInfo.UNAVAILABLE 680 || (rssi >= MIN_LTE_RSSI && rssi <= MAX_LTE_RSSI)); 681 682 int rssnr = cellSignalStrengthLte.getRssnr(); 683 assertTrue("getRssnr() out of range | CellInfo.UNAVAILABLE, rssnr=" + rssnr, 684 rssnr == CellInfo.UNAVAILABLE || (rssnr >= MIN_RSSNR && rssnr <= MAX_RSSNR)); 685 686 int cqiTableIndex = cellSignalStrengthLte.getCqiTableIndex(); 687 assertTrue("getCqiTableIndex() out of range | CellInfo.UNAVAILABLE, cqi=" + cqiTableIndex, 688 cqiTableIndex == CellInfo.UNAVAILABLE || (cqiTableIndex >= CQI_TABLE_INDEX_MIN_LTE 689 && cqiTableIndex <= CQI_TABLE_INDEX_MAX_LTE)); 690 691 int cqi = cellSignalStrengthLte.getCqi(); 692 assertTrue("getCqi() out of range | CellInfo.UNAVAILABLE, cqi=" + cqi, 693 cqi == CellInfo.UNAVAILABLE || (cqi >= MIN_CQI && cqi <= MAX_CQI)); 694 695 int ta = cellSignalStrengthLte.getTimingAdvance(); 696 assertTrue("getTimingAdvance() invalid [0-1282] | CellInfo.UNAVAILABLE, ta=" + ta, 697 ta == CellInfo.UNAVAILABLE || (ta >= 0 && ta <= 1282)); 698 699 int level = cellSignalStrengthLte.getLevel(); 700 assertTrue("getLevel() out of range [0,4], level=" + level, level >= 0 && level <= 4); 701 702 int asuLevel = cellSignalStrengthLte.getAsuLevel(); 703 assertTrue("getAsuLevel() out of range [0,97] (or 99 is unknown), asuLevel=" + asuLevel, 704 (asuLevel == 99) || (asuLevel >= 0 && asuLevel <= 97)); 705 706 int timingAdvance = cellSignalStrengthLte.getTimingAdvance(); 707 assertTrue("getTimingAdvance() out of range [0,1282], timingAdvance=" + timingAdvance, 708 timingAdvance == CellInfo.UNAVAILABLE 709 || (timingAdvance >= 0 && timingAdvance <= 1282)); 710 711 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_2) { 712 assertTrue("RSRP Must be valid for LTE", 713 cellSignalStrengthLte.getRsrp() != CellInfo.UNAVAILABLE); 714 } 715 } 716 verifyCellSignalStrengthLteParcel(CellSignalStrengthLte cellSignalStrengthLte)717 private void verifyCellSignalStrengthLteParcel(CellSignalStrengthLte cellSignalStrengthLte) { 718 Parcel p = Parcel.obtain(); 719 cellSignalStrengthLte.writeToParcel(p, 0); 720 p.setDataPosition(0); 721 722 CellSignalStrengthLte newCss = CellSignalStrengthLte.CREATOR.createFromParcel(p); 723 assertEquals(cellSignalStrengthLte, newCss); 724 } 725 verifyCellIdentityLteBands(int[] lteBands)726 private void verifyCellIdentityLteBands(int[] lteBands) { 727 //Verify the registered cell reports non-null band. 728 assertTrue(lteBands != null); 729 730 //Verify the registered cell reports at least one band. 731 assertTrue(Arrays.stream(lteBands).anyMatch(band -> band > 0)); 732 } 733 734 // Verify wcdma cell information is within correct range. verifyWcdmaInfo(CellInfoWcdma wcdma)735 private void verifyWcdmaInfo(CellInfoWcdma wcdma) { 736 verifyCellConnectionStatus(wcdma.getCellConnectionStatus()); 737 verifyCellInfoWcdmaParcelandHashcode(wcdma); 738 verifyCellIdentityWcdma(wcdma.getCellIdentity(), wcdma.isRegistered()); 739 verifyCellIdentityWcdmaParcel(wcdma.getCellIdentity()); 740 verifyCellSignalStrengthWcdma(wcdma.getCellSignalStrength()); 741 verifyCellSignalStrengthWcdmaParcel(wcdma.getCellSignalStrength()); 742 } 743 verifyCellInfoWcdmaParcelandHashcode(CellInfoWcdma wcdma)744 private void verifyCellInfoWcdmaParcelandHashcode(CellInfoWcdma wcdma) { 745 Parcel p = Parcel.obtain(); 746 wcdma.writeToParcel(p, 0); 747 p.setDataPosition(0); 748 749 CellInfoWcdma newCi = CellInfoWcdma.CREATOR.createFromParcel(p); 750 assertTrue(wcdma.equals(newCi)); 751 assertEquals("hashCode() did not get right hashCode", wcdma.hashCode(), newCi.hashCode()); 752 } 753 verifyCellIdentityWcdma(CellIdentityWcdma wcdma, boolean isRegistered)754 private void verifyCellIdentityWcdma(CellIdentityWcdma wcdma, boolean isRegistered) { 755 verifyPlmnInfo(wcdma.getMccString(), wcdma.getMncString(), wcdma.getMcc(), wcdma.getMnc()); 756 757 int lac = wcdma.getLac(); 758 assertTrue("getLac() out of range [0, 65535], lac=" + lac, 759 (lac >= 0 && lac <= LAC) || lac == CellInfo.UNAVAILABLE); 760 761 int cid = wcdma.getCid(); 762 assertTrue("getCid() out of range [0, 268435455], cid=" + cid, 763 (cid >= 0 && cid <= CID_UMTS) || cid == CellInfo.UNAVAILABLE); 764 765 // Verify wcdma primary scrambling code information. 766 // Primary scrambling code should be within [0, 511]. 767 int psc = wcdma.getPsc(); 768 assertTrue("getPsc() out of range [0, 511], psc=" + psc, psc >= 0 && psc <= PSC); 769 770 verifyPlmnId(wcdma.getMobileNetworkOperator()); 771 772 int uarfcn = wcdma.getUarfcn(); 773 // Reference 3GPP 25.101 Table 5.2 774 // From Appendix E.1, even though UARFCN is numbered from 400, the minumum 775 // usable channel is 412 due to the fixed bandwidth of 5Mhz 776 assertTrue("getUarfcn() out of range [412,11000], uarfcn=" + uarfcn, 777 uarfcn >= 412 && uarfcn <= 11000); 778 779 for (String plmnId : wcdma.getAdditionalPlmns()) { 780 verifyPlmnId(plmnId); 781 } 782 783 verifyCsgInfo(wcdma.getClosedSubscriberGroupInfo()); 784 785 // If the cell is reported as registered, then all the logical cell info must be reported 786 if (isRegistered) { 787 assertTrue("LAC is required for registered cells", lac != CellInfo.UNAVAILABLE); 788 assertTrue("CID is required for registered cells", cid != CellInfo.UNAVAILABLE); 789 assertTrue("MCC is required for registered cells", 790 wcdma.getMccString() != null || wcdma.getMcc() != CellInfo.UNAVAILABLE); 791 assertTrue("MNC is required for registered cells", 792 wcdma.getMncString() != null || wcdma.getMnc() != CellInfo.UNAVAILABLE); 793 assertFalse("PLMN-ID is required for registered cells", 794 TextUtils.isEmpty(wcdma.getMobileNetworkOperator())); 795 } 796 797 verifyCellIdentityWcdmaLocationSanitation(wcdma); 798 } 799 verifyCellIdentityWcdmaLocationSanitation(CellIdentityWcdma wcdma)800 private void verifyCellIdentityWcdmaLocationSanitation(CellIdentityWcdma wcdma) { 801 CellIdentityWcdma sanitized = wcdma.sanitizeLocationInfo(); 802 assertEquals(CellInfo.UNAVAILABLE, sanitized.getLac()); 803 assertEquals(CellInfo.UNAVAILABLE, sanitized.getCid()); 804 assertEquals(CellInfo.UNAVAILABLE, sanitized.getPsc()); 805 assertEquals(CellInfo.UNAVAILABLE, sanitized.getUarfcn()); 806 } 807 verifyCellIdentityWcdmaParcel(CellIdentityWcdma wcdma)808 private void verifyCellIdentityWcdmaParcel(CellIdentityWcdma wcdma) { 809 Parcel p = Parcel.obtain(); 810 wcdma.writeToParcel(p, 0); 811 p.setDataPosition(0); 812 813 CellIdentityWcdma newci = CellIdentityWcdma.CREATOR.createFromParcel(p); 814 assertEquals(wcdma, newci); 815 } 816 verifyCellSignalStrengthWcdma(CellSignalStrengthWcdma wcdma)817 private void verifyCellSignalStrengthWcdma(CellSignalStrengthWcdma wcdma) { 818 verifyRssiDbm(wcdma.getDbm()); 819 820 // Dbm here does not have specific limits. So just calling to verify that it does not crash 821 // the phone 822 wcdma.getDbm(); 823 824 int asuLevel = wcdma.getAsuLevel(); 825 if (wcdma.getRscp() != CellInfo.UNAVAILABLE) { 826 assertTrue("getAsuLevel() out of range 0..96, 255), asuLevel=" + asuLevel, 827 asuLevel == 255 || (asuLevel >= 0 && asuLevel <= 96)); 828 } else if (wcdma.getRssi() != CellInfo.UNAVAILABLE) { 829 assertTrue("getAsuLevel() out of range 0..31, 99), asuLevel=" + asuLevel, 830 asuLevel == 99 || (asuLevel >= 0 && asuLevel <= 31)); 831 } else { 832 assertTrue("getAsuLevel() out of range 0..96, 255), asuLevel=" + asuLevel, 833 asuLevel == 255); 834 } 835 836 int level = wcdma.getLevel(); 837 assertTrue("getLevel() out of range [0,4], level=" + level, level >= 0 && level <= 4); 838 839 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_2) { 840 assertTrue("RSCP Must be valid for WCDMA", wcdma.getRscp() != CellInfo.UNAVAILABLE); 841 } 842 843 int ecNo = wcdma.getEcNo(); 844 assertTrue("getEcNo() out of range [-24,1], EcNo=" + ecNo, 845 (ecNo >= -24 && ecNo <= 1) || ecNo == CellInfo.UNAVAILABLE); 846 } 847 verifyCellSignalStrengthWcdmaParcel(CellSignalStrengthWcdma wcdma)848 private void verifyCellSignalStrengthWcdmaParcel(CellSignalStrengthWcdma wcdma) { 849 Parcel p = Parcel.obtain(); 850 wcdma.writeToParcel(p, 0); 851 p.setDataPosition(0); 852 853 CellSignalStrengthWcdma newCss = CellSignalStrengthWcdma.CREATOR.createFromParcel(p); 854 assertEquals(wcdma, newCss); 855 } 856 857 // Verify gsm cell information is within correct range. verifyGsmInfo(CellInfoGsm gsm)858 private void verifyGsmInfo(CellInfoGsm gsm) { 859 verifyCellConnectionStatus(gsm.getCellConnectionStatus()); 860 verifyCellInfoWcdmaParcelandHashcode(gsm); 861 verifyCellIdentityGsm(gsm.getCellIdentity(), gsm.isRegistered()); 862 verifyCellIdentityGsmParcel(gsm.getCellIdentity()); 863 verifyCellSignalStrengthGsm(gsm.getCellSignalStrength()); 864 verifyCellSignalStrengthGsmParcel(gsm.getCellSignalStrength()); 865 } 866 verifyCellInfoWcdmaParcelandHashcode(CellInfoGsm gsm)867 private void verifyCellInfoWcdmaParcelandHashcode(CellInfoGsm gsm) { 868 Parcel p = Parcel.obtain(); 869 gsm.writeToParcel(p, 0); 870 p.setDataPosition(0); 871 872 CellInfoGsm newCi = CellInfoGsm.CREATOR.createFromParcel(p); 873 assertTrue(gsm.equals(newCi)); 874 assertEquals("hashCode() did not get right hashCode", gsm.hashCode(), newCi.hashCode()); 875 } 876 verifyCellIdentityGsm(CellIdentityGsm gsm, boolean isRegistered)877 private void verifyCellIdentityGsm(CellIdentityGsm gsm, boolean isRegistered) { 878 verifyPlmnInfo(gsm.getMccString(), gsm.getMncString(), gsm.getMcc(), gsm.getMnc()); 879 880 // Local area code and cellid should be with [0, 65535]. 881 int lac = gsm.getLac(); 882 assertTrue("getLac() out of range [0, 65535], lac=" + lac, 883 lac == CellInfo.UNAVAILABLE || (lac >= 0 && lac <= LAC)); 884 int cid = gsm.getCid(); 885 assertTrue("getCid() out range [0, 65535], cid=" + cid, 886 cid == CellInfo.UNAVAILABLE || (cid >= 0 && cid <= CID_GSM)); 887 888 int arfcn = gsm.getArfcn(); 889 // Reference 3GPP 45.005 Table 2-2 890 assertTrue("getArfcn() out of range [0,1024], arfcn=" + arfcn, 891 arfcn == CellInfo.UNAVAILABLE || (arfcn >= 0 && arfcn <= ARFCN)); 892 893 int bsic = gsm.getBsic(); 894 assertTrue("getBsic() out of range [0,63]", bsic >= 0 && bsic <= 63); 895 896 for (String plmnId : gsm.getAdditionalPlmns()) { 897 verifyPlmnId(plmnId); 898 } 899 verifyPlmnId(gsm.getMobileNetworkOperator()); 900 901 // If the cell is reported as registered, then all the logical cell info must be reported 902 if (isRegistered) { 903 assertTrue("LAC is required for registered cells", lac != CellInfo.UNAVAILABLE); 904 assertTrue("CID is required for registered cells", cid != CellInfo.UNAVAILABLE); 905 assertTrue("MCC is required for registered cells", 906 gsm.getMccString() != null || gsm.getMcc() != CellInfo.UNAVAILABLE); 907 assertTrue("MNC is required for registered cells", 908 gsm.getMncString() != null || gsm.getMnc() != CellInfo.UNAVAILABLE); 909 assertFalse("PLMN-ID is required for registered cells", 910 TextUtils.isEmpty(gsm.getMobileNetworkOperator())); 911 } 912 913 verifyCellIdentityGsmLocationSanitation(gsm); 914 } 915 verifyCellIdentityGsmLocationSanitation(CellIdentityGsm gms)916 private void verifyCellIdentityGsmLocationSanitation(CellIdentityGsm gms) { 917 CellIdentityGsm sanitized = gms.sanitizeLocationInfo(); 918 assertEquals(CellInfo.UNAVAILABLE, sanitized.getLac()); 919 assertEquals(CellInfo.UNAVAILABLE, sanitized.getCid()); 920 assertEquals(CellInfo.UNAVAILABLE, sanitized.getArfcn()); 921 assertEquals(CellInfo.UNAVAILABLE, sanitized.getBsic()); 922 } 923 verifyCellIdentityGsmParcel(CellIdentityGsm gsm)924 private void verifyCellIdentityGsmParcel(CellIdentityGsm gsm) { 925 Parcel p = Parcel.obtain(); 926 gsm.writeToParcel(p, 0); 927 p.setDataPosition(0); 928 929 CellIdentityGsm newci = CellIdentityGsm.CREATOR.createFromParcel(p); 930 assertEquals(gsm, newci); 931 } 932 verifyCellSignalStrengthGsm(CellSignalStrengthGsm gsm)933 private void verifyCellSignalStrengthGsm(CellSignalStrengthGsm gsm) { 934 verifyRssiDbm(gsm.getDbm()); 935 936 int level = gsm.getLevel(); 937 assertTrue("getLevel() out of range [0,4], level=" + level, level >= 0 && level <= 4); 938 939 int ta = gsm.getTimingAdvance(); 940 assertTrue("getTimingAdvance() out of range [0,219] | CellInfo.UNAVAILABLE, ta=" + ta, 941 ta == CellInfo.UNAVAILABLE || (ta >= 0 && ta <= 219)); 942 943 assertEquals(gsm.getDbm(), gsm.getRssi()); 944 945 int asuLevel = gsm.getAsuLevel(); 946 assertTrue("getLevel() out of range [0,31] (or 99 is unknown), level=" + asuLevel, 947 asuLevel == 99 || (asuLevel >=0 && asuLevel <= 31)); 948 949 int ber = gsm.getBitErrorRate(); 950 assertTrue("getBitErrorRate out of range [0,7], 99, or CellInfo.UNAVAILABLE, ber=" + ber, 951 ber == 99 || ber == CellInfo.UNAVAILABLE || (ber >= 0 && ber <= 7)); 952 953 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_2) { 954 assertTrue("RSSI Must be valid for GSM", gsm.getDbm() != CellInfo.UNAVAILABLE); 955 } 956 } 957 verifyCellSignalStrengthGsmParcel(CellSignalStrengthGsm gsm)958 private void verifyCellSignalStrengthGsmParcel(CellSignalStrengthGsm gsm) { 959 Parcel p = Parcel.obtain(); 960 gsm.writeToParcel(p, 0); 961 p.setDataPosition(0); 962 963 CellSignalStrengthGsm newCss = CellSignalStrengthGsm.CREATOR.createFromParcel(p); 964 assertEquals(gsm, newCss); 965 } 966 967 // Verify tdscdma cell information is within correct range. verifyTdscdmaInfo(CellInfoTdscdma tdscdma)968 private void verifyTdscdmaInfo(CellInfoTdscdma tdscdma) { 969 verifyCellConnectionStatus(tdscdma.getCellConnectionStatus()); 970 verifyCellInfoTdscdmaParcelandHashcode(tdscdma); 971 verifyCellIdentityTdscdma(tdscdma.getCellIdentity(), tdscdma.isRegistered()); 972 verifyCellIdentityTdscdmaParcel(tdscdma.getCellIdentity()); 973 verifyCellSignalStrengthTdscdma(tdscdma.getCellSignalStrength()); 974 verifyCellSignalStrengthTdscdmaParcel(tdscdma.getCellSignalStrength()); 975 } 976 verifyCellInfoTdscdmaParcelandHashcode(CellInfoTdscdma tdscdma)977 private void verifyCellInfoTdscdmaParcelandHashcode(CellInfoTdscdma tdscdma) { 978 Parcel p = Parcel.obtain(); 979 tdscdma.writeToParcel(p, 0); 980 p.setDataPosition(0); 981 982 CellInfoTdscdma newCi = CellInfoTdscdma.CREATOR.createFromParcel(p); 983 assertTrue(tdscdma.equals(newCi)); 984 assertEquals("hashCode() did not get right hashCode", tdscdma.hashCode(), newCi.hashCode()); 985 } 986 verifyCellIdentityTdscdma(CellIdentityTdscdma tdscdma, boolean isRegistered)987 private void verifyCellIdentityTdscdma(CellIdentityTdscdma tdscdma, boolean isRegistered) { 988 String mccStr = tdscdma.getMccString(); 989 String mncStr = tdscdma.getMncString(); 990 991 // This class was added after numeric mcc/mncs were no longer provided, so it lacks the 992 // basic getMcc() and getMnc() - empty out those checks. 993 verifyPlmnInfo(tdscdma.getMccString(), tdscdma.getMncString(), 994 mccStr != null ? Integer.parseInt(mccStr) : CellInfo.UNAVAILABLE, 995 mncStr != null ? Integer.parseInt(mncStr) : CellInfo.UNAVAILABLE); 996 997 int lac = tdscdma.getLac(); 998 assertTrue("getLac() out of range [0, 65535], lac=" + lac, 999 (lac >= 0 && lac <= LAC) || lac == CellInfo.UNAVAILABLE); 1000 1001 int cid = tdscdma.getCid(); 1002 assertTrue("getCid() out of range [0, 268435455], cid=" + cid, 1003 (cid >= 0 && cid <= CID_UMTS) || cid == CellInfo.UNAVAILABLE); 1004 1005 // Verify tdscdma primary scrambling code information. 1006 // Primary scrambling code should be within [0, 511]. 1007 int cpid = tdscdma.getCpid(); 1008 assertTrue("getCpid() out of range [0, 127], cpid=" + cpid, (cpid >= 0 && cpid <= CPID)); 1009 1010 verifyPlmnId(tdscdma.getMobileNetworkOperator()); 1011 1012 int uarfcn = tdscdma.getUarfcn(); 1013 // Reference 3GPP 25.101 Table 5.2 1014 // From Appendix E.1, even though UARFCN is numbered from 400, the minumum 1015 // usable channel is 412 due to the fixed bandwidth of 5Mhz 1016 assertTrue("getUarfcn() out of range [412,11000], uarfcn=" + uarfcn, 1017 uarfcn >= 412 && uarfcn <= 11000); 1018 1019 for (String plmnId : tdscdma.getAdditionalPlmns()) { 1020 verifyPlmnId(plmnId); 1021 } 1022 1023 verifyCsgInfo(tdscdma.getClosedSubscriberGroupInfo()); 1024 1025 // If the cell is reported as registered, then all the logical cell info must be reported 1026 if (isRegistered) { 1027 assertTrue("LAC is required for registered cells", lac != CellInfo.UNAVAILABLE); 1028 assertTrue("CID is required for registered cells", cid != CellInfo.UNAVAILABLE); 1029 assertTrue("MCC is required for registered cells", tdscdma.getMccString() != null); 1030 assertTrue("MNC is required for registered cells", tdscdma.getMncString() != null); 1031 assertFalse("PLMN-ID is required for registered cells", 1032 TextUtils.isEmpty(tdscdma.getMobileNetworkOperator())); 1033 } 1034 1035 verifyCellIdentityTdscdmaLocationSanitation(tdscdma); 1036 } 1037 verifyCellIdentityTdscdmaLocationSanitation(CellIdentityTdscdma tdscdma)1038 private void verifyCellIdentityTdscdmaLocationSanitation(CellIdentityTdscdma tdscdma) { 1039 CellIdentityTdscdma sanitized = tdscdma.sanitizeLocationInfo(); 1040 assertEquals(CellInfo.UNAVAILABLE, sanitized.getLac()); 1041 assertEquals(CellInfo.UNAVAILABLE, sanitized.getCid()); 1042 assertEquals(CellInfo.UNAVAILABLE, sanitized.getCpid()); 1043 assertEquals(CellInfo.UNAVAILABLE, sanitized.getUarfcn()); 1044 } 1045 verifyCellIdentityTdscdmaParcel(CellIdentityTdscdma tdscdma)1046 private void verifyCellIdentityTdscdmaParcel(CellIdentityTdscdma tdscdma) { 1047 Parcel p = Parcel.obtain(); 1048 tdscdma.writeToParcel(p, 0); 1049 p.setDataPosition(0); 1050 1051 CellIdentityTdscdma newci = CellIdentityTdscdma.CREATOR.createFromParcel(p); 1052 assertEquals(tdscdma, newci); 1053 } 1054 verifyCellSignalStrengthTdscdma(CellSignalStrengthTdscdma tdscdma)1055 private void verifyCellSignalStrengthTdscdma(CellSignalStrengthTdscdma tdscdma) { 1056 verifyRssiDbm(tdscdma.getDbm()); 1057 1058 // Dbm here does not have specific limits. So just calling to verify that it does not crash 1059 // the phone 1060 tdscdma.getDbm(); 1061 1062 int asuLevel = tdscdma.getAsuLevel(); 1063 assertTrue("getLevel() out of range [0,31] (or 99 is unknown), level=" + asuLevel, 1064 asuLevel == 99 || (asuLevel >= 0 && asuLevel <= 31)); 1065 1066 int level = tdscdma.getLevel(); 1067 assertTrue("getLevel() out of range [0,4], level=" + level, level >= 0 && level <= 4); 1068 1069 if (mNetworkHalVersion >= RADIO_HAL_VERSION_1_2) { 1070 assertTrue("RSCP Must be valid for TDSCDMA", tdscdma.getRscp() != CellInfo.UNAVAILABLE); 1071 } 1072 } 1073 verifyCellSignalStrengthTdscdmaParcel(CellSignalStrengthTdscdma tdscdma)1074 private void verifyCellSignalStrengthTdscdmaParcel(CellSignalStrengthTdscdma tdscdma) { 1075 Parcel p = Parcel.obtain(); 1076 tdscdma.writeToParcel(p, 0); 1077 p.setDataPosition(0); 1078 1079 CellSignalStrengthTdscdma newCss = CellSignalStrengthTdscdma.CREATOR.createFromParcel(p); 1080 assertEquals(tdscdma, newCss); 1081 } 1082 1083 // Rssi(in dbm) should be within [MIN_RSSI, MAX_RSSI]. verifyRssiDbm(int dbm)1084 private static void verifyRssiDbm(int dbm) { 1085 assertTrue("getCellSignalStrength().getDbm() out of range, dbm=" + dbm, 1086 dbm >= MIN_RSSI && dbm <= MAX_RSSI); 1087 } 1088 verifyCellConnectionStatus(int status)1089 private static void verifyCellConnectionStatus(int status) { 1090 assertTrue("getCellConnectionStatus() invalid [0,2] | Integer.MAX_VALUE, status=", 1091 status == CellInfo.CONNECTION_NONE 1092 || status == CellInfo.CONNECTION_PRIMARY_SERVING 1093 || status == CellInfo.CONNECTION_SECONDARY_SERVING 1094 || status == CellInfo.CONNECTION_UNKNOWN); 1095 } 1096 verifyPlmnId(String plmnId)1097 private static void verifyPlmnId(String plmnId) { 1098 if (TextUtils.isEmpty(plmnId)) return; 1099 1100 assertTrue("PlmnId() out of range [00000 - 999999], PLMN ID=" + plmnId, 1101 plmnId.matches("^[0-9]{5,6}$")); 1102 } 1103 verifyCsgInfo(@ullable ClosedSubscriberGroupInfo csgInfo)1104 private static void verifyCsgInfo(@Nullable ClosedSubscriberGroupInfo csgInfo) { 1105 if (csgInfo == null) return; 1106 1107 // This is boolean, so as long as it doesn't crash, we're good. 1108 csgInfo.getCsgIndicator(); 1109 // This is nullable, and it's free-form so all we can do is ensure it doesn't crash. 1110 csgInfo.getHomeNodebName(); 1111 1112 // It might be technically possible to have a CSG ID of zero, but if that's the case 1113 // then let someone complain about it. It's far more likely that if it's '0', then there 1114 // is a bug. 1115 assertTrue("CSG Identity out of range", csgInfo.getCsgIdentity() > 0 1116 && csgInfo.getCsgIdentity() <= 0x7FFFFF); 1117 } 1118 } 1119