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