SignalStrength.java revision af86120955f3fe65c2c330e2333009b6ed12081a
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     * Get signal level as an int from 0..4
473     */
474    public int getLevel() {
475        int level;
476
477        if (isGsm) {
478            level = getLteLevel();
479            if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
480                level = getGsmLevel();
481            }
482        } else {
483            int cdmaLevel = getCdmaLevel();
484            int evdoLevel = getEvdoLevel();
485            if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
486                /* We don't know evdo, use cdma */
487                level = cdmaLevel;
488            } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
489                /* We don't know cdma, use evdo */
490                level = evdoLevel;
491            } else {
492                /* We know both, use the lowest level */
493                level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
494            }
495        }
496        if (DBG) log("getLevel=" + level);
497        return level;
498    }
499
500    /**
501     * Get the signal level as an asu value between 0..31, 99 is unknown
502     *
503     * @hide
504     */
505    public int getAsuLevel() {
506        int asuLevel;
507        if (isGsm) {
508            if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
509                asuLevel = getGsmAsuLevel();
510            } else {
511                asuLevel = getLteAsuLevel();
512            }
513        } else {
514            int cdmaAsuLevel = getCdmaAsuLevel();
515            int evdoAsuLevel = getEvdoAsuLevel();
516            if (evdoAsuLevel == 0) {
517                /* We don't know evdo use, cdma */
518                asuLevel = cdmaAsuLevel;
519            } else if (cdmaAsuLevel == 0) {
520                /* We don't know cdma use, evdo */
521                asuLevel = evdoAsuLevel;
522            } else {
523                /* We know both, use the lowest level */
524                asuLevel = cdmaAsuLevel < evdoAsuLevel ? cdmaAsuLevel : evdoAsuLevel;
525            }
526        }
527        if (DBG) log("getAsuLevel=" + asuLevel);
528        return asuLevel;
529    }
530
531    /**
532     * Get the signal strength as dBm
533     *
534     * @hide
535     */
536    public int getDbm() {
537        int dBm;
538
539        if(isGsm()) {
540            dBm = getLteDbm();
541            if (dBm == INVALID) {
542                dBm = getGsmDbm();
543            }
544        } else {
545            int cdmaDbm = getCdmaDbm();
546            int evdoDbm = getEvdoDbm();
547
548            return (evdoDbm == -120) ? cdmaDbm : ((cdmaDbm == -120) ? evdoDbm
549                    : (cdmaDbm < evdoDbm ? cdmaDbm : evdoDbm));
550        }
551        if (DBG) log("getDbm=" + dBm);
552        return dBm;
553    }
554
555    /**
556     * Get Gsm signal strength as dBm
557     *
558     * @hide
559     */
560    public int getGsmDbm() {
561        int dBm;
562
563        int gsmSignalStrength = getGsmSignalStrength();
564        int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
565        if (asu != -1) {
566            dBm = -113 + (2 * asu);
567        } else {
568            dBm = -1;
569        }
570        if (DBG) log("getGsmDbm=" + dBm);
571        return dBm;
572    }
573
574    /**
575     * Get gsm as level 0..4
576     *
577     * @hide
578     */
579    public int getGsmLevel() {
580        int level;
581
582        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
583        // asu = 0 (-113dB or less) is very weak
584        // signal, its better to show 0 bars to the user in such cases.
585        // asu = 99 is a special case, where the signal strength is unknown.
586        int asu = getGsmSignalStrength();
587        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
588        else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
589        else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;
590        else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;
591        else level = SIGNAL_STRENGTH_POOR;
592        if (DBG) log("getGsmLevel=" + level);
593        return level;
594    }
595
596    /**
597     * Get the gsm signal level as an asu value between 0..31, 99 is unknown
598     *
599     * @hide
600     */
601    public int getGsmAsuLevel() {
602        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
603        // asu = 0 (-113dB or less) is very weak
604        // signal, its better to show 0 bars to the user in such cases.
605        // asu = 99 is a special case, where the signal strength is unknown.
606        int level = getGsmSignalStrength();
607        if (DBG) log("getGsmAsuLevel=" + level);
608        return level;
609    }
610
611    /**
612     * Get cdma as level 0..4
613     *
614     * @hide
615     */
616    public int getCdmaLevel() {
617        final int cdmaDbm = getCdmaDbm();
618        final int cdmaEcio = getCdmaEcio();
619        int levelDbm;
620        int levelEcio;
621
622        if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
623        else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
624        else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
625        else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
626        else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
627
628        // Ec/Io are in dB*10
629        if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
630        else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
631        else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
632        else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
633        else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
634
635        int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
636        if (DBG) log("getCdmaLevel=" + level);
637        return level;
638    }
639
640    /**
641     * Get the cdma signal level as an asu value between 0..31, 99 is unknown
642     *
643     * @hide
644     */
645    public int getCdmaAsuLevel() {
646        final int cdmaDbm = getCdmaDbm();
647        final int cdmaEcio = getCdmaEcio();
648        int cdmaAsuLevel;
649        int ecioAsuLevel;
650
651        if (cdmaDbm >= -75) cdmaAsuLevel = 16;
652        else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
653        else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
654        else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
655        else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
656        else cdmaAsuLevel = 99;
657
658        // Ec/Io are in dB*10
659        if (cdmaEcio >= -90) ecioAsuLevel = 16;
660        else if (cdmaEcio >= -100) ecioAsuLevel = 8;
661        else if (cdmaEcio >= -115) ecioAsuLevel = 4;
662        else if (cdmaEcio >= -130) ecioAsuLevel = 2;
663        else if (cdmaEcio >= -150) ecioAsuLevel = 1;
664        else ecioAsuLevel = 99;
665
666        int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
667        if (DBG) log("getCdmaAsuLevel=" + level);
668        return level;
669    }
670
671    /**
672     * Get Evdo as level 0..4
673     *
674     * @hide
675     */
676    public int getEvdoLevel() {
677        int evdoDbm = getEvdoDbm();
678        int evdoSnr = getEvdoSnr();
679        int levelEvdoDbm;
680        int levelEvdoSnr;
681
682        if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
683        else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
684        else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
685        else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
686        else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
687
688        if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
689        else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
690        else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
691        else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
692        else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
693
694        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
695        if (DBG) log("getEvdoLevel=" + level);
696        return level;
697    }
698
699    /**
700     * Get the evdo signal level as an asu value between 0..31, 99 is unknown
701     *
702     * @hide
703     */
704    public int getEvdoAsuLevel() {
705        int evdoDbm = getEvdoDbm();
706        int evdoSnr = getEvdoSnr();
707        int levelEvdoDbm;
708        int levelEvdoSnr;
709
710        if (evdoDbm >= -65) levelEvdoDbm = 16;
711        else if (evdoDbm >= -75) levelEvdoDbm = 8;
712        else if (evdoDbm >= -85) levelEvdoDbm = 4;
713        else if (evdoDbm >= -95) levelEvdoDbm = 2;
714        else if (evdoDbm >= -105) levelEvdoDbm = 1;
715        else levelEvdoDbm = 99;
716
717        if (evdoSnr >= 7) levelEvdoSnr = 16;
718        else if (evdoSnr >= 6) levelEvdoSnr = 8;
719        else if (evdoSnr >= 5) levelEvdoSnr = 4;
720        else if (evdoSnr >= 3) levelEvdoSnr = 2;
721        else if (evdoSnr >= 1) levelEvdoSnr = 1;
722        else levelEvdoSnr = 99;
723
724        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
725        if (DBG) log("getEvdoAsuLevel=" + level);
726        return level;
727    }
728
729    /**
730     * Get LTE as dBm
731     *
732     * @hide
733     */
734    public int getLteDbm() {
735        return mLteRsrp;
736    }
737
738    /**
739     * Get LTE as level 0..4
740     *
741     * @hide
742     */
743    public int getLteLevel() {
744        /*
745         * TS 36.214 Physical Layer Section 5.1.3 TS 36.331 RRC RSSI = received
746         * signal + noise RSRP = reference signal dBm RSRQ = quality of signal
747         * dB= Number of Resource blocksxRSRP/RSSI SNR = gain=signal/noise ratio
748         * = -10log P1/P2 dB
749         */
750        int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
751
752        int rsrpThreshType = Resources.getSystem().getInteger(com.android.internal.R.integer.
753                config_LTE_RSRP_threshold_type);
754        int[] threshRsrp;
755        if (rsrpThreshType == RSRP_THRESH_TYPE_STRICT) {
756            threshRsrp = RSRP_THRESH_STRICT;
757        } else {
758            threshRsrp = RSRP_THRESH_LENIENT;
759        }
760
761        if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1;
762        else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
763        else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
764        else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
765        else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
766        else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
767
768        /*
769         * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
770         * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
771         * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
772         * Icon Only
773         */
774        if (mLteRssnr > 300) snrIconLevel = -1;
775        else if (mLteRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT;
776        else if (mLteRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
777        else if (mLteRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
778        else if (mLteRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
779        else if (mLteRssnr >= -200)
780            snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
781
782        if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
783                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);
784
785        /* Choose a measurement type to use for notification */
786        if (snrIconLevel != -1 && rsrpIconLevel != -1) {
787            /*
788             * The number of bars displayed shall be the smaller of the bars
789             * associated with LTE RSRP and the bars associated with the LTE
790             * RS_SNR
791             */
792            return (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
793        }
794
795        if (snrIconLevel != -1) return snrIconLevel;
796
797        if (rsrpIconLevel != -1) return rsrpIconLevel;
798
799        /* Valid values are (0-63, 99) as defined in TS 36.331 */
800        if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
801        else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
802        else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
803        else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
804        else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
805
806        if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
807                + rssiIconLevel);
808        return rssiIconLevel;
809
810    }
811    /**
812     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
813     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
814     *
815     * @hide
816     */
817    public int getLteAsuLevel() {
818        int lteAsuLevel = 99;
819        int lteDbm = getLteDbm();
820        /*
821         * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
822         * 0   -140 dBm or less
823         * 1   -139 dBm
824         * 2...96  -138... -44 dBm
825         * 97  -43 dBm or greater
826         * 255 not known or not detectable
827         */
828        /*
829         * validateInput will always give a valid range between -140 t0 -44 as
830         * per ril.h. so RSRP >= -43 & <-140 will fall under asu level 255
831         * and not 97 or 0
832         */
833        if (lteDbm == SignalStrength.INVALID) lteAsuLevel = 255;
834        else lteAsuLevel = lteDbm + 140;
835        if (DBG) log("Lte Asu level: "+lteAsuLevel);
836        return lteAsuLevel;
837    }
838
839    /**
840     * @return true if this is for GSM
841     */
842    public boolean isGsm() {
843        return this.isGsm;
844    }
845
846    /**
847     * @return hash code
848     */
849    @Override
850    public int hashCode() {
851        int primeNum = 31;
852        return ((mGsmSignalStrength * primeNum)
853                + (mGsmBitErrorRate * primeNum)
854                + (mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
855                + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
856                + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
857                + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
858                + (isGsm ? 1 : 0));
859    }
860
861    /**
862     * @return true if the signal strengths are the same
863     */
864    @Override
865    public boolean equals (Object o) {
866        SignalStrength s;
867
868        try {
869            s = (SignalStrength) o;
870        } catch (ClassCastException ex) {
871            return false;
872        }
873
874        if (o == null) {
875            return false;
876        }
877
878        return (mGsmSignalStrength == s.mGsmSignalStrength
879                && mGsmBitErrorRate == s.mGsmBitErrorRate
880                && mCdmaDbm == s.mCdmaDbm
881                && mCdmaEcio == s.mCdmaEcio
882                && mEvdoDbm == s.mEvdoDbm
883                && mEvdoEcio == s.mEvdoEcio
884                && mEvdoSnr == s.mEvdoSnr
885                && mLteSignalStrength == s.mLteSignalStrength
886                && mLteRsrp == s.mLteRsrp
887                && mLteRsrq == s.mLteRsrq
888                && mLteRssnr == s.mLteRssnr
889                && mLteCqi == s.mLteCqi
890                && isGsm == s.isGsm);
891    }
892
893    /**
894     * @return string representation.
895     */
896    @Override
897    public String toString() {
898        return ("SignalStrength:"
899                + " " + mGsmSignalStrength
900                + " " + mGsmBitErrorRate
901                + " " + mCdmaDbm
902                + " " + mCdmaEcio
903                + " " + mEvdoDbm
904                + " " + mEvdoEcio
905                + " " + mEvdoSnr
906                + " " + mLteSignalStrength
907                + " " + mLteRsrp
908                + " " + mLteRsrq
909                + " " + mLteRssnr
910                + " " + mLteCqi
911                + " " + (isGsm ? "gsm|lte" : "cdma"));
912    }
913
914    /**
915     * Set SignalStrength based on intent notifier map
916     *
917     * @param m intent notifier map
918     * @hide
919     */
920    private void setFromNotifierBundle(Bundle m) {
921        mGsmSignalStrength = m.getInt("GsmSignalStrength");
922        mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
923        mCdmaDbm = m.getInt("CdmaDbm");
924        mCdmaEcio = m.getInt("CdmaEcio");
925        mEvdoDbm = m.getInt("EvdoDbm");
926        mEvdoEcio = m.getInt("EvdoEcio");
927        mEvdoSnr = m.getInt("EvdoSnr");
928        mLteSignalStrength = m.getInt("LteSignalStrength");
929        mLteRsrp = m.getInt("LteRsrp");
930        mLteRsrq = m.getInt("LteRsrq");
931        mLteRssnr = m.getInt("LteRssnr");
932        mLteCqi = m.getInt("LteCqi");
933        isGsm = m.getBoolean("isGsm");
934    }
935
936    /**
937     * Set intent notifier Bundle based on SignalStrength
938     *
939     * @param m intent notifier Bundle
940     * @hide
941     */
942    public void fillInNotifierBundle(Bundle m) {
943        m.putInt("GsmSignalStrength", mGsmSignalStrength);
944        m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
945        m.putInt("CdmaDbm", mCdmaDbm);
946        m.putInt("CdmaEcio", mCdmaEcio);
947        m.putInt("EvdoDbm", mEvdoDbm);
948        m.putInt("EvdoEcio", mEvdoEcio);
949        m.putInt("EvdoSnr", mEvdoSnr);
950        m.putInt("LteSignalStrength", mLteSignalStrength);
951        m.putInt("LteRsrp", mLteRsrp);
952        m.putInt("LteRsrq", mLteRsrq);
953        m.putInt("LteRssnr", mLteRssnr);
954        m.putInt("LteCqi", mLteCqi);
955        m.putBoolean("isGsm", Boolean.valueOf(isGsm));
956    }
957
958    /**
959     * log
960     */
961    private static void log(String s) {
962        Rlog.w(LOG_TAG, s);
963    }
964}
965