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