1 /*
2  * Copyright (C) 2012 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 
17 package android.telephony;
18 
19 import android.annotation.IntRange;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.PersistableBundle;
24 
25 import com.android.telephony.Rlog;
26 
27 import java.util.Arrays;
28 import java.util.Objects;
29 
30 /**
31  * LTE signal strength related information.
32  */
33 public final class CellSignalStrengthLte extends CellSignalStrength implements Parcelable {
34 
35     private static final String LOG_TAG = "CellSignalStrengthLte";
36     private static final boolean DBG = false;
37 
38     /**
39      * Indicates the unknown or undetectable RSSI value in ASU.
40      *
41      * Reference: TS 27.007 8.5 - Signal quality +CSQ
42      */
43     private static final int SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN = 99;
44     /**
45      * Indicates the maximum valid RSSI value in ASU.
46      *
47      * Reference: TS 27.007 8.5 - Signal quality +CSQ
48      */
49     private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE = 31;
50     /**
51      * Indicates the minimum valid RSSI value in ASU.
52      *
53      * Reference: TS 27.007 8.5 - Signal quality +CSQ
54      */
55     private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE = 0;
56 
57     private static final int MAX_LTE_RSRP = -44;
58     private static final int MIN_LTE_RSRP = -140;
59 
60     /**
61      * Indicates RSRP is considered for {@link #getLevel()} and reported from modem.
62      *
63      * @hide
64      */
65     public static final int USE_RSRP = 1 << 0;
66     /**
67      * Indicates RSRQ is considered for {@link #getLevel()} and reported from modem.
68      *
69      * @hide
70      */
71     public static final int USE_RSRQ = 1 << 1;
72     /**
73      * Indicates RSSNR is considered for {@link #getLevel()} and reported from modem.
74      *
75      * @hide
76      */
77     public static final int USE_RSSNR = 1 << 2;
78 
79     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
80     private int mSignalStrength; // To be removed
81     private int mRssi;
82     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
83     private int mRsrp;
84     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
85     private int mRsrq;
86     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
87     private int mRssnr;
88     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
89     private int mCqi;
90     @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
91     private int mTimingAdvance;
92     private int mLevel;
93 
94     /**
95      * Bit-field integer to determine whether to use Reference Signal Received Power (RSRP),
96      * Reference Signal Received Quality (RSRQ), and/or Reference Signal Signal to Noise Ratio
97      * (RSSNR) for the number of LTE signal bars. If multiple measures are set, the parameter
98      * whose signal level value is smallest is used to indicate the signal level.
99      *
100      *  RSRP = 1 << 0,
101      *  RSRQ = 1 << 1,
102      *  RSSNR = 1 << 2,
103      *
104      * For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1).
105      * If the key is invalid or not configured, a default value (RSRP = 1 << 0) will apply.
106      */
107     private int mParametersUseForLevel;
108 
109     /** @hide */
110     @UnsupportedAppUsage
CellSignalStrengthLte()111     public CellSignalStrengthLte() {
112         setDefaultValues();
113     }
114 
115     /**
116      * Construct a cell signal strength
117      *
118      * @param rssi in dBm [-113,-51], UNKNOWN
119      * @param rsrp in dBm [-140,-43], UNKNOWN
120      * @param rsrq in dB [-34, 3], UNKNOWN
121      * @param rssnr in dB [-20, +30], UNKNOWN
122      * @param cqi [0, 15], UNKNOWN
123      * @param timingAdvance [0, 1282], UNKNOWN
124      *
125      */
126     /** @hide */
CellSignalStrengthLte(int rssi, int rsrp, int rsrq, int rssnr, int cqi, int timingAdvance)127     public CellSignalStrengthLte(int rssi, int rsrp, int rsrq, int rssnr, int cqi,
128             int timingAdvance) {
129 
130         mRssi = inRangeOrUnavailable(rssi, -113, -51);
131         mSignalStrength = mRssi;
132         mRsrp = inRangeOrUnavailable(rsrp, -140, -43);
133         mRsrq = inRangeOrUnavailable(rsrq, -34, 3);
134         mRssnr = inRangeOrUnavailable(rssnr, -20, 30);
135         mCqi = inRangeOrUnavailable(cqi, 0, 15);
136         mTimingAdvance = inRangeOrUnavailable(timingAdvance, 0, 1282);
137         updateLevel(null, null);
138     }
139 
140     /** @hide */
CellSignalStrengthLte(android.hardware.radio.V1_0.LteSignalStrength lte)141     public CellSignalStrengthLte(android.hardware.radio.V1_0.LteSignalStrength lte) {
142         // Convert from HAL values as part of construction.
143         this(convertRssiAsuToDBm(lte.signalStrength),
144                 lte.rsrp != CellInfo.UNAVAILABLE ? -lte.rsrp : lte.rsrp,
145                 lte.rsrq != CellInfo.UNAVAILABLE ? -lte.rsrq : lte.rsrq,
146                 convertRssnrUnitFromTenDbToDB(lte.rssnr), lte.cqi, lte.timingAdvance);
147     }
148 
149     /** @hide */
CellSignalStrengthLte(CellSignalStrengthLte s)150     public CellSignalStrengthLte(CellSignalStrengthLte s) {
151         copyFrom(s);
152     }
153 
154     /** @hide */
copyFrom(CellSignalStrengthLte s)155     protected void copyFrom(CellSignalStrengthLte s) {
156         mSignalStrength = s.mSignalStrength;
157         mRssi = s.mRssi;
158         mRsrp = s.mRsrp;
159         mRsrq = s.mRsrq;
160         mRssnr = s.mRssnr;
161         mCqi = s.mCqi;
162         mTimingAdvance = s.mTimingAdvance;
163         mLevel = s.mLevel;
164         mParametersUseForLevel = s.mParametersUseForLevel;
165     }
166 
167     /** @hide */
168     @Override
copy()169     public CellSignalStrengthLte copy() {
170         return new CellSignalStrengthLte(this);
171     }
172 
173     /** @hide */
174     @Override
setDefaultValues()175     public void setDefaultValues() {
176         mSignalStrength = CellInfo.UNAVAILABLE;
177         mRssi = CellInfo.UNAVAILABLE;
178         mRsrp = CellInfo.UNAVAILABLE;
179         mRsrq = CellInfo.UNAVAILABLE;
180         mRssnr = CellInfo.UNAVAILABLE;
181         mCqi = CellInfo.UNAVAILABLE;
182         mTimingAdvance = CellInfo.UNAVAILABLE;
183         mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
184         mParametersUseForLevel = USE_RSRP;
185     }
186 
187     /** {@inheritDoc} */
188     @Override
189     @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
getLevel()190     public int getLevel() {
191         return mLevel;
192     }
193 
194     // Lifted from Default carrier configs and max range of RSRP
195     private static final int[] sRsrpThresholds = new int[] {
196             -115, /* SIGNAL_STRENGTH_POOR */
197             -105, /* SIGNAL_STRENGTH_MODERATE */
198             -95,  /* SIGNAL_STRENGTH_GOOD */
199             -85   /* SIGNAL_STRENGTH_GREAT */
200     };
201 
202     // Lifted from Default carrier configs and max range of RSRQ
203     private static final int[] sRsrqThresholds = new int[] {
204             -19, /* SIGNAL_STRENGTH_POOR */
205             -17, /* SIGNAL_STRENGTH_MODERATE */
206             -14, /* SIGNAL_STRENGTH_GOOD */
207             -12  /* SIGNAL_STRENGTH_GREAT */
208     };
209     // Lifted from Default carrier configs and max range of RSSNR
210     private static final int[] sRssnrThresholds = new int[] {
211             -3, /* SIGNAL_STRENGTH_POOR */
212             1,  /* SIGNAL_STRENGTH_MODERATE */
213             5,  /* SIGNAL_STRENGTH_GOOD */
214             13  /* SIGNAL_STRENGTH_GREAT */
215     };
216     private static final int sRsrpBoost = 0;
217 
218     /**
219      * Checks if the given parameter type is considered to use for {@link #getLevel()}.
220      *
221      * Note: if multiple parameter types are considered, the smaller level for one of the
222      * parameters would be returned by {@link #getLevel()}
223      *
224      * @param parameterType bitwise OR of {@link #USE_RSRP}, {@link #USE_RSRQ},
225      *         {@link #USE_RSSNR}
226      * @return {@code true} if the level is calculated based on the given parameter type;
227      *      {@code false} otherwise.
228      */
isLevelForParameter(int parameterType)229     private boolean isLevelForParameter(int parameterType) {
230         return (parameterType & mParametersUseForLevel) == parameterType;
231     }
232 
233     /** @hide */
234     @Override
updateLevel(PersistableBundle cc, ServiceState ss)235     public void updateLevel(PersistableBundle cc, ServiceState ss) {
236         int[] rsrpThresholds, rsrqThresholds, rssnrThresholds;
237         boolean rsrpOnly;
238         if (cc == null) {
239             mParametersUseForLevel = USE_RSRP;
240             rsrpThresholds = sRsrpThresholds;
241             rsrqThresholds = sRsrqThresholds;
242             rssnrThresholds = sRssnrThresholds;
243             rsrpOnly = false;
244         } else {
245             mParametersUseForLevel = cc.getInt(
246                     CarrierConfigManager.KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT);
247             if (DBG) {
248                 Rlog.i(LOG_TAG, "Using signal strength level: " + mParametersUseForLevel);
249             }
250             rsrpThresholds = cc.getIntArray(
251                     CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY);
252             if (rsrpThresholds == null) rsrpThresholds = sRsrpThresholds;
253             if (DBG) {
254                 Rlog.i(LOG_TAG, "Applying LTE RSRP Thresholds: "
255                         + Arrays.toString(rsrpThresholds));
256             }
257             rsrqThresholds = cc.getIntArray(
258                     CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY);
259             if (rsrqThresholds == null) rsrqThresholds = sRsrqThresholds;
260             if (DBG) {
261                 Rlog.i(LOG_TAG, "Applying LTE RSRQ Thresholds: "
262                         + Arrays.toString(rsrqThresholds));
263             }
264             rssnrThresholds = cc.getIntArray(
265                     CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY);
266             if (rssnrThresholds == null) rssnrThresholds = sRssnrThresholds;
267             if (DBG) {
268                 Rlog.i(LOG_TAG, "Applying LTE RSSNR Thresholds: "
269                         + Arrays.toString(rssnrThresholds));
270             }
271             rsrpOnly = cc.getBoolean(
272                     CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL, false);
273         }
274 
275         int rsrpBoost = 0;
276         if (ss != null) {
277             rsrpBoost = ss.getLteEarfcnRsrpBoost();
278         }
279 
280         int rsrp = inRangeOrUnavailable(mRsrp + rsrpBoost, MIN_LTE_RSRP, MAX_LTE_RSRP);
281 
282         if (rsrpOnly) {
283             int level = updateLevelWithMeasure(rsrp, rsrpThresholds);
284             if (DBG) log("updateLevel() - rsrp = " + level);
285             if (level != SignalStrength.INVALID) {
286                 mLevel = level;
287                 return;
288             }
289         }
290 
291         int rsrpLevel = SignalStrength.INVALID;
292         int rsrqLevel = SignalStrength.INVALID;
293         int rssnrLevel = SignalStrength.INVALID;
294 
295         if (isLevelForParameter(USE_RSRP)) {
296             rsrpLevel = updateLevelWithMeasure(rsrp, rsrpThresholds);
297             if (DBG) {
298                 Rlog.i(LOG_TAG, "Updated 4G LTE RSRP Level: " + rsrpLevel);
299             }
300         }
301         if (isLevelForParameter(USE_RSRQ)) {
302             rsrqLevel = updateLevelWithMeasure(mRsrq, rsrqThresholds);
303             if (DBG) {
304                 Rlog.i(LOG_TAG, "Updated 4G LTE RSRQ Level: " + rsrqLevel);
305             }
306         }
307         if (isLevelForParameter(USE_RSSNR)) {
308             rssnrLevel = updateLevelWithMeasure(mRssnr, rssnrThresholds);
309             if (DBG) {
310                 Rlog.i(LOG_TAG, "Updated 4G LTE RSSNR Level: " + rssnrLevel);
311             }
312         }
313         // Apply the smaller value among three levels of three measures.
314         mLevel = Math.min(Math.min(rsrpLevel, rsrqLevel), rssnrLevel);
315 
316         if (mLevel == SignalStrength.INVALID) {
317             int rssiLevel;
318             if (mRssi > -51) {
319                 rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
320             } else if (mRssi >= -89) {
321                 rssiLevel = SIGNAL_STRENGTH_GREAT;
322             } else if (mRssi >= -97) {
323                 rssiLevel = SIGNAL_STRENGTH_GOOD;
324             } else if (mRssi >= -103) {
325                 rssiLevel = SIGNAL_STRENGTH_MODERATE;
326             } else if (mRssi >= -113) {
327                 rssiLevel = SIGNAL_STRENGTH_POOR;
328             } else {
329                 rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
330             }
331             if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:" + rssiLevel);
332             mLevel = rssiLevel;
333         }
334     }
335 
336     /**
337      * Update level with corresponding measure and thresholds.
338      *
339      * @param measure corresponding signal measure
340      * @param thresholds corresponding signal thresholds
341      * @return level of the signal strength
342      */
updateLevelWithMeasure(int measure, int[] thresholds)343     private int updateLevelWithMeasure(int measure, int[] thresholds) {
344         int level;
345         if (measure == CellInfo.UNAVAILABLE) {
346             level = SignalStrength.INVALID;
347         } else if (measure >= thresholds[3]) {
348             level = SIGNAL_STRENGTH_GREAT;
349         } else if (measure >= thresholds[2]) {
350             level = SIGNAL_STRENGTH_GOOD;
351         } else if (measure >= thresholds[1]) {
352             level = SIGNAL_STRENGTH_MODERATE;
353         } else if (measure >= thresholds[0]) {
354             level = SIGNAL_STRENGTH_POOR;
355         } else {
356             level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
357         }
358         return level;
359     }
360 
361     /**
362      * Get reference signal received quality
363      *
364      * @return the RSRQ if available or
365      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
366      */
getRsrq()367     public int getRsrq() {
368         return mRsrq;
369     }
370 
371     /**
372      * Get Received Signal Strength Indication (RSSI) in dBm
373      *
374      * The value range is [-113, -51] inclusively or {@link CellInfo#UNAVAILABLE} if unavailable.
375      *
376      * Reference: TS 27.007 8.5 Signal quality +CSQ
377      *
378      * @return the RSSI if available or {@link CellInfo#UNAVAILABLE} if unavailable.
379      */
getRssi()380     public int getRssi() {
381         return mRssi;
382     }
383 
384     /**
385      * Get reference signal signal-to-noise ratio
386      *
387      * @return the RSSNR if available or
388      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
389      */
getRssnr()390     public int getRssnr() {
391         return mRssnr;
392     }
393 
394     /**
395      * Get reference signal received power in dBm
396      *
397      * @return the RSRP of the measured cell.
398      */
getRsrp()399     public int getRsrp() {
400         return mRsrp;
401     }
402 
403     /**
404      * Get channel quality indicator
405      *
406      * @return the CQI if available or
407      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
408      */
getCqi()409     public int getCqi() {
410         return mCqi;
411     }
412 
413     /**
414      * Get signal strength in dBm
415      *
416      * @return the RSRP of the measured cell.
417      */
418     @Override
getDbm()419     public int getDbm() {
420         return mRsrp;
421     }
422 
423     /**
424      * Get the RSRP in ASU.
425      *
426      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
427      *
428      * @return RSCP in ASU 0..97, 255, or UNAVAILABLE
429      */
430     @Override
getAsuLevel()431     public int getAsuLevel() {
432         int lteAsuLevel = 99;
433         int lteDbm = mRsrp;
434         if (lteDbm == CellInfo.UNAVAILABLE) lteAsuLevel = 99;
435         else if (lteDbm <= -140) lteAsuLevel = 0;
436         else if (lteDbm >= -43) lteAsuLevel = 97;
437         else lteAsuLevel = lteDbm + 140;
438         if (DBG) log("Lte Asu level: "+lteAsuLevel);
439         return lteAsuLevel;
440     }
441 
442     /**
443      * Get the timing advance value for LTE, as a value in range of 0..1282.
444      * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} is reported when there is no
445      * active RRC connection. Refer to 3GPP 36.213 Sec 4.2.3
446      *
447      * @return the LTE timing advance if available or
448      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
449      */
getTimingAdvance()450     public int getTimingAdvance() {
451         return mTimingAdvance;
452     }
453 
454     @Override
hashCode()455     public int hashCode() {
456         return Objects.hash(mRssi, mRsrp, mRsrq, mRssnr, mCqi, mTimingAdvance, mLevel);
457     }
458 
459     private static final CellSignalStrengthLte sInvalid = new CellSignalStrengthLte();
460 
461     /** @hide */
462     @Override
isValid()463     public boolean isValid() {
464         return !this.equals(sInvalid);
465     }
466 
467     @Override
equals(Object o)468     public boolean equals (Object o) {
469         CellSignalStrengthLte s;
470 
471         if (!(o instanceof CellSignalStrengthLte)) return false;
472         s = (CellSignalStrengthLte) o;
473 
474         return mRssi == s.mRssi
475                 && mRsrp == s.mRsrp
476                 && mRsrq == s.mRsrq
477                 && mRssnr == s.mRssnr
478                 && mCqi == s.mCqi
479                 && mTimingAdvance == s.mTimingAdvance
480                 && mLevel == s.mLevel;
481     }
482 
483     /**
484      * @return string representation.
485      */
486     @Override
toString()487     public String toString() {
488         return "CellSignalStrengthLte:"
489                 + " rssi=" + mRssi
490                 + " rsrp=" + mRsrp
491                 + " rsrq=" + mRsrq
492                 + " rssnr=" + mRssnr
493                 + " cqi=" + mCqi
494                 + " ta=" + mTimingAdvance
495                 + " level=" + mLevel
496                 + " parametersUseForLevel=" + mParametersUseForLevel;
497     }
498 
499     /** Implement the Parcelable interface */
500     @Override
writeToParcel(Parcel dest, int flags)501     public void writeToParcel(Parcel dest, int flags) {
502         if (DBG) log("writeToParcel(Parcel, int): " + toString());
503         dest.writeInt(mRssi);
504         // Need to multiply rsrp and rsrq by -1
505         // to ensure consistency when reading values written here
506         // unless the values are invalid
507         dest.writeInt(mRsrp);
508         dest.writeInt(mRsrq);
509         dest.writeInt(mRssnr);
510         dest.writeInt(mCqi);
511         dest.writeInt(mTimingAdvance);
512         dest.writeInt(mLevel);
513     }
514 
515     /**
516      * Construct a SignalStrength object from the given parcel
517      * where the token is already been processed.
518      */
CellSignalStrengthLte(Parcel in)519     private CellSignalStrengthLte(Parcel in) {
520         mRssi = in.readInt();
521         mSignalStrength = mRssi;
522         mRsrp = in.readInt();
523         mRsrq = in.readInt();
524         mRssnr = in.readInt();
525         mCqi = in.readInt();
526         mTimingAdvance = in.readInt();
527         mLevel = in.readInt();
528         if (DBG) log("CellSignalStrengthLte(Parcel): " + toString());
529     }
530 
531     /** Implement the Parcelable interface */
532     @Override
describeContents()533     public int describeContents() {
534         return 0;
535     }
536 
537     /** Implement the Parcelable interface */
538     @SuppressWarnings("hiding")
539     public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthLte> CREATOR =
540             new Parcelable.Creator<CellSignalStrengthLte>() {
541         @Override
542         public CellSignalStrengthLte createFromParcel(Parcel in) {
543             return new CellSignalStrengthLte(in);
544         }
545 
546         @Override
547         public CellSignalStrengthLte[] newArray(int size) {
548             return new CellSignalStrengthLte[size];
549         }
550     };
551 
552     /**
553      * log
554      */
log(String s)555     private static void log(String s) {
556         Rlog.w(LOG_TAG, s);
557     }
558 
convertRssnrUnitFromTenDbToDB(int rssnr)559     private static int convertRssnrUnitFromTenDbToDB(int rssnr) {
560         return rssnr / 10;
561     }
562 
convertRssiAsuToDBm(int rssiAsu)563     private static int convertRssiAsuToDBm(int rssiAsu) {
564         if (rssiAsu == SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN) {
565             return CellInfo.UNAVAILABLE;
566         }
567         if ((rssiAsu < SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE
568                 || rssiAsu > SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE)) {
569             Rlog.e(LOG_TAG, "convertRssiAsuToDBm: invalid RSSI in ASU=" + rssiAsu);
570             return CellInfo.UNAVAILABLE;
571         }
572         return -113 + (2 * rssiAsu);
573     }
574 }
575