| /* |
| * 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.annotation.IntRange; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.os.PersistableBundle; |
| |
| import com.android.telephony.Rlog; |
| |
| import java.util.Objects; |
| |
| /** |
| * Signal strength related information. |
| */ |
| public final class CellSignalStrengthCdma extends CellSignalStrength implements Parcelable { |
| |
| private static final String LOG_TAG = "CellSignalStrengthCdma"; |
| private static final boolean DBG = false; |
| |
| 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 mLevel; |
| |
| /** @hide */ |
| public CellSignalStrengthCdma() { |
| setDefaultValues(); |
| } |
| |
| /** |
| * SignalStrength constructor for input from the HAL. |
| * |
| * Note that values received from the HAL require coersion to be compatible here. All values |
| * reported through IRadio are the negative of the actual values (which results in a positive |
| * input to this method. |
| * |
| * <p>Note that this HAL is inconsistent with UMTS-based radio techs as the value indicating |
| * that a field is unreported is negative, rather than a large(r) positive number. |
| * <p>Also note that to keep the public-facing methods of this class consistent with others, |
| * unreported values are coerced to {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} |
| * rather than left as -1, which is a departure from SignalStrength, which is stuck with the |
| * values it currently reports. |
| * |
| * @param cdmaDbm CDMA signal strength value or CellInfo.UNAVAILABLE if invalid. |
| * @param cdmaEcio CDMA pilot/noise ratio or CellInfo.UNAVAILABLE if invalid. |
| * @param evdoDbm negative of the EvDO signal strength value or CellInfo.UNAVAILABLE if invalid. |
| * @param evdoEcio negative of the EvDO pilot/noise ratio or CellInfo.UNAVAILABLE if invalid. |
| * @param evdoSnr an SNR value 0..8 or CellInfo.UNVAILABLE if invalid. |
| * @hide |
| */ |
| public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, |
| int evdoSnr) { |
| mCdmaDbm = inRangeOrUnavailable(cdmaDbm, -120, 0); |
| mCdmaEcio = inRangeOrUnavailable(cdmaEcio, -160, 0); |
| mEvdoDbm = inRangeOrUnavailable(evdoDbm, -120, 0); |
| mEvdoEcio = inRangeOrUnavailable(evdoEcio, -160, 0); |
| mEvdoSnr = inRangeOrUnavailable(evdoSnr, 0, 8); |
| |
| updateLevel(null, null); |
| } |
| |
| /** @hide */ |
| public CellSignalStrengthCdma(android.hardware.radio.V1_0.CdmaSignalStrength cdma, |
| android.hardware.radio.V1_0.EvdoSignalStrength evdo) { |
| // Convert from HAL values as part of construction. |
| this(-cdma.dbm, -cdma.ecio, -evdo.dbm, -evdo.ecio, evdo.signalNoiseRatio); |
| } |
| |
| /** @hide */ |
| public CellSignalStrengthCdma(CellSignalStrengthCdma s) { |
| copyFrom(s); |
| } |
| |
| /** @hide */ |
| protected void copyFrom(CellSignalStrengthCdma s) { |
| mCdmaDbm = s.mCdmaDbm; |
| mCdmaEcio = s.mCdmaEcio; |
| mEvdoDbm = s.mEvdoDbm; |
| mEvdoEcio = s.mEvdoEcio; |
| mEvdoSnr = s.mEvdoSnr; |
| mLevel = s.mLevel; |
| } |
| |
| /** @hide */ |
| @Override |
| public CellSignalStrengthCdma copy() { |
| return new CellSignalStrengthCdma(this); |
| } |
| |
| /** @hide */ |
| @Override |
| public void setDefaultValues() { |
| mCdmaDbm = CellInfo.UNAVAILABLE; |
| mCdmaEcio = CellInfo.UNAVAILABLE; |
| mEvdoDbm = CellInfo.UNAVAILABLE; |
| mEvdoEcio = CellInfo.UNAVAILABLE; |
| mEvdoSnr = CellInfo.UNAVAILABLE; |
| mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT) |
| public int getLevel() { |
| return mLevel; |
| } |
| |
| /** @hide */ |
| @Override |
| public void updateLevel(PersistableBundle cc, ServiceState ss) { |
| int cdmaLevel = getCdmaLevel(); |
| int evdoLevel = getEvdoLevel(); |
| if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| /* We don't know evdo, use cdma */ |
| mLevel = getCdmaLevel(); |
| } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { |
| /* We don't know cdma, use evdo */ |
| mLevel = getEvdoLevel(); |
| } else { |
| /* We know both, use the lowest level */ |
| mLevel = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel; |
| } |
| } |
| |
| /** |
| * Get the 1xRTT Level in (Android) ASU. |
| * |
| * There is no standard definition of ASU for CDMA; however, Android defines it as the |
| * the lesser of the following two results (for 1xRTT): |
| * <table> |
| * <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead> |
| * <tbody> |
| * <tr><td>-75..</td><td>16</td></tr> |
| * <tr><td>-82..-76</td><td>8</td></tr> |
| * <tr><td>-90..-83</td><td>4</td></tr> |
| * <tr><td>-95..-91</td><td>2</td></tr> |
| * <tr><td>-100..-96</td><td>1</td></tr> |
| * <tr><td>..-101</td><td>99</td></tr> |
| * </tbody> |
| * </table> |
| * <table> |
| * <thead><tr><th>Ec/Io Range (dB)</th><th>ASU Value</th></tr><thead> |
| * <tbody> |
| * <tr><td>-90..</td><td>16</td></tr> |
| * <tr><td>-100..-91</td><td>8</td></tr> |
| * <tr><td>-115..-101</td><td>4</td></tr> |
| * <tr><td>-130..-116</td><td>2</td></tr> |
| * <tr><td>--150..-131</td><td>1</td></tr> |
| * <tr><td>..-151</td><td>99</td></tr> |
| * </tbody> |
| * </table> |
| * @return 1xRTT Level in Android ASU {1,2,4,8,16,99} |
| */ |
| @Override |
| public int getAsuLevel() { |
| final int cdmaDbm = getCdmaDbm(); |
| final int cdmaEcio = getCdmaEcio(); |
| int cdmaAsuLevel; |
| int ecioAsuLevel; |
| |
| if (cdmaDbm == CellInfo.UNAVAILABLE) cdmaAsuLevel = 99; |
| else 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 == CellInfo.UNAVAILABLE) ecioAsuLevel = 99; |
| else 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("getAsuLevel=" + level); |
| return level; |
| } |
| |
| /** |
| * Get cdma as level 0..4 |
| */ |
| public int getCdmaLevel() { |
| final int cdmaDbm = getCdmaDbm(); |
| final int cdmaEcio = getCdmaEcio(); |
| int levelDbm; |
| int levelEcio; |
| |
| if (cdmaDbm == CellInfo.UNAVAILABLE) levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| else 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 == CellInfo.UNAVAILABLE) levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| else 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 Evdo as level 0..4 |
| */ |
| public int getEvdoLevel() { |
| int evdoDbm = getEvdoDbm(); |
| int evdoSnr = getEvdoSnr(); |
| int levelEvdoDbm; |
| int levelEvdoSnr; |
| |
| if (evdoDbm == CellInfo.UNAVAILABLE) levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| else 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 == CellInfo.UNAVAILABLE) levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; |
| else 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 Level in (Android) ASU. |
| * |
| * There is no standard definition of ASU for CDMA; however, Android defines it as the |
| * the lesser of the following two results (for EVDO): |
| * <table> |
| * <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead> |
| * <tbody> |
| * <tr><td>-65..</td><td>16</td></tr> |
| * <tr><td>-75..-66</td><td>8</td></tr> |
| * <tr><td>-85..-76</td><td>4</td></tr> |
| * <tr><td>-95..-86</td><td>2</td></tr> |
| * <tr><td>-105..-96</td><td>1</td></tr> |
| * <tr><td>..-106</td><td>99</td></tr> |
| * </tbody> |
| * </table> |
| * <table> |
| * <thead><tr><th>SNR Range (unitless)</th><th>ASU Value</th></tr><thead> |
| * <tbody> |
| * <tr><td>7..</td><td>16</td></tr> |
| * <tr><td>6</td><td>8</td></tr> |
| * <tr><td>5</td><td>4</td></tr> |
| * <tr><td>3..4</td><td>2</td></tr> |
| * <tr><td>1..2</td><td>1</td></tr> |
| * <tr><td>0</td><td>99</td></tr> |
| * </tbody> |
| * </table> |
| * |
| * @return EVDO Level in Android ASU {1,2,4,8,16,99} |
| * |
| * @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 the signal strength as dBm |
| * |
| * @return min(CDMA RSSI, EVDO RSSI) of the measured cell. |
| */ |
| @Override |
| public int getDbm() { |
| int cdmaDbm = getCdmaDbm(); |
| int evdoDbm = getEvdoDbm(); |
| |
| // Use the lower value to be conservative |
| return (cdmaDbm < evdoDbm) ? cdmaDbm : evdoDbm; |
| } |
| |
| /** |
| * Get the CDMA RSSI value in dBm |
| */ |
| public int getCdmaDbm() { |
| return mCdmaDbm; |
| } |
| |
| /** @hide */ |
| public void setCdmaDbm(int cdmaDbm) { |
| mCdmaDbm = cdmaDbm; |
| } |
| |
| /** |
| * Get the CDMA Ec/Io value in dB*10 |
| */ |
| public int getCdmaEcio() { |
| return mCdmaEcio; |
| } |
| |
| /** @hide */ |
| public void setCdmaEcio(int cdmaEcio) { |
| mCdmaEcio = cdmaEcio; |
| } |
| |
| /** |
| * Get the EVDO RSSI value in dBm |
| */ |
| public int getEvdoDbm() { |
| return mEvdoDbm; |
| } |
| |
| /** @hide */ |
| public void setEvdoDbm(int evdoDbm) { |
| mEvdoDbm = evdoDbm; |
| } |
| |
| /** |
| * Get the EVDO Ec/Io value in dB*10 |
| */ |
| public int getEvdoEcio() { |
| return mEvdoEcio; |
| } |
| |
| /** @hide */ |
| public void setEvdoEcio(int evdoEcio) { |
| mEvdoEcio = evdoEcio; |
| } |
| |
| /** |
| * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest. |
| */ |
| public int getEvdoSnr() { |
| return mEvdoSnr; |
| } |
| |
| /** @hide */ |
| public void setEvdoSnr(int evdoSnr) { |
| mEvdoSnr = evdoSnr; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mCdmaDbm, mCdmaEcio, mEvdoDbm, mEvdoEcio, mEvdoSnr, mLevel); |
| } |
| |
| private static final CellSignalStrengthCdma sInvalid = new CellSignalStrengthCdma(); |
| |
| /** @hide */ |
| @Override |
| public boolean isValid() { |
| return !this.equals(sInvalid); |
| } |
| |
| @Override |
| public boolean equals (Object o) { |
| CellSignalStrengthCdma s; |
| if (!(o instanceof CellSignalStrengthCdma)) return false; |
| s = (CellSignalStrengthCdma) o; |
| |
| return mCdmaDbm == s.mCdmaDbm |
| && mCdmaEcio == s.mCdmaEcio |
| && mEvdoDbm == s.mEvdoDbm |
| && mEvdoEcio == s.mEvdoEcio |
| && mEvdoSnr == s.mEvdoSnr |
| && mLevel == s.mLevel; |
| } |
| |
| /** |
| * @return string representation. |
| */ |
| @Override |
| public String toString() { |
| return "CellSignalStrengthCdma:" |
| + " cdmaDbm=" + mCdmaDbm |
| + " cdmaEcio=" + mCdmaEcio |
| + " evdoDbm=" + mEvdoDbm |
| + " evdoEcio=" + mEvdoEcio |
| + " evdoSnr=" + mEvdoSnr |
| + " level=" + mLevel; |
| } |
| |
| /** Implement the Parcelable interface */ |
| @Override |
| public void writeToParcel(Parcel dest, int flags) { |
| if (DBG) log("writeToParcel(Parcel, int): " + toString()); |
| dest.writeInt(mCdmaDbm); |
| dest.writeInt(mCdmaEcio); |
| dest.writeInt(mEvdoDbm); |
| dest.writeInt(mEvdoEcio); |
| dest.writeInt(mEvdoSnr); |
| dest.writeInt(mLevel); |
| } |
| |
| /** |
| * Construct a SignalStrength object from the given parcel |
| * where the TYPE_CDMA token is already been processed. |
| */ |
| private CellSignalStrengthCdma(Parcel in) { |
| // CdmaDbm, CdmaEcio, EvdoDbm and EvdoEcio are written into |
| // the parcel as positive values. |
| // Need to convert into negative values unless the value is invalid |
| mCdmaDbm = in.readInt(); |
| mCdmaEcio = in.readInt(); |
| mEvdoDbm = in.readInt(); |
| mEvdoEcio = in.readInt(); |
| mEvdoSnr = in.readInt(); |
| mLevel = in.readInt(); |
| if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString()); |
| } |
| |
| /** Implement the Parcelable interface */ |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| /** Implement the Parcelable interface */ |
| @SuppressWarnings("hiding") |
| public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthCdma> CREATOR = |
| new Parcelable.Creator<CellSignalStrengthCdma>() { |
| @Override |
| public CellSignalStrengthCdma createFromParcel(Parcel in) { |
| return new CellSignalStrengthCdma(in); |
| } |
| |
| @Override |
| public CellSignalStrengthCdma[] newArray(int size) { |
| return new CellSignalStrengthCdma[size]; |
| } |
| }; |
| |
| /** |
| * log |
| */ |
| private static void log(String s) { |
| Rlog.w(LOG_TAG, s); |
| } |
| } |