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