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.annotation.IntRange; 20 import android.annotation.UnsupportedAppUsage; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.os.PersistableBundle; 24 25 import java.util.Arrays; 26 import java.util.Objects; 27 28 /** 29 * LTE signal strength related information. 30 */ 31 public final class CellSignalStrengthLte extends CellSignalStrength implements Parcelable { 32 33 private static final String LOG_TAG = "CellSignalStrengthLte"; 34 private static final boolean DBG = false; 35 36 /** 37 * Indicates the unknown or undetectable RSSI value in ASU. 38 * 39 * Reference: TS 27.007 8.5 - Signal quality +CSQ 40 */ 41 private static final int SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN = 99; 42 /** 43 * Indicates the maximum valid RSSI value in ASU. 44 * 45 * Reference: TS 27.007 8.5 - Signal quality +CSQ 46 */ 47 private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE = 31; 48 /** 49 * Indicates the minimum valid RSSI value in ASU. 50 * 51 * Reference: TS 27.007 8.5 - Signal quality +CSQ 52 */ 53 private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE = 0; 54 55 private static final int MAX_LTE_RSRP = -44; 56 private static final int MIN_LTE_RSRP = -140; 57 58 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 59 private int mSignalStrength; // To be removed 60 private int mRssi; 61 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 62 private int mRsrp; 63 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 64 private int mRsrq; 65 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 66 private int mRssnr; 67 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 68 private int mCqi; 69 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 70 private int mTimingAdvance; 71 private int mLevel; 72 73 /** @hide */ 74 @UnsupportedAppUsage CellSignalStrengthLte()75 public CellSignalStrengthLte() { 76 setDefaultValues(); 77 } 78 79 /** 80 * Construct a cell signal strength 81 * 82 * @param rssi in dBm [-113,-51], UNKNOWN 83 * @param rsrp in dBm [-140,-43], UNKNOWN 84 * @param rsrq in dB [-20,-3], UNKNOWN 85 * @param rssnr in 10*dB [-200, +300], UNKNOWN 86 * @param cqi [0, 15], UNKNOWN 87 * @param timingAdvance [0, 1282], UNKNOWN 88 * 89 */ 90 /** @hide */ CellSignalStrengthLte(int rssi, int rsrp, int rsrq, int rssnr, int cqi, int timingAdvance)91 public CellSignalStrengthLte(int rssi, int rsrp, int rsrq, int rssnr, int cqi, 92 int timingAdvance) { 93 94 mRssi = inRangeOrUnavailable(rssi, -113, -51); 95 mSignalStrength = mRssi; 96 mRsrp = inRangeOrUnavailable(rsrp, -140, -43); 97 mRsrq = inRangeOrUnavailable(rsrq, -20, -3); 98 mRssnr = inRangeOrUnavailable(rssnr, -200, 300); 99 mCqi = inRangeOrUnavailable(cqi, 0, 15); 100 mTimingAdvance = inRangeOrUnavailable(timingAdvance, 0, 1282); 101 updateLevel(null, null); 102 } 103 104 /** @hide */ CellSignalStrengthLte(android.hardware.radio.V1_0.LteSignalStrength lte)105 public CellSignalStrengthLte(android.hardware.radio.V1_0.LteSignalStrength lte) { 106 // Convert from HAL values as part of construction. 107 this(convertRssiAsuToDBm(lte.signalStrength), 108 lte.rsrp != CellInfo.UNAVAILABLE ? -lte.rsrp : lte.rsrp, 109 lte.rsrq != CellInfo.UNAVAILABLE ? -lte.rsrq : lte.rsrq, 110 lte.rssnr, lte.cqi, lte.timingAdvance); 111 } 112 113 /** @hide */ CellSignalStrengthLte(CellSignalStrengthLte s)114 public CellSignalStrengthLte(CellSignalStrengthLte s) { 115 copyFrom(s); 116 } 117 118 /** @hide */ copyFrom(CellSignalStrengthLte s)119 protected void copyFrom(CellSignalStrengthLte s) { 120 mSignalStrength = s.mSignalStrength; 121 mRssi = s.mRssi; 122 mRsrp = s.mRsrp; 123 mRsrq = s.mRsrq; 124 mRssnr = s.mRssnr; 125 mCqi = s.mCqi; 126 mTimingAdvance = s.mTimingAdvance; 127 mLevel = s.mLevel; 128 } 129 130 /** @hide */ 131 @Override copy()132 public CellSignalStrengthLte copy() { 133 return new CellSignalStrengthLte(this); 134 } 135 136 /** @hide */ 137 @Override setDefaultValues()138 public void setDefaultValues() { 139 mSignalStrength = CellInfo.UNAVAILABLE; 140 mRssi = CellInfo.UNAVAILABLE; 141 mRsrp = CellInfo.UNAVAILABLE; 142 mRsrq = CellInfo.UNAVAILABLE; 143 mRssnr = CellInfo.UNAVAILABLE; 144 mCqi = CellInfo.UNAVAILABLE; 145 mTimingAdvance = CellInfo.UNAVAILABLE; 146 mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 147 } 148 149 /** {@inheritDoc} */ 150 @Override 151 @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT) getLevel()152 public int getLevel() { 153 return mLevel; 154 } 155 156 // Lifted from Default carrier configs and max range of RSRP 157 private static final int[] sThresholds = new int[]{-115, -105, -95, -85}; 158 private static final int sRsrpBoost = 0; 159 160 /** @hide */ 161 @Override updateLevel(PersistableBundle cc, ServiceState ss)162 public void updateLevel(PersistableBundle cc, ServiceState ss) { 163 int[] thresholds; 164 boolean rsrpOnly; 165 if (cc == null) { 166 thresholds = sThresholds; 167 rsrpOnly = false; 168 } else { 169 rsrpOnly = cc.getBoolean( 170 CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL, false); 171 thresholds = cc.getIntArray( 172 CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY); 173 if (thresholds == null) thresholds = sThresholds; 174 if (DBG) log("updateLevel() carrierconfig - rsrpOnly=" 175 + rsrpOnly + ", thresholds=" + Arrays.toString(thresholds)); 176 } 177 178 179 int rsrpBoost = 0; 180 if (ss != null) { 181 rsrpBoost = ss.getLteEarfcnRsrpBoost(); 182 } 183 184 int rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 185 int rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 186 int snrIconLevel = -1; 187 188 int rsrp = mRsrp + rsrpBoost; 189 190 if (rsrp < MIN_LTE_RSRP || rsrp > MAX_LTE_RSRP) { 191 rsrpIconLevel = -1; 192 } else { 193 rsrpIconLevel = thresholds.length; 194 while (rsrpIconLevel > 0 && rsrp < thresholds[rsrpIconLevel - 1]) rsrpIconLevel--; 195 } 196 197 if (rsrpOnly) { 198 if (DBG) log("updateLevel() - rsrp = " + rsrpIconLevel); 199 if (rsrpIconLevel != -1) { 200 mLevel = rsrpIconLevel; 201 return; 202 } 203 } 204 205 /* 206 * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5 207 * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars 208 * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna 209 * Icon Only 210 */ 211 if (mRssnr > 300) snrIconLevel = -1; 212 else if (mRssnr >= 130) snrIconLevel = SIGNAL_STRENGTH_GREAT; 213 else if (mRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD; 214 else if (mRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE; 215 else if (mRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR; 216 else if (mRssnr >= -200) 217 snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 218 219 if (DBG) log("updateLevel() - rsrp:" + mRsrp + " snr:" + mRssnr + " rsrpIconLevel:" 220 + rsrpIconLevel + " snrIconLevel:" + snrIconLevel 221 + " lteRsrpBoost:" + sRsrpBoost); 222 223 /* Choose a measurement type to use for notification */ 224 if (snrIconLevel != -1 && rsrpIconLevel != -1) { 225 /* 226 * The number of bars displayed shall be the smaller of the bars 227 * associated with LTE RSRP and the bars associated with the LTE 228 * RS_SNR 229 */ 230 mLevel = (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel); 231 return; 232 } 233 234 if (snrIconLevel != -1) { 235 mLevel = snrIconLevel; 236 return; 237 } 238 239 if (rsrpIconLevel != -1) { 240 mLevel = rsrpIconLevel; 241 return; 242 } 243 244 if (mRssi > -51) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 245 else if (mRssi >= -89) rssiIconLevel = SIGNAL_STRENGTH_GREAT; 246 else if (mRssi >= -97) rssiIconLevel = SIGNAL_STRENGTH_GOOD; 247 else if (mRssi >= -103) rssiIconLevel = SIGNAL_STRENGTH_MODERATE; 248 else if (mRssi >= -113) rssiIconLevel = SIGNAL_STRENGTH_POOR; 249 else rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 250 if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:" 251 + rssiIconLevel); 252 mLevel = rssiIconLevel; 253 } 254 255 /** 256 * Get reference signal received quality 257 * 258 * @return the RSRQ if available or 259 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 260 */ getRsrq()261 public int getRsrq() { 262 return mRsrq; 263 } 264 265 /** 266 * Get Received Signal Strength Indication (RSSI) in dBm 267 * 268 * The value range is [-113, -51] inclusively or {@link CellInfo#UNAVAILABLE} if unavailable. 269 * 270 * Reference: TS 27.007 8.5 Signal quality +CSQ 271 * 272 * @return the RSSI if available or {@link CellInfo#UNAVAILABLE} if unavailable. 273 */ getRssi()274 public int getRssi() { 275 return mRssi; 276 } 277 278 /** 279 * Get reference signal signal-to-noise ratio 280 * 281 * @return the RSSNR if available or 282 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 283 */ getRssnr()284 public int getRssnr() { 285 return mRssnr; 286 } 287 288 /** 289 * Get reference signal received power in dBm 290 * 291 * @return the RSRP of the measured cell. 292 */ getRsrp()293 public int getRsrp() { 294 return mRsrp; 295 } 296 297 /** 298 * Get channel quality indicator 299 * 300 * @return the CQI if available or 301 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 302 */ getCqi()303 public int getCqi() { 304 return mCqi; 305 } 306 307 /** 308 * Get signal strength in dBm 309 * 310 * @return the RSRP of the measured cell. 311 */ 312 @Override getDbm()313 public int getDbm() { 314 return mRsrp; 315 } 316 317 /** 318 * Get the RSRP in ASU. 319 * 320 * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69 321 * 322 * @return RSCP in ASU 0..97, 255, or UNAVAILABLE 323 */ 324 @Override getAsuLevel()325 public int getAsuLevel() { 326 int lteAsuLevel = 99; 327 int lteDbm = mRsrp; 328 if (lteDbm == CellInfo.UNAVAILABLE) lteAsuLevel = 99; 329 else if (lteDbm <= -140) lteAsuLevel = 0; 330 else if (lteDbm >= -43) lteAsuLevel = 97; 331 else lteAsuLevel = lteDbm + 140; 332 if (DBG) log("Lte Asu level: "+lteAsuLevel); 333 return lteAsuLevel; 334 } 335 336 /** 337 * Get the timing advance value for LTE, as a value in range of 0..1282. 338 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} is reported when there is no 339 * active RRC connection. Refer to 3GPP 36.213 Sec 4.2.3 340 * 341 * @return the LTE timing advance if available or 342 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 343 */ getTimingAdvance()344 public int getTimingAdvance() { 345 return mTimingAdvance; 346 } 347 348 @Override hashCode()349 public int hashCode() { 350 return Objects.hash(mRssi, mRsrp, mRsrq, mRssnr, mCqi, mTimingAdvance, mLevel); 351 } 352 353 private static final CellSignalStrengthLte sInvalid = new CellSignalStrengthLte(); 354 355 /** @hide */ 356 @Override isValid()357 public boolean isValid() { 358 return !this.equals(sInvalid); 359 } 360 361 @Override equals(Object o)362 public boolean equals (Object o) { 363 CellSignalStrengthLte s; 364 365 if (!(o instanceof CellSignalStrengthLte)) return false; 366 s = (CellSignalStrengthLte) o; 367 368 return mRssi == s.mRssi 369 && mRsrp == s.mRsrp 370 && mRsrq == s.mRsrq 371 && mRssnr == s.mRssnr 372 && mCqi == s.mCqi 373 && mTimingAdvance == s.mTimingAdvance 374 && mLevel == s.mLevel; 375 } 376 377 /** 378 * @return string representation. 379 */ 380 @Override toString()381 public String toString() { 382 return "CellSignalStrengthLte:" 383 + " rssi=" + mRssi 384 + " rsrp=" + mRsrp 385 + " rsrq=" + mRsrq 386 + " rssnr=" + mRssnr 387 + " cqi=" + mCqi 388 + " ta=" + mTimingAdvance 389 + " level=" + mLevel; 390 } 391 392 /** Implement the Parcelable interface */ 393 @Override writeToParcel(Parcel dest, int flags)394 public void writeToParcel(Parcel dest, int flags) { 395 if (DBG) log("writeToParcel(Parcel, int): " + toString()); 396 dest.writeInt(mRssi); 397 // Need to multiply rsrp and rsrq by -1 398 // to ensure consistency when reading values written here 399 // unless the values are invalid 400 dest.writeInt(mRsrp); 401 dest.writeInt(mRsrq); 402 dest.writeInt(mRssnr); 403 dest.writeInt(mCqi); 404 dest.writeInt(mTimingAdvance); 405 dest.writeInt(mLevel); 406 } 407 408 /** 409 * Construct a SignalStrength object from the given parcel 410 * where the token is already been processed. 411 */ CellSignalStrengthLte(Parcel in)412 private CellSignalStrengthLte(Parcel in) { 413 mRssi = in.readInt(); 414 mSignalStrength = mRssi; 415 mRsrp = in.readInt(); 416 mRsrq = in.readInt(); 417 mRssnr = in.readInt(); 418 mCqi = in.readInt(); 419 mTimingAdvance = in.readInt(); 420 mLevel = in.readInt(); 421 if (DBG) log("CellSignalStrengthLte(Parcel): " + toString()); 422 } 423 424 /** Implement the Parcelable interface */ 425 @Override describeContents()426 public int describeContents() { 427 return 0; 428 } 429 430 /** Implement the Parcelable interface */ 431 @SuppressWarnings("hiding") 432 public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthLte> CREATOR = 433 new Parcelable.Creator<CellSignalStrengthLte>() { 434 @Override 435 public CellSignalStrengthLte createFromParcel(Parcel in) { 436 return new CellSignalStrengthLte(in); 437 } 438 439 @Override 440 public CellSignalStrengthLte[] newArray(int size) { 441 return new CellSignalStrengthLte[size]; 442 } 443 }; 444 445 /** 446 * log 447 */ log(String s)448 private static void log(String s) { 449 Rlog.w(LOG_TAG, s); 450 } 451 convertRssiAsuToDBm(int rssiAsu)452 private static int convertRssiAsuToDBm(int rssiAsu) { 453 if (rssiAsu == SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN) { 454 return CellInfo.UNAVAILABLE; 455 } 456 if ((rssiAsu < SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE 457 || rssiAsu > SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE)) { 458 Rlog.e(LOG_TAG, "convertRssiAsuToDBm: invalid RSSI in ASU=" + rssiAsu); 459 return CellInfo.UNAVAILABLE; 460 } 461 return -113 + (2 * rssiAsu); 462 } 463 } 464