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(CellSignalStrengthTdscdma s)78     public CellSignalStrengthTdscdma(CellSignalStrengthTdscdma s) {
79         copyFrom(s);
80     }
81 
82     /** @hide */
copyFrom(CellSignalStrengthTdscdma s)83     protected void copyFrom(CellSignalStrengthTdscdma s) {
84         mRssi = s.mRssi;
85         mBitErrorRate = s.mBitErrorRate;
86         mRscp = s.mRscp;
87         mLevel = s.mLevel;
88     }
89 
90     /** @hide */
91     @Override
copy()92     public CellSignalStrengthTdscdma copy() {
93         return new CellSignalStrengthTdscdma(this);
94     }
95 
96     /** @hide */
97     @Override
setDefaultValues()98     public void setDefaultValues() {
99         mRssi = CellInfo.UNAVAILABLE;
100         mBitErrorRate = CellInfo.UNAVAILABLE;
101         mRscp = CellInfo.UNAVAILABLE;
102         mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
103     }
104 
105 
106     /** {@inheritDoc} */
107     @Override
108     @IntRange(from = 0, to = 4)
getLevel()109     public int getLevel() {
110         return mLevel;
111     }
112 
113     /** @hide */
114     @Override
updateLevel(PersistableBundle cc, ServiceState ss)115     public void updateLevel(PersistableBundle cc, ServiceState ss) {
116         if (mRscp > TDSCDMA_RSCP_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
117         else if (mRscp >= TDSCDMA_RSCP_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
118         else if (mRscp >= TDSCDMA_RSCP_GOOD)  mLevel = SIGNAL_STRENGTH_GOOD;
119         else if (mRscp >= TDSCDMA_RSCP_MODERATE)  mLevel = SIGNAL_STRENGTH_MODERATE;
120         else if (mRscp >= TDSCDMA_RSCP_POOR) mLevel = SIGNAL_STRENGTH_POOR;
121         else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
122     }
123 
124     /**
125      * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
126      */
127     @Override
getDbm()128     public int getDbm() {
129         return mRscp;
130     }
131 
132     /**
133      * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
134      */
getRscp()135     public int getRscp() {
136         return mRscp;
137     }
138 
139     /**
140      * Get the RSSI as dBm value -113..-51dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
141      *
142      * @hide
143      */
getRssi()144     public int getRssi() {
145         return mRssi;
146     }
147 
148     /**
149      * Get the BER as an ASU value 0..7, 99, or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
150      * @hide
151      */
getBitErrorRate()152     public int getBitErrorRate() {
153         return mBitErrorRate;
154     }
155 
156     /**
157      * Get the RSCP in ASU.
158      *
159      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
160      *
161      * @return RSCP in ASU 0..96, 255, or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
162      */
163     @Override
getAsuLevel()164     public int getAsuLevel() {
165         if (mRscp != CellInfo.UNAVAILABLE) return getAsuFromRscpDbm(mRscp);
166         // For historical reasons, if RSCP is unavailable, this API will very incorrectly return
167         // RSSI. This hackery will be removed when most devices are using Radio HAL 1.2+
168         if (mRssi != CellInfo.UNAVAILABLE) return getAsuFromRssiDbm(mRssi);
169         return getAsuFromRscpDbm(CellInfo.UNAVAILABLE);
170     }
171 
172     @Override
hashCode()173     public int hashCode() {
174         return Objects.hash(mRssi, mBitErrorRate, mRscp, mLevel);
175     }
176 
177     private static final CellSignalStrengthTdscdma sInvalid = new CellSignalStrengthTdscdma();
178 
179     /** @hide */
180     @Override
isValid()181     public boolean isValid() {
182         return !this.equals(sInvalid);
183     }
184 
185     @Override
equals(Object o)186     public boolean equals(Object o) {
187         if (!(o instanceof CellSignalStrengthTdscdma)) return false;
188         CellSignalStrengthTdscdma s = (CellSignalStrengthTdscdma) o;
189 
190         return mRssi == s.mRssi
191                 && mBitErrorRate == s.mBitErrorRate
192                 && mRscp == s.mRscp
193                 && mLevel == s.mLevel;
194     }
195 
196     /**
197      * @return string representation.
198      */
199     @Override
toString()200     public String toString() {
201         return "CellSignalStrengthTdscdma:"
202                 + " rssi=" + mRssi
203                 + " ber=" + mBitErrorRate
204                 + " rscp=" + mRscp
205                 + " level=" + mLevel;
206     }
207 
208     /** Implement the Parcelable interface */
209     @Override
writeToParcel(Parcel dest, int flags)210     public void writeToParcel(Parcel dest, int flags) {
211         if (DBG) log("writeToParcel(Parcel, int): " + toString());
212         dest.writeInt(mRssi);
213         dest.writeInt(mBitErrorRate);
214         dest.writeInt(mRscp);
215         dest.writeInt(mLevel);
216     }
217 
218     /**
219      * Construct a SignalStrength object from the given parcel
220      * where the token is already been processed.
221      */
CellSignalStrengthTdscdma(Parcel in)222     private CellSignalStrengthTdscdma(Parcel in) {
223         mRssi = in.readInt();
224         mBitErrorRate = in.readInt();
225         mRscp = in.readInt();
226         mLevel = in.readInt();
227         if (DBG) log("CellSignalStrengthTdscdma(Parcel): " + toString());
228     }
229 
230     /** Implement the Parcelable interface */
231     @Override
describeContents()232     public int describeContents() {
233         return 0;
234     }
235 
236     /** Implement the Parcelable interface */
237     @SuppressWarnings("hiding")
238     @NonNull
239     public static final Parcelable.Creator<CellSignalStrengthTdscdma> CREATOR =
240             new Parcelable.Creator<CellSignalStrengthTdscdma>() {
241         @Override
242         public @NonNull CellSignalStrengthTdscdma createFromParcel(Parcel in) {
243             return new CellSignalStrengthTdscdma(in);
244         }
245 
246         @Override
247         public @NonNull CellSignalStrengthTdscdma[] newArray(int size) {
248             return new CellSignalStrengthTdscdma[size];
249         }
250     };
251 
252     /**
253      * log
254      */
log(String s)255     private static void log(String s) {
256         Rlog.w(LOG_TAG, s);
257     }
258 }
259