1 /* 2 * Copyright (C) 2018 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.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.os.PersistableBundle; 25 26 import com.android.telephony.Rlog; 27 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 import java.util.Arrays; 31 import java.util.Collections; 32 import java.util.List; 33 import java.util.Objects; 34 import java.util.stream.Collectors; 35 36 /** 37 * 5G NR signal strength related information. 38 */ 39 public final class CellSignalStrengthNr extends CellSignalStrength implements Parcelable { 40 /** 41 * The value is used to indicate that the asu level is unknown. 42 * Reference: 3GPP TS 27.007 section 8.69. 43 * @hide 44 */ 45 public static final int UNKNOWN_ASU_LEVEL = 99; 46 47 private static final boolean VDBG = false; 48 49 private static final String TAG = "CellSignalStrengthNr"; 50 51 // Lifted from Default carrier configs and max range of SSRSRP 52 // Boundaries: [-156 dB, -31 dB] 53 private int[] mSsRsrpThresholds = new int[] { 54 -110, /* SIGNAL_STRENGTH_POOR */ 55 -90, /* SIGNAL_STRENGTH_MODERATE */ 56 -80, /* SIGNAL_STRENGTH_GOOD */ 57 -65, /* SIGNAL_STRENGTH_GREAT */ 58 }; 59 60 // Lifted from Default carrier configs and max range of SSRSRQ 61 // Boundaries: [-43 dB, 20 dB] 62 private int[] mSsRsrqThresholds = new int[] { 63 -31, /* SIGNAL_STRENGTH_POOR */ 64 -19, /* SIGNAL_STRENGTH_MODERATE */ 65 -7, /* SIGNAL_STRENGTH_GOOD */ 66 6 /* SIGNAL_STRENGTH_GREAT */ 67 }; 68 69 // Lifted from Default carrier configs and max range of SSSINR 70 // Boundaries: [-23 dB, 40 dB] 71 private int[] mSsSinrThresholds = new int[] { 72 -5, /* SIGNAL_STRENGTH_POOR */ 73 5, /* SIGNAL_STRENGTH_MODERATE */ 74 15, /* SIGNAL_STRENGTH_GOOD */ 75 30 /* SIGNAL_STRENGTH_GREAT */ 76 }; 77 78 /** 79 * Indicates SSRSRP is considered for {@link #getLevel()} and reporting from modem. 80 * 81 * @hide 82 */ 83 public static final int USE_SSRSRP = 1 << 0; 84 /** 85 * Indicates SSRSRQ is considered for {@link #getLevel()} and reporting from modem. 86 * 87 * @hide 88 */ 89 public static final int USE_SSRSRQ = 1 << 1; 90 /** 91 * Indicates SSSINR is considered for {@link #getLevel()} and reporting from modem. 92 * 93 * @hide 94 */ 95 public static final int USE_SSSINR = 1 << 2; 96 97 /** 98 * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP), 99 * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference 100 * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the 101 * parameter whose value is smallest is used to indicate the signal bar. 102 * 103 * @hide 104 */ 105 @IntDef(flag = true, prefix = { "USE_" }, value = { 106 USE_SSRSRP, 107 USE_SSRSRQ, 108 USE_SSSINR 109 }) 110 @Retention(RetentionPolicy.SOURCE) 111 public @interface SignalLevelAndReportCriteriaSource {} 112 113 private int mCsiRsrp; 114 private int mCsiRsrq; 115 private int mCsiSinr; 116 /** 117 * CSI channel quality indicator (CQI) table index. There are multiple CQI tables. 118 * The definition of CQI in each table is different. 119 * 120 * Reference: 3GPP TS 138.214 section 5.2.2.1. 121 * 122 * Range [1, 3]. 123 */ 124 private int mCsiCqiTableIndex; 125 /** 126 * CSI channel quality indicators (CQI) for all subbands. 127 * 128 * If the CQI report is for the entire wideband, a single CQI index is provided. 129 * If the CQI report is for all subbands, one CQI index is provided for each subband, 130 * in ascending order of subband index. 131 * If CQI is not available, the CQI report is empty. 132 * 133 * Reference: 3GPP TS 138.214 section 5.2.2.1. 134 * 135 * Range [0, 15] for each CQI. 136 */ 137 private List<Integer> mCsiCqiReport; 138 private int mSsRsrp; 139 private int mSsRsrq; 140 private int mSsSinr; 141 private int mLevel; 142 143 /** 144 * Bit-field integer to determine whether to use SS reference signal received power (SSRSRP), 145 * SS reference signal received quality (SSRSRQ), or/and SS signal-to-noise and interference 146 * ratio (SSSINR) for the number of 5G NR signal bars. If multiple measures are set bit, the 147 * parameter whose value is smallest is used to indicate the signal bar. 148 * 149 * SSRSRP = 1 << 0, 150 * SSRSRQ = 1 << 1, 151 * SSSINR = 1 << 2, 152 * 153 * For example, if both SSRSRP and SSSINR are used, the value of key is 5 (1 << 0 | 1 << 2). 154 * If the key is invalid or not configured, a default value (SSRSRP = 1 << 0) will apply. 155 */ 156 private int mParametersUseForLevel; 157 158 /** @hide */ CellSignalStrengthNr()159 public CellSignalStrengthNr() { 160 setDefaultValues(); 161 } 162 163 /** 164 * @param csiRsrp CSI reference signal received power. 165 * @param csiRsrq CSI reference signal received quality. 166 * @param csiSinr CSI signal-to-noise and interference ratio. 167 * @param csiCqiTableIndex CSI CSI channel quality indicator (CQI) table index. 168 * @param csiCqiReport CSI channel quality indicators (CQI) for all subbands. 169 * @param ssRsrp SS reference signal received power. 170 * @param ssRsrq SS reference signal received quality. 171 * @param ssSinr SS signal-to-noise and interference ratio. 172 * @hide 173 */ CellSignalStrengthNr(int csiRsrp, int csiRsrq, int csiSinr, int csiCqiTableIndex, List<Byte> csiCqiReport, int ssRsrp, int ssRsrq, int ssSinr)174 public CellSignalStrengthNr(int csiRsrp, int csiRsrq, int csiSinr, int csiCqiTableIndex, 175 List<Byte> csiCqiReport, int ssRsrp, int ssRsrq, int ssSinr) { 176 mCsiRsrp = inRangeOrUnavailable(csiRsrp, -156, -31); 177 mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3); 178 mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23); 179 mCsiCqiTableIndex = inRangeOrUnavailable(csiCqiTableIndex, 1, 3); 180 mCsiCqiReport = csiCqiReport.stream() 181 .map(cqi -> inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 0, 15)) 182 .collect(Collectors.toList()); 183 mSsRsrp = inRangeOrUnavailable(ssRsrp, -156, -31); 184 mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20); 185 mSsSinr = inRangeOrUnavailable(ssSinr, -23, 40); 186 updateLevel(null, null); 187 } 188 189 /** 190 * @param csiRsrp CSI reference signal received power. 191 * @param csiRsrq CSI reference signal received quality. 192 * @param csiSinr CSI signal-to-noise and interference ratio. 193 * @param ssRsrp SS reference signal received power. 194 * @param ssRsrq SS reference signal received quality. 195 * @param ssSinr SS signal-to-noise and interference ratio. 196 * @hide 197 */ CellSignalStrengthNr( int csiRsrp, int csiRsrq, int csiSinr, int ssRsrp, int ssRsrq, int ssSinr)198 public CellSignalStrengthNr( 199 int csiRsrp, int csiRsrq, int csiSinr, int ssRsrp, int ssRsrq, int ssSinr) { 200 this(csiRsrp, csiRsrq, csiSinr, CellInfo.UNAVAILABLE, Collections.emptyList(), 201 ssRsrp, ssRsrq, ssSinr); 202 } 203 204 /** 205 * Flip sign cell strength value when taking in the value from hal 206 * @param val cell strength value 207 * @return flipped value 208 * @hide 209 */ flip(int val)210 public static int flip(int val) { 211 return val != CellInfo.UNAVAILABLE ? -val : val; 212 } 213 214 /** 215 * Reference: 3GPP TS 38.133 10.1.6.1. 216 * Range: -156 dBm to -31 dBm. 217 * @return SS reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported 218 * value. 219 */ getSsRsrp()220 public int getSsRsrp() { 221 return mSsRsrp; 222 } 223 224 /** 225 * Reference: 3GPP TS 38.215; 3GPP TS 38.133 section 10 226 * Range: -43 dB to 20 dB. 227 * @return SS reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported 228 * value. 229 */ getSsRsrq()230 public int getSsRsrq() { 231 return mSsRsrq; 232 } 233 234 /** 235 * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1 236 * Range: -23 dB to 40 dB 237 * @return SS signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means 238 * unreported value. 239 */ getSsSinr()240 public int getSsSinr() { 241 return mSsSinr; 242 } 243 244 /** 245 * Reference: 3GPP TS 38.133 10.1.6.1. 246 * Range: -156 dBm to -31 dBm. 247 * @return CSI reference signal received power, {@link CellInfo#UNAVAILABLE} means unreported 248 * value. 249 */ getCsiRsrp()250 public int getCsiRsrp() { 251 return mCsiRsrp; 252 } 253 254 /** 255 * Reference: 3GPP TS 38.215. 256 * Range: -20 dB to -3 dB. 257 * @return CSI reference signal received quality, {@link CellInfo#UNAVAILABLE} means unreported 258 * value. 259 */ getCsiRsrq()260 public int getCsiRsrq() { 261 return mCsiRsrq; 262 } 263 264 /** 265 * Reference: 3GPP TS 38.215 Sec 5.1.*, 3GPP TS 38.133 10.1.16.1 266 * Range: -23 dB to 23 dB 267 * @return CSI signal-to-noise and interference ratio, {@link CellInfo#UNAVAILABLE} means 268 * unreported value. 269 */ getCsiSinr()270 public int getCsiSinr() { 271 return mCsiSinr; 272 } 273 274 /** 275 * Return CSI channel quality indicator (CQI) table index. There are multiple CQI tables. 276 * The definition of CQI in each table is different. 277 * 278 * Reference: 3GPP TS 138.214 section 5.2.2.1. 279 * 280 * @return the CQI table index if available or 281 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 282 */ 283 @IntRange(from = 1, to = 3) getCsiCqiTableIndex()284 public int getCsiCqiTableIndex() { 285 return mCsiCqiTableIndex; 286 } 287 /** 288 * Return a list of CSI channel quality indicators (CQI) for all subbands. 289 * 290 * If the CQI report is for the entire wideband, a single CQI index is provided. 291 * If the CQI report is for all subbands, one CQI index is provided for each subband, 292 * in ascending order of subband index. 293 * If CQI is not available, the CQI report is empty. 294 * 295 * Reference: 3GPP TS 138.214 section 5.2.2.1. 296 * 297 * @return the CQIs for all subbands if available or empty list if unavailable. 298 */ 299 @NonNull 300 @IntRange(from = 0, to = 15) getCsiCqiReport()301 public List<Integer> getCsiCqiReport() { 302 return mCsiCqiReport; 303 } 304 305 @Override describeContents()306 public int describeContents() { 307 return 0; 308 } 309 310 /** @hide */ 311 @Override writeToParcel(Parcel dest, int flags)312 public void writeToParcel(Parcel dest, int flags) { 313 dest.writeInt(mCsiRsrp); 314 dest.writeInt(mCsiRsrq); 315 dest.writeInt(mCsiSinr); 316 dest.writeInt(mCsiCqiTableIndex); 317 dest.writeList(mCsiCqiReport); 318 dest.writeInt(mSsRsrp); 319 dest.writeInt(mSsRsrq); 320 dest.writeInt(mSsSinr); 321 dest.writeInt(mLevel); 322 } 323 CellSignalStrengthNr(Parcel in)324 private CellSignalStrengthNr(Parcel in) { 325 mCsiRsrp = in.readInt(); 326 mCsiRsrq = in.readInt(); 327 mCsiSinr = in.readInt(); 328 mCsiCqiTableIndex = in.readInt(); 329 mCsiCqiReport = in.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class); 330 mSsRsrp = in.readInt(); 331 mSsRsrq = in.readInt(); 332 mSsSinr = in.readInt(); 333 mLevel = in.readInt(); 334 } 335 336 /** @hide */ 337 @Override setDefaultValues()338 public void setDefaultValues() { 339 mCsiRsrp = CellInfo.UNAVAILABLE; 340 mCsiRsrq = CellInfo.UNAVAILABLE; 341 mCsiSinr = CellInfo.UNAVAILABLE; 342 mCsiCqiTableIndex = CellInfo.UNAVAILABLE; 343 mCsiCqiReport = Collections.emptyList(); 344 mSsRsrp = CellInfo.UNAVAILABLE; 345 mSsRsrq = CellInfo.UNAVAILABLE; 346 mSsSinr = CellInfo.UNAVAILABLE; 347 mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 348 mParametersUseForLevel = USE_SSRSRP; 349 } 350 351 /** {@inheritDoc} */ 352 @Override 353 @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT) getLevel()354 public int getLevel() { 355 return mLevel; 356 } 357 358 /** 359 * Checks if the given parameter type is considered to use for {@link #getLevel()}. 360 * 361 * Note: if multiple parameter types are considered, the smaller level for one of the 362 * parameters would be returned by {@link #getLevel()} 363 * 364 * @param parameterType bitwise OR of {@link #USE_SSRSRP}, {@link #USE_SSRSRQ}, 365 * {@link #USE_SSSINR} 366 * @return {@code true} if the level is calculated based on the given parameter type; 367 * {@code false} otherwise. 368 * 369 */ isLevelForParameter(@ignalLevelAndReportCriteriaSource int parameterType)370 private boolean isLevelForParameter(@SignalLevelAndReportCriteriaSource int parameterType) { 371 return (parameterType & mParametersUseForLevel) == parameterType; 372 } 373 374 /** @hide */ 375 @Override updateLevel(PersistableBundle cc, ServiceState ss)376 public void updateLevel(PersistableBundle cc, ServiceState ss) { 377 if (cc == null) { 378 mParametersUseForLevel = USE_SSRSRP; 379 } else { 380 mParametersUseForLevel = cc.getInt( 381 CarrierConfigManager.KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT, USE_SSRSRP); 382 mSsRsrpThresholds = cc.getIntArray( 383 CarrierConfigManager.KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY); 384 if (VDBG) { 385 Rlog.i(TAG, "Applying 5G NR SSRSRP Thresholds: " 386 + Arrays.toString(mSsRsrpThresholds)); 387 } 388 mSsRsrqThresholds = cc.getIntArray( 389 CarrierConfigManager.KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY); 390 if (VDBG) { 391 Rlog.i(TAG, "Applying 5G NR SSRSRQ Thresholds: " 392 + Arrays.toString(mSsRsrqThresholds)); 393 } 394 mSsSinrThresholds = cc.getIntArray( 395 CarrierConfigManager.KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY); 396 if (VDBG) { 397 Rlog.i(TAG, "Applying 5G NR SSSINR Thresholds: " 398 + Arrays.toString(mSsSinrThresholds)); 399 } 400 } 401 int ssRsrpLevel = SignalStrength.INVALID; 402 int ssRsrqLevel = SignalStrength.INVALID; 403 int ssSinrLevel = SignalStrength.INVALID; 404 if (isLevelForParameter(USE_SSRSRP)) { 405 int rsrpBoost = 0; 406 if (ss != null) { 407 rsrpBoost = ss.getArfcnRsrpBoost(); 408 } 409 ssRsrpLevel = updateLevelWithMeasure(mSsRsrp + rsrpBoost, mSsRsrpThresholds); 410 if (VDBG) { 411 Rlog.i(TAG, "Updated 5G NR SSRSRP Level: " + ssRsrpLevel); 412 } 413 } 414 if (isLevelForParameter(USE_SSRSRQ)) { 415 ssRsrqLevel = updateLevelWithMeasure(mSsRsrq, mSsRsrqThresholds); 416 if (VDBG) { 417 Rlog.i(TAG, "Updated 5G NR SSRSRQ Level: " + ssRsrqLevel); 418 } 419 } 420 if (isLevelForParameter(USE_SSSINR)) { 421 ssSinrLevel = updateLevelWithMeasure(mSsSinr, mSsSinrThresholds); 422 if (VDBG) { 423 Rlog.i(TAG, "Updated 5G NR SSSINR Level: " + ssSinrLevel); 424 } 425 } 426 // Apply the smaller value among three levels of three measures. 427 mLevel = Math.min(Math.min(ssRsrpLevel, ssRsrqLevel), ssSinrLevel); 428 } 429 430 /** 431 * Update level with corresponding measure and thresholds. 432 * 433 * @param measure corresponding signal measure 434 * @param thresholds corresponding signal thresholds 435 * @return level of the signal strength 436 */ updateLevelWithMeasure(int measure, int[] thresholds)437 private int updateLevelWithMeasure(int measure, int[] thresholds) { 438 int level; 439 if (measure == CellInfo.UNAVAILABLE) { 440 level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 441 } else if (measure >= thresholds[3]) { 442 level = SIGNAL_STRENGTH_GREAT; 443 } else if (measure >= thresholds[2]) { 444 level = SIGNAL_STRENGTH_GOOD; 445 } else if (measure >= thresholds[1]) { 446 level = SIGNAL_STRENGTH_MODERATE; 447 } else if (measure >= thresholds[0]) { 448 level = SIGNAL_STRENGTH_POOR; 449 } else { 450 level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 451 } 452 return level; 453 } 454 455 /** 456 * Get the RSRP in ASU. 457 * 458 * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69 459 * 460 * @return RSRP in ASU 0..97, 255, or UNAVAILABLE 461 */ 462 @Override getAsuLevel()463 public int getAsuLevel() { 464 int asuLevel; 465 int nrDbm = getDbm(); 466 if (nrDbm == CellInfo.UNAVAILABLE) { 467 asuLevel = UNKNOWN_ASU_LEVEL; 468 } else if (nrDbm <= -140) { 469 asuLevel = 0; 470 } else if (nrDbm >= -43) { 471 asuLevel = 97; 472 } else { 473 asuLevel = nrDbm + 140; 474 } 475 return asuLevel; 476 } 477 478 /** 479 * Get the SS-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}. 480 */ 481 @Override getDbm()482 public int getDbm() { 483 return mSsRsrp; 484 } 485 486 /** @hide */ CellSignalStrengthNr(CellSignalStrengthNr s)487 public CellSignalStrengthNr(CellSignalStrengthNr s) { 488 mCsiRsrp = s.mCsiRsrp; 489 mCsiRsrq = s.mCsiRsrq; 490 mCsiSinr = s.mCsiSinr; 491 mCsiCqiTableIndex = s.mCsiCqiTableIndex; 492 mCsiCqiReport = s.mCsiCqiReport; 493 mSsRsrp = s.mSsRsrp; 494 mSsRsrq = s.mSsRsrq; 495 mSsSinr = s.mSsSinr; 496 mLevel = s.mLevel; 497 mParametersUseForLevel = s.mParametersUseForLevel; 498 } 499 500 /** @hide */ 501 @Override copy()502 public CellSignalStrengthNr copy() { 503 return new CellSignalStrengthNr(this); 504 } 505 506 @Override hashCode()507 public int hashCode() { 508 return Objects.hash(mCsiRsrp, mCsiRsrq, mCsiSinr, mCsiCqiTableIndex, 509 mCsiCqiReport, mSsRsrp, mSsRsrq, mSsSinr, mLevel); 510 } 511 512 private static final CellSignalStrengthNr sInvalid = new CellSignalStrengthNr(); 513 514 /** @hide */ 515 @Override isValid()516 public boolean isValid() { 517 return !this.equals(sInvalid); 518 } 519 520 @Override equals(Object obj)521 public boolean equals(Object obj) { 522 if (obj instanceof CellSignalStrengthNr) { 523 CellSignalStrengthNr o = (CellSignalStrengthNr) obj; 524 return mCsiRsrp == o.mCsiRsrp && mCsiRsrq == o.mCsiRsrq && mCsiSinr == o.mCsiSinr 525 && mCsiCqiTableIndex == o.mCsiCqiTableIndex 526 && mCsiCqiReport.equals(o.mCsiCqiReport) 527 && mSsRsrp == o.mSsRsrp && mSsRsrq == o.mSsRsrq && mSsSinr == o.mSsSinr 528 && mLevel == o.mLevel; 529 } 530 return false; 531 } 532 533 @Override toString()534 public String toString() { 535 return new StringBuilder() 536 .append(TAG + ":{") 537 .append(" csiRsrp = " + mCsiRsrp) 538 .append(" csiRsrq = " + mCsiRsrq) 539 .append(" csiCqiTableIndex = " + mCsiCqiTableIndex) 540 .append(" csiCqiReport = " + mCsiCqiReport) 541 .append(" ssRsrp = " + mSsRsrp) 542 .append(" ssRsrq = " + mSsRsrq) 543 .append(" ssSinr = " + mSsSinr) 544 .append(" level = " + mLevel) 545 .append(" parametersUseForLevel = " + mParametersUseForLevel) 546 .append(" }") 547 .toString(); 548 } 549 550 /** Implement the Parcelable interface */ 551 public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthNr> CREATOR = 552 new Parcelable.Creator<CellSignalStrengthNr>() { 553 @Override 554 public CellSignalStrengthNr createFromParcel(Parcel in) { 555 return new CellSignalStrengthNr(in); 556 } 557 558 @Override 559 public CellSignalStrengthNr[] newArray(int size) { 560 return new CellSignalStrengthNr[size]; 561 } 562 }; 563 } 564