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.os.Parcel;
20 import android.os.Parcelable;
21 import android.telephony.Rlog;
22 
23 import java.util.Objects;
24 
25 /**
26  * LTE signal strength related information.
27  */
28 public final class CellSignalStrengthLte extends CellSignalStrength implements Parcelable {
29 
30     private static final String LOG_TAG = "CellSignalStrengthLte";
31     private static final boolean DBG = false;
32 
33     private int mSignalStrength;
34     private int mRsrp;
35     private int mRsrq;
36     private int mRssnr;
37     private int mCqi;
38     private int mTimingAdvance;
39 
40     /** @hide */
CellSignalStrengthLte()41     public CellSignalStrengthLte() {
42         setDefaultValues();
43     }
44 
45     /** @hide */
CellSignalStrengthLte(int signalStrength, int rsrp, int rsrq, int rssnr, int cqi, int timingAdvance)46     public CellSignalStrengthLte(int signalStrength, int rsrp, int rsrq, int rssnr, int cqi,
47             int timingAdvance) {
48         mSignalStrength = signalStrength;
49         mRsrp = rsrp;
50         mRsrq = rsrq;
51         mRssnr = rssnr;
52         mCqi = cqi;
53         mTimingAdvance = timingAdvance;
54     }
55 
56     /** @hide */
CellSignalStrengthLte(CellSignalStrengthLte s)57     public CellSignalStrengthLte(CellSignalStrengthLte s) {
58         copyFrom(s);
59     }
60 
61     /** @hide */
copyFrom(CellSignalStrengthLte s)62     protected void copyFrom(CellSignalStrengthLte s) {
63         mSignalStrength = s.mSignalStrength;
64         mRsrp = s.mRsrp;
65         mRsrq = s.mRsrq;
66         mRssnr = s.mRssnr;
67         mCqi = s.mCqi;
68         mTimingAdvance = s.mTimingAdvance;
69     }
70 
71     /** @hide */
72     @Override
copy()73     public CellSignalStrengthLte copy() {
74         return new CellSignalStrengthLte(this);
75     }
76 
77     /** @hide */
78     @Override
setDefaultValues()79     public void setDefaultValues() {
80         mSignalStrength = Integer.MAX_VALUE;
81         mRsrp = Integer.MAX_VALUE;
82         mRsrq = Integer.MAX_VALUE;
83         mRssnr = Integer.MAX_VALUE;
84         mCqi = Integer.MAX_VALUE;
85         mTimingAdvance = Integer.MAX_VALUE;
86     }
87 
88     /**
89      * Get signal level as an int from 0..4
90      */
91     @Override
getLevel()92     public int getLevel() {
93         int levelRsrp = 0;
94         int levelRssnr = 0;
95 
96         if (mRsrp == Integer.MAX_VALUE) levelRsrp = 0;
97         else if (mRsrp >= -95) levelRsrp = SIGNAL_STRENGTH_GREAT;
98         else if (mRsrp >= -105) levelRsrp = SIGNAL_STRENGTH_GOOD;
99         else if (mRsrp >= -115) levelRsrp = SIGNAL_STRENGTH_MODERATE;
100         else levelRsrp = SIGNAL_STRENGTH_POOR;
101 
102         // See RIL_LTE_SignalStrength in ril.h
103         if (mRssnr == Integer.MAX_VALUE) levelRssnr = 0;
104         else if (mRssnr >= 45) levelRssnr = SIGNAL_STRENGTH_GREAT;
105         else if (mRssnr >= 10) levelRssnr = SIGNAL_STRENGTH_GOOD;
106         else if (mRssnr >= -30) levelRssnr = SIGNAL_STRENGTH_MODERATE;
107         else levelRssnr = SIGNAL_STRENGTH_POOR;
108 
109         int level;
110         if (mRsrp == Integer.MAX_VALUE)
111             level = levelRssnr;
112         else if (mRssnr == Integer.MAX_VALUE)
113             level = levelRsrp;
114         else
115             level = (levelRssnr < levelRsrp) ? levelRssnr : levelRsrp;
116 
117         if (DBG) log("Lte rsrp level: " + levelRsrp
118                 + " snr level: " + levelRssnr + " level: " + level);
119         return level;
120     }
121 
122     /**
123      * Get reference signal received quality
124      */
getRsrq()125     public int getRsrq() {
126         return mRsrq;
127     }
128 
129     /**
130      * Get reference signal signal-to-noise ratio
131      */
getRssnr()132     public int getRssnr() {
133         return mRssnr;
134     }
135 
136     /**
137      * Get reference signal received power
138      */
getRsrp()139     public int getRsrp() {
140         return mRsrp;
141     }
142 
143     /**
144      * Get channel quality indicator
145      */
getCqi()146     public int getCqi() {
147         return mCqi;
148     }
149 
150     /**
151      * Get signal strength as dBm
152      */
153     @Override
getDbm()154     public int getDbm() {
155         return mRsrp;
156     }
157 
158     /**
159      * Get the LTE signal level as an asu value between 0..97, 99 is unknown
160      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
161      */
162     @Override
getAsuLevel()163     public int getAsuLevel() {
164         int lteAsuLevel = 99;
165         int lteDbm = getDbm();
166         if (lteDbm == Integer.MAX_VALUE) lteAsuLevel = 99;
167         else if (lteDbm <= -140) lteAsuLevel = 0;
168         else if (lteDbm >= -43) lteAsuLevel = 97;
169         else lteAsuLevel = lteDbm + 140;
170         if (DBG) log("Lte Asu level: "+lteAsuLevel);
171         return lteAsuLevel;
172     }
173 
174     /**
175      * Get the timing advance value for LTE, as a value in range of 0..1282.
176      * Integer.MAX_VALUE is reported when there is no active RRC
177      * connection. Refer to 3GPP 36.213 Sec 4.2.3
178      * @return the LTE timing advance, if available.
179      */
getTimingAdvance()180     public int getTimingAdvance() {
181         return mTimingAdvance;
182     }
183 
184     @Override
hashCode()185     public int hashCode() {
186         return Objects.hash(mSignalStrength, mRsrp, mRsrq, mRssnr, mCqi, mTimingAdvance);
187     }
188 
189     @Override
equals(Object o)190     public boolean equals (Object o) {
191         CellSignalStrengthLte s;
192 
193         try {
194             s = (CellSignalStrengthLte) o;
195         } catch (ClassCastException ex) {
196             return false;
197         }
198 
199         if (o == null) {
200             return false;
201         }
202 
203         return mSignalStrength == s.mSignalStrength
204                 && mRsrp == s.mRsrp
205                 && mRsrq == s.mRsrq
206                 && mRssnr == s.mRssnr
207                 && mCqi == s.mCqi
208                 && mTimingAdvance == s.mTimingAdvance;
209     }
210 
211     /**
212      * @return string representation.
213      */
214     @Override
toString()215     public String toString() {
216         return "CellSignalStrengthLte:"
217                 + " ss=" + mSignalStrength
218                 + " rsrp=" + mRsrp
219                 + " rsrq=" + mRsrq
220                 + " rssnr=" + mRssnr
221                 + " cqi=" + mCqi
222                 + " ta=" + mTimingAdvance;
223     }
224 
225     /** Implement the Parcelable interface */
226     @Override
writeToParcel(Parcel dest, int flags)227     public void writeToParcel(Parcel dest, int flags) {
228         if (DBG) log("writeToParcel(Parcel, int): " + toString());
229         dest.writeInt(mSignalStrength);
230         // Need to multiply rsrp and rsrq by -1
231         // to ensure consistency when reading values written here
232         // unless the values are invalid
233         dest.writeInt(mRsrp * (mRsrp != Integer.MAX_VALUE ? -1 : 1));
234         dest.writeInt(mRsrq * (mRsrq != Integer.MAX_VALUE ? -1 : 1));
235         dest.writeInt(mRssnr);
236         dest.writeInt(mCqi);
237         dest.writeInt(mTimingAdvance);
238     }
239 
240     /**
241      * Construct a SignalStrength object from the given parcel
242      * where the token is already been processed.
243      */
CellSignalStrengthLte(Parcel in)244     private CellSignalStrengthLte(Parcel in) {
245         mSignalStrength = in.readInt();
246         // rsrp and rsrq are written into the parcel as positive values.
247         // Need to convert into negative values unless the values are invalid
248         mRsrp = in.readInt();
249         if (mRsrp != Integer.MAX_VALUE) mRsrp *= -1;
250         mRsrq = in.readInt();
251         if (mRsrq != Integer.MAX_VALUE) mRsrq *= -1;
252         mRssnr = in.readInt();
253         mCqi = in.readInt();
254         mTimingAdvance = in.readInt();
255         if (DBG) log("CellSignalStrengthLte(Parcel): " + toString());
256     }
257 
258     /** Implement the Parcelable interface */
259     @Override
describeContents()260     public int describeContents() {
261         return 0;
262     }
263 
264     /** Implement the Parcelable interface */
265     @SuppressWarnings("hiding")
266     public static final Parcelable.Creator<CellSignalStrengthLte> CREATOR =
267             new Parcelable.Creator<CellSignalStrengthLte>() {
268         @Override
269         public CellSignalStrengthLte createFromParcel(Parcel in) {
270             return new CellSignalStrengthLte(in);
271         }
272 
273         @Override
274         public CellSignalStrengthLte[] newArray(int size) {
275             return new CellSignalStrengthLte[size];
276         }
277     };
278 
279     /**
280      * log
281      */
log(String s)282     private static void log(String s) {
283         Rlog.w(LOG_TAG, s);
284     }
285 }
286