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;
23import android.content.res.Resources;
24
25/**
26 * Contains phone signal strength related information.
27 */
28public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
433    public int getGsmBitErrorRate() {
434        return this.mGsmBitErrorRate;
435    }
436
437    /**
438     * Get the CDMA RSSI value in dBm
439     */
440    public int getCdmaDbm() {
441        return this.mCdmaDbm;
442    }
443
444    /**
445     * Get the CDMA Ec/Io value in dB*10
446     */
447    public int getCdmaEcio() {
448        return this.mCdmaEcio;
449    }
450
451    /**
452     * Get the EVDO RSSI value in dBm
453     */
454    public int getEvdoDbm() {
455        return this.mEvdoDbm;
456    }
457
458    /**
459     * Get the EVDO Ec/Io value in dB*10
460     */
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     */
468    public int getEvdoSnr() {
469        return this.mEvdoSnr;
470    }
471
472    /** @hide */
473    public int getLteSignalStrength() {
474        return mLteSignalStrength;
475    }
476
477    /** @hide */
478    public int getLteRsrp() {
479        return mLteRsrp;
480    }
481
482    /** @hide */
483    public int getLteRsrq() {
484        return mLteRsrq;
485    }
486
487    /** @hide */
488    public int getLteRssnr() {
489        return mLteRssnr;
490    }
491
492    /** @hide */
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     */
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     */
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     */
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     */
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     */
776    public int getLteDbm() {
777        return mLteRsrp;
778    }
779
780    /**
781     * Get LTE as level 0..4
782     *
783     * @hide
784     */
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     */
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     */
884    public boolean isGsm() {
885        return this.isGsm;
886    }
887
888    /**
889     * @return get TD_SCDMA dbm
890     *
891     * @hide
892     */
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     */
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     */
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
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
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
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     */
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     */
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     */
1055    private static void log(String s) {
1056        Rlog.w(LOG_TAG, s);
1057    }
1058}
1059