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