2 * Copyright (C) 2009 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 * Copyright (C) 2009 The Android Open Source Project
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package android.telephony;
20 import android.os.Bundle;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.util.Log;
26 * Contains phone signal strength related information.
28 public class SignalStrength implements Parcelable {
30 private static final String LOG_TAG = "SignalStrength";
31 private static final boolean DBG = false;
34 public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
36 public static final int SIGNAL_STRENGTH_POOR = 1;
38 public static final int SIGNAL_STRENGTH_MODERATE = 2;
40 public static final int SIGNAL_STRENGTH_GOOD = 3;
42 public static final int SIGNAL_STRENGTH_GREAT = 4;
44 public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
46 public static final String[] SIGNAL_STRENGTH_NAMES = {
47 "none", "poor", "moderate", "good", "great"
50 private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
51 private int mGsmBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5
52 private int mCdmaDbm; // This value is the RSSI value
53 private int mCdmaEcio; // This value is the Ec/Io
54 private int mEvdoDbm; // This value is the EVDO RSSI value
55 private int mEvdoEcio; // This value is the EVDO Ec/Io
56 private int mEvdoSnr; // Valid values are 0-8. 8 is the highest signal to noise ratio
57 private int mLteSignalStrength;
60 private int mLteRssnr;
63 private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
66 * Create a new SignalStrength from a intent notifier Bundle
68 * This method is used by PhoneStateIntentReceiver and maybe by
69 * external applications.
71 * @param m Bundle from intent notifier
72 * @return newly created SignalStrength
76 public static SignalStrength newFromBundle(Bundle m) {
78 ret = new SignalStrength();
79 ret.setFromNotifierBundle(m);
88 public SignalStrength() {
89 mGsmSignalStrength = 99;
90 mGsmBitErrorRate = -1;
96 mLteSignalStrength = -1;
109 public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
110 int cdmaDbm, int cdmaEcio,
111 int evdoDbm, int evdoEcio, int evdoSnr,
112 int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
114 mGsmSignalStrength = gsmSignalStrength;
115 mGsmBitErrorRate = gsmBitErrorRate;
117 mCdmaEcio = cdmaEcio;
119 mEvdoEcio = evdoEcio;
121 mLteSignalStrength = lteSignalStrength;
124 mLteRssnr = lteRssnr;
134 public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
135 int cdmaDbm, int cdmaEcio,
136 int evdoDbm, int evdoEcio, int evdoSnr,
138 this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
139 evdoDbm, evdoEcio, evdoSnr, -1, -1, -1, -1, -1, gsm);
145 * @param s Source SignalStrength
149 public SignalStrength(SignalStrength s) {
156 protected void copyFrom(SignalStrength s) {
157 mGsmSignalStrength = s.mGsmSignalStrength;
158 mGsmBitErrorRate = s.mGsmBitErrorRate;
159 mCdmaDbm = s.mCdmaDbm;
160 mCdmaEcio = s.mCdmaEcio;
161 mEvdoDbm = s.mEvdoDbm;
162 mEvdoEcio = s.mEvdoEcio;
163 mEvdoSnr = s.mEvdoSnr;
164 mLteSignalStrength = s.mLteSignalStrength;
165 mLteRsrp = s.mLteRsrp;
166 mLteRsrq = s.mLteRsrq;
167 mLteRssnr = s.mLteRssnr;
173 * Construct a SignalStrength object from the given parcel.
177 public SignalStrength(Parcel in) {
178 mGsmSignalStrength = in.readInt();
179 mGsmBitErrorRate = in.readInt();
180 mCdmaDbm = in.readInt();
181 mCdmaEcio = in.readInt();
182 mEvdoDbm = in.readInt();
183 mEvdoEcio = in.readInt();
184 mEvdoSnr = in.readInt();
185 mLteSignalStrength = in.readInt();
186 mLteRsrp = in.readInt();
187 mLteRsrq = in.readInt();
188 mLteRssnr = in.readInt();
189 mLteCqi = in.readInt();
190 isGsm = (in.readInt() != 0);
194 * {@link Parcelable#writeToParcel}
196 public void writeToParcel(Parcel out, int flags) {
197 out.writeInt(mGsmSignalStrength);
198 out.writeInt(mGsmBitErrorRate);
199 out.writeInt(mCdmaDbm);
200 out.writeInt(mCdmaEcio);
201 out.writeInt(mEvdoDbm);
202 out.writeInt(mEvdoEcio);
203 out.writeInt(mEvdoSnr);
204 out.writeInt(mLteSignalStrength);
205 out.writeInt(mLteRsrp);
206 out.writeInt(mLteRsrq);
207 out.writeInt(mLteRssnr);
208 out.writeInt(mLteCqi);
209 out.writeInt(isGsm ? 1 : 0);
213 * {@link Parcelable#describeContents}
215 public int describeContents() {
220 * {@link Parcelable.Creator}
224 public static final Parcelable.Creator<SignalStrength> CREATOR = new Parcelable.Creator() {
225 public SignalStrength createFromParcel(Parcel in) {
226 return new SignalStrength(in);
229 public SignalStrength[] newArray(int size) {
230 return new SignalStrength[size];
235 * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS 27.007 8.5
237 public int getGsmSignalStrength() {
238 return this.mGsmSignalStrength;
242 * Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5
244 public int getGsmBitErrorRate() {
245 return this.mGsmBitErrorRate;
249 * Get the CDMA RSSI value in dBm
251 public int getCdmaDbm() {
252 return this.mCdmaDbm;
256 * Get the CDMA Ec/Io value in dB*10
258 public int getCdmaEcio() {
259 return this.mCdmaEcio;
263 * Get the EVDO RSSI value in dBm
265 public int getEvdoDbm() {
266 return this.mEvdoDbm;
270 * Get the EVDO Ec/Io value in dB*10
272 public int getEvdoEcio() {
273 return this.mEvdoEcio;
277 * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
279 public int getEvdoSnr() {
280 return this.mEvdoSnr;
284 * Get signal level as an int from 0..4
288 public int getLevel() {
292 if ((mLteSignalStrength == -1)
296 && (mLteCqi == -1)) {
297 level = getGsmLevel();
299 level = getLteLevel();
302 int cdmaLevel = getCdmaLevel();
303 int evdoLevel = getEvdoLevel();
304 if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
305 /* We don't know evdo, use cdma */
306 level = getCdmaLevel();
307 } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
308 /* We don't know cdma, use evdo */
309 level = getEvdoLevel();
311 /* We know both, use the lowest level */
312 level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
315 if (DBG) log("getLevel=" + level);
320 * Get the signal level as an asu value between 0..31, 99 is unknown
324 public int getAsuLevel() {
327 if ((mLteSignalStrength == -1)
331 && (mLteCqi == -1)) {
332 asuLevel = getGsmAsuLevel();
334 asuLevel = getLteAsuLevel();
337 int cdmaAsuLevel = getCdmaAsuLevel();
338 int evdoAsuLevel = getEvdoAsuLevel();
339 if (evdoAsuLevel == 0) {
340 /* We don't know evdo use, cdma */
341 asuLevel = cdmaAsuLevel;
342 } else if (cdmaAsuLevel == 0) {
343 /* We don't know cdma use, evdo */
344 asuLevel = evdoAsuLevel;
346 /* We know both, use the lowest level */
347 asuLevel = cdmaAsuLevel < evdoAsuLevel ? cdmaAsuLevel : evdoAsuLevel;
350 if (DBG) log("getAsuLevel=" + asuLevel);
355 * Get the signal strength as dBm
359 public int getDbm() {
363 if ((mLteSignalStrength == -1)
367 && (mLteCqi == -1)) {
375 if (DBG) log("getDbm=" + dBm);
380 * Get Gsm signal strength as dBm
384 public int getGsmDbm() {
387 int gsmSignalStrength = getGsmSignalStrength();
388 int asu = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
390 dBm = -113 + (2 * asu);
394 if (DBG) log("getGsmDbm=" + dBm);
399 * Get gsm as level 0..4
403 public int getGsmLevel() {
406 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
407 // asu = 0 (-113dB or less) is very weak
408 // signal, its better to show 0 bars to the user in such cases.
409 // asu = 99 is a special case, where the signal strength is unknown.
410 int asu = getGsmSignalStrength();
411 if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
412 else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
413 else if (asu >= 8) level = SIGNAL_STRENGTH_GOOD;
414 else if (asu >= 5) level = SIGNAL_STRENGTH_MODERATE;
415 else level = SIGNAL_STRENGTH_POOR;
416 if (DBG) log("getGsmLevel=" + level);
421 * Get the gsm signal level as an asu value between 0..31, 99 is unknown
425 public int getGsmAsuLevel() {
426 // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
427 // asu = 0 (-113dB or less) is very weak
428 // signal, its better to show 0 bars to the user in such cases.
429 // asu = 99 is a special case, where the signal strength is unknown.
430 int level = getGsmSignalStrength();
431 if (DBG) log("getGsmAsuLevel=" + level);
436 * Get cdma as level 0..4
440 public int getCdmaLevel() {
441 final int cdmaDbm = getCdmaDbm();
442 final int cdmaEcio = getCdmaEcio();
446 if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
447 else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
448 else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
449 else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
450 else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
452 // Ec/Io are in dB*10
453 if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
454 else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
455 else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
456 else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
457 else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
459 int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
460 if (DBG) log("getCdmaLevel=" + level);
465 * Get the cdma signal level as an asu value between 0..31, 99 is unknown
469 public int getCdmaAsuLevel() {
470 final int cdmaDbm = getCdmaDbm();
471 final int cdmaEcio = getCdmaEcio();
475 if (cdmaDbm >= -75) cdmaAsuLevel = 16;
476 else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
477 else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
478 else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
479 else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
480 else cdmaAsuLevel = 99;
482 // Ec/Io are in dB*10
483 if (cdmaEcio >= -90) ecioAsuLevel = 16;
484 else if (cdmaEcio >= -100) ecioAsuLevel = 8;
485 else if (cdmaEcio >= -115) ecioAsuLevel = 4;
486 else if (cdmaEcio >= -130) ecioAsuLevel = 2;
487 else if (cdmaEcio >= -150) ecioAsuLevel = 1;
488 else ecioAsuLevel = 99;
490 int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
491 if (DBG) log("getCdmaAsuLevel=" + level);
496 * Get Evdo as level 0..4
500 public int getEvdoLevel() {
501 int evdoDbm = getEvdoDbm();
502 int evdoSnr = getEvdoSnr();
506 if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
507 else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
508 else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
509 else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
510 else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
512 if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
513 else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
514 else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
515 else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
516 else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
518 int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
519 if (DBG) log("getEvdoLevel=" + level);
524 * Get the evdo signal level as an asu value between 0..31, 99 is unknown
528 public int getEvdoAsuLevel() {
529 int evdoDbm = getEvdoDbm();
530 int evdoSnr = getEvdoSnr();
534 if (evdoDbm >= -65) levelEvdoDbm = 16;
535 else if (evdoDbm >= -75) levelEvdoDbm = 8;
536 else if (evdoDbm >= -85) levelEvdoDbm = 4;
537 else if (evdoDbm >= -95) levelEvdoDbm = 2;
538 else if (evdoDbm >= -105) levelEvdoDbm = 1;
539 else levelEvdoDbm = 99;
541 if (evdoSnr >= 7) levelEvdoSnr = 16;
542 else if (evdoSnr >= 6) levelEvdoSnr = 8;
543 else if (evdoSnr >= 5) levelEvdoSnr = 4;
544 else if (evdoSnr >= 3) levelEvdoSnr = 2;
545 else if (evdoSnr >= 1) levelEvdoSnr = 1;
546 else levelEvdoSnr = 99;
548 int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
549 if (DBG) log("getEvdoAsuLevel=" + level);
558 public int getLteDbm() {
563 * Get LTE as level 0..4
567 public int getLteLevel() {
568 int levelLteRsrp = 0;
570 if (mLteRsrp == -1) levelLteRsrp = 0;
571 else if (mLteRsrp >= -85) levelLteRsrp = SIGNAL_STRENGTH_GREAT;
572 else if (mLteRsrp >= -95) levelLteRsrp = SIGNAL_STRENGTH_GOOD;
573 else if (mLteRsrp >= -105) levelLteRsrp = SIGNAL_STRENGTH_MODERATE;
574 else if (mLteRsrp >= -115) levelLteRsrp = SIGNAL_STRENGTH_POOR;
575 else levelLteRsrp = 0;
577 if (DBG) log("Lte level: "+levelLteRsrp);
582 * Get the LTE signal level as an asu value between 0..97, 99 is unknown
583 * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
587 public int getLteAsuLevel() {
588 int lteAsuLevel = 99;
589 int lteDbm = getLteDbm();
590 if (lteDbm <= -140) lteAsuLevel = 0;
591 else if (lteDbm >= -43) lteAsuLevel = 97;
592 else lteAsuLevel = lteDbm + 140;
593 if (DBG) log("Lte Asu level: "+lteAsuLevel);
598 * @return true if this is for GSM
600 public boolean isGsm() {
608 public int hashCode() {
610 return ((mGsmSignalStrength * primeNum)
611 + (mGsmBitErrorRate * primeNum)
612 + (mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
613 + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
614 + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
615 + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
620 * @return true if the signal strengths are the same
623 public boolean equals (Object o) {
627 s = (SignalStrength) o;
628 } catch (ClassCastException ex) {
636 return (mGsmSignalStrength == s.mGsmSignalStrength
637 && mGsmBitErrorRate == s.mGsmBitErrorRate
638 && mCdmaDbm == s.mCdmaDbm
639 && mCdmaEcio == s.mCdmaEcio
640 && mEvdoDbm == s.mEvdoDbm
641 && mEvdoEcio == s.mEvdoEcio
642 && mEvdoSnr == s.mEvdoSnr
643 && mLteSignalStrength == s.mLteSignalStrength
644 && mLteRsrp == s.mLteRsrp
645 && mLteRsrq == s.mLteRsrq
646 && mLteRssnr == s.mLteRssnr
647 && mLteCqi == s.mLteCqi
648 && isGsm == s.isGsm);
652 * @return string representation.
655 public String toString() {
656 return ("SignalStrength:"
657 + " " + mGsmSignalStrength
658 + " " + mGsmBitErrorRate
664 + " " + mLteSignalStrength
669 + " " + (isGsm ? "gsm|lte" : "cdma"));
673 * Set SignalStrength based on intent notifier map
675 * @param m intent notifier map
678 private void setFromNotifierBundle(Bundle m) {
679 mGsmSignalStrength = m.getInt("GsmSignalStrength");
680 mGsmBitErrorRate = m.getInt("GsmBitErrorRate");
681 mCdmaDbm = m.getInt("CdmaDbm");
682 mCdmaEcio = m.getInt("CdmaEcio");
683 mEvdoDbm = m.getInt("EvdoDbm");
684 mEvdoEcio = m.getInt("EvdoEcio");
685 mEvdoSnr = m.getInt("EvdoSnr");
686 mLteSignalStrength = m.getInt("LteSignalStrength");
687 mLteRsrp = m.getInt("LteRsrp");
688 mLteRsrq = m.getInt("LteRsrq");
689 mLteRssnr = m.getInt("LteRssnr");
690 mLteCqi = m.getInt("LteCqi");
691 isGsm = m.getBoolean("isGsm");
695 * Set intent notifier Bundle based on SignalStrength
697 * @param m intent notifier Bundle
700 public void fillInNotifierBundle(Bundle m) {
701 m.putInt("GsmSignalStrength", mGsmSignalStrength);
702 m.putInt("GsmBitErrorRate", mGsmBitErrorRate);
703 m.putInt("CdmaDbm", mCdmaDbm);
704 m.putInt("CdmaEcio", mCdmaEcio);
705 m.putInt("EvdoDbm", mEvdoDbm);
706 m.putInt("EvdoEcio", mEvdoEcio);
707 m.putInt("EvdoSnr", mEvdoSnr);
708 m.putInt("LteSignalStrength", mLteSignalStrength);
709 m.putInt("LteRsrp", mLteRsrp);
710 m.putInt("LteRsrq", mLteRsrq);
711 m.putInt("LteRssnr", mLteRssnr);
712 m.putInt("LteCqi", mLteCqi);
713 m.putBoolean("isGsm", Boolean.valueOf(isGsm));
719 private static void log(String s) {