• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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