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.IntRange;
20 import android.annotation.NonNull;
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.util.Objects;
28 
29 /**
30  * Tdscdma signal strength related information.
31  *
32  * This class provides signal strength and signal quality information for the TD-SCDMA air
33  * interface. For more information see 3gpp 25.225.
34  */
35 public final class CellSignalStrengthTdscdma extends CellSignalStrength implements Parcelable {
36 
37     private static final String LOG_TAG = "CellSignalStrengthTdscdma";
38     private static final boolean DBG = false;
39 
40     // These levels are arbitrary but carried over from SignalStrength.java for consistency.
41     private static final int TDSCDMA_RSCP_MAX = -24;
42     private static final int TDSCDMA_RSCP_GREAT = -49;
43     private static final int TDSCDMA_RSCP_GOOD = -73;
44     private static final int TDSCDMA_RSCP_MODERATE = -97;
45     private static final int TDSCDMA_RSCP_POOR = -110;
46     private static final int TDSCDMA_RSCP_MIN = -120;
47 
48 
49     private int mRssi; // in dBm [-113, -51], CellInfo.UNAVAILABLE
50 
51     private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
52                                // CellInfo.UNAVAILABLE if unknown
53     private int mRscp; // Pilot Power in dBm [-120, -24] or CellInfo.UNAVAILABLE
54                        // CellInfo.UNAVAILABLE if unknown
55 
56     private int mLevel;
57 
58     /** @hide */
CellSignalStrengthTdscdma()59     public CellSignalStrengthTdscdma() {
60         setDefaultValues();
61     }
62 
63     /**
64      * @param rssi in dBm [-113, -51] or UNAVAILABLE
65      * @param ber [0-7], 99 or UNAVAILABLE
66      * @param rscp in dBm [-120, -24] or UNAVAILABLE
67      *
68      * @hide
69      */
CellSignalStrengthTdscdma(int rssi, int ber, int rscp)70     public CellSignalStrengthTdscdma(int rssi, int ber, int rscp) {
71         mRssi = inRangeOrUnavailable(rssi, -113, -51);
72         mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
73         mRscp = inRangeOrUnavailable(rscp, -120, -24);
74         updateLevel(null, null);
75     }
76 
77     /** @hide */
CellSignalStrengthTdscdma(android.hardware.radio.V1_0.TdScdmaSignalStrength tdscdma)78     public CellSignalStrengthTdscdma(android.hardware.radio.V1_0.TdScdmaSignalStrength tdscdma) {
79         // Convert from HAL values as part of construction.
80         this(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
81                 tdscdma.rscp != CellInfo.UNAVAILABLE ? -tdscdma.rscp : tdscdma.rscp);
82 
83         if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
84             setDefaultValues();
85         }
86     }
87 
88     /** @hide */
CellSignalStrengthTdscdma(android.hardware.radio.V1_2.TdscdmaSignalStrength tdscdma)89     public CellSignalStrengthTdscdma(android.hardware.radio.V1_2.TdscdmaSignalStrength tdscdma) {
90         // Convert from HAL values as part of construction.
91         this(getRssiDbmFromAsu(tdscdma.signalStrength),
92                 tdscdma.bitErrorRate, getRscpDbmFromAsu(tdscdma.rscp));
93 
94         if (mRssi == CellInfo.UNAVAILABLE && mRscp == CellInfo.UNAVAILABLE) {
95             setDefaultValues();
96         }
97     }
98 
99     /** @hide */
CellSignalStrengthTdscdma(CellSignalStrengthTdscdma s)100     public CellSignalStrengthTdscdma(CellSignalStrengthTdscdma s) {
101         copyFrom(s);
102     }
103 
104     /** @hide */
copyFrom(CellSignalStrengthTdscdma s)105     protected void copyFrom(CellSignalStrengthTdscdma s) {
106         mRssi = s.mRssi;
107         mBitErrorRate = s.mBitErrorRate;
108         mRscp = s.mRscp;
109         mLevel = s.mLevel;
110     }
111 
112     /** @hide */
113     @Override
copy()114     public CellSignalStrengthTdscdma copy() {
115         return new CellSignalStrengthTdscdma(this);
116     }
117 
118     /** @hide */
119     @Override
setDefaultValues()120     public void setDefaultValues() {
121         mRssi = CellInfo.UNAVAILABLE;
122         mBitErrorRate = CellInfo.UNAVAILABLE;
123         mRscp = CellInfo.UNAVAILABLE;
124         mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
125     }
126 
127 
128     /** {@inheritDoc} */
129     @Override
130     @IntRange(from = 0, to = 4)
getLevel()131     public int getLevel() {
132         return mLevel;
133     }
134 
135     /** @hide */
136     @Override
updateLevel(PersistableBundle cc, ServiceState ss)137     public void updateLevel(PersistableBundle cc, ServiceState ss) {
138         if (mRscp > TDSCDMA_RSCP_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
139         else if (mRscp >= TDSCDMA_RSCP_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
140         else if (mRscp >= TDSCDMA_RSCP_GOOD)  mLevel = SIGNAL_STRENGTH_GOOD;
141         else if (mRscp >= TDSCDMA_RSCP_MODERATE)  mLevel = SIGNAL_STRENGTH_MODERATE;
142         else if (mRscp >= TDSCDMA_RSCP_POOR) mLevel = SIGNAL_STRENGTH_POOR;
143         else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
144     }
145 
146     /**
147      * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
148      */
149     @Override
getDbm()150     public int getDbm() {
151         return mRscp;
152     }
153 
154     /**
155      * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
156      */
getRscp()157     public int getRscp() {
158         return mRscp;
159     }
160 
161     /**
162      * Get the RSSI as dBm value -113..-51dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
163      *
164      * @hide
165      */
getRssi()166     public int getRssi() {
167         return mRssi;
168     }
169 
170     /**
171      * Get the BER as an ASU value 0..7, 99, or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
172      * @hide
173      */
getBitErrorRate()174     public int getBitErrorRate() {
175         return mBitErrorRate;
176     }
177 
178     /**
179      * Get the RSCP in ASU.
180      *
181      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
182      *
183      * @return RSCP in ASU 0..96, 255, or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
184      */
185     @Override
getAsuLevel()186     public int getAsuLevel() {
187         if (mRscp != CellInfo.UNAVAILABLE) return getAsuFromRscpDbm(mRscp);
188         // For historical reasons, if RSCP is unavailable, this API will very incorrectly return
189         // RSSI. This hackery will be removed when most devices are using Radio HAL 1.2+
190         if (mRssi != CellInfo.UNAVAILABLE) return getAsuFromRssiDbm(mRssi);
191         return getAsuFromRscpDbm(CellInfo.UNAVAILABLE);
192     }
193 
194     @Override
hashCode()195     public int hashCode() {
196         return Objects.hash(mRssi, mBitErrorRate, mRscp, mLevel);
197     }
198 
199     private static final CellSignalStrengthTdscdma sInvalid = new CellSignalStrengthTdscdma();
200 
201     /** @hide */
202     @Override
isValid()203     public boolean isValid() {
204         return !this.equals(sInvalid);
205     }
206 
207     @Override
equals(Object o)208     public boolean equals(Object o) {
209         if (!(o instanceof CellSignalStrengthTdscdma)) return false;
210         CellSignalStrengthTdscdma s = (CellSignalStrengthTdscdma) o;
211 
212         return mRssi == s.mRssi
213                 && mBitErrorRate == s.mBitErrorRate
214                 && mRscp == s.mRscp
215                 && mLevel == s.mLevel;
216     }
217 
218     /**
219      * @return string representation.
220      */
221     @Override
toString()222     public String toString() {
223         return "CellSignalStrengthTdscdma:"
224                 + " rssi=" + mRssi
225                 + " ber=" + mBitErrorRate
226                 + " rscp=" + mRscp
227                 + " level=" + mLevel;
228     }
229 
230     /** Implement the Parcelable interface */
231     @Override
writeToParcel(Parcel dest, int flags)232     public void writeToParcel(Parcel dest, int flags) {
233         if (DBG) log("writeToParcel(Parcel, int): " + toString());
234         dest.writeInt(mRssi);
235         dest.writeInt(mBitErrorRate);
236         dest.writeInt(mRscp);
237         dest.writeInt(mLevel);
238     }
239 
240     /**
241      * Construct a SignalStrength object from the given parcel
242      * where the token is already been processed.
243      */
CellSignalStrengthTdscdma(Parcel in)244     private CellSignalStrengthTdscdma(Parcel in) {
245         mRssi = in.readInt();
246         mBitErrorRate = in.readInt();
247         mRscp = in.readInt();
248         mLevel = in.readInt();
249         if (DBG) log("CellSignalStrengthTdscdma(Parcel): " + toString());
250     }
251 
252     /** Implement the Parcelable interface */
253     @Override
describeContents()254     public int describeContents() {
255         return 0;
256     }
257 
258     /** Implement the Parcelable interface */
259     @SuppressWarnings("hiding")
260     @NonNull
261     public static final Parcelable.Creator<CellSignalStrengthTdscdma> CREATOR =
262             new Parcelable.Creator<CellSignalStrengthTdscdma>() {
263         @Override
264         public @NonNull CellSignalStrengthTdscdma createFromParcel(Parcel in) {
265             return new CellSignalStrengthTdscdma(in);
266         }
267 
268         @Override
269         public @NonNull CellSignalStrengthTdscdma[] newArray(int size) {
270             return new CellSignalStrengthTdscdma[size];
271         }
272     };
273 
274     /**
275      * log
276      */
log(String s)277     private static void log(String s) {
278         Rlog.w(LOG_TAG, s);
279     }
280 }
281