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