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.compat.annotation.UnsupportedAppUsage; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.os.PersistableBundle; 24 25 import com.android.telephony.Rlog; 26 27 import java.util.Arrays; 28 import java.util.Objects; 29 30 /** 31 * LTE signal strength related information. 32 */ 33 public final class CellSignalStrengthLte extends CellSignalStrength implements Parcelable { 34 35 private static final String LOG_TAG = "CellSignalStrengthLte"; 36 private static final boolean DBG = false; 37 38 /** 39 * Indicates the unknown or undetectable RSSI value in ASU. 40 * 41 * Reference: TS 27.007 8.5 - Signal quality +CSQ 42 */ 43 private static final int SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN = 99; 44 /** 45 * Indicates the maximum valid RSSI value in ASU. 46 * 47 * Reference: TS 27.007 8.5 - Signal quality +CSQ 48 */ 49 private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE = 31; 50 /** 51 * Indicates the minimum valid RSSI value in ASU. 52 * 53 * Reference: TS 27.007 8.5 - Signal quality +CSQ 54 */ 55 private static final int SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE = 0; 56 57 private static final int MAX_LTE_RSRP = -44; 58 private static final int MIN_LTE_RSRP = -140; 59 60 /** 61 * Indicates RSRP is considered for {@link #getLevel()} and reported from modem. 62 * 63 * @hide 64 */ 65 public static final int USE_RSRP = 1 << 0; 66 /** 67 * Indicates RSRQ is considered for {@link #getLevel()} and reported from modem. 68 * 69 * @hide 70 */ 71 public static final int USE_RSRQ = 1 << 1; 72 /** 73 * Indicates RSSNR is considered for {@link #getLevel()} and reported from modem. 74 * 75 * @hide 76 */ 77 public static final int USE_RSSNR = 1 << 2; 78 79 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 80 private int mSignalStrength; // To be removed 81 private int mRssi; 82 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 83 private int mRsrp; 84 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 85 private int mRsrq; 86 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 87 private int mRssnr; 88 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 89 private int mCqi; 90 @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P) 91 private int mTimingAdvance; 92 private int mLevel; 93 94 /** 95 * Bit-field integer to determine whether to use Reference Signal Received Power (RSRP), 96 * Reference Signal Received Quality (RSRQ), and/or Reference Signal Signal to Noise Ratio 97 * (RSSNR) for the number of LTE signal bars. If multiple measures are set, the parameter 98 * whose signal level value is smallest is used to indicate the signal level. 99 * 100 * RSRP = 1 << 0, 101 * RSRQ = 1 << 1, 102 * RSSNR = 1 << 2, 103 * 104 * For example, if both RSRP and RSRQ are used, the value of key is 3 (1 << 0 | 1 << 1). 105 * If the key is invalid or not configured, a default value (RSRP = 1 << 0) will apply. 106 */ 107 private int mParametersUseForLevel; 108 109 /** @hide */ 110 @UnsupportedAppUsage CellSignalStrengthLte()111 public CellSignalStrengthLte() { 112 setDefaultValues(); 113 } 114 115 /** 116 * Construct a cell signal strength 117 * 118 * @param rssi in dBm [-113,-51], UNKNOWN 119 * @param rsrp in dBm [-140,-43], UNKNOWN 120 * @param rsrq in dB [-34, 3], UNKNOWN 121 * @param rssnr in dB [-20, +30], UNKNOWN 122 * @param cqi [0, 15], UNKNOWN 123 * @param timingAdvance [0, 1282], UNKNOWN 124 * 125 */ 126 /** @hide */ CellSignalStrengthLte(int rssi, int rsrp, int rsrq, int rssnr, int cqi, int timingAdvance)127 public CellSignalStrengthLte(int rssi, int rsrp, int rsrq, int rssnr, int cqi, 128 int timingAdvance) { 129 130 mRssi = inRangeOrUnavailable(rssi, -113, -51); 131 mSignalStrength = mRssi; 132 mRsrp = inRangeOrUnavailable(rsrp, -140, -43); 133 mRsrq = inRangeOrUnavailable(rsrq, -34, 3); 134 mRssnr = inRangeOrUnavailable(rssnr, -20, 30); 135 mCqi = inRangeOrUnavailable(cqi, 0, 15); 136 mTimingAdvance = inRangeOrUnavailable(timingAdvance, 0, 1282); 137 updateLevel(null, null); 138 } 139 140 /** @hide */ CellSignalStrengthLte(android.hardware.radio.V1_0.LteSignalStrength lte)141 public CellSignalStrengthLte(android.hardware.radio.V1_0.LteSignalStrength lte) { 142 // Convert from HAL values as part of construction. 143 this(convertRssiAsuToDBm(lte.signalStrength), 144 lte.rsrp != CellInfo.UNAVAILABLE ? -lte.rsrp : lte.rsrp, 145 lte.rsrq != CellInfo.UNAVAILABLE ? -lte.rsrq : lte.rsrq, 146 convertRssnrUnitFromTenDbToDB(lte.rssnr), lte.cqi, lte.timingAdvance); 147 } 148 149 /** @hide */ CellSignalStrengthLte(CellSignalStrengthLte s)150 public CellSignalStrengthLte(CellSignalStrengthLte s) { 151 copyFrom(s); 152 } 153 154 /** @hide */ copyFrom(CellSignalStrengthLte s)155 protected void copyFrom(CellSignalStrengthLte s) { 156 mSignalStrength = s.mSignalStrength; 157 mRssi = s.mRssi; 158 mRsrp = s.mRsrp; 159 mRsrq = s.mRsrq; 160 mRssnr = s.mRssnr; 161 mCqi = s.mCqi; 162 mTimingAdvance = s.mTimingAdvance; 163 mLevel = s.mLevel; 164 mParametersUseForLevel = s.mParametersUseForLevel; 165 } 166 167 /** @hide */ 168 @Override copy()169 public CellSignalStrengthLte copy() { 170 return new CellSignalStrengthLte(this); 171 } 172 173 /** @hide */ 174 @Override setDefaultValues()175 public void setDefaultValues() { 176 mSignalStrength = CellInfo.UNAVAILABLE; 177 mRssi = CellInfo.UNAVAILABLE; 178 mRsrp = CellInfo.UNAVAILABLE; 179 mRsrq = CellInfo.UNAVAILABLE; 180 mRssnr = CellInfo.UNAVAILABLE; 181 mCqi = CellInfo.UNAVAILABLE; 182 mTimingAdvance = CellInfo.UNAVAILABLE; 183 mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 184 mParametersUseForLevel = USE_RSRP; 185 } 186 187 /** {@inheritDoc} */ 188 @Override 189 @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT) getLevel()190 public int getLevel() { 191 return mLevel; 192 } 193 194 // Lifted from Default carrier configs and max range of RSRP 195 private static final int[] sRsrpThresholds = new int[] { 196 -115, /* SIGNAL_STRENGTH_POOR */ 197 -105, /* SIGNAL_STRENGTH_MODERATE */ 198 -95, /* SIGNAL_STRENGTH_GOOD */ 199 -85 /* SIGNAL_STRENGTH_GREAT */ 200 }; 201 202 // Lifted from Default carrier configs and max range of RSRQ 203 private static final int[] sRsrqThresholds = new int[] { 204 -19, /* SIGNAL_STRENGTH_POOR */ 205 -17, /* SIGNAL_STRENGTH_MODERATE */ 206 -14, /* SIGNAL_STRENGTH_GOOD */ 207 -12 /* SIGNAL_STRENGTH_GREAT */ 208 }; 209 // Lifted from Default carrier configs and max range of RSSNR 210 private static final int[] sRssnrThresholds = new int[] { 211 -3, /* SIGNAL_STRENGTH_POOR */ 212 1, /* SIGNAL_STRENGTH_MODERATE */ 213 5, /* SIGNAL_STRENGTH_GOOD */ 214 13 /* SIGNAL_STRENGTH_GREAT */ 215 }; 216 private static final int sRsrpBoost = 0; 217 218 /** 219 * Checks if the given parameter type is considered to use for {@link #getLevel()}. 220 * 221 * Note: if multiple parameter types are considered, the smaller level for one of the 222 * parameters would be returned by {@link #getLevel()} 223 * 224 * @param parameterType bitwise OR of {@link #USE_RSRP}, {@link #USE_RSRQ}, 225 * {@link #USE_RSSNR} 226 * @return {@code true} if the level is calculated based on the given parameter type; 227 * {@code false} otherwise. 228 */ isLevelForParameter(int parameterType)229 private boolean isLevelForParameter(int parameterType) { 230 return (parameterType & mParametersUseForLevel) == parameterType; 231 } 232 233 /** @hide */ 234 @Override updateLevel(PersistableBundle cc, ServiceState ss)235 public void updateLevel(PersistableBundle cc, ServiceState ss) { 236 int[] rsrpThresholds, rsrqThresholds, rssnrThresholds; 237 boolean rsrpOnly; 238 if (cc == null) { 239 mParametersUseForLevel = USE_RSRP; 240 rsrpThresholds = sRsrpThresholds; 241 rsrqThresholds = sRsrqThresholds; 242 rssnrThresholds = sRssnrThresholds; 243 rsrpOnly = false; 244 } else { 245 mParametersUseForLevel = cc.getInt( 246 CarrierConfigManager.KEY_PARAMETERS_USED_FOR_LTE_SIGNAL_BAR_INT); 247 if (DBG) { 248 Rlog.i(LOG_TAG, "Using signal strength level: " + mParametersUseForLevel); 249 } 250 rsrpThresholds = cc.getIntArray( 251 CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY); 252 if (rsrpThresholds == null) rsrpThresholds = sRsrpThresholds; 253 if (DBG) { 254 Rlog.i(LOG_TAG, "Applying LTE RSRP Thresholds: " 255 + Arrays.toString(rsrpThresholds)); 256 } 257 rsrqThresholds = cc.getIntArray( 258 CarrierConfigManager.KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY); 259 if (rsrqThresholds == null) rsrqThresholds = sRsrqThresholds; 260 if (DBG) { 261 Rlog.i(LOG_TAG, "Applying LTE RSRQ Thresholds: " 262 + Arrays.toString(rsrqThresholds)); 263 } 264 rssnrThresholds = cc.getIntArray( 265 CarrierConfigManager.KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY); 266 if (rssnrThresholds == null) rssnrThresholds = sRssnrThresholds; 267 if (DBG) { 268 Rlog.i(LOG_TAG, "Applying LTE RSSNR Thresholds: " 269 + Arrays.toString(rssnrThresholds)); 270 } 271 rsrpOnly = cc.getBoolean( 272 CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL, false); 273 } 274 275 int rsrpBoost = 0; 276 if (ss != null) { 277 rsrpBoost = ss.getLteEarfcnRsrpBoost(); 278 } 279 280 int rsrp = inRangeOrUnavailable(mRsrp + rsrpBoost, MIN_LTE_RSRP, MAX_LTE_RSRP); 281 282 if (rsrpOnly) { 283 int level = updateLevelWithMeasure(rsrp, rsrpThresholds); 284 if (DBG) log("updateLevel() - rsrp = " + level); 285 if (level != SignalStrength.INVALID) { 286 mLevel = level; 287 return; 288 } 289 } 290 291 int rsrpLevel = SignalStrength.INVALID; 292 int rsrqLevel = SignalStrength.INVALID; 293 int rssnrLevel = SignalStrength.INVALID; 294 295 if (isLevelForParameter(USE_RSRP)) { 296 rsrpLevel = updateLevelWithMeasure(rsrp, rsrpThresholds); 297 if (DBG) { 298 Rlog.i(LOG_TAG, "Updated 4G LTE RSRP Level: " + rsrpLevel); 299 } 300 } 301 if (isLevelForParameter(USE_RSRQ)) { 302 rsrqLevel = updateLevelWithMeasure(mRsrq, rsrqThresholds); 303 if (DBG) { 304 Rlog.i(LOG_TAG, "Updated 4G LTE RSRQ Level: " + rsrqLevel); 305 } 306 } 307 if (isLevelForParameter(USE_RSSNR)) { 308 rssnrLevel = updateLevelWithMeasure(mRssnr, rssnrThresholds); 309 if (DBG) { 310 Rlog.i(LOG_TAG, "Updated 4G LTE RSSNR Level: " + rssnrLevel); 311 } 312 } 313 // Apply the smaller value among three levels of three measures. 314 mLevel = Math.min(Math.min(rsrpLevel, rsrqLevel), rssnrLevel); 315 316 if (mLevel == SignalStrength.INVALID) { 317 int rssiLevel; 318 if (mRssi > -51) { 319 rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 320 } else if (mRssi >= -89) { 321 rssiLevel = SIGNAL_STRENGTH_GREAT; 322 } else if (mRssi >= -97) { 323 rssiLevel = SIGNAL_STRENGTH_GOOD; 324 } else if (mRssi >= -103) { 325 rssiLevel = SIGNAL_STRENGTH_MODERATE; 326 } else if (mRssi >= -113) { 327 rssiLevel = SIGNAL_STRENGTH_POOR; 328 } else { 329 rssiLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 330 } 331 if (DBG) log("getLteLevel - rssi:" + mRssi + " rssiIconLevel:" + rssiLevel); 332 mLevel = rssiLevel; 333 } 334 } 335 336 /** 337 * Update level with corresponding measure and thresholds. 338 * 339 * @param measure corresponding signal measure 340 * @param thresholds corresponding signal thresholds 341 * @return level of the signal strength 342 */ updateLevelWithMeasure(int measure, int[] thresholds)343 private int updateLevelWithMeasure(int measure, int[] thresholds) { 344 int level; 345 if (measure == CellInfo.UNAVAILABLE) { 346 level = SignalStrength.INVALID; 347 } else if (measure >= thresholds[3]) { 348 level = SIGNAL_STRENGTH_GREAT; 349 } else if (measure >= thresholds[2]) { 350 level = SIGNAL_STRENGTH_GOOD; 351 } else if (measure >= thresholds[1]) { 352 level = SIGNAL_STRENGTH_MODERATE; 353 } else if (measure >= thresholds[0]) { 354 level = SIGNAL_STRENGTH_POOR; 355 } else { 356 level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 357 } 358 return level; 359 } 360 361 /** 362 * Get reference signal received quality 363 * 364 * @return the RSRQ if available or 365 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 366 */ getRsrq()367 public int getRsrq() { 368 return mRsrq; 369 } 370 371 /** 372 * Get Received Signal Strength Indication (RSSI) in dBm 373 * 374 * The value range is [-113, -51] inclusively or {@link CellInfo#UNAVAILABLE} if unavailable. 375 * 376 * Reference: TS 27.007 8.5 Signal quality +CSQ 377 * 378 * @return the RSSI if available or {@link CellInfo#UNAVAILABLE} if unavailable. 379 */ getRssi()380 public int getRssi() { 381 return mRssi; 382 } 383 384 /** 385 * Get reference signal signal-to-noise ratio 386 * 387 * @return the RSSNR if available or 388 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 389 */ getRssnr()390 public int getRssnr() { 391 return mRssnr; 392 } 393 394 /** 395 * Get reference signal received power in dBm 396 * 397 * @return the RSRP of the measured cell. 398 */ getRsrp()399 public int getRsrp() { 400 return mRsrp; 401 } 402 403 /** 404 * Get channel quality indicator 405 * 406 * @return the CQI if available or 407 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 408 */ getCqi()409 public int getCqi() { 410 return mCqi; 411 } 412 413 /** 414 * Get signal strength in dBm 415 * 416 * @return the RSRP of the measured cell. 417 */ 418 @Override getDbm()419 public int getDbm() { 420 return mRsrp; 421 } 422 423 /** 424 * Get the RSRP in ASU. 425 * 426 * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69 427 * 428 * @return RSCP in ASU 0..97, 255, or UNAVAILABLE 429 */ 430 @Override getAsuLevel()431 public int getAsuLevel() { 432 int lteAsuLevel = 99; 433 int lteDbm = mRsrp; 434 if (lteDbm == CellInfo.UNAVAILABLE) lteAsuLevel = 99; 435 else if (lteDbm <= -140) lteAsuLevel = 0; 436 else if (lteDbm >= -43) lteAsuLevel = 97; 437 else lteAsuLevel = lteDbm + 140; 438 if (DBG) log("Lte Asu level: "+lteAsuLevel); 439 return lteAsuLevel; 440 } 441 442 /** 443 * Get the timing advance value for LTE, as a value in range of 0..1282. 444 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} is reported when there is no 445 * active RRC connection. Refer to 3GPP 36.213 Sec 4.2.3 446 * 447 * @return the LTE timing advance if available or 448 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 449 */ getTimingAdvance()450 public int getTimingAdvance() { 451 return mTimingAdvance; 452 } 453 454 @Override hashCode()455 public int hashCode() { 456 return Objects.hash(mRssi, mRsrp, mRsrq, mRssnr, mCqi, mTimingAdvance, mLevel); 457 } 458 459 private static final CellSignalStrengthLte sInvalid = new CellSignalStrengthLte(); 460 461 /** @hide */ 462 @Override isValid()463 public boolean isValid() { 464 return !this.equals(sInvalid); 465 } 466 467 @Override equals(Object o)468 public boolean equals (Object o) { 469 CellSignalStrengthLte s; 470 471 if (!(o instanceof CellSignalStrengthLte)) return false; 472 s = (CellSignalStrengthLte) o; 473 474 return mRssi == s.mRssi 475 && mRsrp == s.mRsrp 476 && mRsrq == s.mRsrq 477 && mRssnr == s.mRssnr 478 && mCqi == s.mCqi 479 && mTimingAdvance == s.mTimingAdvance 480 && mLevel == s.mLevel; 481 } 482 483 /** 484 * @return string representation. 485 */ 486 @Override toString()487 public String toString() { 488 return "CellSignalStrengthLte:" 489 + " rssi=" + mRssi 490 + " rsrp=" + mRsrp 491 + " rsrq=" + mRsrq 492 + " rssnr=" + mRssnr 493 + " cqi=" + mCqi 494 + " ta=" + mTimingAdvance 495 + " level=" + mLevel 496 + " parametersUseForLevel=" + mParametersUseForLevel; 497 } 498 499 /** Implement the Parcelable interface */ 500 @Override writeToParcel(Parcel dest, int flags)501 public void writeToParcel(Parcel dest, int flags) { 502 if (DBG) log("writeToParcel(Parcel, int): " + toString()); 503 dest.writeInt(mRssi); 504 // Need to multiply rsrp and rsrq by -1 505 // to ensure consistency when reading values written here 506 // unless the values are invalid 507 dest.writeInt(mRsrp); 508 dest.writeInt(mRsrq); 509 dest.writeInt(mRssnr); 510 dest.writeInt(mCqi); 511 dest.writeInt(mTimingAdvance); 512 dest.writeInt(mLevel); 513 } 514 515 /** 516 * Construct a SignalStrength object from the given parcel 517 * where the token is already been processed. 518 */ CellSignalStrengthLte(Parcel in)519 private CellSignalStrengthLte(Parcel in) { 520 mRssi = in.readInt(); 521 mSignalStrength = mRssi; 522 mRsrp = in.readInt(); 523 mRsrq = in.readInt(); 524 mRssnr = in.readInt(); 525 mCqi = in.readInt(); 526 mTimingAdvance = in.readInt(); 527 mLevel = in.readInt(); 528 if (DBG) log("CellSignalStrengthLte(Parcel): " + toString()); 529 } 530 531 /** Implement the Parcelable interface */ 532 @Override describeContents()533 public int describeContents() { 534 return 0; 535 } 536 537 /** Implement the Parcelable interface */ 538 @SuppressWarnings("hiding") 539 public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthLte> CREATOR = 540 new Parcelable.Creator<CellSignalStrengthLte>() { 541 @Override 542 public CellSignalStrengthLte createFromParcel(Parcel in) { 543 return new CellSignalStrengthLte(in); 544 } 545 546 @Override 547 public CellSignalStrengthLte[] newArray(int size) { 548 return new CellSignalStrengthLte[size]; 549 } 550 }; 551 552 /** 553 * log 554 */ log(String s)555 private static void log(String s) { 556 Rlog.w(LOG_TAG, s); 557 } 558 convertRssnrUnitFromTenDbToDB(int rssnr)559 private static int convertRssnrUnitFromTenDbToDB(int rssnr) { 560 return rssnr / 10; 561 } 562 convertRssiAsuToDBm(int rssiAsu)563 private static int convertRssiAsuToDBm(int rssiAsu) { 564 if (rssiAsu == SIGNAL_STRENGTH_LTE_RSSI_ASU_UNKNOWN) { 565 return CellInfo.UNAVAILABLE; 566 } 567 if ((rssiAsu < SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MIN_VALUE 568 || rssiAsu > SIGNAL_STRENGTH_LTE_RSSI_VALID_ASU_MAX_VALUE)) { 569 Rlog.e(LOG_TAG, "convertRssiAsuToDBm: invalid RSSI in ASU=" + rssiAsu); 570 return CellInfo.UNAVAILABLE; 571 } 572 return -113 + (2 * rssiAsu); 573 } 574 } 575