• 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.annotation.StringDef;
21 import android.annotation.UnsupportedAppUsage;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.PersistableBundle;
25 import android.telephony.Rlog;
26 import android.text.TextUtils;
27 
28 import java.lang.annotation.Retention;
29 import java.lang.annotation.RetentionPolicy;
30 import java.util.Objects;
31 
32 /**
33  * Wcdma signal strength related information.
34  */
35 public final class CellSignalStrengthWcdma extends CellSignalStrength implements Parcelable {
36 
37     private static final String LOG_TAG = "CellSignalStrengthWcdma";
38     private static final boolean DBG = false;
39 
40     private static final int WCDMA_RSSI_MAX = -51;
41     private static final int WCDMA_RSSI_GREAT = -77;
42     private static final int WCDMA_RSSI_GOOD = -87;
43     private static final int WCDMA_RSSI_MODERATE = -97;
44     private static final int WCDMA_RSSI_POOR = -107;
45     private static final int WCDMA_RSSI_MIN = -113;
46 
47     private static final int[] sRssiThresholds = new int[]{
48             WCDMA_RSSI_POOR, WCDMA_RSSI_MODERATE, WCDMA_RSSI_GOOD, WCDMA_RSSI_GREAT};
49 
50     private static final int WCDMA_RSCP_MAX = -24;
51     private static final int WCDMA_RSCP_GREAT = -85;
52     private static final int WCDMA_RSCP_GOOD = -95;
53     private static final int WCDMA_RSCP_MODERATE = -105;
54     private static final int WCDMA_RSCP_POOR = -115;
55     private static final int WCDMA_RSCP_MIN = -120;
56 
57     private static final int[] sRscpThresholds = new int[] {
58             WCDMA_RSCP_POOR, WCDMA_RSCP_MODERATE, WCDMA_RSCP_GOOD, WCDMA_RSCP_GREAT};
59 
60     // TODO: Because these are used as values in CarrierConfig, they should be exposed somehow.
61     /** @hide */
62     @Retention(RetentionPolicy.SOURCE)
63     @StringDef({LEVEL_CALCULATION_METHOD_RSSI, LEVEL_CALCULATION_METHOD_RSCP})
64     public @interface LevelCalculationMethod {}
65     /** @hide */
66     public static final String LEVEL_CALCULATION_METHOD_RSSI = "rssi";
67     /** @hide */
68     public static final String LEVEL_CALCULATION_METHOD_RSCP = "rscp";
69 
70     // Default to RSSI for backwards compatibility with older devices
71     private static final String DEFAULT_LEVEL_CALCULATION_METHOD = LEVEL_CALCULATION_METHOD_RSSI;
72 
73     private int mRssi; // in dBm [-113, 51] or CellInfo.UNAVAILABLE if unknown
74 
75     @UnsupportedAppUsage
76     private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
77                                // CellInfo.UNAVAILABLE if unknown
78     private int mRscp; // in dBm [-120, -24]
79     private int mEcNo; // range -24, 1, CellInfo.UNAVAILABLE if unknown
80     private int mLevel;
81 
82     /** @hide */
CellSignalStrengthWcdma()83     public CellSignalStrengthWcdma() {
84         setDefaultValues();
85     }
86 
87     /** @hide */
CellSignalStrengthWcdma(int rssi, int ber, int rscp, int ecno)88     public CellSignalStrengthWcdma(int rssi, int ber, int rscp, int ecno) {
89         mRssi = inRangeOrUnavailable(rssi, WCDMA_RSSI_MIN, WCDMA_RSSI_MAX);
90         mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
91         mRscp = inRangeOrUnavailable(rscp, -120, -24);
92         mEcNo = inRangeOrUnavailable(ecno, -24, 1);
93         updateLevel(null, null);
94     }
95 
96     /** @hide */
CellSignalStrengthWcdma(android.hardware.radio.V1_0.WcdmaSignalStrength wcdma)97     public CellSignalStrengthWcdma(android.hardware.radio.V1_0.WcdmaSignalStrength wcdma) {
98         // Convert from HAL values as part of construction.
99         this(getRssiDbmFromAsu(wcdma.signalStrength), wcdma.bitErrorRate,
100                 CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE);
101 
102         if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
103             setDefaultValues();
104         }
105     }
106 
107     /** @hide */
CellSignalStrengthWcdma(android.hardware.radio.V1_2.WcdmaSignalStrength wcdma)108     public CellSignalStrengthWcdma(android.hardware.radio.V1_2.WcdmaSignalStrength wcdma) {
109         // Convert from HAL values as part of construction.
110         this(getRssiDbmFromAsu(wcdma.base.signalStrength),
111                     wcdma.base.bitErrorRate,
112                     getRscpDbmFromAsu(wcdma.rscp),
113                     getEcNoDbFromAsu(wcdma.ecno));
114 
115         if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
116             setDefaultValues();
117         }
118     }
119 
120     /** @hide */
CellSignalStrengthWcdma(CellSignalStrengthWcdma s)121     public CellSignalStrengthWcdma(CellSignalStrengthWcdma s) {
122         copyFrom(s);
123     }
124 
125     /** @hide */
copyFrom(CellSignalStrengthWcdma s)126     protected void copyFrom(CellSignalStrengthWcdma s) {
127         mRssi = s.mRssi;
128         mBitErrorRate = s.mBitErrorRate;
129         mRscp = s.mRscp;
130         mEcNo = s.mEcNo;
131         mLevel = s.mLevel;
132     }
133 
134     /** @hide */
135     @Override
copy()136     public CellSignalStrengthWcdma copy() {
137         return new CellSignalStrengthWcdma(this);
138     }
139 
140     /** @hide */
141     @Override
setDefaultValues()142     public void setDefaultValues() {
143         mRssi = CellInfo.UNAVAILABLE;
144         mBitErrorRate = CellInfo.UNAVAILABLE;
145         mRscp = CellInfo.UNAVAILABLE;
146         mEcNo = CellInfo.UNAVAILABLE;
147         mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
148     }
149 
150     /** {@inheritDoc} */
151     @Override
152     @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
getLevel()153     public int getLevel() {
154         return mLevel;
155     }
156 
157     /** @hide */
158     @Override
updateLevel(PersistableBundle cc, ServiceState ss)159     public void updateLevel(PersistableBundle cc, ServiceState ss) {
160         String calcMethod;
161         int[] rscpThresholds;
162 
163         if (cc == null) {
164             calcMethod = DEFAULT_LEVEL_CALCULATION_METHOD;
165             rscpThresholds = sRscpThresholds;
166         } else {
167             // TODO: abstract this entire thing into a series of functions
168             calcMethod = cc.getString(
169                     CarrierConfigManager.KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING,
170                     DEFAULT_LEVEL_CALCULATION_METHOD);
171             if (TextUtils.isEmpty(calcMethod)) calcMethod = DEFAULT_LEVEL_CALCULATION_METHOD;
172             rscpThresholds = cc.getIntArray(
173                     CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
174             if (rscpThresholds == null || rscpThresholds.length != NUM_SIGNAL_STRENGTH_THRESHOLDS) {
175                 rscpThresholds = sRscpThresholds;
176             }
177         }
178 
179         int level = NUM_SIGNAL_STRENGTH_THRESHOLDS;
180         switch (calcMethod) {
181             case LEVEL_CALCULATION_METHOD_RSCP:
182                 if (mRscp < WCDMA_RSCP_MIN || mRscp > WCDMA_RSCP_MAX) {
183                     mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
184                     return;
185                 }
186                 while (level > 0 && mRscp < rscpThresholds[level - 1]) level--;
187                 mLevel = level;
188                 return;
189             default:
190                 loge("Invalid Level Calculation Method for CellSignalStrengthWcdma = "
191                         + calcMethod);
192                 /** fall through */
193             case LEVEL_CALCULATION_METHOD_RSSI:
194                 if (mRssi < WCDMA_RSSI_MIN || mRssi > WCDMA_RSSI_MAX) {
195                     mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
196                     return;
197                 }
198                 while (level > 0 && mRssi < sRssiThresholds[level - 1]) level--;
199                 mLevel = level;
200                 return;
201         }
202     }
203 
204     /**
205      * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
206      */
207     @Override
getDbm()208     public int getDbm() {
209         if (mRscp != CellInfo.UNAVAILABLE) return mRscp;
210         return mRssi;
211     }
212 
213     /**
214      * Get the RSCP in ASU.
215      *
216      * Asu is calculated based on 3GPP RSCP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
217      *
218      * @return RSCP in ASU 0..96, 255, or UNAVAILABLE
219      */
220     @Override
getAsuLevel()221     public int getAsuLevel() {
222         if (mRscp != CellInfo.UNAVAILABLE) return getAsuFromRscpDbm(mRscp);
223         // For historical reasons, if RSCP is unavailable, this API will very incorrectly return
224         // RSSI. This hackery will be removed when most devices are using Radio HAL 1.2+
225         if (mRssi != CellInfo.UNAVAILABLE) return getAsuFromRssiDbm(mRssi);
226         return getAsuFromRscpDbm(CellInfo.UNAVAILABLE);
227     }
228 
229     /**
230      * Get the RSSI as dBm
231      *
232      * @hide
233      */
getRssi()234     public int getRssi() {
235         return mRssi;
236     }
237 
238     /**
239      * Get the RSCP as dBm
240      *
241      * @hide
242      */
getRscp()243     public int getRscp() {
244         return mRscp;
245     }
246 
247     /**
248      * Get the Ec/No as dB
249      *
250      * @hide
251      */
getEcNo()252     public int getEcNo() {
253         return mEcNo;
254     }
255 
256     /**
257      * Return the Bit Error Rate
258      *
259      * @returns the bit error rate (0-7, 99) as defined in TS 27.007 8.5 or UNAVAILABLE.
260      * @hide
261      */
getBitErrorRate()262     public int getBitErrorRate() {
263         return mBitErrorRate;
264     }
265 
266     @Override
hashCode()267     public int hashCode() {
268         return Objects.hash(mRssi, mBitErrorRate, mRscp, mEcNo, mLevel);
269     }
270 
271     private static final CellSignalStrengthWcdma sInvalid = new CellSignalStrengthWcdma();
272 
273     /** @hide */
274     @Override
isValid()275     public boolean isValid() {
276         return !this.equals(sInvalid);
277     }
278 
279     @Override
equals(Object o)280     public boolean equals(Object o) {
281         if (!(o instanceof CellSignalStrengthWcdma)) return false;
282         CellSignalStrengthWcdma s = (CellSignalStrengthWcdma) o;
283 
284         return mRssi == s.mRssi
285                 && mBitErrorRate == s.mBitErrorRate
286                 && mRscp == s.mRscp
287                 && mEcNo == s.mEcNo
288                 && mLevel == s.mLevel;
289     }
290 
291     /**
292      * @return string representation.
293      */
294     @Override
toString()295     public String toString() {
296         return "CellSignalStrengthWcdma:"
297                 + " ss=" + mRssi
298                 + " ber=" + mBitErrorRate
299                 + " rscp=" + mRscp
300                 + " ecno=" + mEcNo
301                 + " level=" + mLevel;
302     }
303 
304     /** Implement the Parcelable interface */
305     @Override
writeToParcel(Parcel dest, int flags)306     public void writeToParcel(Parcel dest, int flags) {
307         if (DBG) log("writeToParcel(Parcel, int): " + toString());
308         dest.writeInt(mRssi);
309         dest.writeInt(mBitErrorRate);
310         dest.writeInt(mRscp);
311         dest.writeInt(mEcNo);
312         dest.writeInt(mLevel);
313     }
314 
315     /**
316      * Construct a SignalStrength object from the given parcel
317      * where the token is already been processed.
318      */
CellSignalStrengthWcdma(Parcel in)319     private CellSignalStrengthWcdma(Parcel in) {
320         mRssi = in.readInt();
321         mBitErrorRate = in.readInt();
322         mRscp = in.readInt();
323         mEcNo = in.readInt();
324         mLevel = in.readInt();
325         if (DBG) log("CellSignalStrengthWcdma(Parcel): " + toString());
326     }
327 
328     /** Implement the Parcelable interface */
329     @Override
describeContents()330     public int describeContents() {
331         return 0;
332     }
333 
334     /** Implement the Parcelable interface */
335     @SuppressWarnings("hiding")
336     public static final @android.annotation.NonNull Parcelable.Creator<CellSignalStrengthWcdma> CREATOR =
337             new Parcelable.Creator<CellSignalStrengthWcdma>() {
338         @Override
339         public CellSignalStrengthWcdma createFromParcel(Parcel in) {
340             return new CellSignalStrengthWcdma(in);
341         }
342 
343         @Override
344         public CellSignalStrengthWcdma[] newArray(int size) {
345             return new CellSignalStrengthWcdma[size];
346         }
347     };
348 
349     /**
350      * log warning
351      */
log(String s)352     private static void log(String s) {
353         Rlog.w(LOG_TAG, s);
354     }
355 
356     /**
357      * log error
358      */
loge(String s)359     private static void loge(String s) {
360         Rlog.e(LOG_TAG, s);
361     }
362 }
363