• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 static android.text.TextUtils.formatSimple;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.compat.annotation.UnsupportedAppUsage;
24 import android.os.Parcel;
25 import android.telephony.gsm.GsmCellLocation;
26 import android.text.TextUtils;
27 import android.util.ArraySet;
28 
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Objects;
32 import java.util.Set;
33 
34 /**
35  * CellIdentity to represent a unique UMTS cell
36  */
37 public final class CellIdentityWcdma extends CellIdentity {
38     private static final String TAG = CellIdentityWcdma.class.getSimpleName();
39     private static final boolean DBG = false;
40 
41     private static final int MAX_LAC = 65535;
42     private static final int MAX_CID = 268435455;
43     private static final int MAX_PSC = 511;
44     private static final int MAX_UARFCN = 16383; // a 14 bit number; TS 25.331 ex sec 10.3.8.15
45 
46     // 16-bit Location Area Code, 0..65535
47     private final int mLac;
48     // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455
49     private final int mCid;
50     // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
51     private final int mPsc;
52     // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.4
53     @UnsupportedAppUsage
54     private final int mUarfcn;
55 
56     // a list of additional PLMN-IDs reported for this cell
57     private final ArraySet<String> mAdditionalPlmns;
58 
59     @Nullable
60     private final ClosedSubscriberGroupInfo mCsgInfo;
61 
62     /**
63      * @hide
64      */
CellIdentityWcdma()65     public CellIdentityWcdma() {
66         super(TAG, CellInfo.TYPE_WCDMA, null, null, null, null);
67         mLac = CellInfo.UNAVAILABLE;
68         mCid = CellInfo.UNAVAILABLE;
69         mPsc = CellInfo.UNAVAILABLE;
70         mUarfcn = CellInfo.UNAVAILABLE;
71         mAdditionalPlmns = new ArraySet<>();
72         mCsgInfo = null;
73         mGlobalCellId = null;
74     }
75 
76     /**
77      * public constructor
78      * @param lac 16-bit Location Area Code, 0..65535
79      * @param cid 28-bit UMTS Cell Identity
80      * @param psc 9-bit UMTS Primary Scrambling Code
81      * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
82      * @param mccStr 3-digit Mobile Country Code in string format
83      * @param mncStr 2 or 3-digit Mobile Network Code in string format
84      * @param alphal long alpha Operator Name String or Enhanced Operator Name String
85      * @param alphas short alpha Operator Name String or Enhanced Operator Name String
86      * @param additionalPlmns a list of additional PLMN IDs broadcast by the cell
87      * @param csgInfo info about the closed subscriber group broadcast by the cell
88      *
89      * @hide
90      */
CellIdentityWcdma(int lac, int cid, int psc, int uarfcn, @Nullable String mccStr, @Nullable String mncStr, @Nullable String alphal, @Nullable String alphas, @NonNull Collection<String> additionalPlmns, @Nullable ClosedSubscriberGroupInfo csgInfo)91     public CellIdentityWcdma(int lac, int cid, int psc, int uarfcn, @Nullable String mccStr,
92             @Nullable String mncStr, @Nullable String alphal, @Nullable String alphas,
93             @NonNull Collection<String> additionalPlmns,
94             @Nullable ClosedSubscriberGroupInfo csgInfo) {
95         super(TAG, CellInfo.TYPE_WCDMA, mccStr, mncStr, alphal, alphas);
96         mLac = inRangeOrUnavailable(lac, 0, MAX_LAC);
97         mCid = inRangeOrUnavailable(cid, 0, MAX_CID);
98         mPsc = inRangeOrUnavailable(psc, 0, MAX_PSC);
99         mUarfcn = inRangeOrUnavailable(uarfcn, 0, MAX_UARFCN);
100         mAdditionalPlmns = new ArraySet<>(additionalPlmns.size());
101         for (String plmn : additionalPlmns) {
102             if (isValidPlmn(plmn)) {
103                 mAdditionalPlmns.add(plmn);
104             }
105         }
106         mCsgInfo = csgInfo;
107         updateGlobalCellId();
108     }
109 
CellIdentityWcdma(@onNull CellIdentityWcdma cid)110     private CellIdentityWcdma(@NonNull CellIdentityWcdma cid) {
111         this(cid.mLac, cid.mCid, cid.mPsc, cid.mUarfcn, cid.mMccStr,
112                 cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo);
113     }
114 
115     /** @hide */
116     @Override
sanitizeLocationInfo()117     public @NonNull CellIdentityWcdma sanitizeLocationInfo() {
118         return new CellIdentityWcdma(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
119                 CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mMccStr, mMncStr,
120                 mAlphaLong, mAlphaShort, mAdditionalPlmns, null);
121     }
122 
copy()123     @NonNull CellIdentityWcdma copy() {
124         return new CellIdentityWcdma(this);
125     }
126 
127     /** @hide */
128     @Override
updateGlobalCellId()129     protected void updateGlobalCellId() {
130         mGlobalCellId = null;
131         String plmn = getPlmn();
132         if (plmn == null) return;
133 
134         if (mLac == CellInfo.UNAVAILABLE || mCid == CellInfo.UNAVAILABLE) return;
135 
136         mGlobalCellId = plmn + formatSimple("%04x%04x", mLac, mCid);
137     }
138 
139     /**
140      * @return 3-digit Mobile Country Code, 0..999,
141      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
142      * @deprecated Use {@link #getMccString} instead.
143      */
144     @Deprecated
getMcc()145     public int getMcc() {
146         return (mMccStr != null) ? Integer.valueOf(mMccStr) : CellInfo.UNAVAILABLE;
147     }
148 
149     /**
150      * @return 2 or 3-digit Mobile Network Code, 0..999,
151      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
152      * @deprecated Use {@link #getMncString} instead.
153      */
154     @Deprecated
getMnc()155     public int getMnc() {
156         return (mMncStr != null) ? Integer.valueOf(mMncStr) : CellInfo.UNAVAILABLE;
157     }
158 
159     /**
160      * @return 16-bit Location Area Code, 0..65535,
161      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
162      */
getLac()163     public int getLac() {
164         return mLac;
165     }
166 
167     /**
168      * @return CID
169      * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455,
170      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
171      */
getCid()172     public int getCid() {
173         return mCid;
174     }
175 
176     /**
177      * @return 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511,
178      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
179      */
getPsc()180     public int getPsc() {
181         return mPsc;
182     }
183 
184     /**
185      * @return Mobile Country Code in string version, null if unavailable.
186      */
187     @Nullable
getMccString()188     public String getMccString() {
189         return mMccStr;
190     }
191 
192     /**
193      * @return Mobile Network Code in string version, null if unavailable.
194      */
195     @Nullable
getMncString()196     public String getMncString() {
197         return mMncStr;
198     }
199 
200     /**
201      * @return a 5 or 6 character string (MCC+MNC), null if any field is unknown
202      */
203     @Nullable
getMobileNetworkOperator()204     public String getMobileNetworkOperator() {
205         return (mMccStr == null || mMncStr == null) ? null : mMccStr + mMncStr;
206     }
207 
208     @Override
hashCode()209     public int hashCode() {
210         return Objects.hash(mLac, mCid, mPsc, mAdditionalPlmns.hashCode(), super.hashCode());
211     }
212 
213     /**
214      * @return 16-bit UMTS Absolute RF Channel Number,
215      *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
216      */
getUarfcn()217     public int getUarfcn() {
218         return mUarfcn;
219     }
220 
221     /** @hide */
222     @Override
getChannelNumber()223     public int getChannelNumber() {
224         return mUarfcn;
225     }
226 
227     /**
228      * @return a list of additional PLMN IDs supported by this cell.
229      */
230     @NonNull
getAdditionalPlmns()231     public Set<String> getAdditionalPlmns() {
232         return Collections.unmodifiableSet(mAdditionalPlmns);
233     }
234 
235     /**
236      * @return closed subscriber group information about the cell if available, otherwise null.
237      */
238     @Nullable
getClosedSubscriberGroupInfo()239     public ClosedSubscriberGroupInfo getClosedSubscriberGroupInfo() {
240         return mCsgInfo;
241     }
242 
243     /** @hide */
244     @NonNull
245     @Override
asCellLocation()246     public GsmCellLocation asCellLocation() {
247         GsmCellLocation cl = new GsmCellLocation();
248         int lac = mLac != CellInfo.UNAVAILABLE ? mLac : -1;
249         int cid = mCid != CellInfo.UNAVAILABLE ? mCid : -1;
250         int psc = mPsc != CellInfo.UNAVAILABLE ? mPsc : -1;
251         cl.setLacAndCid(lac, cid);
252         cl.setPsc(psc);
253 
254         return cl;
255     }
256 
257     @Override
equals(Object other)258     public boolean equals(Object other) {
259         if (this == other) {
260             return true;
261         }
262 
263         if (!(other instanceof CellIdentityWcdma)) {
264             return false;
265         }
266 
267         CellIdentityWcdma o = (CellIdentityWcdma) other;
268         return mLac == o.mLac
269                 && mCid == o.mCid
270                 && mPsc == o.mPsc
271                 && mUarfcn == o.mUarfcn
272                 && TextUtils.equals(mMccStr, o.mMccStr)
273                 && TextUtils.equals(mMncStr, o.mMncStr)
274                 && mAdditionalPlmns.equals(o.mAdditionalPlmns)
275                 && Objects.equals(mCsgInfo, o.mCsgInfo)
276                 && super.equals(other);
277     }
278 
279     @Override
toString()280     public String toString() {
281         return new StringBuilder(TAG)
282         .append(":{ mLac=").append(mLac)
283         .append(" mCid=").append(mCid)
284         .append(" mPsc=").append(mPsc)
285         .append(" mUarfcn=").append(mUarfcn)
286         .append(" mMcc=").append(mMccStr)
287         .append(" mMnc=").append(mMncStr)
288         .append(" mAlphaLong=").append(mAlphaLong)
289         .append(" mAlphaShort=").append(mAlphaShort)
290         .append(" mAdditionalPlmns=").append(mAdditionalPlmns)
291         .append(" mCsgInfo=").append(mCsgInfo)
292         .append("}").toString();
293     }
294 
295     /** Implement the Parcelable interface */
296     @Override
writeToParcel(Parcel dest, int flags)297     public void writeToParcel(Parcel dest, int flags) {
298         if (DBG) log("writeToParcel(Parcel, int): " + toString());
299         super.writeToParcel(dest, CellInfo.TYPE_WCDMA);
300         dest.writeInt(mLac);
301         dest.writeInt(mCid);
302         dest.writeInt(mPsc);
303         dest.writeInt(mUarfcn);
304         dest.writeArraySet(mAdditionalPlmns);
305         dest.writeParcelable(mCsgInfo, flags);
306     }
307 
308     /** Construct from Parcel, type has already been processed */
CellIdentityWcdma(Parcel in)309     private CellIdentityWcdma(Parcel in) {
310         super(TAG, CellInfo.TYPE_WCDMA, in);
311         mLac = in.readInt();
312         mCid = in.readInt();
313         mPsc = in.readInt();
314         mUarfcn = in.readInt();
315         mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null);
316         mCsgInfo = in.readParcelable(null, android.telephony.ClosedSubscriberGroupInfo.class);
317 
318         updateGlobalCellId();
319         if (DBG) log(toString());
320     }
321 
322     /** Implement the Parcelable interface */
323     @SuppressWarnings("hiding")
324     public static final @android.annotation.NonNull Creator<CellIdentityWcdma> CREATOR =
325             new Creator<CellIdentityWcdma>() {
326                 @Override
327                 public CellIdentityWcdma createFromParcel(Parcel in) {
328                     in.readInt();   // skip
329                     return createFromParcelBody(in);
330                 }
331 
332                 @Override
333                 public CellIdentityWcdma[] newArray(int size) {
334                     return new CellIdentityWcdma[size];
335                 }
336             };
337 
338     /** @hide */
createFromParcelBody(Parcel in)339     protected static CellIdentityWcdma createFromParcelBody(Parcel in) {
340         return new CellIdentityWcdma(in);
341     }
342 }
343