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 27 import android.annotation.Nullable; 28 import android.content.Context; 29 import android.content.pm.PackageManager; 30 import android.os.Parcel; 31 import android.os.SystemClock; 32 import android.telephony.AccessNetworkConstants; 33 import android.telephony.CellIdentity; 34 import android.telephony.CellIdentityCdma; 35 import android.telephony.CellIdentityGsm; 36 import android.telephony.CellIdentityLte; 37 import android.telephony.CellIdentityNr; 38 import android.telephony.CellIdentityTdscdma; 39 import android.telephony.CellIdentityWcdma; 40 import android.telephony.CellInfo; 41 import android.telephony.CellInfoCdma; 42 import android.telephony.CellInfoGsm; 43 import android.telephony.CellInfoLte; 44 import android.telephony.CellInfoNr; 45 import android.telephony.CellInfoTdscdma; 46 import android.telephony.CellInfoWcdma; 47 import android.telephony.CellSignalStrengthCdma; 48 import android.telephony.CellSignalStrengthGsm; 49 import android.telephony.CellSignalStrengthLte; 50 import android.telephony.CellSignalStrengthNr; 51 import android.telephony.CellSignalStrengthTdscdma; 52 import android.telephony.CellSignalStrengthWcdma; 53 import android.telephony.ClosedSubscriberGroupInfo; 54 import android.telephony.NetworkRegistrationInfo; 55 import android.telephony.PhoneStateListener; 56 import android.telephony.ServiceState; 57 import android.telephony.TelephonyManager; 58 import android.text.TextUtils; 59 import android.util.Log; 60 import android.util.Pair; 61 62 import androidx.test.InstrumentationRegistry; 63 64 import org.junit.Before; 65 import org.junit.Test; 66 67 import java.util.Arrays; 68 import java.util.List; 69 import java.util.concurrent.Executor; 70 71 /** 72 * Test TelephonyManager.getAllCellInfo() 73 * <p> 74 * 75 * Test that the Cellular Location APIs return proper and complete information. 76 * <ul> 77 * <li>At least one cell must be reported as the registered cell. 78 * <li>Registered cells must report the technology-specific fields consisting of a globally 79 * unique cell identifier. 80 * <li>All cells must report a technology-specific physical cell identifier, such as a tuple 81 * of the frequency and a phyisical cell ID that allows them to be uniquely identified 82 * given a known global cell. 83 * <li>All cells must report at least one valid power measurement. 84 * </ul> 85 * 86 */ 87 public class CellInfoTest { 88 private static final String TAG = "android.telephony.cts.CellInfoTest"; 89 90 // Maximum and minimum possible RSSI values(in dbm). 91 private static final int MAX_RSSI = -10; 92 private static final int MIN_RSSI = -150; 93 // Maximum and minimum possible RSRP values(in dbm). 94 private static final int MAX_RSRP = -44; 95 private static final int MIN_RSRP = -140; 96 // Maximum and minimum possible RSRQ values. 97 private static final int MAX_RSRQ = -3; 98 private static final int MIN_RSRQ = -35; 99 // Maximum and minimum possible RSSNR values. 100 private static final int MAX_RSSNR = 30; 101 private static final int MIN_RSSNR = -20; 102 // Maximum and minimum possible CQI values. 103 private static final int MAX_CQI = 15; 104 private static final int MIN_CQI = 0; 105 106 /** 107 * Maximum and minimum valid LTE RSSI values in dBm 108 * 109 * The valid RSSI ASU range from current HAL is [0,31]. 110 * Convert RSSI ASU to dBm: dBm = -113 + 2 * ASU, which is [-113, -51] 111 * 112 * Reference: TS 27.007 8.5 - Signal quality +CSQ 113 */ 114 private static final int MAX_LTE_RSSI = -51; 115 private static final int MIN_LTE_RSSI = -113; 116 117 // The followings are parameters for testing CellIdentityCdma 118 // Network Id ranges from 0 to 65535. 119 private static final int NETWORK_ID = 65535; 120 // CDMA System Id ranges from 0 to 32767 121 private static final int SYSTEM_ID = 32767; 122 // Base Station Id ranges from 0 to 65535 123 private static final int BASESTATION_ID = 65535; 124 // Longitude ranges from -2592000 to 2592000. 125 private static final int LONGITUDE = 2592000; 126 // Latitude ranges from -1296000 to 1296000. 127 private static final int LATITUDE = 1296000; 128 // Cell identity ranges from 0 to 268435456. 129 130 // The followings are parameters for testing CellIdentityLte 131 private static final int CI = 268435456; 132 // Physical cell id ranges from 0 to 503. 133 private static final int PCI = 503; 134 // Tracking area code ranges from 0 to 65535. 135 private static final int TAC = 65535; 136 // Absolute RF Channel Number ranges from 0 to 262143. 137 private static final int EARFCN_MAX = 262143; 138 private static final int BANDWIDTH_LOW = 1400; // kHz 139 private static final int BANDWIDTH_HIGH = 20000; // kHz 140 // 3GPP TS 36.101 141 private static final int BAND_MIN_LTE = 1; 142 private static final int BAND_MAX_LTE = 88; 143 //3GPP TS 136.213 section 7.2.3 144 private static final int CQI_TABLE_INDEX_MIN_LTE = 1; 145 private static final int CQI_TABLE_INDEX_MAX_LTE = 6; 146 147 // The followings are parameters for testing CellIdentityWcdma 148 // Location Area Code ranges from 0 to 65535. 149 private static final int LAC = 65535; 150 // UMTS Cell Identity ranges from 0 to 268435455. 151 private static final int CID_UMTS = 268435455; 152 // Primary Scrambling Code ranges from 0 to 511. 153 private static final int PSC = 511; 154 // Cell Parameters Index rangest from 0-127. 155 private static final int CPID = 127; 156 157 // The followings are parameters for testing CellIdentityGsm 158 // GSM Cell Identity ranges from 0 to 65535. 159 private static final int CID_GSM = 65535; 160 // GSM Absolute RF Channel Number ranges from 0 to 65535. 161 private static final int ARFCN = 1024; 162 163 // The followings are parameters for testing CellIdentityNr 164 // 3GPP TS 38.101-1 and 38.101-2 165 private static final int BAND_FR1_MIN_NR = 1; 166 private static final int BAND_FR1_MAX_NR = 95; 167 private static final int BAND_FR2_MIN_NR = 257; 168 private static final int BAND_FR2_MAX_NR = 261; 169 //3GPP TS 138.214 section 5.2.2.1 170 private static final int CQI_TABLE_INDEX_MIN_NR = 1; 171 private static final int CQI_TABLE_INDEX_MAX_NR = 3; 172 173 // 3gpp 36.101 Sec 5.7.2 174 private static final int CHANNEL_RASTER_EUTRAN = 100; //kHz 175 176 private static final int MAX_CELLINFO_WAIT_MILLIS = 5000; 177 private static final int MAX_LISTENER_WAIT_MILLIS = 1000; // usually much less 178 // The maximum interval between CellInfo updates from the modem. In the AOSP code it varies 179 // between 2 and 10 seconds, and there is an allowable modem delay of 3 seconds, so if we 180 // cannot get a seconds CellInfo update within 15 seconds, then something is broken. 181 // See DeviceStateMonitor#CELL_INFO_INTERVAL_* 182 private static final int MAX_CELLINFO_INTERVAL_MILLIS = 15000; // in AOSP the max is 10s 183 private static final int RADIO_HAL_VERSION_1_2 = makeRadioVersion(1, 2); 184 private static final int RADIO_HAL_VERSION_1_5 = makeRadioVersion(1, 5); 185 186 private PackageManager mPm; 187 private TelephonyManager mTm; 188 189 private int mRadioHalVersion; 190 makeRadioVersion(int major, int minor)191 private static final int makeRadioVersion(int major, int minor) { 192 if (major < 0 || minor < 0) return 0; 193 return major * 100 + minor; 194 } 195 196 private Executor mSimpleExecutor = new Executor() { 197 @Override 198 public void execute(Runnable r) { 199 r.run(); 200 } 201 }; 202 203 private static class CellInfoResultsCallback extends TelephonyManager.CellInfoCallback { 204 List<CellInfo> cellInfo; 205 206 @Override onCellInfo(List<CellInfo> cellInfo)207 public synchronized void onCellInfo(List<CellInfo> cellInfo) { 208 this.cellInfo = cellInfo; 209 notifyAll(); 210 } 211 wait(int millis)212 public synchronized void wait(int millis) throws InterruptedException { 213 if (cellInfo == null) { 214 super.wait(millis); 215 } 216 } 217 } 218 219 private static class CellInfoListener extends PhoneStateListener { 220 List<CellInfo> cellInfo; 221 CellInfoListener(Executor e)222 public CellInfoListener(Executor e) { 223 super(e); 224 } 225 226 @Override onCellInfoChanged(List<CellInfo> cellInfo)227 public synchronized void onCellInfoChanged(List<CellInfo> cellInfo) { 228 this.cellInfo = cellInfo; 229 notifyAll(); 230 } 231 wait(int millis)232 public synchronized void wait(int millis) throws InterruptedException { 233 if (cellInfo == null) { 234 super.wait(millis); 235 } 236 } 237 } 238 isCamped()239 private boolean isCamped() { 240 InstrumentationRegistry.getInstrumentation().getUiAutomation() 241 .adoptShellPermissionIdentity("android.permission.READ_PHONE_STATE"); 242 243 ServiceState ss = mTm.getServiceState(); 244 if (ss == null) return false; 245 if (ss.getState() == ServiceState.STATE_EMERGENCY_ONLY) return true; 246 List<NetworkRegistrationInfo> nris = ss.getNetworkRegistrationInfoList(); 247 for (NetworkRegistrationInfo nri : nris) { 248 if (nri.getTransportType() != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) continue; 249 if (nri.isRegistered()) return true; 250 } 251 return false; 252 } 253 254 @Before setUp()255 public void setUp() throws Exception { 256 mTm = (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE); 257 mPm = getContext().getPackageManager(); 258 Pair<Integer, Integer> verPair = mTm.getRadioHalVersion(); 259 mRadioHalVersion = makeRadioVersion(verPair.first, verPair.second); 260 TelephonyManagerTest.grantLocationPermissions(); 261 } 262 263 /** 264 * Test to ensure that the PhoneStateListener receives callbacks every time that new CellInfo 265 * is received and not otherwise. 266 */ 267 @Test testPhoneStateListenerCallback()268 public void testPhoneStateListenerCallback() throws Throwable { 269 if (!mPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) return; 270 271 CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback(); 272 // Prime the system by requesting a CellInfoUpdate 273 mTm.requestCellInfoUpdate(mSimpleExecutor, resultsCallback); 274 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 275 // Register a new PhoneStateListener for CellInfo 276 CellInfoListener listener = new CellInfoListener(mSimpleExecutor); 277 mTm.listen(listener, PhoneStateListener.LISTEN_CELL_INFO); 278 // Expect a callback immediately upon registration 279 listener.wait(MAX_LISTENER_WAIT_MILLIS); 280 assertNotNull("CellInfo Listener Never Fired on Registration", listener.cellInfo); 281 // Save the initial listener result as a baseline 282 List<CellInfo> referenceList = listener.cellInfo; 283 assertFalse("CellInfo does not contain valid results", referenceList.isEmpty()); 284 assertTrue("Listener Didn't Receive the Right Data", 285 referenceList.containsAll(resultsCallback.cellInfo)); 286 listener.cellInfo = null; 287 resultsCallback.cellInfo = null; 288 long timeoutTime = SystemClock.elapsedRealtime() + MAX_CELLINFO_INTERVAL_MILLIS; 289 while (timeoutTime > SystemClock.elapsedRealtime()) { 290 // Request a CellInfo update to try and coax an update from the listener 291 mTm.requestCellInfoUpdate(mSimpleExecutor, resultsCallback); 292 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 293 assertNotNull("CellInfoCallback should return valid data", resultsCallback.cellInfo); 294 if (referenceList.containsAll(resultsCallback.cellInfo)) { 295 // Check the a call to getAllCellInfo doesn't trigger the listener. 296 mTm.getAllCellInfo(); 297 // Wait for the listener to fire; it shouldn't. 298 listener.wait(MAX_LISTENER_WAIT_MILLIS); 299 // Check to ensure the listener didn't fire for stale data. 300 assertNull("PhoneStateListener Fired For Old CellInfo Data", listener.cellInfo); 301 } else { 302 // If there is new CellInfo data, then the listener should fire 303 listener.wait(MAX_LISTENER_WAIT_MILLIS); 304 assertNotNull("Listener did not receive updated CellInfo Data", 305 listener.cellInfo); 306 assertFalse("CellInfo data should be different from the old listener data." 307 + referenceList + " : " + listener.cellInfo, 308 referenceList.containsAll(listener.cellInfo)); 309 return; // pass the test 310 } 311 // Reset the resultsCallback for the next iteration 312 resultsCallback.cellInfo = null; 313 } 314 } 315 316 @Test testCellInfo()317 public void testCellInfo() throws Throwable { 318 if(!(mPm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY))) { 319 Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY"); 320 return; 321 } 322 323 if (!isCamped()) fail("Device is not camped to a cell"); 324 325 // Make a blocking call to requestCellInfoUpdate for results (for simplicity of test). 326 CellInfoResultsCallback resultsCallback = new CellInfoResultsCallback(); 327 mTm.requestCellInfoUpdate(mSimpleExecutor, resultsCallback); 328 resultsCallback.wait(MAX_CELLINFO_WAIT_MILLIS); 329 List<CellInfo> allCellInfo = resultsCallback.cellInfo; 330 331 assertNotNull("TelephonyManager.getAllCellInfo() returned NULL!", allCellInfo); 332 assertTrue("TelephonyManager.getAllCellInfo() returned zero-length list!", 333 allCellInfo.size() > 0); 334 335 int numRegisteredCells = 0; 336 for (CellInfo cellInfo : allCellInfo) { 337 if (cellInfo.isRegistered()) { 338 ++numRegisteredCells; 339 } 340 verifyBaseCellInfo(cellInfo); 341 verifyBaseCellIdentity(cellInfo.getCellIdentity(), cellInfo.isRegistered()); 342 if (cellInfo instanceof CellInfoLte) { 343 verifyLteInfo((CellInfoLte) cellInfo); 344 } else if (cellInfo instanceof CellInfoWcdma) { 345 verifyWcdmaInfo((CellInfoWcdma) cellInfo); 346 } else if (cellInfo instanceof CellInfoGsm) { 347 verifyGsmInfo((CellInfoGsm) cellInfo); 348 } else if (cellInfo instanceof CellInfoCdma) { 349 verifyCdmaInfo((CellInfoCdma) cellInfo); 350 } else if (cellInfo instanceof CellInfoTdscdma) { 351 verifyTdscdmaInfo((CellInfoTdscdma) cellInfo); 352 } else if (cellInfo instanceof CellInfoNr) { 353 verifyNrInfo((CellInfoNr) cellInfo); 354 } else { 355 fail("Unknown CellInfo Type reported."); 356 } 357 } 358 359 //FIXME: The maximum needs to be calculated based on the number of 360 // radios and the technologies used (ex SRLTE); however, we have 361 // not hit any of these cases yet. 362 assertTrue("None or too many registered cells : " + numRegisteredCells, 363 numRegisteredCells > 0 && numRegisteredCells <= 2); 364 } 365 verifyBaseCellInfo(CellInfo info)366 private void verifyBaseCellInfo(CellInfo info) { 367 assertTrue("Invalid timestamp in CellInfo: " + info.getTimeStamp(), 368 info.getTimeStamp() > 0 && info.getTimeStamp() < Long.MAX_VALUE); 369 370 long curTime = SystemClock.elapsedRealtime(); 371 assertTrue("Invalid timestamp in CellInfo: " + info.getTimestampMillis(), 372 info.getTimestampMillis() > 0 && info.getTimestampMillis() <= curTime); 373 374 if (mRadioHalVersion >= RADIO_HAL_VERSION_1_2) { 375 // In HAL 1.2 or greater, the connection status must be reported 376 assertTrue(info.getCellConnectionStatus() != CellInfo.CONNECTION_UNKNOWN); 377 } 378 } 379 verifyBaseCellIdentity(CellIdentity id, boolean isRegistered)380 private void verifyBaseCellIdentity(CellIdentity id, boolean isRegistered) { 381 if (mRadioHalVersion >= RADIO_HAL_VERSION_1_2) { 382 if (isRegistered) { 383 String alphaLong = (String) id.getOperatorAlphaLong(); 384 assertNotNull("getOperatorAlphaLong() returns NULL!", alphaLong); 385 386 String alphaShort = (String) id.getOperatorAlphaShort(); 387 assertNotNull("getOperatorAlphaShort() returns NULL!", alphaShort); 388 } 389 } 390 } 391 verifyCdmaInfo(CellInfoCdma cdma)392 private void verifyCdmaInfo(CellInfoCdma cdma) { 393 verifyCellConnectionStatus(cdma.getCellConnectionStatus()); 394 verifyCellInfoCdmaParcelandHashcode(cdma); 395 verifyCellIdentityCdma(cdma.getCellIdentity(), cdma.isRegistered()); 396 verifyCellIdentityCdmaParcel(cdma.getCellIdentity()); 397 verifyCellSignalStrengthCdma(cdma.getCellSignalStrength()); 398 verifyCellSignalStrengthCdmaParcel(cdma.getCellSignalStrength()); 399 } 400 verifyCellInfoCdmaParcelandHashcode(CellInfoCdma cdma)401 private void verifyCellInfoCdmaParcelandHashcode(CellInfoCdma cdma) { 402 Parcel p = Parcel.obtain(); 403 cdma.writeToParcel(p, 0); 404 p.setDataPosition(0); 405 406 CellInfoCdma newCi = CellInfoCdma.CREATOR.createFromParcel(p); 407 assertTrue(cdma.equals(newCi)); 408 assertEquals("hashCode() did not get right hashCode", cdma.hashCode(), newCi.hashCode()); 409 } 410 verifyCellIdentityCdma(CellIdentityCdma cdma, boolean isRegistered)411 private void verifyCellIdentityCdma(CellIdentityCdma cdma, boolean isRegistered) { 412 int networkId = cdma.getNetworkId(); 413 assertTrue("getNetworkId() out of range [0,65535], networkId=" + networkId, 414 networkId == CellInfo.UNAVAILABLE || (networkId >= 0 && networkId <= NETWORK_ID)); 415 416 int systemId = cdma.getSystemId(); 417 assertTrue("getSystemId() out of range [0,32767], systemId=" + systemId, 418 systemId == CellInfo.UNAVAILABLE || (systemId >= 0 && systemId <= SYSTEM_ID)); 419 420 int basestationId = cdma.getBasestationId(); 421 assertTrue("getBasestationId() out of range [0,65535], basestationId=" + basestationId, 422 basestationId == CellInfo.UNAVAILABLE 423 || (basestationId >= 0 && basestationId <= BASESTATION_ID)); 424 425 int longitude = cdma.getLongitude(); 426 assertTrue("getLongitude() out of range [-2592000,2592000], longitude=" + longitude, 427 longitude == CellInfo.UNAVAILABLE 428 || (longitude >= -LONGITUDE && longitude <= LONGITUDE)); 429 430 int latitude = cdma.getLatitude(); 431 assertTrue("getLatitude() out of range [-1296000,1296000], latitude=" + latitude, 432 latitude == CellInfo.UNAVAILABLE 433 || (latitude >= -LATITUDE && latitude <= LATITUDE)); 434 435 if (isRegistered) { 436 assertTrue("SID is required for registered cells", systemId != CellInfo.UNAVAILABLE); 437 assertTrue("NID is required for registered cells", networkId != CellInfo.UNAVAILABLE); 438 assertTrue("BSID is required for registered cells", 439 basestationId != CellInfo.UNAVAILABLE); 440 } 441 442 verifyCellIdentityCdmaLocationSanitation(cdma); 443 } 444 verifyCellIdentityCdmaLocationSanitation(CellIdentityCdma cdma)445 private void verifyCellIdentityCdmaLocationSanitation(CellIdentityCdma cdma) { 446 CellIdentityCdma sanitized = cdma.sanitizeLocationInfo(); 447 assertEquals(CellInfo.UNAVAILABLE, sanitized.getNetworkId()); 448 assertEquals(CellInfo.UNAVAILABLE, sanitized.getSystemId()); 449 assertEquals(CellInfo.UNAVAILABLE, sanitized.getBasestationId()); 450 assertEquals(CellInfo.UNAVAILABLE, sanitized.getLongitude()); 451 assertEquals(CellInfo.UNAVAILABLE, sanitized.getLatitude()); 452 } 453 verifyCellIdentityCdmaParcel(CellIdentityCdma cdma)454 private void verifyCellIdentityCdmaParcel(CellIdentityCdma cdma) { 455 Parcel p = Parcel.obtain(); 456 cdma.writeToParcel(p, 0); 457 p.setDataPosition(0); 458 459 CellIdentityCdma newCi = CellIdentityCdma.CREATOR.createFromParcel(p); 460 assertTrue(cdma.equals(newCi)); 461 } 462 verifyCellSignalStrengthCdma(CellSignalStrengthCdma cdma)463 private void verifyCellSignalStrengthCdma(CellSignalStrengthCdma cdma) { 464 int level = cdma.getLevel(); 465 assertTrue("getLevel() out of range [0,4], level=" + level, 466 level >= 0 && level <= 4); 467 468 int asuLevel = cdma.getAsuLevel(); 469 assertTrue("getAsuLevel() out of range [0,97] (or 99 is unknown), asuLevel=" + asuLevel, 470 asuLevel == 99 || (asuLevel >= 0 && asuLevel <= 97)); 471 472 int cdmaLevel = cdma.getCdmaLevel(); 473 assertTrue("getCdmaLevel() out of range [0,4], cdmaLevel=" + cdmaLevel, 474 cdmaLevel >= 0 && cdmaLevel <= 4); 475 476 int evdoLevel = cdma.getEvdoLevel(); 477 assertTrue("getEvdoLevel() out of range [0,4], evdoLevel=" + evdoLevel, 478 evdoLevel >= 0 && evdoLevel <= 4); 479 480 // The following four fields do not have specific limits. So just calling to verify that 481 // they don't crash the phone. 482 int cdmaDbm = cdma.getCdmaDbm(); 483 int evdoDbm = cdma.getEvdoDbm(); 484 cdma.getCdmaEcio(); 485 cdma.getEvdoEcio(); 486 487 int dbm = (cdmaDbm < evdoDbm) ? cdmaDbm : evdoDbm; 488 assertEquals("getDbm() did not get correct value", dbm, cdma.getDbm()); 489 490 int evdoSnr = cdma.getEvdoSnr(); 491 assertTrue("getEvdoSnr() out of range [0,8], evdoSnr=" + evdoSnr, 492 (evdoSnr == CellInfo.UNAVAILABLE) || (evdoSnr >= 0 && evdoSnr <= 8)); 493 } 494 verifyCellSignalStrengthCdmaParcel(CellSignalStrengthCdma cdma)495 private void verifyCellSignalStrengthCdmaParcel(CellSignalStrengthCdma cdma) { 496 Parcel p = Parcel.obtain(); 497 cdma.writeToParcel(p, 0); 498 p.setDataPosition(0); 499 500 CellSignalStrengthCdma newCss = CellSignalStrengthCdma.CREATOR.createFromParcel(p); 501 assertEquals(cdma, newCss); 502 } 503 verifyPlmnInfo(String mccStr, String mncStr, int mcc, int mnc)504 private static void verifyPlmnInfo(String mccStr, String mncStr, int mcc, int mnc) { 505 // If either int value is invalid, all values must be invalid 506 if (mcc == CellInfo.UNAVAILABLE) { 507 assertTrue("MNC and MNC must always be reported together.", 508 mnc == CellInfo.UNAVAILABLE && mccStr == null && mncStr == null); 509 return; 510 } 511 512 assertTrue("getMcc() out of range [0, 999], mcc=" + mcc, (mcc >= 0 && mcc <= 999)); 513 assertTrue("getMnc() out of range [0, 999], mnc=" + mnc, (mnc >= 0 && mnc <= 999)); 514 assertTrue("MCC and MNC Strings must always be reported together.", 515 (mccStr == null) == (mncStr == null)); 516 517 // For legacy compatibility, it's possible to have int values without valid string values 518 // but not the other way around. 519 // mccStr is set as NULL if empty, unknown or invalid. 520 assertTrue("getMccString() out of range [0, 999], mcc=" + mccStr, 521 mccStr == null || mccStr.matches("^[0-9]{3}$")); 522 // mccStr must either be null or match mcc integer. 523 assertTrue("MccString must match Mcc Integer, str=" + mccStr + " int=" + mcc, 524 mccStr == null || mcc == Integer.parseInt(mccStr)); 525 526 // mncStr is set as NULL if empty, unknown or invalid. 527 assertTrue("getMncString() out of range [0, 999], mnc=" + mncStr, 528 mncStr == null || mncStr.matches("^[0-9]{2,3}$")); 529 // mncStr must either be null or match mnc integer. 530 assertTrue("MncString must match Mnc Integer, str=" + mncStr + " int=" + mnc, 531 mncStr == null || mnc == Integer.parseInt(mncStr)); 532 } 533 534 // Verify lte cell information is within correct range. verifyLteInfo(CellInfoLte lte)535 private void verifyLteInfo(CellInfoLte lte) { 536 verifyCellConnectionStatus(lte.getCellConnectionStatus()); 537 verifyCellInfoLteParcelandHashcode(lte); 538 verifyCellIdentityLte(lte.getCellIdentity(), lte.isRegistered()); 539 verifyCellIdentityLteParcel(lte.getCellIdentity()); 540 verifyCellSignalStrengthLte(lte.getCellSignalStrength()); 541 verifyCellSignalStrengthLteParcel(lte.getCellSignalStrength()); 542 } 543 544 // Verify NR 5G cell information is within correct range. verifyNrInfo(CellInfoNr nr)545 private void verifyNrInfo(CellInfoNr nr) { 546 verifyCellConnectionStatus(nr.getCellConnectionStatus()); 547 verifyCellIdentityNr((CellIdentityNr) nr.getCellIdentity(), nr.isRegistered()); 548 verifyCellIdentityNrParcel((CellIdentityNr) nr.getCellIdentity()); 549 verifyCellSignalStrengthNr((CellSignalStrengthNr) nr.getCellSignalStrength()); 550 verifyCellSignalStrengthNrParcel((CellSignalStrengthNr) nr.getCellSignalStrength()); 551 } 552 verifyCellSignalStrengthNrParcel(CellSignalStrengthNr nr)553 private void verifyCellSignalStrengthNrParcel(CellSignalStrengthNr nr) { 554 Parcel p = Parcel.obtain(); 555 nr.writeToParcel(p, 0); 556 p.setDataPosition(0); 557 558 CellSignalStrengthNr newCss = CellSignalStrengthNr.CREATOR.createFromParcel(p); 559 assertEquals(nr, newCss); 560 } 561 verifyCellIdentityNrParcel(CellIdentityNr nr)562 private void verifyCellIdentityNrParcel(CellIdentityNr nr) { 563 Parcel p = Parcel.obtain(); 564 nr.writeToParcel(p, 0); 565 p.setDataPosition(0); 566 567 CellIdentityNr newCi = CellIdentityNr.CREATOR.createFromParcel(p); 568 assertEquals(nr, newCi); 569 } 570 verifyCellIdentityNr(CellIdentityNr nr, boolean isRegistered)571 private void verifyCellIdentityNr(CellIdentityNr nr, boolean isRegistered) { 572 // This class was added after numeric mcc/mncs were no longer provided, so it lacks the 573 // basic getMcc() and getMnc() - empty out those checks. 574 String mccStr = nr.getMccString(); 575 String mncStr = nr.getMncString(); 576 verifyPlmnInfo(mccStr, mncStr, 577 mccStr != null ? Integer.parseInt(mccStr) : CellInfo.UNAVAILABLE, 578 mncStr != null ? Integer.parseInt(mncStr) : CellInfo.UNAVAILABLE); 579 580 int pci = nr.getPci(); 581 assertTrue("getPci() out of range [0, 1007], pci = " + pci, 0 <= pci && pci <= 1007); 582 583 int tac = nr.getTac(); 584 assertTrue("getTac() out of range [0, 16777215], tac = " + tac, 585 (tac == Integer.MAX_VALUE) || (0 <= tac && tac <= 16777215)); 586 587 int nrArfcn = nr.getNrarfcn(); 588 assertTrue("getNrarfcn() out of range [0, 3279165], nrarfcn = " + nrArfcn, 589 0 <= nrArfcn && nrArfcn <= 3279165); 590 591 for (String plmnId : nr.getAdditionalPlmns()) { 592 verifyPlmnId(plmnId); 593 } 594 595 if (mRadioHalVersion >= RADIO_HAL_VERSION_1_5) { 596 int[] bands = nr.getBands(); 597 598 for (int band: bands) { 599 assertTrue("getBand out of range [1, 95] or [257, 261], band = " + band, 600 (band >= BAND_FR1_MIN_NR && band <= BAND_FR1_MAX_NR) 601 || (band >= BAND_FR2_MIN_NR && band <= BAND_FR2_MAX_NR)); 602 603 verifyCellIdentityNrBands(bands); 604 } 605 } 606 607 // If the cell is reported as registered, then all the logical cell info must be reported 608 if (isRegistered) { 609 assertTrue("TAC is required for registered cells", tac != CellInfo.UNAVAILABLE); 610 assertTrue("MCC is required for registered cells", nr.getMccString() != null); 611 assertTrue("MNC is required for registered cells", nr.getMncString() != null); 612 } 613 614 verifyCellIdentityNrLocationSanitation(nr); 615 } 616 verifyCellIdentityNrLocationSanitation(CellIdentityNr nr)617 private void verifyCellIdentityNrLocationSanitation(CellIdentityNr nr) { 618 CellIdentityNr sanitized = nr.sanitizeLocationInfo(); 619 assertEquals(CellInfo.UNAVAILABLE, sanitized.getPci()); 620 assertEquals(CellInfo.UNAVAILABLE, sanitized.getTac()); 621 assertEquals(CellInfo.UNAVAILABLE_LONG, sanitized.getNci()); 622 } 623 verifyCellSignalStrengthNr(CellSignalStrengthNr nr)624 private void verifyCellSignalStrengthNr(CellSignalStrengthNr nr) { 625 int csiRsrp = nr.getCsiRsrp(); 626 int csiRsrq = nr.getCsiRsrq(); 627 int csiSinr = nr.getSsSinr(); 628 int csiCqiTableIndex = nr.getCsiCqiTableIndex(); 629 List<Integer> csiCqiReport = nr.getCsiCqiReport(); 630 int ssRsrp = nr.getSsRsrp(); 631 int ssRsrq = nr.getSsRsrq(); 632 int ssSinr = nr.getSsSinr(); 633 634 assertTrue("getCsiRsrp() out of range [-140, -44] | Integer.MAX_INTEGER, csiRsrp = " 635 + csiRsrp, -140 <= csiRsrp && csiRsrp <= -44 636 || csiRsrp == CellInfo.UNAVAILABLE); 637 assertTrue("getCsiRsrq() out of range [-20, -3] | Integer.MAX_INTEGER, csiRsrq = " 638 + csiRsrq, -20 <= csiRsrq && csiRsrq <= -3 || csiRsrq == CellInfo.UNAVAILABLE); 639 assertTrue("getCsiSinr() out of range [-23, 40] | Integer.MAX_INTEGER, csiSinr = " 640 + csiSinr, -23 <= csiSinr && csiSinr <= 40 || csiSinr == CellInfo.UNAVAILABLE); 641 assertTrue("getCsiCqiTableIndex() out of range | CellInfo.UNAVAILABLE, csiCqiTableIndex=" 642 + csiCqiTableIndex, csiCqiTableIndex == CellInfo.UNAVAILABLE 643 || (csiCqiTableIndex >= CQI_TABLE_INDEX_MIN_NR 644 && csiCqiTableIndex <= CQI_TABLE_INDEX_MAX_NR)); 645 assertTrue("cqi in getCsiCqiReport() out of range | CellInfo.UNAVAILABLE, csiCqiReport=" 646 + csiCqiReport, csiCqiReport.stream() 647 .allMatch(cqi -> cqi.intValue() == CellInfo.UNAVAILABLE 648 || (cqi.intValue() >= MIN_CQI && cqi.intValue() <= MAX_CQI))); 649 assertTrue("getSsRsrp() out of range [-140, -44] | Integer.MAX_INTEGER, ssRsrp = " 650 + ssRsrp, -140 <= ssRsrp && ssRsrp <= -44 651 || ssRsrp == CellInfo.UNAVAILABLE); 652 assertTrue("getSsRsrq() out of range [-20, -3] | Integer.MAX_INTEGER, ssRsrq = " 653 + ssRsrq, -20 <= ssRsrq && ssRsrq <= -3 || ssRsrq == CellInfo.UNAVAILABLE); 654 assertTrue("getSsSinr() out of range [-23, 40] | Integer.MAX_INTEGER, ssSinr = " 655 + ssSinr, -23 <= ssSinr && ssSinr <= 40 || ssSinr == 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 (mRadioHalVersion >= 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 (mRadioHalVersion >= 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 (mRadioHalVersion >= 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 (mRadioHalVersion >= 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 (mRadioHalVersion >= 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