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