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.os.Parcel; 21 import android.os.Parcelable; 22 import android.os.PersistableBundle; 23 24 import com.android.telephony.Rlog; 25 26 import java.util.Objects; 27 28 /** 29 * Signal strength related information. 30 */ 31 public final class CellSignalStrengthCdma extends CellSignalStrength implements Parcelable { 32 33 private static final String LOG_TAG = "CellSignalStrengthCdma"; 34 private static final boolean DBG = false; 35 36 private int mCdmaDbm; // This value is the RSSI value 37 private int mCdmaEcio; // This value is the Ec/Io 38 private int mEvdoDbm; // This value is the EVDO RSSI value 39 private int mEvdoEcio; // This value is the EVDO Ec/Io 40 private int mEvdoSnr; // Valid values are 0-8. 8 is the highest signal to noise ratio 41 private int mLevel; 42 43 /** @hide */ CellSignalStrengthCdma()44 public CellSignalStrengthCdma() { 45 setDefaultValues(); 46 } 47 48 /** 49 * SignalStrength constructor for input from the HAL. 50 * 51 * Note that values received from the HAL require coersion to be compatible here. All values 52 * reported through IRadio are the negative of the actual values (which results in a positive 53 * input to this method. 54 * 55 * <p>Note that this HAL is inconsistent with UMTS-based radio techs as the value indicating 56 * that a field is unreported is negative, rather than a large(r) positive number. 57 * <p>Also note that to keep the public-facing methods of this class consistent with others, 58 * unreported values are coerced to {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} 59 * rather than left as -1, which is a departure from SignalStrength, which is stuck with the 60 * values it currently reports. 61 * 62 * @param cdmaDbm CDMA signal strength value or CellInfo.UNAVAILABLE if invalid. 63 * @param cdmaEcio CDMA pilot/noise ratio or CellInfo.UNAVAILABLE if invalid. 64 * @param evdoDbm negative of the EvDO signal strength value or CellInfo.UNAVAILABLE if invalid. 65 * @param evdoEcio negative of the EvDO pilot/noise ratio or CellInfo.UNAVAILABLE if invalid. 66 * @param evdoSnr an SNR value 0..8 or CellInfo.UNVAILABLE if invalid. 67 * @hide 68 */ CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr)69 public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, 70 int evdoSnr) { 71 mCdmaDbm = inRangeOrUnavailable(cdmaDbm, -120, 0); 72 mCdmaEcio = inRangeOrUnavailable(cdmaEcio, -160, 0); 73 mEvdoDbm = inRangeOrUnavailable(evdoDbm, -120, 0); 74 mEvdoEcio = inRangeOrUnavailable(evdoEcio, -160, 0); 75 mEvdoSnr = inRangeOrUnavailable(evdoSnr, 0, 8); 76 77 updateLevel(null, null); 78 } 79 80 /** @hide */ CellSignalStrengthCdma(CellSignalStrengthCdma s)81 public CellSignalStrengthCdma(CellSignalStrengthCdma s) { 82 copyFrom(s); 83 } 84 85 /** @hide */ copyFrom(CellSignalStrengthCdma s)86 protected void copyFrom(CellSignalStrengthCdma s) { 87 mCdmaDbm = s.mCdmaDbm; 88 mCdmaEcio = s.mCdmaEcio; 89 mEvdoDbm = s.mEvdoDbm; 90 mEvdoEcio = s.mEvdoEcio; 91 mEvdoSnr = s.mEvdoSnr; 92 mLevel = s.mLevel; 93 } 94 95 /** @hide */ 96 @Override copy()97 public CellSignalStrengthCdma copy() { 98 return new CellSignalStrengthCdma(this); 99 } 100 101 /** @hide */ 102 @Override setDefaultValues()103 public void setDefaultValues() { 104 mCdmaDbm = CellInfo.UNAVAILABLE; 105 mCdmaEcio = CellInfo.UNAVAILABLE; 106 mEvdoDbm = CellInfo.UNAVAILABLE; 107 mEvdoEcio = CellInfo.UNAVAILABLE; 108 mEvdoSnr = CellInfo.UNAVAILABLE; 109 mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 110 } 111 112 /** {@inheritDoc} */ 113 @Override 114 @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT) getLevel()115 public int getLevel() { 116 return mLevel; 117 } 118 119 /** @hide */ 120 @Override updateLevel(PersistableBundle cc, ServiceState ss)121 public void updateLevel(PersistableBundle cc, ServiceState ss) { 122 int cdmaLevel = getCdmaLevel(); 123 int evdoLevel = getEvdoLevel(); 124 if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { 125 /* We don't know evdo, use cdma */ 126 mLevel = getCdmaLevel(); 127 } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { 128 /* We don't know cdma, use evdo */ 129 mLevel = getEvdoLevel(); 130 } else { 131 /* We know both, use the lowest level */ 132 mLevel = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel; 133 } 134 } 135 136 /** 137 * Get the 1xRTT Level in (Android) ASU. 138 * 139 * There is no standard definition of ASU for CDMA; however, Android defines it as the 140 * the lesser of the following two results (for 1xRTT): 141 * <table> 142 * <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead> 143 * <tbody> 144 * <tr><td>-75..</td><td>16</td></tr> 145 * <tr><td>-82..-76</td><td>8</td></tr> 146 * <tr><td>-90..-83</td><td>4</td></tr> 147 * <tr><td>-95..-91</td><td>2</td></tr> 148 * <tr><td>-100..-96</td><td>1</td></tr> 149 * <tr><td>..-101</td><td>99</td></tr> 150 * </tbody> 151 * </table> 152 * <table> 153 * <thead><tr><th>Ec/Io Range (dB)</th><th>ASU Value</th></tr><thead> 154 * <tbody> 155 * <tr><td>-90..</td><td>16</td></tr> 156 * <tr><td>-100..-91</td><td>8</td></tr> 157 * <tr><td>-115..-101</td><td>4</td></tr> 158 * <tr><td>-130..-116</td><td>2</td></tr> 159 * <tr><td>--150..-131</td><td>1</td></tr> 160 * <tr><td>..-151</td><td>99</td></tr> 161 * </tbody> 162 * </table> 163 * @return 1xRTT Level in Android ASU {1,2,4,8,16,99} 164 */ 165 @Override 166 public int getAsuLevel() { 167 final int cdmaDbm = getCdmaDbm(); 168 final int cdmaEcio = getCdmaEcio(); 169 int cdmaAsuLevel; 170 int ecioAsuLevel; 171 172 if (cdmaDbm == CellInfo.UNAVAILABLE) cdmaAsuLevel = 99; 173 else if (cdmaDbm >= -75) cdmaAsuLevel = 16; 174 else if (cdmaDbm >= -82) cdmaAsuLevel = 8; 175 else if (cdmaDbm >= -90) cdmaAsuLevel = 4; 176 else if (cdmaDbm >= -95) cdmaAsuLevel = 2; 177 else if (cdmaDbm >= -100) cdmaAsuLevel = 1; 178 else cdmaAsuLevel = 99; 179 180 // Ec/Io are in dB*10 181 if (cdmaEcio == CellInfo.UNAVAILABLE) ecioAsuLevel = 99; 182 else if (cdmaEcio >= -90) ecioAsuLevel = 16; 183 else if (cdmaEcio >= -100) ecioAsuLevel = 8; 184 else if (cdmaEcio >= -115) ecioAsuLevel = 4; 185 else if (cdmaEcio >= -130) ecioAsuLevel = 2; 186 else if (cdmaEcio >= -150) ecioAsuLevel = 1; 187 else ecioAsuLevel = 99; 188 189 int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel; 190 if (DBG) log("getAsuLevel=" + level); 191 return level; 192 } 193 194 /** 195 * Get cdma as level 0..4 196 */ getCdmaLevel()197 public int getCdmaLevel() { 198 final int cdmaDbm = getCdmaDbm(); 199 final int cdmaEcio = getCdmaEcio(); 200 int levelDbm; 201 int levelEcio; 202 203 if (cdmaDbm == CellInfo.UNAVAILABLE) levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 204 else if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT; 205 else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD; 206 else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE; 207 else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR; 208 else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 209 210 // Ec/Io are in dB*10 211 if (cdmaEcio == CellInfo.UNAVAILABLE) levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 212 else if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT; 213 else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD; 214 else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE; 215 else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR; 216 else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 217 218 int level = (levelDbm < levelEcio) ? levelDbm : levelEcio; 219 if (DBG) log("getCdmaLevel=" + level); 220 return level; 221 } 222 223 /** 224 * Get Evdo as level 0..4 225 */ getEvdoLevel()226 public int getEvdoLevel() { 227 int evdoDbm = getEvdoDbm(); 228 int evdoSnr = getEvdoSnr(); 229 int levelEvdoDbm; 230 int levelEvdoSnr; 231 232 if (evdoDbm == CellInfo.UNAVAILABLE) levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 233 else if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT; 234 else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD; 235 else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE; 236 else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR; 237 else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 238 239 if (evdoSnr == CellInfo.UNAVAILABLE) levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 240 else if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT; 241 else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD; 242 else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE; 243 else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR; 244 else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN; 245 246 int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; 247 if (DBG) log("getEvdoLevel=" + level); 248 return level; 249 } 250 251 /** 252 * Get the EVDO Level in (Android) ASU. 253 * 254 * There is no standard definition of ASU for CDMA; however, Android defines it as the 255 * the lesser of the following two results (for EVDO): 256 * <table> 257 * <thead><tr><th>RSSI Range (dBm)</th><th>ASU Value</th></tr><thead> 258 * <tbody> 259 * <tr><td>-65..</td><td>16</td></tr> 260 * <tr><td>-75..-66</td><td>8</td></tr> 261 * <tr><td>-85..-76</td><td>4</td></tr> 262 * <tr><td>-95..-86</td><td>2</td></tr> 263 * <tr><td>-105..-96</td><td>1</td></tr> 264 * <tr><td>..-106</td><td>99</td></tr> 265 * </tbody> 266 * </table> 267 * <table> 268 * <thead><tr><th>SNR Range (unitless)</th><th>ASU Value</th></tr><thead> 269 * <tbody> 270 * <tr><td>7..</td><td>16</td></tr> 271 * <tr><td>6</td><td>8</td></tr> 272 * <tr><td>5</td><td>4</td></tr> 273 * <tr><td>3..4</td><td>2</td></tr> 274 * <tr><td>1..2</td><td>1</td></tr> 275 * <tr><td>0</td><td>99</td></tr> 276 * </tbody> 277 * </table> 278 * 279 * @return EVDO Level in Android ASU {1,2,4,8,16,99} 280 * 281 * @hide 282 */ getEvdoAsuLevel()283 public int getEvdoAsuLevel() { 284 int evdoDbm = getEvdoDbm(); 285 int evdoSnr = getEvdoSnr(); 286 int levelEvdoDbm; 287 int levelEvdoSnr; 288 289 if (evdoDbm >= -65) levelEvdoDbm = 16; 290 else if (evdoDbm >= -75) levelEvdoDbm = 8; 291 else if (evdoDbm >= -85) levelEvdoDbm = 4; 292 else if (evdoDbm >= -95) levelEvdoDbm = 2; 293 else if (evdoDbm >= -105) levelEvdoDbm = 1; 294 else levelEvdoDbm = 99; 295 296 if (evdoSnr >= 7) levelEvdoSnr = 16; 297 else if (evdoSnr >= 6) levelEvdoSnr = 8; 298 else if (evdoSnr >= 5) levelEvdoSnr = 4; 299 else if (evdoSnr >= 3) levelEvdoSnr = 2; 300 else if (evdoSnr >= 1) levelEvdoSnr = 1; 301 else levelEvdoSnr = 99; 302 303 int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr; 304 if (DBG) log("getEvdoAsuLevel=" + level); 305 return level; 306 } 307 308 /** 309 * Get the signal strength as dBm 310 * 311 * @return min(CDMA RSSI, EVDO RSSI) of the measured cell. 312 */ 313 @Override getDbm()314 public int getDbm() { 315 int cdmaDbm = getCdmaDbm(); 316 int evdoDbm = getEvdoDbm(); 317 318 // Use the lower value to be conservative 319 return (cdmaDbm < evdoDbm) ? cdmaDbm : evdoDbm; 320 } 321 322 /** 323 * Get the CDMA RSSI value in dBm 324 */ getCdmaDbm()325 public int getCdmaDbm() { 326 return mCdmaDbm; 327 } 328 329 /** @hide */ setCdmaDbm(int cdmaDbm)330 public void setCdmaDbm(int cdmaDbm) { 331 mCdmaDbm = cdmaDbm; 332 } 333 334 /** 335 * Get the CDMA Ec/Io value in dB*10 336 */ getCdmaEcio()337 public int getCdmaEcio() { 338 return mCdmaEcio; 339 } 340 341 /** @hide */ setCdmaEcio(int cdmaEcio)342 public void setCdmaEcio(int cdmaEcio) { 343 mCdmaEcio = cdmaEcio; 344 } 345 346 /** 347 * Get the EVDO RSSI value in dBm 348 */ getEvdoDbm()349 public int getEvdoDbm() { 350 return mEvdoDbm; 351 } 352 353 /** @hide */ setEvdoDbm(int evdoDbm)354 public void setEvdoDbm(int evdoDbm) { 355 mEvdoDbm = evdoDbm; 356 } 357 358 /** 359 * Get the EVDO Ec/Io value in dB*10 360 */ getEvdoEcio()361 public int getEvdoEcio() { 362 return mEvdoEcio; 363 } 364 365 /** @hide */ setEvdoEcio(int evdoEcio)366 public void setEvdoEcio(int evdoEcio) { 367 mEvdoEcio = evdoEcio; 368 } 369 370 /** 371 * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest. 372 */ getEvdoSnr()373 public int getEvdoSnr() { 374 return mEvdoSnr; 375 } 376 377 /** @hide */ setEvdoSnr(int evdoSnr)378 public void setEvdoSnr(int evdoSnr) { 379 mEvdoSnr = evdoSnr; 380 } 381 382 @Override hashCode()383 public int hashCode() { 384 return Objects.hash(mCdmaDbm, mCdmaEcio, mEvdoDbm, mEvdoEcio, mEvdoSnr, mLevel); 385 } 386 387 private static final CellSignalStrengthCdma sInvalid = new CellSignalStrengthCdma(); 388 389 /** @hide */ 390 @Override isValid()391 public boolean isValid() { 392 return !this.equals(sInvalid); 393 } 394 395 @Override equals(Object o)396 public boolean equals (Object o) { 397 CellSignalStrengthCdma s; 398 if (!(o instanceof CellSignalStrengthCdma)) return false; 399 s = (CellSignalStrengthCdma) o; 400 401 return mCdmaDbm == s.mCdmaDbm 402 && mCdmaEcio == s.mCdmaEcio 403 && mEvdoDbm == s.mEvdoDbm 404 && mEvdoEcio == s.mEvdoEcio 405 && mEvdoSnr == s.mEvdoSnr 406 && mLevel == s.mLevel; 407 } 408 409 /** 410 * @return string representation. 411 */ 412 @Override toString()413 public String toString() { 414 return "CellSignalStrengthCdma:" 415 + " cdmaDbm=" + mCdmaDbm 416 + " cdmaEcio=" + mCdmaEcio 417 + " evdoDbm=" + mEvdoDbm 418 + " evdoEcio=" + mEvdoEcio 419 + " evdoSnr=" + mEvdoSnr 420 + " level=" + mLevel; 421 } 422 423 /** Implement the Parcelable interface */ 424 @Override writeToParcel(Parcel dest, int flags)425 public void writeToParcel(Parcel dest, int flags) { 426 if (DBG) log("writeToParcel(Parcel, int): " + toString()); 427 dest.writeInt(mCdmaDbm); 428 dest.writeInt(mCdmaEcio); 429 dest.writeInt(mEvdoDbm); 430 dest.writeInt(mEvdoEcio); 431 dest.writeInt(mEvdoSnr); 432 dest.writeInt(mLevel); 433 } 434 435 /** 436 * Construct a SignalStrength object from the given parcel 437 * where the TYPE_CDMA token is already been processed. 438 */ CellSignalStrengthCdma(Parcel in)439 private CellSignalStrengthCdma(Parcel in) { 440 // CdmaDbm, CdmaEcio, EvdoDbm and EvdoEcio are written into 441 // the parcel as positive values. 442 // Need to convert into negative values unless the value is invalid 443 mCdmaDbm = in.readInt(); 444 mCdmaEcio = in.readInt(); 445 mEvdoDbm = in.readInt(); 446 mEvdoEcio = in.readInt(); 447 mEvdoSnr = in.readInt(); 448 mLevel = in.readInt(); 449 if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString()); 450 } 451 452 /** Implement the Parcelable interface */ 453 @Override describeContents()454 public int describeContents() { 455 return 0; 456 } 457 458 /** Implement the Parcelable interface */ 459 @SuppressWarnings("hiding") 460 public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthCdma> CREATOR = 461 new Parcelable.Creator<CellSignalStrengthCdma>() { 462 @Override 463 public CellSignalStrengthCdma createFromParcel(Parcel in) { 464 return new CellSignalStrengthCdma(in); 465 } 466 467 @Override 468 public CellSignalStrengthCdma[] newArray(int size) { 469 return new CellSignalStrengthCdma[size]; 470 } 471 }; 472 473 /** 474 * log 475 */ log(String s)476 private static void log(String s) { 477 Rlog.w(LOG_TAG, s); 478 } 479 } 480