1 /*
2  * Copyright (C) 2018 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.IntDef;
20 import android.annotation.IntRange;
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.lang.annotation.Retention;
28 import java.lang.annotation.RetentionPolicy;
29 import java.util.Arrays;
30 import java.util.Objects;
31 
32 /**
33  * 5G NR signal strength related information.
34  */
35 public final class CellSignalStrengthNr extends CellSignalStrength implements Parcelable {
36     /**
37      * The value is used to indicate that the asu level is unknown.
38      * Reference: 3GPP TS 27.007 section 8.69.
39      * @hide
40      */
41     public static final int UNKNOWN_ASU_LEVEL = 99;
42 
43     private static final boolean VDBG = false;
44 
45     private static final String TAG = "CellSignalStrengthNr";
46 
47     // Lifted from Default carrier configs and max range of SSRSRP
48     // Boundaries: [-140 dB, -44 dB]
49     private int[] mSsRsrpThresholds = new int[] {
50             -110, /* SIGNAL_STRENGTH_POOR */
51             -90, /* SIGNAL_STRENGTH_MODERATE */
52             -80, /* SIGNAL_STRENGTH_GOOD */
53             -65,  /* SIGNAL_STRENGTH_GREAT */
54     };
55 
56     // Lifted from Default carrier configs and max range of SSRSRQ
57     // Boundaries: [-43 dB, 20 dB]
58     private int[] mSsRsrqThresholds = new int[] {
59             -31, /* SIGNAL_STRENGTH_POOR */
60             -19, /* SIGNAL_STRENGTH_MODERATE */
61             -7, /* SIGNAL_STRENGTH_GOOD */
62             6  /* SIGNAL_STRENGTH_GREAT */
63     };
64 
65     // Lifted from Default carrier configs and max range of SSSINR
66     // Boundaries: [-23 dB, 40 dB]
67     private int[] mSsSinrThresholds = new int[] {
68             -5, /* SIGNAL_STRENGTH_POOR */
69             5, /* SIGNAL_STRENGTH_MODERATE */
70             15, /* SIGNAL_STRENGTH_GOOD */
71             30  /* SIGNAL_STRENGTH_GREAT */
72     };
73 
74     /**
75      * Indicates SSRSRP is considered for {@link #getLevel()} and reporting from modem.
76      *
77      * @hide
78      */
79     public static final int USE_SSRSRP = 1 << 0;
80     /**
81      * Indicates SSRSRQ is considered for {@link #getLevel()} and reporting from modem.
82      *
83      * @hide
84      */
85     public static final int USE_SSRSRQ = 1 << 1;
86     /**
87      * Indicates SSSINR is considered for {@link #getLevel()} and reporting from modem.
88      *
89      * @hide
90      */
91     public static final int USE_SSSINR = 1 << 2;
92 
93     /**
94      * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
95      * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
96      * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
97      * parameter whose value is smallest is used to indicate the signal bar.
98      *
99      * @hide
100      */
101     @IntDef(flag = true, prefix = { "USE_" }, value = {
102         USE_SSRSRP,
103         USE_SSRSRQ,
104         USE_SSSINR
105     })
106     @Retention(RetentionPolicy.SOURCE)
107     public @interface SignalLevelAndReportCriteriaSource {}
108 
109     private int mCsiRsrp;
110     private int mCsiRsrq;
111     private int mCsiSinr;
112     private int mSsRsrp;
113     private int mSsRsrq;
114     private int mSsSinr;
115     private int mLevel;
116 
117     /**
118      * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP),
119      * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference
120      * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the
121      * parameter whose value is smallest is used to indicate the signal bar.
122      *
123      *  SSRSRP = 1 << 0,
124      *  SSRSRQ = 1 << 1,
125      *  SSSINR = 1 << 2,
126      *
127      * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2).
128      * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply.
129      */
130     private int mParametersUseForLevel;
131 
132     /** @hide */
CellSignalStrengthNr()133     public CellSignalStrengthNr() {
134         setDefaultValues();
135     }
136 
137     /**
138      * @param csiRsrp CSI reference signal received power.
139      * @param csiRsrq CSI reference signal received quality.
140      * @param csiSinr CSI signal-to-noise and interference ratio.
141      * @param ssRsrp SS reference signal received power.
142      * @param ssRsrq SS reference signal received quality.
143      * @param ssSinr SS signal-to-noise and interference ratio.
144      * @hide
145      */
CellSignalStrengthNr( int csiRsrp, int csiRsrq, int csiSinr, int ssRsrp, int ssRsrq, int ssSinr)146     public CellSignalStrengthNr(
147             int csiRsrp, int csiRsrq, int csiSinr, int ssRsrp, int ssRsrq, int ssSinr) {
148         mCsiRsrp = inRangeOrUnavailable(csiRsrp, -140, -44);
149         mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3);
150         mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23);
151         mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44);
152         mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20);
153         mSsSinr = inRangeOrUnavailable(ssSinr, -23, 40);
154         updateLevel(null, null);
155     }
156 
157     /**
158      * @hide
159      * @param ss signal strength from modem.
160      */
CellSignalStrengthNr(android.hardware.radio.V1_4.NrSignalStrength ss)161     public CellSignalStrengthNr(android.hardware.radio.V1_4.NrSignalStrength ss) {
162         this(flip(ss.csiRsrp), flip(ss.csiRsrq), ss.csiSinr, flip(ss.ssRsrp), flip(ss.ssRsrq),
163                 ss.ssSinr);
164     }
165 
166     /**
167      * Flip sign cell strength value when taking in the value from hal
168      * @param val cell strength value
169      * @return flipped value
170      */
flip(int val)171     private static int flip(int val) {
172         return val != CellInfo.UNAVAILABLE ? -val : val;
173     }
174 
175     /**
176      * Reference: 3GPP TS 38.215.
177      * Range: -140 dBm to -44 dBm.
178      * @return SS reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
179      * value.
180      */
getSsRsrp()181     public int getSsRsrp() {
182         return mSsRsrp;
183     }
184 
185     /**
186      * Reference: 3GPP TS 38.215; 3GPP TS 38.133 section 10
187      * Range: -43 dB to 20 dB.
188      * @return SS reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported
189      * value.
190      */
getSsRsrq()191     public int getSsRsrq() {
192         return mSsRsrq;
193     }
194 
195     /**
196      * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1
197      * Range: -23 dB to 40 dB
198      * @return SS signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means
199      * unreported value.
200      */
getSsSinr()201     public int getSsSinr() {
202         return mSsSinr;
203     }
204 
205     /**
206      * Reference: 3GPP TS 38.215.
207      * Range: -140 dBm to -44 dBm.
208      * @return CSI reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported
209      * value.
210      */
getCsiRsrp()211     public int getCsiRsrp() {
212         return mCsiRsrp;
213     }
214 
215     /**
216      * Reference: 3GPP TS 38.215.
217      * Range: -20 dB to -3 dB.
218      * @return CSI reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported
219      * value.
220      */
getCsiRsrq()221     public int getCsiRsrq() {
222         return mCsiRsrq;
223     }
224 
225     /**
226      * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1
227      * Range: -23 dB to 23 dB
228      * @return CSI signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means
229      * unreported value.
230      */
getCsiSinr()231     public int getCsiSinr() {
232         return mCsiSinr;
233     }
234 
235     @Override
describeContents()236     public int describeContents() {
237         return 0;
238     }
239 
240     /** @hide */
241     @Override
writeToParcel(Parcel dest, int flags)242     public void writeToParcel(Parcel dest, int flags) {
243         dest.writeInt(mCsiRsrp);
244         dest.writeInt(mCsiRsrq);
245         dest.writeInt(mCsiSinr);
246         dest.writeInt(mSsRsrp);
247         dest.writeInt(mSsRsrq);
248         dest.writeInt(mSsSinr);
249         dest.writeInt(mLevel);
250     }
251 
CellSignalStrengthNr(Parcel in)252     private CellSignalStrengthNr(Parcel in) {
253         mCsiRsrp = in.readInt();
254         mCsiRsrq = in.readInt();
255         mCsiSinr = in.readInt();
256         mSsRsrp = in.readInt();
257         mSsRsrq = in.readInt();
258         mSsSinr = in.readInt();
259         mLevel = in.readInt();
260     }
261 
262     /** @hide */
263     @Override
setDefaultValues()264     public void setDefaultValues() {
265         mCsiRsrp = CellInfo.UNAVAILABLE;
266         mCsiRsrq = CellInfo.UNAVAILABLE;
267         mCsiSinr = CellInfo.UNAVAILABLE;
268         mSsRsrp = CellInfo.UNAVAILABLE;
269         mSsRsrq = CellInfo.UNAVAILABLE;
270         mSsSinr = CellInfo.UNAVAILABLE;
271         mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
272         mParametersUseForLevel = USE_SSRSRP;
273     }
274 
275     /** {@inheritDoc} */
276     @Override
277     @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
getLevel()278     public int getLevel() {
279         return mLevel;
280     }
281 
282     /**
283      * Checks if the given parameter type is considered to use for {@link #getLevel()}.
284      *
285      * Note: if multiple parameter types are considered, the smaller level for one of the
286      * parameters would be returned by {@link #getLevel()}
287      *
288      * @param parameterType bitwise OR of {@link #USE_SSRSRP}, {@link #USE_SSRSRQ},
289      *         {@link #USE_SSSINR}
290      * @return {@code true} if the level is calculated based on the given parameter type;
291      *      {@code false} otherwise.
292      *
293      */
isLevelForParameter(@ignalLevelAndReportCriteriaSource int parameterType)294     private boolean isLevelForParameter(@SignalLevelAndReportCriteriaSource int parameterType) {
295         return (parameterType & mParametersUseForLevel) == parameterType;
296     }
297 
298     /** @hide */
299     @Override
updateLevel(PersistableBundle cc, ServiceState ss)300     public void updateLevel(PersistableBundle cc, ServiceState ss) {
301         if (cc == null) {
302             mParametersUseForLevel = USE_SSRSRP;
303         } else {
304             mParametersUseForLevel = cc.getInt(
305                     CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, USE_SSRSRP);
306             mSsRsrpThresholds = cc.getIntArray(
307                     CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY);
308             if (VDBG) {
309                 Rlog.i(TAG, "Applying 5G NR SSRSRP Thresholds: "
310                         + Arrays.toString(mSsRsrpThresholds));
311             }
312             mSsRsrqThresholds = cc.getIntArray(
313                     CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY);
314             if (VDBG) {
315                 Rlog.i(TAG, "Applying 5G NR SSRSRQ Thresholds: "
316                         + Arrays.toString(mSsRsrqThresholds));
317             }
318             mSsSinrThresholds = cc.getIntArray(
319                     CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY);
320             if (VDBG) {
321                 Rlog.i(TAG, "Applying 5G NR SSSINR Thresholds: "
322                         + Arrays.toString(mSsSinrThresholds));
323             }
324         }
325         int ssRsrpLevel = SignalStrength.INVALID;
326         int ssRsrqLevel = SignalStrength.INVALID;
327         int ssSinrLevel = SignalStrength.INVALID;
328         if (isLevelForParameter(USE_SSRSRP)) {
329             ssRsrpLevel = updateLevelWithMeasure(mSsRsrp, mSsRsrpThresholds);
330             if (VDBG) {
331                 Rlog.i(TAG, "Updated 5G NR SSRSRP Level: " + ssRsrpLevel);
332             }
333         }
334         if (isLevelForParameter(USE_SSRSRQ)) {
335             ssRsrqLevel = updateLevelWithMeasure(mSsRsrq, mSsRsrqThresholds);
336             if (VDBG) {
337                 Rlog.i(TAG, "Updated 5G NR SSRSRQ Level: " + ssRsrqLevel);
338             }
339         }
340         if (isLevelForParameter(USE_SSSINR)) {
341             ssSinrLevel = updateLevelWithMeasure(mSsSinr, mSsSinrThresholds);
342             if (VDBG) {
343                 Rlog.i(TAG, "Updated 5G NR SSSINR Level: " + ssSinrLevel);
344             }
345         }
346         // Apply the smaller value among three levels of three measures.
347         mLevel = Math.min(Math.min(ssRsrpLevel, ssRsrqLevel), ssSinrLevel);
348     }
349 
350     /**
351      * Update level with corresponding measure and thresholds.
352      *
353      * @param measure corresponding signal measure
354      * @param thresholds corresponding signal thresholds
355      * @return level of the signal strength
356      */
updateLevelWithMeasure(int measure, int[] thresholds)357     private int updateLevelWithMeasure(int measure, int[] thresholds) {
358         int level;
359         if (measure == CellInfo.UNAVAILABLE) {
360             level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
361         } else if (measure > thresholds[3]) {
362             level = SIGNAL_STRENGTH_GREAT;
363         } else if (measure > thresholds[2]) {
364             level = SIGNAL_STRENGTH_GOOD;
365         } else if (measure > thresholds[1]) {
366             level = SIGNAL_STRENGTH_MODERATE;
367         }  else if (measure > thresholds[0]) {
368             level = SIGNAL_STRENGTH_POOR;
369         } else {
370             level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
371         }
372         return level;
373     }
374 
375     /**
376      * Get the RSRP in ASU.
377      *
378      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
379      *
380      * @return RSRP in ASU 0..97, 255, or UNAVAILABLE
381      */
382     @Override
getAsuLevel()383     public int getAsuLevel() {
384         int asuLevel;
385         int nrDbm = getDbm();
386         if (nrDbm == CellInfo.UNAVAILABLE) {
387             asuLevel = UNKNOWN_ASU_LEVEL;
388         } else if (nrDbm <= -140) {
389             asuLevel = 0;
390         } else if (nrDbm >= -43) {
391             asuLevel = 97;
392         } else {
393             asuLevel = nrDbm + 140;
394         }
395         return asuLevel;
396     }
397 
398     /**
399      * Get the SS-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
400      */
401     @Override
getDbm()402     public int getDbm() {
403         return mSsRsrp;
404     }
405 
406     /** @hide */
CellSignalStrengthNr(CellSignalStrengthNr s)407     public CellSignalStrengthNr(CellSignalStrengthNr s) {
408         mCsiRsrp = s.mCsiRsrp;
409         mCsiRsrq = s.mCsiRsrq;
410         mCsiSinr = s.mCsiSinr;
411         mSsRsrp = s.mSsRsrp;
412         mSsRsrq = s.mSsRsrq;
413         mSsSinr = s.mSsSinr;
414         mLevel = s.mLevel;
415         mParametersUseForLevel = s.mParametersUseForLevel;
416     }
417 
418     /** @hide */
419     @Override
copy()420     public CellSignalStrengthNr copy() {
421         return new CellSignalStrengthNr(this);
422     }
423 
424     @Override
hashCode()425     public int hashCode() {
426         return Objects.hash(mCsiRsrp, mCsiRsrq, mCsiSinr, mSsRsrp, mSsRsrq, mSsSinr, mLevel);
427     }
428 
429     private static final CellSignalStrengthNr sInvalid = new CellSignalStrengthNr();
430 
431     /** @hide */
432     @Override
isValid()433     public boolean isValid() {
434         return !this.equals(sInvalid);
435     }
436 
437     @Override
equals(Object obj)438     public boolean equals(Object obj) {
439         if (obj instanceof CellSignalStrengthNr) {
440             CellSignalStrengthNr o = (CellSignalStrengthNr) obj;
441             return mCsiRsrp == o.mCsiRsrp && mCsiRsrq == o.mCsiRsrq && mCsiSinr == o.mCsiSinr
442                     && mSsRsrp == o.mSsRsrp && mSsRsrq == o.mSsRsrq && mSsSinr == o.mSsSinr
443                     && mLevel == o.mLevel;
444         }
445         return false;
446     }
447 
448     @Override
toString()449     public String toString() {
450         return new StringBuilder()
451                 .append(TAG + ":{")
452                 .append(" csiRsrp = " + mCsiRsrp)
453                 .append(" csiRsrq = " + mCsiRsrq)
454                 .append(" csiSinr = " + mCsiSinr)
455                 .append(" ssRsrp = " + mSsRsrp)
456                 .append(" ssRsrq = " + mSsRsrq)
457                 .append(" ssSinr = " + mSsSinr)
458                 .append(" level = " + mLevel)
459                 .append(" parametersUseForLevel = " + mParametersUseForLevel)
460                 .append(" }")
461                 .toString();
462     }
463 
464     /** Implement the Parcelable interface */
465     public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthNr> CREATOR =
466             new Parcelable.Creator<CellSignalStrengthNr>() {
467         @Override
468         public CellSignalStrengthNr createFromParcel(Parcel in) {
469             return new CellSignalStrengthNr(in);
470         }
471 
472         @Override
473         public CellSignalStrengthNr[] newArray(int size) {
474             return new CellSignalStrengthNr[size];
475         }
476     };
477 }
478