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.util.Log;
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     * {@link Parcelable#writeToParcel}
278     */
279    public void writeToParcel(Parcel out, int flags) {
280        out.writeInt(mGsmSignalStrength);
281        out.writeInt(mGsmBitErrorRate);
282        out.writeInt(mCdmaDbm);
283        out.writeInt(mCdmaEcio);
284        out.writeInt(mEvdoDbm);
285        out.writeInt(mEvdoEcio);
286        out.writeInt(mEvdoSnr);
287        out.writeInt(mLteSignalStrength);
288        out.writeInt(mLteRsrp);
289        out.writeInt(mLteRsrq);
290        out.writeInt(mLteRssnr);
291        out.writeInt(mLteCqi);
292        out.writeInt(isGsm ? 1 : 0);
293    }
294
295    /**
296     * {@link Parcelable#describeContents}
297     */
298    public int describeContents() {
299        return 0;
300    }
301
302    /**
303     * {@link Parcelable.Creator}
304     *
305     * @hide
306     */
307    public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
308        public SignalStrength createFromParcel(Parcel in) {
309            return new SignalStrength(in);
310        }
311
312        public SignalStrength[] newArray(int size) {
313            return new SignalStrength[size];
314        }
315    };
316
317    /**
318     * Validate the individual signal strength fields as per the range
319     * specified in ril.h
320     * Set to invalid any field that is not in the valid range
321     * Cdma, evdo, lte rsrp & rsrq values are sign converted
322     * when received from ril interface
323     *
324     * @return
325     *      Valid values for all signalstrength fields
326     * @hide
327     */
328    public void validateInput() {
329        if (DBG) log("Signal before validate=" + this);
330        // TS 27.007 8.5
331        mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99;
332        // BER no change;
333
334        mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
335        mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
336
337        mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
338        mEvdoEcio = (mEvdoEcio > 0) ? -mEvdoEcio : -1;
339        mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
340
341        // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
342        mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
343        mLteRsrp = ((mLteRsrp >= 44) && (mLteRsrp <= 140)) ? -mLteRsrp : SignalStrength.INVALID;
344        mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
345        mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
346                : SignalStrength.INVALID;
347        // Cqi no change
348        if (DBG) log("Signal after validate=" + this);
349    }
350
351    /**
352     * @param true - Gsm, Lte phones
353     *        false - Cdma phones
354     *
355     * Used by voice phone to set the isGsm
356     *        flag
357     * @hide
358     */
359    public void setGsm(boolean gsmFlag) {
360        isGsm = gsmFlag;
361    }
362
363    /**
364     * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS
365     * 27.007 8.5
366     */
367    public int getGsmSignalStrength() {
368        return this.mGsmSignalStrength;
369    }
370
371    /**
372     * Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5
373     */
374    public int getGsmBitErrorRate() {
375        return this.mGsmBitErrorRate;
376    }
377
378    /**
379     * Get the CDMA RSSI value in dBm
380     */
381    public int getCdmaDbm() {
382        return this.mCdmaDbm;
383    }
384
385    /**
386     * Get the CDMA Ec/Io value in dB*10
387     */
388    public int getCdmaEcio() {
389        return this.mCdmaEcio;
390    }
391
392    /**
393     * Get the EVDO RSSI value in dBm
394     */
395    public int getEvdoDbm() {
396        return this.mEvdoDbm;
397    }
398
399    /**
400     * Get the EVDO Ec/Io value in dB*10
401     */
402    public int getEvdoEcio() {
403        return this.mEvdoEcio;
404    }
405
406    /**
407     * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
408     */
409    public int getEvdoSnr() {
410        return this.mEvdoSnr;
411    }
412
413    /** @hide */
414    public int getLteSignalStrenght() {
415        return mLteSignalStrength;
416    }
417
418    /** @hide */
419    public int getLteRsrp() {
420        return mLteRsrp;
421    }
422
423    /** @hide */
424    public int getLteRsrq() {
425        return mLteRsrq;
426    }
427
428    /** @hide */
429    public int getLteRssnr() {
430        return mLteRssnr;
431    }
432
433    /** @hide */
434    public int getLteCqi() {
435        return mLteCqi;
436    }
437
438    /**
439     * Get signal level as an int from 0..4
440     *
441     * @hide
442     */
443    public int getLevel() {
444        int level;
445
446        if (isGsm) {
447            level = getLteLevel();
448            if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
449                level = getGsmLevel();
450            }
451        } else {
452            int cdmaLevel = getCdmaLevel();
453            int evdoLevel = getEvdoLevel();
454            if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
455                /* We don't know evdo, use cdma */
456                level = cdmaLevel;
457            } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
458                /* We don't know cdma, use evdo */
459                level = evdoLevel;
460            } else {
461                /* We know both, use the lowest level */
462                level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
463            }
464        }
465        if (DBG) log("getLevel=" + level);
466        return level;
467    }
468
469    /**
470     * Get the signal level as an asu value between 0..31, 99 is unknown
471     *
472     * @hide
473     */
474    public int getAsuLevel() {
475        int asuLevel;
476        if (isGsm) {
477            if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
478                asuLevel = getGsmAsuLevel();
479            } else {
480                asuLevel = getLteAsuLevel();
481            }
482        } else {
483            int cdmaAsuLevel = getCdmaAsuLevel();
484            int evdoAsuLevel = getEvdoAsuLevel();
485            if (evdoAsuLevel == 0) {
486                /* We don't know evdo use, cdma */
487                asuLevel = cdmaAsuLevel;
488            } else if (cdmaAsuLevel == 0) {
489                /* We don't know cdma use, evdo */
490                asuLevel = evdoAsuLevel;
491            } else {
492                /* We know both, use the lowest level */
493                asuLevel = cdmaAsuLevel < evdoAsuLevel ? cdmaAsuLevel : evdoAsuLevel;
494            }
495        }
496        if (DBG) log("getAsuLevel=" + asuLevel);
497        return asuLevel;
498    }
499
500    /**
501     * Get the signal strength as dBm
502     *
503     * @hide
504     */
505    public int getDbm() {
506        int dBm;
507
508        if(isGsm()) {
509            if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
510                dBm = getGsmDbm();
511            } else {
512                dBm = getLteDbm();
513            }
514        } else {
515            int cdmaDbm = getCdmaDbm();
516            int evdoDbm = getEvdoDbm();
517
518            return (evdoDbm == -120) ? cdmaDbm : ((cdmaDbm == -120) ? evdoDbm
519                    : (cdmaDbm < evdoDbm ? cdmaDbm : evdoDbm));
520        }
521        if (DBG) log("getDbm=" + dBm);
522        return dBm;
523    }
524
525    /**
526     * Get Gsm signal strength as dBm
527     *
528     * @hide
529     */
530    public int getGsmDbm() {
531        int dBm;
532
533        int gsmSignalStrength = getGsmSignalStrength();
534        int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
535        if (asu != -1) {
536            dBm = -113 + (2 * asu);
537        } else {
538            dBm = -1;
539        }
540        if (DBG) log("getGsmDbm=" + dBm);
541        return dBm;
542    }
543
544    /**
545     * Get gsm as level 0..4
546     *
547     * @hide
548     */
549    public int getGsmLevel() {
550        int level;
551
552        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
553        // asu = 0 (-113dB or less) is very weak
554        // signal, its better to show 0 bars to the user in such cases.
555        // asu = 99 is a special case, where the signal strength is unknown.
556        int asu = getGsmSignalStrength();
557        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
558        else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
559        else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;
560        else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;
561        else level = SIGNAL_STRENGTH_POOR;
562        if (DBG) log("getGsmLevel=" + level);
563        return level;
564    }
565
566    /**
567     * Get the gsm signal level as an asu value between 0..31, 99 is unknown
568     *
569     * @hide
570     */
571    public int getGsmAsuLevel() {
572        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
573        // asu = 0 (-113dB or less) is very weak
574        // signal, its better to show 0 bars to the user in such cases.
575        // asu = 99 is a special case, where the signal strength is unknown.
576        int level = getGsmSignalStrength();
577        if (DBG) log("getGsmAsuLevel=" + level);
578        return level;
579    }
580
581    /**
582     * Get cdma as level 0..4
583     *
584     * @hide
585     */
586    public int getCdmaLevel() {
587        final int cdmaDbm = getCdmaDbm();
588        final int cdmaEcio = getCdmaEcio();
589        int levelDbm;
590        int levelEcio;
591
592        if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
593        else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
594        else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
595        else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
596        else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
597
598        // Ec/Io are in dB*10
599        if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
600        else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
601        else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
602        else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
603        else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
604
605        int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
606        if (DBG) log("getCdmaLevel=" + level);
607        return level;
608    }
609
610    /**
611     * Get the cdma signal level as an asu value between 0..31, 99 is unknown
612     *
613     * @hide
614     */
615    public int getCdmaAsuLevel() {
616        final int cdmaDbm = getCdmaDbm();
617        final int cdmaEcio = getCdmaEcio();
618        int cdmaAsuLevel;
619        int ecioAsuLevel;
620
621        if (cdmaDbm >= -75) cdmaAsuLevel = 16;
622        else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
623        else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
624        else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
625        else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
626        else cdmaAsuLevel = 99;
627
628        // Ec/Io are in dB*10
629        if (cdmaEcio >= -90) ecioAsuLevel = 16;
630        else if (cdmaEcio >= -100) ecioAsuLevel = 8;
631        else if (cdmaEcio >= -115) ecioAsuLevel = 4;
632        else if (cdmaEcio >= -130) ecioAsuLevel = 2;
633        else if (cdmaEcio >= -150) ecioAsuLevel = 1;
634        else ecioAsuLevel = 99;
635
636        int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
637        if (DBG) log("getCdmaAsuLevel=" + level);
638        return level;
639    }
640
641    /**
642     * Get Evdo as level 0..4
643     *
644     * @hide
645     */
646    public int getEvdoLevel() {
647        int evdoDbm = getEvdoDbm();
648        int evdoSnr = getEvdoSnr();
649        int levelEvdoDbm;
650        int levelEvdoSnr;
651
652        if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
653        else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
654        else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
655        else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
656        else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
657
658        if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
659        else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
660        else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
661        else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
662        else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
663
664        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
665        if (DBG) log("getEvdoLevel=" + level);
666        return level;
667    }
668
669    /**
670     * Get the evdo signal level as an asu value between 0..31, 99 is unknown
671     *
672     * @hide
673     */
674    public int getEvdoAsuLevel() {
675        int evdoDbm = getEvdoDbm();
676        int evdoSnr = getEvdoSnr();
677        int levelEvdoDbm;
678        int levelEvdoSnr;
679
680        if (evdoDbm >= -65) levelEvdoDbm = 16;
681        else if (evdoDbm >= -75) levelEvdoDbm = 8;
682        else if (evdoDbm >= -85) levelEvdoDbm = 4;
683        else if (evdoDbm >= -95) levelEvdoDbm = 2;
684        else if (evdoDbm >= -105) levelEvdoDbm = 1;
685        else levelEvdoDbm = 99;
686
687        if (evdoSnr >= 7) levelEvdoSnr = 16;
688        else if (evdoSnr >= 6) levelEvdoSnr = 8;
689        else if (evdoSnr >= 5) levelEvdoSnr = 4;
690        else if (evdoSnr >= 3) levelEvdoSnr = 2;
691        else if (evdoSnr >= 1) levelEvdoSnr = 1;
692        else levelEvdoSnr = 99;
693
694        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
695        if (DBG) log("getEvdoAsuLevel=" + level);
696        return level;
697    }
698
699    /**
700     * Get LTE as dBm
701     *
702     * @hide
703     */
704    public int getLteDbm() {
705        return mLteRsrp;
706    }
707
708    /**
709     * Get LTE as level 0..4
710     *
711     * @hide
712     */
713    public int getLteLevel() {
714        /*
715         * TS 36.214 Physical Layer Section 5.1.3 TS 36.331 RRC RSSI = received
716         * signal + noise RSRP = reference signal dBm RSRQ = quality of signal
717         * dB= Number of Resource blocksxRSRP/RSSI SNR = gain=signal/noise ratio
718         * = -10log P1/P2 dB
719         */
720        int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
721
722        if (mLteRsrp > -44) rsrpIconLevel = -1;
723        else if (mLteRsrp >= -85) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
724        else if (mLteRsrp >= -95) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
725        else if (mLteRsrp >= -105) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
726        else if (mLteRsrp >= -115) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
727        else if (mLteRsrp >= -140) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
728
729        /*
730         * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
731         * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
732         * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
733         * Icon Only
734         */
735        if (mLteRssnr > 300) snrIconLevel = -1;
736        else if (mLteRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
737        else if (mLteRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
738        else if (mLteRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
739        else if (mLteRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
740        else if (mLteRssnr >= -200)
741            snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
742
743        if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
744                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);
745
746        /* Choose a measurement type to use for notification */
747        if (snrIconLevel != -1 && rsrpIconLevel != -1) {
748            /*
749             * The number of bars displayed shall be the smaller of the bars
750             * associated with LTE RSRP and the bars associated with the LTE
751             * RS_SNR
752             */
753            return (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
754        }
755
756        if (snrIconLevel != -1) return snrIconLevel;
757
758        if (rsrpIconLevel != -1) return rsrpIconLevel;
759
760        /* Valid values are (0-63, 99) as defined in TS 36.331 */
761        if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
762        else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
763        else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
764        else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
765        else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
766        if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
767                + rssiIconLevel);
768        return rssiIconLevel;
769
770    }
771    /**
772     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
773     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
774     *
775     * @hide
776     */
777    public int getLteAsuLevel() {
778        int lteAsuLevel = 99;
779        int lteDbm = getLteDbm();
780        /*
781         * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
782         * 0   -140 dBm or less
783         * 1   -139 dBm
784         * 2...96  -138... -44 dBm
785         * 97  -43 dBm or greater
786         * 255 not known or not detectable
787         */
788        /*
789         * validateInput will always give a valid range between -140 t0 -44 as
790         * per ril.h. so RSRP >= -43 & <-140 will fall under asu level 255
791         * and not 97 or 0
792         */
793        if (lteDbm == SignalStrength.INVALID) lteAsuLevel = 255;
794        else lteAsuLevel = lteDbm + 140;
795        if (DBG) log("Lte Asu level: "+lteAsuLevel);
796        return lteAsuLevel;
797    }
798
799    /**
800     * @return true if this is for GSM
801     */
802    public boolean isGsm() {
803        return this.isGsm;
804    }
805
806    /**
807     * @return hash code
808     */
809    @Override
810    public int hashCode() {
811        int primeNum = 31;
812        return ((mGsmSignalStrength * primeNum)
813                + (mGsmBitErrorRate * primeNum)
814                + (mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
815                + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
816                + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
817                + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
818                + (isGsm ? 1 : 0));
819    }
820
821    /**
822     * @return true if the signal strengths are the same
823     */
824    @Override
825    public boolean equals (Object o) {
826        SignalStrength s;
827
828        try {
829            s = (SignalStrength) o;
830        } catch (ClassCastException ex) {
831            return false;
832        }
833
834        if (o == null) {
835            return false;
836        }
837
838        return (mGsmSignalStrength == s.mGsmSignalStrength
839                && mGsmBitErrorRate == s.mGsmBitErrorRate
840                && mCdmaDbm == s.mCdmaDbm
841                && mCdmaEcio == s.mCdmaEcio
842                && mEvdoDbm == s.mEvdoDbm
843                && mEvdoEcio == s.mEvdoEcio
844                && mEvdoSnr == s.mEvdoSnr
845                && mLteSignalStrength == s.mLteSignalStrength
846                && mLteRsrp == s.mLteRsrp
847                && mLteRsrq == s.mLteRsrq
848                && mLteRssnr == s.mLteRssnr
849                && mLteCqi == s.mLteCqi
850                && isGsm == s.isGsm);
851    }
852
853    /**
854     * @return string representation.
855     */
856    @Override
857    public String toString() {
858        return ("SignalStrength:"
859                + " " + mGsmSignalStrength
860                + " " + mGsmBitErrorRate
861                + " " + mCdmaDbm
862                + " " + mCdmaEcio
863                + " " + mEvdoDbm
864                + " " + mEvdoEcio
865                + " " + mEvdoSnr
866                + " " + mLteSignalStrength
867                + " " + mLteRsrp
868                + " " + mLteRsrq
869                + " " + mLteRssnr
870                + " " + mLteCqi
871                + " " + (isGsm ? "gsm|lte" : "cdma"));
872    }
873
874    /**
875     * Set SignalStrength based on intent notifier map
876     *
877     * @param m intent notifier map
878     * @hide
879     */
880    private void setFromNotifierBundle(Bundle m) {
881        mGsmSignalStrength = m.getInt("GsmSignalStrength");
882        mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
883        mCdmaDbm = m.getInt("CdmaDbm");
884        mCdmaEcio = m.getInt("CdmaEcio");
885        mEvdoDbm = m.getInt("EvdoDbm");
886        mEvdoEcio = m.getInt("EvdoEcio");
887        mEvdoSnr = m.getInt("EvdoSnr");
888        mLteSignalStrength = m.getInt("LteSignalStrength");
889        mLteRsrp = m.getInt("LteRsrp");
890        mLteRsrq = m.getInt("LteRsrq");
891        mLteRssnr = m.getInt("LteRssnr");
892        mLteCqi = m.getInt("LteCqi");
893        isGsm = m.getBoolean("isGsm");
894    }
895
896    /**
897     * Set intent notifier Bundle based on SignalStrength
898     *
899     * @param m intent notifier Bundle
900     * @hide
901     */
902    public void fillInNotifierBundle(Bundle m) {
903        m.putInt("GsmSignalStrength", mGsmSignalStrength);
904        m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
905        m.putInt("CdmaDbm", mCdmaDbm);
906        m.putInt("CdmaEcio", mCdmaEcio);
907        m.putInt("EvdoDbm", mEvdoDbm);
908        m.putInt("EvdoEcio", mEvdoEcio);
909        m.putInt("EvdoSnr", mEvdoSnr);
910        m.putInt("LteSignalStrength", mLteSignalStrength);
911        m.putInt("LteRsrp", mLteRsrp);
912        m.putInt("LteRsrq", mLteRsrq);
913        m.putInt("LteRssnr", mLteRssnr);
914        m.putInt("LteCqi", mLteCqi);
915        m.putBoolean("isGsm", Boolean.valueOf(isGsm));
916    }
917
918    /**
919     * log
920     */
921    private static void log(String s) {
922        Log.w(LOG_TAG, s);
923    }
924}
925