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