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