| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.telephony; |
| |
| import android.os.Bundle; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.telephony.Rlog; |
| import android.util.Log; |
| import android.content.res.Resources; |
| |
| /** |
| * Contains phone signal strength related information. |
| */ |
| public class SignalStrength implements Parcelable { |
| |
| private static final String LOG_TAG = "SignalStrength"; |
| private static final boolean DBG = false; |
| |
| /** @hide */ |
| public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0; |
| /** @hide */ |
| public static final int SIGNAL_STRENGTH_POOR = 1; |
| /** @hide */ |
| public static final int SIGNAL_STRENGTH_MODERATE = 2; |
| /** @hide */ |
| public static final int SIGNAL_STRENGTH_GOOD = 3; |
| /** @hide */ |
| public static final int SIGNAL_STRENGTH_GREAT = 4; |
| /** @hide */ |
| public static final int NUM_SIGNAL_STRENGTH_BINS = 5; |
| /** @hide */ |
| public static final String[] SIGNAL_STRENGTH_NAMES = { |
| "none", "poor", "moderate", "good", "great" |
| }; |
| |
| /** @hide */ |
| //Use int max, as -1 is a valid value in signal strength |
| public static final int INVALID = 0x7FFFFFFF; |
| |
| private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5 |
| private int mGsmBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 |
| private int mCdmaDbm; // This value is the RSSI value |
| private int mCdmaEcio; // This value is the Ec/Io |
| private int mEvdoDbm; // This value is the EVDO RSSI value |
| private int mEvdoEcio; // This value is the EVDO Ec/Io |
| private int mEvdoSnr; // Valid values are 0-8. 8 is the highest signal to noise ratio |
| private int mLteSignalStrength; |
| private int mLteRsrp; |
| private int mLteRsrq; |
| private int mLteRssnr; |
| private int mLteCqi; |
| private int mTdScdmaRscp; |
| |
| private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult |
| |
| /** |
| * Create a new SignalStrength from a intent notifier Bundle |
| * |
| * This method is used by PhoneStateIntentReceiver and maybe by |
| * external applications. |
| * |
| * @param m Bundle from intent notifier |
| * @return newly created SignalStrength |
| * |
| * @hide |
| */ |
| public static SignalStrength newFromBundle(Bundle m) { |
| SignalStrength ret; |
| ret = new SignalStrength(); |
| ret.setFromNotifierBundle(m); |
| return ret; |
| } |
| |
| /** |
| * Empty constructor |
| * |
| * @hide |
| */ |
| public SignalStrength() { |
| mGsmSignalStrength = 99; |
| mGsmBitErrorRate = -1; |
| mCdmaDbm = -1; |
| mCdmaEcio = -1; |
| mEvdoDbm = -1; |
| mEvdoEcio = -1; |
| mEvdoSnr = -1; |
| mLteSignalStrength = 99; |
| mLteRsrp = INVALID; |
| mLteRsrq = INVALID; |
| mLteRssnr = INVALID; |
| mLteCqi = INVALID; |
| mTdScdmaRscp = INVALID; |
| isGsm = true; |
| } |
| |
| /** |
| * This constructor is used to create SignalStrength with default |
| * values and set the isGsmFlag with the value passed in the input |
| * |
| * @param gsmFlag true if Gsm Phone,false if Cdma phone |
| * @return newly created SignalStrength |
| * @hide |
| */ |
| public SignalStrength(boolean gsmFlag) { |
| mGsmSignalStrength = 99; |
| mGsmBitErrorRate = -1; |
| mCdmaDbm = -1; |
| mCdmaEcio = -1; |
| mEvdoDbm = -1; |
| mEvdoEcio = -1; |
| mEvdoSnr = -1; |
| mLteSignalStrength = 99; |
| mLteRsrp = INVALID; |
| mLteRsrq = INVALID; |
| mLteRssnr = INVALID; |
| mLteCqi = INVALID; |
| mTdScdmaRscp = INVALID; |
| isGsm = gsmFlag; |
| } |
| |
| /** |
| * Constructor |
| * |
| * @hide |
| */ |
| public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate, |
| int cdmaDbm, int cdmaEcio, |
| int evdoDbm, int evdoEcio, int evdoSnr, |
| int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi, |
| int tdScdmaRscp, boolean gsmFlag) { |
| initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio, |
| evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp, |
| lteRsrq, lteRssnr, lteCqi, gsmFlag); |
| mTdScdmaRscp = tdScdmaRscp; |
| } |
| |
| /** |
| * Constructor |
| * |
| * @hide |
| */ |
| public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate, |
| int cdmaDbm, int cdmaEcio, |
| int evdoDbm, int evdoEcio, int evdoSnr, |
| int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi, |
| boolean gsmFlag) { |
| initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio, |
| evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp, |
| lteRsrq, lteRssnr, lteCqi, gsmFlag); |
| } |
| |
| /** |
| * Constructor |
| * |
| * @hide |
| */ |
| public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate, |
| int cdmaDbm, int cdmaEcio, |
| int evdoDbm, int evdoEcio, int evdoSnr, |
| boolean gsmFlag) { |
| initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio, |
| evdoDbm, evdoEcio, evdoSnr, 99, INVALID, |
| INVALID, INVALID, INVALID, gsmFlag); |
| } |
| |
| /** |
| * Copy constructors |
| * |
| * @param s Source SignalStrength |
| * |
| * @hide |
| */ |
| public SignalStrength(SignalStrength s) { |
| copyFrom(s); |
| } |
| |
| /** |
| * Initialize gsm/cdma values, sets lte values to defaults. |
| * |
| * @param gsmSignalStrength |
| * @param gsmBitErrorRate |
| * @param cdmaDbm |
| * @param cdmaEcio |
| * @param evdoDbm |
| * @param evdoEcio |
| * @param evdoSnr |
| * @param gsm |
| * |
| * @hide |
| */ |
| public void initialize(int gsmSignalStrength, int gsmBitErrorRate, |
| int cdmaDbm, int cdmaEcio, |
| int evdoDbm, int evdoEcio, int evdoSnr, |
| boolean gsm) { |
| initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio, |
| evdoDbm, evdoEcio, evdoSnr, 99, INVALID, |
| INVALID, INVALID, INVALID, gsm); |
| } |
| |
| /** |
| * Initialize all the values |
| * |
| * @param gsmSignalStrength |
| * @param gsmBitErrorRate |
| * @param cdmaDbm |
| * @param cdmaEcio |
| * @param evdoDbm |
| * @param evdoEcio |
| * @param evdoSnr |
| * @param lteSignalStrength |
| * @param lteRsrp |
| * @param lteRsrq |
| * @param lteRssnr |
| * @param lteCqi |
| * @param gsm |
| * |
| * @hide |
| */ |
| public void initialize(int gsmSignalStrength, int gsmBitErrorRate, |
| int cdmaDbm, int cdmaEcio, |
| int evdoDbm, int evdoEcio, int evdoSnr, |
| int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi, |
| boolean gsm) { |
| mGsmSignalStrength = gsmSignalStrength; |
| mGsmBitErrorRate = gsmBitErrorRate; |
| mCdmaDbm = cdmaDbm; |
| mCdmaEcio = cdmaEcio; |
| mEvdoDbm = evdoDbm; |
| mEvdoEcio = evdoEcio; |
| mEvdoSnr = evdoSnr; |
| mLteSignalStrength = lteSignalStrength; |
| mLteRsrp = lteRsrp; |
| mLteRsrq = lteRsrq; |
| mLteRssnr = lteRssnr; |
| mLteCqi = lteCqi; |
| mTdScdmaRscp = INVALID; |
| isGsm = gsm; |
| if (DBG) log("initialize: " + toString()); |
| } |
| |
| /** |
| * @hide |
| */ |
| protected void copyFrom(SignalStrength s) { |
| mGsmSignalStrength = s.mGsmSignalStrength; |
| mGsmBitErrorRate = s.mGsmBitErrorRate; |
| mCdmaDbm = s.mCdmaDbm; |
| mCdmaEcio = s.mCdmaEcio; |
| mEvdoDbm = s.mEvdoDbm; |
| mEvdoEcio = s.mEvdoEcio; |
| mEvdoSnr = s.mEvdoSnr; |
| mLteSignalStrength = s.mLteSignalStrength; |
| mLteRsrp = s.mLteRsrp; |
| mLteRsrq = s.mLteRsrq; |
| mLteRssnr = s.mLteRssnr; |
| mLteCqi = s.mLteCqi; |
| mTdScdmaRscp = s.mTdScdmaRscp; |
| isGsm = s.isGsm; |
| } |
| |
| /** |
| * Construct a SignalStrength object from the given parcel. |
| * |
| * @hide |
| */ |
| public SignalStrength(Parcel in) { |
| if (DBG) log("Size of signalstrength parcel:" + in.dataSize()); |
| |
| mGsmSignalStrength = in.readInt(); |
| mGsmBitErrorRate = in.readInt(); |
| mCdmaDbm = in.readInt(); |
| mCdmaEcio = in.readInt(); |
| mEvdoDbm = in.readInt(); |
| mEvdoEcio = in.readInt(); |
| mEvdoSnr = in.readInt(); |
| mLteSignalStrength = in.readInt(); |
| mLteRsrp = in.readInt(); |
| mLteRsrq = in.readInt(); |
| mLteRssnr = in.readInt(); |
| mLteCqi = in.readInt(); |
| mTdScdmaRscp = in.readInt(); |
| isGsm = (in.readInt() != 0); |
| } |
| |
| /** |
| * Make a SignalStrength object from the given parcel as passed up by |
| * the ril which does not have isGsm. isGsm will be changed by ServiceStateTracker |
| * so the default is a don't care. |
| * |
| * @hide |
| */ |
| public static SignalStrength makeSignalStrengthFromRilParcel(Parcel in) { |
| if (DBG) log("Size of signalstrength parcel:" + in.dataSize()); |
| |
| SignalStrength ss = new SignalStrength(); |
| ss.mGsmSignalStrength = in.readInt(); |
| ss.mGsmBitErrorRate = in.readInt(); |
| ss.mCdmaDbm = in.readInt(); |
| ss.mCdmaEcio = in.readInt(); |
| ss.mEvdoDbm = in.readInt(); |
| ss.mEvdoEcio = in.readInt(); |
| ss.mEvdoSnr = in.readInt(); |
| ss.mLteSignalStrength = in.readInt(); |
| ss.mLteRsrp = in.readInt(); |
| ss.mLteRsrq = in.readInt(); |
| ss.mLteRssnr = in.readInt(); |
| ss.mLteCqi = in.readInt(); |
| ss.mTdScdmaRscp = in.readInt(); |
| return ss; |
| } |
| |
| /** |
| * {@link Parcelable#writeToParcel} |
| */ |
| public void writeToParcel(Parcel out, int flags) { |
| out.writeInt(mGsmSignalStrength); |
| out.writeInt(mGsmBitErrorRate); |
| out.writeInt(mCdmaDbm); |
| out.writeInt(mCdmaEcio); |
| out.writeInt(mEvdoDbm); |
| out.writeInt(mEvdoEcio); |
| out.writeInt(mEvdoSnr); |
| out.writeInt(mLteSignalStrength); |
| out.writeInt(mLteRsrp); |
| out.writeInt(mLteRsrq); |
| out.writeInt(mLteRssnr); |
| out.writeInt(mLteCqi); |
| out.writeInt(mTdScdmaRscp); |
| out.writeInt(isGsm ? 1 : 0); |
| } |
| |
| /** |
| * {@link Parcelable#describeContents} |
| */ |
| public int describeContents() { |
| return 0; |
| } |
| |
| /** |
| * {@link Parcelable.Creator} |
| * |
| * @hide |
| */ |
| public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() { |
| public SignalStrength createFromParcel(Parcel in) { |
| return new SignalStrength(in); |
| } |
| |
| public SignalStrength[] newArray(int size) { |
| return new SignalStrength[size]; |
| } |
| }; |
| |
| /** |
| * Validate the individual signal strength fields as per the range |
| * specified in ril.h |
| * Set to invalid any field that is not in the valid range |
| * Cdma, evdo, lte rsrp & rsrq values are sign converted |
| * when received from ril interface |
| * |
| * @return |
| * Valid values for all signalstrength fields |
| * @hide |
| */ |
| public void validateInput() { |
| if (DBG) log("Signal before validate=" + this); |
| // TS 27.007 8.5 |
| mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99; |
| // BER no change; |
| |
| mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120; |
| mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160; |
| |
| mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120; |
| mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1; |
| mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1; |
| |
| // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC |
| mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99; |
| mLteRsrp = ((mLteRsrp >= 44) && (mLteRsrp <= 140)) ? -mLteRsrp : SignalStrength.INVALID; |
| mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID; |
| mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr |
| : SignalStrength.INVALID; |
| |
| mTdScdmaRscp = ((mTdScdmaRscp >= 25) && (mTdScdmaRscp <= 120)) |
| ? -mTdScdmaRscp : SignalStrength.INVALID; |
| // Cqi no change |
| if (DBG) log("Signal after validate=" + this); |
| } |
| |
| /** |
| * @param true - Gsm, Lte phones |
| * false - Cdma phones |
| * |
| * Used by voice phone to set the isGsm |
| * flag |
| * @hide |
| */ |
| public void setGsm(boolean gsmFlag) { |
| isGsm = gsmFlag; |
| } |
| |
| /** |
| * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS |
| * 27.007 8.5 |
| */ |
| public int getGsmSignalStrength() { |
| return this.mGsmSignalStrength; |
| } |
| |
| /** |
| * Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5 |
| */ |
| public int getGsmBitErrorRate() { |
| return this.mGsmBitErrorRate; |
| } |
| |
| /** |
| * Get the CDMA RSSI value in dBm |
| */ |
| public int getCdmaDbm() { |
| return this.mCdmaDbm; |
| } |
| |
| /** |
| * Get the CDMA Ec/Io value in dB*10 |
| */ |
| public int getCdmaEcio() { |
| return this.mCdmaEcio; |
| } |
| |
| /** |
| * Get the EVDO RSSI value in dBm |
| */ |
| public int getEvdoDbm() { |
| return this.mEvdoDbm; |
| } |
| |
| /** |
| * Get the EVDO Ec/Io value in dB*10 |
| */ |
| public int getEvdoEcio() { |
| return this.mEvdoEcio; |
| } |
| |
| /** |
| * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest. |
| */ |
| public int getEvdoSnr() { |
| return this.mEvdoSnr; |
| } |
| |
| /** @hide */ |
| public int getLteSignalStrength() { |
| return mLteSignalStrength; |
| } |
| |
| /** @hide */ |
| public int getLteRsrp() { |
| return mLteRsrp; |
| } |
| |
| /** @hide */ |
| public int getLteRsrq() { |
| return mLteRsrq; |
| } |
| |
| /** @hide */ |
| public int getLteRssnr() { |
| return mLteRssnr; |
| } |
| |
| /** @hide */ |
| public int getLteCqi() { |
| return mLteCqi; |
| } |
| |
| /** |
| * Retrieve an abstract level value for the overall signal strength. |
| * |
| * @return a single integer from 0 to 4 representing the general signal quality. |
| * This may take into account many different radio technology inputs. |
| * 0 represents very poor signal strength |
| * while 4 represents a very strong signal strength. |
| */ |
| public int getLevel() { |
| int level = 0; |
| |
| if (isGsm) { |
| level = getLteLevel(); |
| if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| level = getTdScdmaLevel(); |
| if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| level = getGsmLevel(); |
| } |
| } |
| } else { |
| int cdmaLevel = getCdmaLevel(); |
| int evdoLevel = getEvdoLevel(); |
| if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| /* We don't know evdo, use cdma */ |
| level = cdmaLevel; |
| } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| /* We don't know cdma, use evdo */ |
| level = evdoLevel; |
| } else { |
| /* We know both, use the lowest level */ |
| level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel; |
| } |
| } |
| if (DBG) log("getLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get the signal level as an asu value between 0..31, 99 is unknown |
| * |
| * @hide |
| */ |
| public int getAsuLevel() { |
| int asuLevel = 0; |
| if (isGsm) { |
| if (getLteLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| asuLevel = getGsmAsuLevel(); |
| } else { |
| asuLevel = getTdScdmaAsuLevel(); |
| } |
| } else { |
| asuLevel = getLteAsuLevel(); |
| } |
| } else { |
| int cdmaAsuLevel = getCdmaAsuLevel(); |
| int evdoAsuLevel = getEvdoAsuLevel(); |
| if (evdoAsuLevel == 0) { |
| /* We don't know evdo use, cdma */ |
| asuLevel = cdmaAsuLevel; |
| } else if (cdmaAsuLevel == 0) { |
| /* We don't know cdma use, evdo */ |
| asuLevel = evdoAsuLevel; |
| } else { |
| /* We know both, use the lowest level */ |
| asuLevel = cdmaAsuLevel < evdoAsuLevel ? cdmaAsuLevel : evdoAsuLevel; |
| } |
| } |
| if (DBG) log("getAsuLevel=" + asuLevel); |
| return asuLevel; |
| } |
| |
| /** |
| * Get the signal strength as dBm |
| * |
| * @hide |
| */ |
| public int getDbm() { |
| int dBm = INVALID; |
| |
| if(isGsm()) { |
| dBm = getLteDbm(); |
| if (dBm == INVALID) { |
| if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| dBm = getGsmDbm(); |
| } else { |
| dBm = getTdScdmaDbm(); |
| } |
| } |
| } else { |
| int cdmaDbm = getCdmaDbm(); |
| int evdoDbm = getEvdoDbm(); |
| |
| return (evdoDbm == -120) ? cdmaDbm : ((cdmaDbm == -120) ? evdoDbm |
| : (cdmaDbm < evdoDbm ? cdmaDbm : evdoDbm)); |
| } |
| if (DBG) log("getDbm=" + dBm); |
| return dBm; |
| } |
| |
| /** |
| * Get Gsm signal strength as dBm |
| * |
| * @hide |
| */ |
| public int getGsmDbm() { |
| int dBm; |
| |
| int gsmSignalStrength = getGsmSignalStrength(); |
| int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength); |
| if (asu != -1) { |
| dBm = -113 + (2 * asu); |
| } else { |
| dBm = -1; |
| } |
| if (DBG) log("getGsmDbm=" + dBm); |
| return dBm; |
| } |
| |
| /** |
| * Get gsm as level 0..4 |
| * |
| * @hide |
| */ |
| public int getGsmLevel() { |
| int level; |
| |
| // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5 |
| // asu = 0 (-113dB or less) is very weak |
| // signal, its better to show 0 bars to the user in such cases. |
| // asu = 99 is a special case, where the signal strength is unknown. |
| int asu = getGsmSignalStrength(); |
| if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT; |
| else if (asu >= 8) level = SIGNAL_STRENGTH_GOOD; |
| else if (asu >= 5) level = SIGNAL_STRENGTH_MODERATE; |
| else level = SIGNAL_STRENGTH_POOR; |
| if (DBG) log("getGsmLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get the gsm signal level as an asu value between 0..31, 99 is unknown |
| * |
| * @hide |
| */ |
| public int getGsmAsuLevel() { |
| // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5 |
| // asu = 0 (-113dB or less) is very weak |
| // signal, its better to show 0 bars to the user in such cases. |
| // asu = 99 is a special case, where the signal strength is unknown. |
| int level = getGsmSignalStrength(); |
| if (DBG) log("getGsmAsuLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get cdma as level 0..4 |
| * |
| * @hide |
| */ |
| public int getCdmaLevel() { |
| final int cdmaDbm = getCdmaDbm(); |
| final int cdmaEcio = getCdmaEcio(); |
| int levelDbm; |
| int levelEcio; |
| |
| if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT; |
| else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD; |
| else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE; |
| else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR; |
| else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| |
| // Ec/Io are in dB*10 |
| if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT; |
| else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD; |
| else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE; |
| else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR; |
| else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| |
| int level = (levelDbm < levelEcio) ? levelDbm : levelEcio; |
| if (DBG) log("getCdmaLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get the cdma signal level as an asu value between 0..31, 99 is unknown |
| * |
| * @hide |
| */ |
| public int getCdmaAsuLevel() { |
| final int cdmaDbm = getCdmaDbm(); |
| final int cdmaEcio = getCdmaEcio(); |
| int cdmaAsuLevel; |
| int ecioAsuLevel; |
| |
| if (cdmaDbm >= -75) cdmaAsuLevel = 16; |
| else if (cdmaDbm >= -82) cdmaAsuLevel = 8; |
| else if (cdmaDbm >= -90) cdmaAsuLevel = 4; |
| else if (cdmaDbm >= -95) cdmaAsuLevel = 2; |
| else if (cdmaDbm >= -100) cdmaAsuLevel = 1; |
| else cdmaAsuLevel = 99; |
| |
| // Ec/Io are in dB*10 |
| if (cdmaEcio >= -90) ecioAsuLevel = 16; |
| else if (cdmaEcio >= -100) ecioAsuLevel = 8; |
| else if (cdmaEcio >= -115) ecioAsuLevel = 4; |
| else if (cdmaEcio >= -130) ecioAsuLevel = 2; |
| else if (cdmaEcio >= -150) ecioAsuLevel = 1; |
| else ecioAsuLevel = 99; |
| |
| int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel; |
| if (DBG) log("getCdmaAsuLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get Evdo as level 0..4 |
| * |
| * @hide |
| */ |
| public int getEvdoLevel() { |
| int evdoDbm = getEvdoDbm(); |
| int evdoSnr = getEvdoSnr(); |
| int levelEvdoDbm; |
| int levelEvdoSnr; |
| |
| if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT; |
| else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD; |
| else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE; |
| else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR; |
| else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| |
| if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT; |
| else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD; |
| else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE; |
| else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR; |
| else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| |
| int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; |
| if (DBG) log("getEvdoLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get the evdo signal level as an asu value between 0..31, 99 is unknown |
| * |
| * @hide |
| */ |
| public int getEvdoAsuLevel() { |
| int evdoDbm = getEvdoDbm(); |
| int evdoSnr = getEvdoSnr(); |
| int levelEvdoDbm; |
| int levelEvdoSnr; |
| |
| if (evdoDbm >= -65) levelEvdoDbm = 16; |
| else if (evdoDbm >= -75) levelEvdoDbm = 8; |
| else if (evdoDbm >= -85) levelEvdoDbm = 4; |
| else if (evdoDbm >= -95) levelEvdoDbm = 2; |
| else if (evdoDbm >= -105) levelEvdoDbm = 1; |
| else levelEvdoDbm = 99; |
| |
| if (evdoSnr >= 7) levelEvdoSnr = 16; |
| else if (evdoSnr >= 6) levelEvdoSnr = 8; |
| else if (evdoSnr >= 5) levelEvdoSnr = 4; |
| else if (evdoSnr >= 3) levelEvdoSnr = 2; |
| else if (evdoSnr >= 1) levelEvdoSnr = 1; |
| else levelEvdoSnr = 99; |
| |
| int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; |
| if (DBG) log("getEvdoAsuLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get LTE as dBm |
| * |
| * @hide |
| */ |
| public int getLteDbm() { |
| return mLteRsrp; |
| } |
| |
| /** |
| * Get LTE as level 0..4 |
| * |
| * @hide |
| */ |
| public int getLteLevel() { |
| /* |
| * TS 36.214 Physical Layer Section 5.1.3 TS 36.331 RRC RSSI = received |
| * signal + noise RSRP = reference signal dBm RSRQ = quality of signal |
| * dB= Number of Resource blocksxRSRP/RSSI SNR = gain=signal/noise ratio |
| * = -10log P1/P2 dB |
| */ |
| int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1; |
| |
| int[] threshRsrp = Resources.getSystem().getIntArray( |
| com.android.internal.R.array.config_lteDbmThresholds); |
| if (threshRsrp.length != 6) { |
| Log.wtf(LOG_TAG, "getLteLevel - config_lteDbmThresholds has invalid num of elements." |
| + " Cannot evaluate RSRP signal."); |
| } else { |
| if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1; |
| else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT; |
| else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD; |
| else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE; |
| else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR; |
| else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| } |
| |
| /* |
| * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5 |
| * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars |
| * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna |
| * Icon Only |
| */ |
| if (mLteRssnr > 300) snrIconLevel = -1; |
| else if (mLteRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT; |
| else if (mLteRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD; |
| else if (mLteRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE; |
| else if (mLteRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR; |
| else if (mLteRssnr >= -200) |
| snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| |
| if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:" |
| + rsrpIconLevel + " snrIconLevel:" + snrIconLevel); |
| |
| /* Choose a measurement type to use for notification */ |
| if (snrIconLevel != -1 && rsrpIconLevel != -1) { |
| /* |
| * The number of bars displayed shall be the smaller of the bars |
| * associated with LTE RSRP and the bars associated with the LTE |
| * RS_SNR |
| */ |
| return (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel); |
| } |
| |
| if (snrIconLevel != -1) return snrIconLevel; |
| |
| if (rsrpIconLevel != -1) return rsrpIconLevel; |
| |
| /* Valid values are (0-63, 99) as defined in TS 36.331 */ |
| if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT; |
| else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD; |
| else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE; |
| else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR; |
| |
| if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:" |
| + rssiIconLevel); |
| return rssiIconLevel; |
| |
| } |
| /** |
| * Get the LTE signal level as an asu value between 0..97, 99 is unknown |
| * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69 |
| * |
| * @hide |
| */ |
| public int getLteAsuLevel() { |
| int lteAsuLevel = 99; |
| int lteDbm = getLteDbm(); |
| /* |
| * 3GPP 27.007 (Ver 10.3.0) Sec 8.69 |
| * 0 -140 dBm or less |
| * 1 -139 dBm |
| * 2...96 -138... -44 dBm |
| * 97 -43 dBm or greater |
| * 255 not known or not detectable |
| */ |
| /* |
| * validateInput will always give a valid range between -140 t0 -44 as |
| * per ril.h. so RSRP >= -43 & <-140 will fall under asu level 255 |
| * and not 97 or 0 |
| */ |
| if (lteDbm == SignalStrength.INVALID) lteAsuLevel = 255; |
| else lteAsuLevel = lteDbm + 140; |
| if (DBG) log("Lte Asu level: "+lteAsuLevel); |
| return lteAsuLevel; |
| } |
| |
| /** |
| * @return true if this is for GSM |
| */ |
| public boolean isGsm() { |
| return this.isGsm; |
| } |
| |
| /** |
| * @return get TD_SCDMA dbm |
| * |
| * @hide |
| */ |
| public int getTdScdmaDbm() { |
| return this.mTdScdmaRscp; |
| } |
| |
| /** |
| * Get TD-SCDMA as level 0..4 |
| * Range : 25 to 120 |
| * INT_MAX: 0x7FFFFFFF denotes invalid value |
| * Reference: 3GPP TS 25.123, section 9.1.1.1 |
| * |
| * @hide |
| */ |
| public int getTdScdmaLevel() { |
| final int tdScdmaDbm = getTdScdmaDbm(); |
| int level; |
| |
| if ((tdScdmaDbm > -25) || (tdScdmaDbm == SignalStrength.INVALID)) |
| level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| else if (tdScdmaDbm >= -49) level = SIGNAL_STRENGTH_GREAT; |
| else if (tdScdmaDbm >= -73) level = SIGNAL_STRENGTH_GOOD; |
| else if (tdScdmaDbm >= -97) level = SIGNAL_STRENGTH_MODERATE; |
| else if (tdScdmaDbm >= -110) level = SIGNAL_STRENGTH_POOR; |
| else level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| |
| if (DBG) log("getTdScdmaLevel = " + level); |
| return level; |
| } |
| |
| /** |
| * Get the TD-SCDMA signal level as an asu value. |
| * |
| * @hide |
| */ |
| public int getTdScdmaAsuLevel() { |
| final int tdScdmaDbm = getTdScdmaDbm(); |
| int tdScdmaAsuLevel; |
| |
| if (tdScdmaDbm == INVALID) tdScdmaAsuLevel = 255; |
| else tdScdmaAsuLevel = tdScdmaDbm + 120; |
| if (DBG) log("TD-SCDMA Asu level: " + tdScdmaAsuLevel); |
| return tdScdmaAsuLevel; |
| } |
| |
| /** |
| * @return hash code |
| */ |
| @Override |
| public int hashCode() { |
| int primeNum = 31; |
| return ((mGsmSignalStrength * primeNum) |
| + (mGsmBitErrorRate * primeNum) |
| + (mCdmaDbm * primeNum) + (mCdmaEcio * primeNum) |
| + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum) |
| + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum) |
| + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum) |
| + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0)); |
| } |
| |
| /** |
| * @return true if the signal strengths are the same |
| */ |
| @Override |
| public boolean equals (Object o) { |
| SignalStrength s; |
| |
| try { |
| s = (SignalStrength) o; |
| } catch (ClassCastException ex) { |
| return false; |
| } |
| |
| if (o == null) { |
| return false; |
| } |
| |
| return (mGsmSignalStrength == s.mGsmSignalStrength |
| && mGsmBitErrorRate == s.mGsmBitErrorRate |
| && mCdmaDbm == s.mCdmaDbm |
| && mCdmaEcio == s.mCdmaEcio |
| && mEvdoDbm == s.mEvdoDbm |
| && mEvdoEcio == s.mEvdoEcio |
| && mEvdoSnr == s.mEvdoSnr |
| && mLteSignalStrength == s.mLteSignalStrength |
| && mLteRsrp == s.mLteRsrp |
| && mLteRsrq == s.mLteRsrq |
| && mLteRssnr == s.mLteRssnr |
| && mLteCqi == s.mLteCqi |
| && mTdScdmaRscp == s.mTdScdmaRscp |
| && isGsm == s.isGsm); |
| } |
| |
| /** |
| * @return string representation. |
| */ |
| @Override |
| public String toString() { |
| return ("SignalStrength:" |
| + " " + mGsmSignalStrength |
| + " " + mGsmBitErrorRate |
| + " " + mCdmaDbm |
| + " " + mCdmaEcio |
| + " " + mEvdoDbm |
| + " " + mEvdoEcio |
| + " " + mEvdoSnr |
| + " " + mLteSignalStrength |
| + " " + mLteRsrp |
| + " " + mLteRsrq |
| + " " + mLteRssnr |
| + " " + mLteCqi |
| + " " + mTdScdmaRscp |
| + " " + (isGsm ? "gsm|lte" : "cdma")); |
| } |
| |
| /** |
| * Set SignalStrength based on intent notifier map |
| * |
| * @param m intent notifier map |
| * @hide |
| */ |
| private void setFromNotifierBundle(Bundle m) { |
| mGsmSignalStrength = m.getInt("GsmSignalStrength"); |
| mGsmBitErrorRate = m.getInt("GsmBitErrorRate"); |
| mCdmaDbm = m.getInt("CdmaDbm"); |
| mCdmaEcio = m.getInt("CdmaEcio"); |
| mEvdoDbm = m.getInt("EvdoDbm"); |
| mEvdoEcio = m.getInt("EvdoEcio"); |
| mEvdoSnr = m.getInt("EvdoSnr"); |
| mLteSignalStrength = m.getInt("LteSignalStrength"); |
| mLteRsrp = m.getInt("LteRsrp"); |
| mLteRsrq = m.getInt("LteRsrq"); |
| mLteRssnr = m.getInt("LteRssnr"); |
| mLteCqi = m.getInt("LteCqi"); |
| mTdScdmaRscp = m.getInt("TdScdma"); |
| isGsm = m.getBoolean("isGsm"); |
| } |
| |
| /** |
| * Set intent notifier Bundle based on SignalStrength |
| * |
| * @param m intent notifier Bundle |
| * @hide |
| */ |
| public void fillInNotifierBundle(Bundle m) { |
| m.putInt("GsmSignalStrength", mGsmSignalStrength); |
| m.putInt("GsmBitErrorRate", mGsmBitErrorRate); |
| m.putInt("CdmaDbm", mCdmaDbm); |
| m.putInt("CdmaEcio", mCdmaEcio); |
| m.putInt("EvdoDbm", mEvdoDbm); |
| m.putInt("EvdoEcio", mEvdoEcio); |
| m.putInt("EvdoSnr", mEvdoSnr); |
| m.putInt("LteSignalStrength", mLteSignalStrength); |
| m.putInt("LteRsrp", mLteRsrp); |
| m.putInt("LteRsrq", mLteRsrq); |
| m.putInt("LteRssnr", mLteRssnr); |
| m.putInt("LteCqi", mLteCqi); |
| m.putInt("TdScdma", mTdScdmaRscp); |
| m.putBoolean("isGsm", isGsm); |
| } |
| |
| /** |
| * log |
| */ |
| private static void log(String s) { |
| Rlog.w(LOG_TAG, s); |
| } |
| } |