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.os.Bundle;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.telephony.Rlog;
23 import android.content.res.Resources;
24 
25 /**
26  * Contains phone signal strength related information.
27  */
28 public class SignalStrength implements Parcelable {
29 
30     private static final String LOG_TAG = "SignalStrength";
31     private static final boolean DBG = false;
32 
33     /** @hide */
34     public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
35     /** @hide */
36     public static final int SIGNAL_STRENGTH_POOR = 1;
37     /** @hide */
38     public static final int SIGNAL_STRENGTH_MODERATE = 2;
39     /** @hide */
40     public static final int SIGNAL_STRENGTH_GOOD = 3;
41     /** @hide */
42     public static final int SIGNAL_STRENGTH_GREAT = 4;
43     /** @hide */
44     public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
45     /** @hide */
46     public static final String[] SIGNAL_STRENGTH_NAMES = {
47         "none", "poor", "moderate", "good", "great"
48     };
49 
50     /** @hide */
51     //Use int max, as -1 is a valid value in signal strength
52     public static final int INVALID = 0x7FFFFFFF;
53 
54     private static final int RSRP_THRESH_TYPE_STRICT = 0;
55     private static final int[] RSRP_THRESH_STRICT = new int[] {-140, -115, -105, -95, -85, -44};
56     private static final int[] RSRP_THRESH_LENIENT = new int[] {-140, -128, -118, -108, -98, -44};
57 
58 
59     private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
60     private int mGsmBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
61     private int mCdmaDbm;   // This value is the RSSI value
62     private int mCdmaEcio;  // This value is the Ec/Io
63     private int mEvdoDbm;   // This value is the EVDO RSSI value
64     private int mEvdoEcio;  // This value is the EVDO Ec/Io
65     private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
66     private int mLteSignalStrength;
67     private int mLteRsrp;
68     private int mLteRsrq;
69     private int mLteRssnr;
70     private int mLteCqi;
71 
72     private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
73 
74     /**
75      * Create a new SignalStrength from a intent notifier Bundle
76      *
77      * This method is used by PhoneStateIntentReceiver and maybe by
78      * external applications.
79      *
80      * @param m Bundle from intent notifier
81      * @return newly created SignalStrength
82      *
83      * @hide
84      */
newFromBundle(Bundle m)85     public static SignalStrength newFromBundle(Bundle m) {
86         SignalStrength ret;
87         ret = new SignalStrength();
88         ret.setFromNotifierBundle(m);
89         return ret;
90     }
91 
92     /**
93      * Empty constructor
94      *
95      * @hide
96      */
SignalStrength()97     public SignalStrength() {
98         mGsmSignalStrength = 99;
99         mGsmBitErrorRate = -1;
100         mCdmaDbm = -1;
101         mCdmaEcio = -1;
102         mEvdoDbm = -1;
103         mEvdoEcio = -1;
104         mEvdoSnr = -1;
105         mLteSignalStrength = 99;
106         mLteRsrp = INVALID;
107         mLteRsrq = INVALID;
108         mLteRssnr = INVALID;
109         mLteCqi = INVALID;
110         isGsm = true;
111     }
112 
113     /**
114      * This constructor is used to create SignalStrength with default
115      * values and set the isGsmFlag with the value passed in the input
116      *
117      * @param gsmFlag true if Gsm Phone,false if Cdma phone
118      * @return newly created SignalStrength
119      * @hide
120      */
SignalStrength(boolean gsmFlag)121     public SignalStrength(boolean gsmFlag) {
122         mGsmSignalStrength = 99;
123         mGsmBitErrorRate = -1;
124         mCdmaDbm = -1;
125         mCdmaEcio = -1;
126         mEvdoDbm = -1;
127         mEvdoEcio = -1;
128         mEvdoSnr = -1;
129         mLteSignalStrength = 99;
130         mLteRsrp = INVALID;
131         mLteRsrq = INVALID;
132         mLteRssnr = INVALID;
133         mLteCqi = INVALID;
134         isGsm = gsmFlag;
135     }
136 
137     /**
138      * Constructor
139      *
140      * @hide
141      */
SignalStrength(int gsmSignalStrength, int gsmBitErrorRate, int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr, int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi, boolean gsmFlag)142     public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
143             int cdmaDbm, int cdmaEcio,
144             int evdoDbm, int evdoEcio, int evdoSnr,
145             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
146             boolean gsmFlag) {
147         initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
148                 evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
149                 lteRsrq, lteRssnr, lteCqi, gsmFlag);
150     }
151 
152     /**
153      * Constructor
154      *
155      * @hide
156      */
SignalStrength(int gsmSignalStrength, int gsmBitErrorRate, int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr, boolean gsmFlag)157     public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
158             int cdmaDbm, int cdmaEcio,
159             int evdoDbm, int evdoEcio, int evdoSnr,
160             boolean gsmFlag) {
161         initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
162                 evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
163                 INVALID, INVALID, INVALID, gsmFlag);
164     }
165 
166     /**
167      * Copy constructors
168      *
169      * @param s Source SignalStrength
170      *
171      * @hide
172      */
SignalStrength(SignalStrength s)173     public SignalStrength(SignalStrength s) {
174         copyFrom(s);
175     }
176 
177     /**
178      * Initialize gsm/cdma values, sets lte values to defaults.
179      *
180      * @param gsmSignalStrength
181      * @param gsmBitErrorRate
182      * @param cdmaDbm
183      * @param cdmaEcio
184      * @param evdoDbm
185      * @param evdoEcio
186      * @param evdoSnr
187      * @param gsm
188      *
189      * @hide
190      */
initialize(int gsmSignalStrength, int gsmBitErrorRate, int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr, boolean gsm)191     public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
192             int cdmaDbm, int cdmaEcio,
193             int evdoDbm, int evdoEcio, int evdoSnr,
194             boolean gsm) {
195         initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
196                 evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
197                 INVALID, INVALID, INVALID, gsm);
198     }
199 
200     /**
201      * Initialize all the values
202      *
203      * @param gsmSignalStrength
204      * @param gsmBitErrorRate
205      * @param cdmaDbm
206      * @param cdmaEcio
207      * @param evdoDbm
208      * @param evdoEcio
209      * @param evdoSnr
210      * @param lteSignalStrength
211      * @param lteRsrp
212      * @param lteRsrq
213      * @param lteRssnr
214      * @param lteCqi
215      * @param gsm
216      *
217      * @hide
218      */
initialize(int gsmSignalStrength, int gsmBitErrorRate, int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr, int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi, boolean gsm)219     public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
220             int cdmaDbm, int cdmaEcio,
221             int evdoDbm, int evdoEcio, int evdoSnr,
222             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
223             boolean gsm) {
224         mGsmSignalStrength = gsmSignalStrength;
225         mGsmBitErrorRate = gsmBitErrorRate;
226         mCdmaDbm = cdmaDbm;
227         mCdmaEcio = cdmaEcio;
228         mEvdoDbm = evdoDbm;
229         mEvdoEcio = evdoEcio;
230         mEvdoSnr = evdoSnr;
231         mLteSignalStrength = lteSignalStrength;
232         mLteRsrp = lteRsrp;
233         mLteRsrq = lteRsrq;
234         mLteRssnr = lteRssnr;
235         mLteCqi = lteCqi;
236         isGsm = gsm;
237         if (DBG) log("initialize: " + toString());
238     }
239 
240     /**
241      * @hide
242      */
copyFrom(SignalStrength s)243     protected void copyFrom(SignalStrength s) {
244         mGsmSignalStrength = s.mGsmSignalStrength;
245         mGsmBitErrorRate = s.mGsmBitErrorRate;
246         mCdmaDbm = s.mCdmaDbm;
247         mCdmaEcio = s.mCdmaEcio;
248         mEvdoDbm = s.mEvdoDbm;
249         mEvdoEcio = s.mEvdoEcio;
250         mEvdoSnr = s.mEvdoSnr;
251         mLteSignalStrength = s.mLteSignalStrength;
252         mLteRsrp = s.mLteRsrp;
253         mLteRsrq = s.mLteRsrq;
254         mLteRssnr = s.mLteRssnr;
255         mLteCqi = s.mLteCqi;
256         isGsm = s.isGsm;
257     }
258 
259     /**
260      * Construct a SignalStrength object from the given parcel.
261      *
262      * @hide
263      */
SignalStrength(Parcel in)264     public SignalStrength(Parcel in) {
265         if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
266 
267         mGsmSignalStrength = in.readInt();
268         mGsmBitErrorRate = in.readInt();
269         mCdmaDbm = in.readInt();
270         mCdmaEcio = in.readInt();
271         mEvdoDbm = in.readInt();
272         mEvdoEcio = in.readInt();
273         mEvdoSnr = in.readInt();
274         mLteSignalStrength = in.readInt();
275         mLteRsrp = in.readInt();
276         mLteRsrq = in.readInt();
277         mLteRssnr = in.readInt();
278         mLteCqi = in.readInt();
279         isGsm = (in.readInt() != 0);
280     }
281 
282     /**
283      * Make a SignalStrength object from the given parcel as passed up by
284      * the ril which does not have isGsm. isGsm will be changed by ServiceStateTracker
285      * so the default is a don't care.
286      *
287      * @hide
288      */
makeSignalStrengthFromRilParcel(Parcel in)289     public static SignalStrength makeSignalStrengthFromRilParcel(Parcel in) {
290         if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
291 
292         SignalStrength ss = new SignalStrength();
293         ss.mGsmSignalStrength = in.readInt();
294         ss.mGsmBitErrorRate = in.readInt();
295         ss.mCdmaDbm = in.readInt();
296         ss.mCdmaEcio = in.readInt();
297         ss.mEvdoDbm = in.readInt();
298         ss.mEvdoEcio = in.readInt();
299         ss.mEvdoSnr = in.readInt();
300         ss.mLteSignalStrength = in.readInt();
301         ss.mLteRsrp = in.readInt();
302         ss.mLteRsrq = in.readInt();
303         ss.mLteRssnr = in.readInt();
304         ss.mLteCqi = in.readInt();
305 
306         return ss;
307     }
308 
309     /**
310      * {@link Parcelable#writeToParcel}
311      */
writeToParcel(Parcel out, int flags)312     public void writeToParcel(Parcel out, int flags) {
313         out.writeInt(mGsmSignalStrength);
314         out.writeInt(mGsmBitErrorRate);
315         out.writeInt(mCdmaDbm);
316         out.writeInt(mCdmaEcio);
317         out.writeInt(mEvdoDbm);
318         out.writeInt(mEvdoEcio);
319         out.writeInt(mEvdoSnr);
320         out.writeInt(mLteSignalStrength);
321         out.writeInt(mLteRsrp);
322         out.writeInt(mLteRsrq);
323         out.writeInt(mLteRssnr);
324         out.writeInt(mLteCqi);
325         out.writeInt(isGsm ? 1 : 0);
326     }
327 
328     /**
329      * {@link Parcelable#describeContents}
330      */
describeContents()331     public int describeContents() {
332         return 0;
333     }
334 
335     /**
336      * {@link Parcelable.Creator}
337      *
338      * @hide
339      */
340     public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
341         public SignalStrength createFromParcel(Parcel in) {
342             return new SignalStrength(in);
343         }
344 
345         public SignalStrength[] newArray(int size) {
346             return new SignalStrength[size];
347         }
348     };
349 
350     /**
351      * Validate the individual signal strength fields as per the range
352      * specified in ril.h
353      * Set to invalid any field that is not in the valid range
354      * Cdma, evdo, lte rsrp & rsrq values are sign converted
355      * when received from ril interface
356      *
357      * @return
358      *      Valid values for all signalstrength fields
359      * @hide
360      */
validateInput()361     public void validateInput() {
362         if (DBG) log("Signal before validate=" + this);
363         // TS 27.007 8.5
364         mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99;
365         // BER no change;
366 
367         mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
368         mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
369 
370         mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
371         mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1;
372         mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
373 
374         // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
375         mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
376         mLteRsrp = ((mLteRsrp >= 44) && (mLteRsrp <= 140)) ? -mLteRsrp : SignalStrength.INVALID;
377         mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
378         mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
379                 : SignalStrength.INVALID;
380         // Cqi no change
381         if (DBG) log("Signal after validate=" + this);
382     }
383 
384     /**
385      * @param true - Gsm, Lte phones
386      *        false - Cdma phones
387      *
388      * Used by voice phone to set the isGsm
389      *        flag
390      * @hide
391      */
setGsm(boolean gsmFlag)392     public void setGsm(boolean gsmFlag) {
393         isGsm = gsmFlag;
394     }
395 
396     /**
397      * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS
398      * 27.007 8.5
399      */
getGsmSignalStrength()400     public int getGsmSignalStrength() {
401         return this.mGsmSignalStrength;
402     }
403 
404     /**
405      * Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5
406      */
getGsmBitErrorRate()407     public int getGsmBitErrorRate() {
408         return this.mGsmBitErrorRate;
409     }
410 
411     /**
412      * Get the CDMA RSSI value in dBm
413      */
getCdmaDbm()414     public int getCdmaDbm() {
415         return this.mCdmaDbm;
416     }
417 
418     /**
419      * Get the CDMA Ec/Io value in dB*10
420      */
getCdmaEcio()421     public int getCdmaEcio() {
422         return this.mCdmaEcio;
423     }
424 
425     /**
426      * Get the EVDO RSSI value in dBm
427      */
getEvdoDbm()428     public int getEvdoDbm() {
429         return this.mEvdoDbm;
430     }
431 
432     /**
433      * Get the EVDO Ec/Io value in dB*10
434      */
getEvdoEcio()435     public int getEvdoEcio() {
436         return this.mEvdoEcio;
437     }
438 
439     /**
440      * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
441      */
getEvdoSnr()442     public int getEvdoSnr() {
443         return this.mEvdoSnr;
444     }
445 
446     /** @hide */
getLteSignalStrength()447     public int getLteSignalStrength() {
448         return mLteSignalStrength;
449     }
450 
451     /** @hide */
getLteRsrp()452     public int getLteRsrp() {
453         return mLteRsrp;
454     }
455 
456     /** @hide */
getLteRsrq()457     public int getLteRsrq() {
458         return mLteRsrq;
459     }
460 
461     /** @hide */
getLteRssnr()462     public int getLteRssnr() {
463         return mLteRssnr;
464     }
465 
466     /** @hide */
getLteCqi()467     public int getLteCqi() {
468         return mLteCqi;
469     }
470 
471     /**
472      * Get signal level as an int from 0..4
473      *
474      * @hide
475      */
getLevel()476     public int getLevel() {
477         int level;
478 
479         if (isGsm) {
480             level = getLteLevel();
481             if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
482                 level = getGsmLevel();
483             }
484         } else {
485             int cdmaLevel = getCdmaLevel();
486             int evdoLevel = getEvdoLevel();
487             if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
488                 /* We don't know evdo, use cdma */
489                 level = cdmaLevel;
490             } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
491                 /* We don't know cdma, use evdo */
492                 level = evdoLevel;
493             } else {
494                 /* We know both, use the lowest level */
495                 level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
496             }
497         }
498         if (DBG) log("getLevel=" + level);
499         return level;
500     }
501 
502     /**
503      * Get the signal level as an asu value between 0..31, 99 is unknown
504      *
505      * @hide
506      */
507     public int getAsuLevel() {
508         int asuLevel;
509         if (isGsm) {
510             if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
511                 asuLevel = getGsmAsuLevel();
512             } else {
513                 asuLevel = getLteAsuLevel();
514             }
515         } else {
516             int cdmaAsuLevel = getCdmaAsuLevel();
517             int evdoAsuLevel = getEvdoAsuLevel();
518             if (evdoAsuLevel == 0) {
519                 /* We don't know evdo use, cdma */
520                 asuLevel = cdmaAsuLevel;
521             } else if (cdmaAsuLevel == 0) {
522                 /* We don't know cdma use, evdo */
523                 asuLevel = evdoAsuLevel;
524             } else {
525                 /* We know both, use the lowest level */
526                 asuLevel = cdmaAsuLevel < evdoAsuLevel ? cdmaAsuLevel : evdoAsuLevel;
527             }
528         }
529         if (DBG) log("getAsuLevel=" + asuLevel);
530         return asuLevel;
531     }
532 
533     /**
534      * Get the signal strength as dBm
535      *
536      * @hide
537      */
538     public int getDbm() {
539         int dBm;
540 
541         if(isGsm()) {
542             dBm = getLteDbm();
543             if (dBm == INVALID) {
544                 dBm = getGsmDbm();
545             }
546         } else {
547             int cdmaDbm = getCdmaDbm();
548             int evdoDbm = getEvdoDbm();
549 
550             return (evdoDbm == -120) ? cdmaDbm : ((cdmaDbm == -120) ? evdoDbm
551                     : (cdmaDbm < evdoDbm ? cdmaDbm : evdoDbm));
552         }
553         if (DBG) log("getDbm=" + dBm);
554         return dBm;
555     }
556 
557     /**
558      * Get Gsm signal strength as dBm
559      *
560      * @hide
561      */
562     public int getGsmDbm() {
563         int dBm;
564 
565         int gsmSignalStrength = getGsmSignalStrength();
566         int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
567         if (asu != -1) {
568             dBm = -113 + (2 * asu);
569         } else {
570             dBm = -1;
571         }
572         if (DBG) log("getGsmDbm=" + dBm);
573         return dBm;
574     }
575 
576     /**
577      * Get gsm as level 0..4
578      *
579      * @hide
580      */
581     public int getGsmLevel() {
582         int level;
583 
584         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
585         // asu = 0 (-113dB or less) is very weak
586         // signal, its better to show 0 bars to the user in such cases.
587         // asu = 99 is a special case, where the signal strength is unknown.
588         int asu = getGsmSignalStrength();
589         if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
590         else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
591         else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;
592         else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;
593         else level = SIGNAL_STRENGTH_POOR;
594         if (DBG) log("getGsmLevel=" + level);
595         return level;
596     }
597 
598     /**
599      * Get the gsm signal level as an asu value between 0..31, 99 is unknown
600      *
601      * @hide
602      */
603     public int getGsmAsuLevel() {
604         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
605         // asu = 0 (-113dB or less) is very weak
606         // signal, its better to show 0 bars to the user in such cases.
607         // asu = 99 is a special case, where the signal strength is unknown.
608         int level = getGsmSignalStrength();
609         if (DBG) log("getGsmAsuLevel=" + level);
610         return level;
611     }
612 
613     /**
614      * Get cdma as level 0..4
615      *
616      * @hide
617      */
618     public int getCdmaLevel() {
619         final int cdmaDbm = getCdmaDbm();
620         final int cdmaEcio = getCdmaEcio();
621         int levelDbm;
622         int levelEcio;
623 
624         if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
625         else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
626         else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
627         else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
628         else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
629 
630         // Ec/Io are in dB*10
631         if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
632         else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
633         else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
634         else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
635         else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
636 
637         int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
638         if (DBG) log("getCdmaLevel=" + level);
639         return level;
640     }
641 
642     /**
643      * Get the cdma signal level as an asu value between 0..31, 99 is unknown
644      *
645      * @hide
646      */
getCdmaAsuLevel()647     public int getCdmaAsuLevel() {
648         final int cdmaDbm = getCdmaDbm();
649         final int cdmaEcio = getCdmaEcio();
650         int cdmaAsuLevel;
651         int ecioAsuLevel;
652 
653         if (cdmaDbm >= -75) cdmaAsuLevel = 16;
654         else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
655         else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
656         else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
657         else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
658         else cdmaAsuLevel = 99;
659 
660         // Ec/Io are in dB*10
661         if (cdmaEcio >= -90) ecioAsuLevel = 16;
662         else if (cdmaEcio >= -100) ecioAsuLevel = 8;
663         else if (cdmaEcio >= -115) ecioAsuLevel = 4;
664         else if (cdmaEcio >= -130) ecioAsuLevel = 2;
665         else if (cdmaEcio >= -150) ecioAsuLevel = 1;
666         else ecioAsuLevel = 99;
667 
668         int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
669         if (DBG) log("getCdmaAsuLevel=" + level);
670         return level;
671     }
672 
673     /**
674      * Get Evdo as level 0..4
675      *
676      * @hide
677      */
getEvdoLevel()678     public int getEvdoLevel() {
679         int evdoDbm = getEvdoDbm();
680         int evdoSnr = getEvdoSnr();
681         int levelEvdoDbm;
682         int levelEvdoSnr;
683 
684         if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
685         else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
686         else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
687         else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
688         else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
689 
690         if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
691         else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
692         else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
693         else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
694         else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
695 
696         int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
697         if (DBG) log("getEvdoLevel=" + level);
698         return level;
699     }
700 
701     /**
702      * Get the evdo signal level as an asu value between 0..31, 99 is unknown
703      *
704      * @hide
705      */
getEvdoAsuLevel()706     public int getEvdoAsuLevel() {
707         int evdoDbm = getEvdoDbm();
708         int evdoSnr = getEvdoSnr();
709         int levelEvdoDbm;
710         int levelEvdoSnr;
711 
712         if (evdoDbm >= -65) levelEvdoDbm = 16;
713         else if (evdoDbm >= -75) levelEvdoDbm = 8;
714         else if (evdoDbm >= -85) levelEvdoDbm = 4;
715         else if (evdoDbm >= -95) levelEvdoDbm = 2;
716         else if (evdoDbm >= -105) levelEvdoDbm = 1;
717         else levelEvdoDbm = 99;
718 
719         if (evdoSnr >= 7) levelEvdoSnr = 16;
720         else if (evdoSnr >= 6) levelEvdoSnr = 8;
721         else if (evdoSnr >= 5) levelEvdoSnr = 4;
722         else if (evdoSnr >= 3) levelEvdoSnr = 2;
723         else if (evdoSnr >= 1) levelEvdoSnr = 1;
724         else levelEvdoSnr = 99;
725 
726         int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
727         if (DBG) log("getEvdoAsuLevel=" + level);
728         return level;
729     }
730 
731     /**
732      * Get LTE as dBm
733      *
734      * @hide
735      */
getLteDbm()736     public int getLteDbm() {
737         return mLteRsrp;
738     }
739 
740     /**
741      * Get LTE as level 0..4
742      *
743      * @hide
744      */
getLteLevel()745     public int getLteLevel() {
746         /*
747          * TS 36.214 Physical Layer Section 5.1.3 TS 36.331 RRC RSSI = received
748          * signal + noise RSRP = reference signal dBm RSRQ = quality of signal
749          * dB= Number of Resource blocksxRSRP/RSSI SNR = gain=signal/noise ratio
750          * = -10log P1/P2 dB
751          */
752         int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
753 
754         int rsrpThreshType = Resources.getSystem().getInteger(com.android.internal.R.integer.
755                 config_LTE_RSRP_threshold_type);
756         int[] threshRsrp;
757         if (rsrpThreshType == RSRP_THRESH_TYPE_STRICT) {
758             threshRsrp = RSRP_THRESH_STRICT;
759         } else {
760             threshRsrp = RSRP_THRESH_LENIENT;
761         }
762 
763         if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1;
764         else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
765         else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
766         else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
767         else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
768         else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
769 
770         /*
771          * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
772          * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
773          * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
774          * Icon Only
775          */
776         if (mLteRssnr > 300) snrIconLevel = -1;
777         else if (mLteRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
778         else if (mLteRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
779         else if (mLteRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
780         else if (mLteRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
781         else if (mLteRssnr >= -200)
782             snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
783 
784         if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
785                 + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);
786 
787         /* Choose a measurement type to use for notification */
788         if (snrIconLevel != -1 && rsrpIconLevel != -1) {
789             /*
790              * The number of bars displayed shall be the smaller of the bars
791              * associated with LTE RSRP and the bars associated with the LTE
792              * RS_SNR
793              */
794             return (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
795         }
796 
797         if (snrIconLevel != -1) return snrIconLevel;
798 
799         if (rsrpIconLevel != -1) return rsrpIconLevel;
800 
801         /* Valid values are (0-63, 99) as defined in TS 36.331 */
802         if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
803         else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
804         else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
805         else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
806         else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
807 
808         if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
809                 + rssiIconLevel);
810         return rssiIconLevel;
811 
812     }
813     /**
814      * Get the LTE signal level as an asu value between 0..97, 99 is unknown
815      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
816      *
817      * @hide
818      */
getLteAsuLevel()819     public int getLteAsuLevel() {
820         int lteAsuLevel = 99;
821         int lteDbm = getLteDbm();
822         /*
823          * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
824          * 0   -140 dBm or less
825          * 1   -139 dBm
826          * 2...96  -138... -44 dBm
827          * 97  -43 dBm or greater
828          * 255 not known or not detectable
829          */
830         /*
831          * validateInput will always give a valid range between -140 t0 -44 as
832          * per ril.h. so RSRP >= -43 & <-140 will fall under asu level 255
833          * and not 97 or 0
834          */
835         if (lteDbm == SignalStrength.INVALID) lteAsuLevel = 255;
836         else lteAsuLevel = lteDbm + 140;
837         if (DBG) log("Lte Asu level: "+lteAsuLevel);
838         return lteAsuLevel;
839     }
840 
841     /**
842      * @return true if this is for GSM
843      */
isGsm()844     public boolean isGsm() {
845         return this.isGsm;
846     }
847 
848     /**
849      * @return hash code
850      */
851     @Override
hashCode()852     public int hashCode() {
853         int primeNum = 31;
854         return ((mGsmSignalStrength * primeNum)
855                 + (mGsmBitErrorRate * primeNum)
856                 + (mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
857                 + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
858                 + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
859                 + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
860                 + (isGsm ? 1 : 0));
861     }
862 
863     /**
864      * @return true if the signal strengths are the same
865      */
866     @Override
equals(Object o)867     public boolean equals (Object o) {
868         SignalStrength s;
869 
870         try {
871             s = (SignalStrength) o;
872         } catch (ClassCastException ex) {
873             return false;
874         }
875 
876         if (o == null) {
877             return false;
878         }
879 
880         return (mGsmSignalStrength == s.mGsmSignalStrength
881                 && mGsmBitErrorRate == s.mGsmBitErrorRate
882                 && mCdmaDbm == s.mCdmaDbm
883                 && mCdmaEcio == s.mCdmaEcio
884                 && mEvdoDbm == s.mEvdoDbm
885                 && mEvdoEcio == s.mEvdoEcio
886                 && mEvdoSnr == s.mEvdoSnr
887                 && mLteSignalStrength == s.mLteSignalStrength
888                 && mLteRsrp == s.mLteRsrp
889                 && mLteRsrq == s.mLteRsrq
890                 && mLteRssnr == s.mLteRssnr
891                 && mLteCqi == s.mLteCqi
892                 && isGsm == s.isGsm);
893     }
894 
895     /**
896      * @return string representation.
897      */
898     @Override
toString()899     public String toString() {
900         return ("SignalStrength:"
901                 + " " + mGsmSignalStrength
902                 + " " + mGsmBitErrorRate
903                 + " " + mCdmaDbm
904                 + " " + mCdmaEcio
905                 + " " + mEvdoDbm
906                 + " " + mEvdoEcio
907                 + " " + mEvdoSnr
908                 + " " + mLteSignalStrength
909                 + " " + mLteRsrp
910                 + " " + mLteRsrq
911                 + " " + mLteRssnr
912                 + " " + mLteCqi
913                 + " " + (isGsm ? "gsm|lte" : "cdma"));
914     }
915 
916     /**
917      * Set SignalStrength based on intent notifier map
918      *
919      * @param m intent notifier map
920      * @hide
921      */
setFromNotifierBundle(Bundle m)922     private void setFromNotifierBundle(Bundle m) {
923         mGsmSignalStrength = m.getInt("GsmSignalStrength");
924         mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
925         mCdmaDbm = m.getInt("CdmaDbm");
926         mCdmaEcio = m.getInt("CdmaEcio");
927         mEvdoDbm = m.getInt("EvdoDbm");
928         mEvdoEcio = m.getInt("EvdoEcio");
929         mEvdoSnr = m.getInt("EvdoSnr");
930         mLteSignalStrength = m.getInt("LteSignalStrength");
931         mLteRsrp = m.getInt("LteRsrp");
932         mLteRsrq = m.getInt("LteRsrq");
933         mLteRssnr = m.getInt("LteRssnr");
934         mLteCqi = m.getInt("LteCqi");
935         isGsm = m.getBoolean("isGsm");
936     }
937 
938     /**
939      * Set intent notifier Bundle based on SignalStrength
940      *
941      * @param m intent notifier Bundle
942      * @hide
943      */
fillInNotifierBundle(Bundle m)944     public void fillInNotifierBundle(Bundle m) {
945         m.putInt("GsmSignalStrength", mGsmSignalStrength);
946         m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
947         m.putInt("CdmaDbm", mCdmaDbm);
948         m.putInt("CdmaEcio", mCdmaEcio);
949         m.putInt("EvdoDbm", mEvdoDbm);
950         m.putInt("EvdoEcio", mEvdoEcio);
951         m.putInt("EvdoSnr", mEvdoSnr);
952         m.putInt("LteSignalStrength", mLteSignalStrength);
953         m.putInt("LteRsrp", mLteRsrp);
954         m.putInt("LteRsrq", mLteRsrq);
955         m.putInt("LteRssnr", mLteRssnr);
956         m.putInt("LteCqi", mLteCqi);
957         m.putBoolean("isGsm", Boolean.valueOf(isGsm));
958     }
959 
960     /**
961      * log
962      */
log(String s)963     private static void log(String s) {
964         Rlog.w(LOG_TAG, s);
965     }
966 }
967