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      * Retrieve an abstract level value for the overall signal strength.
473      *
474      * @return a single integer from 0 to 4 representing the general signal quality.
475      *     This may take into account many different radio technology inputs.
476      *     0 represents very poor signal strength
477      *     while 4 represents a very strong signal strength.
478      */
getLevel()479     public int getLevel() {
480         int level;
481 
482         if (isGsm) {
483             level = getLteLevel();
484             if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
485                 level = getGsmLevel();
486             }
487         } else {
488             int cdmaLevel = getCdmaLevel();
489             int evdoLevel = getEvdoLevel();
490             if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
491                 /* We don't know evdo, use cdma */
492                 level = cdmaLevel;
493             } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
494                 /* We don't know cdma, use evdo */
495                 level = evdoLevel;
496             } else {
497                 /* We know both, use the lowest level */
498                 level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
499             }
500         }
501         if (DBG) log("getLevel=" + level);
502         return level;
503     }
504 
505     /**
506      * Get the signal level as an asu value between 0..31, 99 is unknown
507      *
508      * @hide
509      */
510     public int getAsuLevel() {
511         int asuLevel;
512         if (isGsm) {
513             if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
514                 asuLevel = getGsmAsuLevel();
515             } else {
516                 asuLevel = getLteAsuLevel();
517             }
518         } else {
519             int cdmaAsuLevel = getCdmaAsuLevel();
520             int evdoAsuLevel = getEvdoAsuLevel();
521             if (evdoAsuLevel == 0) {
522                 /* We don't know evdo use, cdma */
523                 asuLevel = cdmaAsuLevel;
524             } else if (cdmaAsuLevel == 0) {
525                 /* We don't know cdma use, evdo */
526                 asuLevel = evdoAsuLevel;
527             } else {
528                 /* We know both, use the lowest level */
529                 asuLevel = cdmaAsuLevel < evdoAsuLevel ? cdmaAsuLevel : evdoAsuLevel;
530             }
531         }
532         if (DBG) log("getAsuLevel=" + asuLevel);
533         return asuLevel;
534     }
535 
536     /**
537      * Get the signal strength as dBm
538      *
539      * @hide
540      */
541     public int getDbm() {
542         int dBm;
543 
544         if(isGsm()) {
545             dBm = getLteDbm();
546             if (dBm == INVALID) {
547                 dBm = getGsmDbm();
548             }
549         } else {
550             int cdmaDbm = getCdmaDbm();
551             int evdoDbm = getEvdoDbm();
552 
553             return (evdoDbm == -120) ? cdmaDbm : ((cdmaDbm == -120) ? evdoDbm
554                     : (cdmaDbm < evdoDbm ? cdmaDbm : evdoDbm));
555         }
556         if (DBG) log("getDbm=" + dBm);
557         return dBm;
558     }
559 
560     /**
561      * Get Gsm signal strength as dBm
562      *
563      * @hide
564      */
565     public int getGsmDbm() {
566         int dBm;
567 
568         int gsmSignalStrength = getGsmSignalStrength();
569         int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
570         if (asu != -1) {
571             dBm = -113 + (2 * asu);
572         } else {
573             dBm = -1;
574         }
575         if (DBG) log("getGsmDbm=" + dBm);
576         return dBm;
577     }
578 
579     /**
580      * Get gsm as level 0..4
581      *
582      * @hide
583      */
584     public int getGsmLevel() {
585         int level;
586 
587         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
588         // asu = 0 (-113dB or less) is very weak
589         // signal, its better to show 0 bars to the user in such cases.
590         // asu = 99 is a special case, where the signal strength is unknown.
591         int asu = getGsmSignalStrength();
592         if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
593         else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
594         else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;
595         else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;
596         else level = SIGNAL_STRENGTH_POOR;
597         if (DBG) log("getGsmLevel=" + level);
598         return level;
599     }
600 
601     /**
602      * Get the gsm signal level as an asu value between 0..31, 99 is unknown
603      *
604      * @hide
605      */
606     public int getGsmAsuLevel() {
607         // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
608         // asu = 0 (-113dB or less) is very weak
609         // signal, its better to show 0 bars to the user in such cases.
610         // asu = 99 is a special case, where the signal strength is unknown.
611         int level = getGsmSignalStrength();
612         if (DBG) log("getGsmAsuLevel=" + level);
613         return level;
614     }
615 
616     /**
617      * Get cdma as level 0..4
618      *
619      * @hide
620      */
621     public int getCdmaLevel() {
622         final int cdmaDbm = getCdmaDbm();
623         final int cdmaEcio = getCdmaEcio();
624         int levelDbm;
625         int levelEcio;
626 
627         if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
628         else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
629         else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
630         else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
631         else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
632 
633         // Ec/Io are in dB*10
634         if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
635         else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
636         else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
637         else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
638         else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
639 
640         int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
641         if (DBG) log("getCdmaLevel=" + level);
642         return level;
643     }
644 
645     /**
646      * Get the cdma signal level as an asu value between 0..31, 99 is unknown
647      *
648      * @hide
649      */
getCdmaAsuLevel()650     public int getCdmaAsuLevel() {
651         final int cdmaDbm = getCdmaDbm();
652         final int cdmaEcio = getCdmaEcio();
653         int cdmaAsuLevel;
654         int ecioAsuLevel;
655 
656         if (cdmaDbm >= -75) cdmaAsuLevel = 16;
657         else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
658         else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
659         else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
660         else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
661         else cdmaAsuLevel = 99;
662 
663         // Ec/Io are in dB*10
664         if (cdmaEcio >= -90) ecioAsuLevel = 16;
665         else if (cdmaEcio >= -100) ecioAsuLevel = 8;
666         else if (cdmaEcio >= -115) ecioAsuLevel = 4;
667         else if (cdmaEcio >= -130) ecioAsuLevel = 2;
668         else if (cdmaEcio >= -150) ecioAsuLevel = 1;
669         else ecioAsuLevel = 99;
670 
671         int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
672         if (DBG) log("getCdmaAsuLevel=" + level);
673         return level;
674     }
675 
676     /**
677      * Get Evdo as level 0..4
678      *
679      * @hide
680      */
getEvdoLevel()681     public int getEvdoLevel() {
682         int evdoDbm = getEvdoDbm();
683         int evdoSnr = getEvdoSnr();
684         int levelEvdoDbm;
685         int levelEvdoSnr;
686 
687         if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
688         else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
689         else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
690         else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
691         else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
692 
693         if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
694         else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
695         else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
696         else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
697         else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
698 
699         int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
700         if (DBG) log("getEvdoLevel=" + level);
701         return level;
702     }
703 
704     /**
705      * Get the evdo signal level as an asu value between 0..31, 99 is unknown
706      *
707      * @hide
708      */
getEvdoAsuLevel()709     public int getEvdoAsuLevel() {
710         int evdoDbm = getEvdoDbm();
711         int evdoSnr = getEvdoSnr();
712         int levelEvdoDbm;
713         int levelEvdoSnr;
714 
715         if (evdoDbm >= -65) levelEvdoDbm = 16;
716         else if (evdoDbm >= -75) levelEvdoDbm = 8;
717         else if (evdoDbm >= -85) levelEvdoDbm = 4;
718         else if (evdoDbm >= -95) levelEvdoDbm = 2;
719         else if (evdoDbm >= -105) levelEvdoDbm = 1;
720         else levelEvdoDbm = 99;
721 
722         if (evdoSnr >= 7) levelEvdoSnr = 16;
723         else if (evdoSnr >= 6) levelEvdoSnr = 8;
724         else if (evdoSnr >= 5) levelEvdoSnr = 4;
725         else if (evdoSnr >= 3) levelEvdoSnr = 2;
726         else if (evdoSnr >= 1) levelEvdoSnr = 1;
727         else levelEvdoSnr = 99;
728 
729         int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
730         if (DBG) log("getEvdoAsuLevel=" + level);
731         return level;
732     }
733 
734     /**
735      * Get LTE as dBm
736      *
737      * @hide
738      */
getLteDbm()739     public int getLteDbm() {
740         return mLteRsrp;
741     }
742 
743     /**
744      * Get LTE as level 0..4
745      *
746      * @hide
747      */
getLteLevel()748     public int getLteLevel() {
749         /*
750          * TS 36.214 Physical Layer Section 5.1.3 TS 36.331 RRC RSSI = received
751          * signal + noise RSRP = reference signal dBm RSRQ = quality of signal
752          * dB= Number of Resource blocksxRSRP/RSSI SNR = gain=signal/noise ratio
753          * = -10log P1/P2 dB
754          */
755         int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
756 
757         int rsrpThreshType = Resources.getSystem().getInteger(com.android.internal.R.integer.
758                 config_LTE_RSRP_threshold_type);
759         int[] threshRsrp;
760         if (rsrpThreshType == RSRP_THRESH_TYPE_STRICT) {
761             threshRsrp = RSRP_THRESH_STRICT;
762         } else {
763             threshRsrp = RSRP_THRESH_LENIENT;
764         }
765 
766         if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1;
767         else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
768         else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
769         else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
770         else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
771         else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
772 
773         /*
774          * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
775          * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
776          * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
777          * Icon Only
778          */
779         if (mLteRssnr > 300) snrIconLevel = -1;
780         else if (mLteRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
781         else if (mLteRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
782         else if (mLteRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
783         else if (mLteRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
784         else if (mLteRssnr >= -200)
785             snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
786 
787         if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
788                 + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);
789 
790         /* Choose a measurement type to use for notification */
791         if (snrIconLevel != -1 && rsrpIconLevel != -1) {
792             /*
793              * The number of bars displayed shall be the smaller of the bars
794              * associated with LTE RSRP and the bars associated with the LTE
795              * RS_SNR
796              */
797             return (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
798         }
799 
800         if (snrIconLevel != -1) return snrIconLevel;
801 
802         if (rsrpIconLevel != -1) return rsrpIconLevel;
803 
804         /* Valid values are (0-63, 99) as defined in TS 36.331 */
805         if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
806         else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
807         else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
808         else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
809         else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
810 
811         if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
812                 + rssiIconLevel);
813         return rssiIconLevel;
814 
815     }
816     /**
817      * Get the LTE signal level as an asu value between 0..97, 99 is unknown
818      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
819      *
820      * @hide
821      */
getLteAsuLevel()822     public int getLteAsuLevel() {
823         int lteAsuLevel = 99;
824         int lteDbm = getLteDbm();
825         /*
826          * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
827          * 0   -140 dBm or less
828          * 1   -139 dBm
829          * 2...96  -138... -44 dBm
830          * 97  -43 dBm or greater
831          * 255 not known or not detectable
832          */
833         /*
834          * validateInput will always give a valid range between -140 t0 -44 as
835          * per ril.h. so RSRP >= -43 & <-140 will fall under asu level 255
836          * and not 97 or 0
837          */
838         if (lteDbm == SignalStrength.INVALID) lteAsuLevel = 255;
839         else lteAsuLevel = lteDbm + 140;
840         if (DBG) log("Lte Asu level: "+lteAsuLevel);
841         return lteAsuLevel;
842     }
843 
844     /**
845      * @return true if this is for GSM
846      */
isGsm()847     public boolean isGsm() {
848         return this.isGsm;
849     }
850 
851     /**
852      * @return hash code
853      */
854     @Override
hashCode()855     public int hashCode() {
856         int primeNum = 31;
857         return ((mGsmSignalStrength * primeNum)
858                 + (mGsmBitErrorRate * primeNum)
859                 + (mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
860                 + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
861                 + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
862                 + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
863                 + (isGsm ? 1 : 0));
864     }
865 
866     /**
867      * @return true if the signal strengths are the same
868      */
869     @Override
equals(Object o)870     public boolean equals (Object o) {
871         SignalStrength s;
872 
873         try {
874             s = (SignalStrength) o;
875         } catch (ClassCastException ex) {
876             return false;
877         }
878 
879         if (o == null) {
880             return false;
881         }
882 
883         return (mGsmSignalStrength == s.mGsmSignalStrength
884                 && mGsmBitErrorRate == s.mGsmBitErrorRate
885                 && mCdmaDbm == s.mCdmaDbm
886                 && mCdmaEcio == s.mCdmaEcio
887                 && mEvdoDbm == s.mEvdoDbm
888                 && mEvdoEcio == s.mEvdoEcio
889                 && mEvdoSnr == s.mEvdoSnr
890                 && mLteSignalStrength == s.mLteSignalStrength
891                 && mLteRsrp == s.mLteRsrp
892                 && mLteRsrq == s.mLteRsrq
893                 && mLteRssnr == s.mLteRssnr
894                 && mLteCqi == s.mLteCqi
895                 && isGsm == s.isGsm);
896     }
897 
898     /**
899      * @return string representation.
900      */
901     @Override
toString()902     public String toString() {
903         return ("SignalStrength:"
904                 + " " + mGsmSignalStrength
905                 + " " + mGsmBitErrorRate
906                 + " " + mCdmaDbm
907                 + " " + mCdmaEcio
908                 + " " + mEvdoDbm
909                 + " " + mEvdoEcio
910                 + " " + mEvdoSnr
911                 + " " + mLteSignalStrength
912                 + " " + mLteRsrp
913                 + " " + mLteRsrq
914                 + " " + mLteRssnr
915                 + " " + mLteCqi
916                 + " " + (isGsm ? "gsm|lte" : "cdma"));
917     }
918 
919     /**
920      * Set SignalStrength based on intent notifier map
921      *
922      * @param m intent notifier map
923      * @hide
924      */
setFromNotifierBundle(Bundle m)925     private void setFromNotifierBundle(Bundle m) {
926         mGsmSignalStrength = m.getInt("GsmSignalStrength");
927         mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
928         mCdmaDbm = m.getInt("CdmaDbm");
929         mCdmaEcio = m.getInt("CdmaEcio");
930         mEvdoDbm = m.getInt("EvdoDbm");
931         mEvdoEcio = m.getInt("EvdoEcio");
932         mEvdoSnr = m.getInt("EvdoSnr");
933         mLteSignalStrength = m.getInt("LteSignalStrength");
934         mLteRsrp = m.getInt("LteRsrp");
935         mLteRsrq = m.getInt("LteRsrq");
936         mLteRssnr = m.getInt("LteRssnr");
937         mLteCqi = m.getInt("LteCqi");
938         isGsm = m.getBoolean("isGsm");
939     }
940 
941     /**
942      * Set intent notifier Bundle based on SignalStrength
943      *
944      * @param m intent notifier Bundle
945      * @hide
946      */
fillInNotifierBundle(Bundle m)947     public void fillInNotifierBundle(Bundle m) {
948         m.putInt("GsmSignalStrength", mGsmSignalStrength);
949         m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
950         m.putInt("CdmaDbm", mCdmaDbm);
951         m.putInt("CdmaEcio", mCdmaEcio);
952         m.putInt("EvdoDbm", mEvdoDbm);
953         m.putInt("EvdoEcio", mEvdoEcio);
954         m.putInt("EvdoSnr", mEvdoSnr);
955         m.putInt("LteSignalStrength", mLteSignalStrength);
956         m.putInt("LteRsrp", mLteRsrp);
957         m.putInt("LteRsrq", mLteRsrq);
958         m.putInt("LteRssnr", mLteRssnr);
959         m.putInt("LteCqi", mLteCqi);
960         m.putBoolean("isGsm", Boolean.valueOf(isGsm));
961     }
962 
963     /**
964      * log
965      */
log(String s)966     private static void log(String s) {
967         Rlog.w(LOG_TAG, s);
968     }
969 }
970