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