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