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