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