1 /*
2  * Copyright 2017 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.CallSuper;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.text.TextUtils;
24 
25 import java.util.Objects;
26 import java.util.UUID;
27 
28 /**
29  * CellIdentity represents the identity of a unique cell. This is the base class for
30  * CellIdentityXxx which represents cell identity for specific network access technology.
31  */
32 public abstract class CellIdentity implements Parcelable {
33 
34     /** @hide */
35     public static final int INVALID_CHANNEL_NUMBER = -1;
36 
37     // Log tag
38     /** @hide */
39     protected final String mTag;
40     // Cell identity type
41     /** @hide */
42     protected final int mType;
43     // 3-digit Mobile Country Code in string format. Null for CDMA cell identity.
44     /** @hide */
45     protected final String mMccStr;
46     // 2 or 3-digit Mobile Network Code in string format. Null for CDMA cell identity.
47     /** @hide */
48     protected final String mMncStr;
49 
50     // long alpha Operator Name String or Enhanced Operator Name String
51     /** @hide */
52     protected String mAlphaLong;
53     // short alpha Operator Name String or Enhanced Operator Name String
54     /** @hide */
55     protected String mAlphaShort;
56 
57     /** @hide */
CellIdentity(String tag, int type, String mcc, String mnc, String alphal, String alphas)58     protected CellIdentity(String tag, int type, String mcc, String mnc, String alphal,
59                            String alphas) {
60         mTag = tag;
61         mType = type;
62 
63         // Only allow INT_MAX if unknown string mcc/mnc
64         if (mcc == null || mcc.matches("^[0-9]{3}$")) {
65             mMccStr = mcc;
66         } else if (mcc.isEmpty() || mcc.equals(String.valueOf(Integer.MAX_VALUE))) {
67             // If the mccStr is empty or unknown, set it as null.
68             mMccStr = null;
69         } else {
70             // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MCC format
71             // after the bug got fixed.
72             mMccStr = null;
73             log("invalid MCC format: " + mcc);
74         }
75 
76         if (mnc == null || mnc.matches("^[0-9]{2,3}$")) {
77             mMncStr = mnc;
78         } else if (mnc.isEmpty() || mnc.equals(String.valueOf(Integer.MAX_VALUE))) {
79             // If the mncStr is empty or unknown, set it as null.
80             mMncStr = null;
81         } else {
82             // TODO: b/69384059 Should throw IllegalArgumentException for the invalid MNC format
83             // after the bug got fixed.
84             mMncStr = null;
85             log("invalid MNC format: " + mnc);
86         }
87 
88         if ((mMccStr != null && mMncStr == null) || (mMccStr == null && mMncStr != null)) {
89             AnomalyReporter.reportAnomaly(
90                     UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
91                     "CellIdentity Missing Half of PLMN ID");
92         }
93 
94         mAlphaLong = alphal;
95         mAlphaShort = alphas;
96     }
97 
98     /** Implement the Parcelable interface */
99     @Override
describeContents()100     public int describeContents() {
101         return 0;
102     }
103 
104     /**
105      * @hide
106      * @return The type of the cell identity
107      */
getType()108     public @CellInfo.Type int getType() {
109         return mType;
110     }
111 
112     /**
113      * @return MCC or null for CDMA
114      * @hide
115      */
getMccString()116     public String getMccString() {
117         return mMccStr;
118     }
119 
120     /**
121      * @return MNC or null for CDMA
122      * @hide
123      */
getMncString()124     public String getMncString() {
125         return mMncStr;
126     }
127 
128     /**
129      * Returns the channel number of the cell identity.
130      *
131      * @hide
132      * @return The channel number, or {@link #INVALID_CHANNEL_NUMBER} if not implemented
133      */
getChannelNumber()134     public int getChannelNumber() {
135         return INVALID_CHANNEL_NUMBER;
136     }
137 
138     /**
139      * @return The long alpha tag associated with the current scan result (may be the operator
140      * name string or extended operator name string). May be null if unknown.
141      */
142     @Nullable
getOperatorAlphaLong()143     public CharSequence getOperatorAlphaLong() {
144         return mAlphaLong;
145     }
146 
147     /**
148      * @hide
149      */
setOperatorAlphaLong(String alphaLong)150     public void setOperatorAlphaLong(String alphaLong) {
151         mAlphaLong = alphaLong;
152     }
153 
154     /**
155      * @return The short alpha tag associated with the current scan result (may be the operator
156      * name string or extended operator name string).  May be null if unknown.
157      */
158     @Nullable
getOperatorAlphaShort()159     public CharSequence getOperatorAlphaShort() {
160         return mAlphaShort;
161     }
162 
163     /**
164      * @hide
165      */
setOperatorAlphaShort(String alphaShort)166     public void setOperatorAlphaShort(String alphaShort) {
167         mAlphaShort = alphaShort;
168     }
169 
170     /**
171      * @return a CellLocation object for this CellIdentity
172      * @hide
173      */
asCellLocation()174     public abstract CellLocation asCellLocation();
175 
176     @Override
equals(Object other)177     public boolean equals(Object other) {
178         if (!(other instanceof CellIdentity)) {
179             return false;
180         }
181 
182         CellIdentity o = (CellIdentity) other;
183         return mType == o.mType
184                 && TextUtils.equals(mMccStr, o.mMccStr)
185                 && TextUtils.equals(mMncStr, o.mMncStr)
186                 && TextUtils.equals(mAlphaLong, o.mAlphaLong)
187                 && TextUtils.equals(mAlphaShort, o.mAlphaShort);
188     }
189 
190     @Override
hashCode()191     public int hashCode() {
192         return Objects.hash(mAlphaLong, mAlphaShort, mMccStr, mMncStr, mType);
193     }
194 
195     /**
196      * Used by child classes for parceling.
197      *
198      * @hide
199      */
200     @CallSuper
writeToParcel(Parcel dest, int type)201     public void writeToParcel(Parcel dest, int type) {
202         dest.writeInt(type);
203         dest.writeString(mMccStr);
204         dest.writeString(mMncStr);
205         dest.writeString(mAlphaLong);
206         dest.writeString(mAlphaShort);
207     }
208 
209     /**
210      * Construct from Parcel
211      * @hide
212      */
CellIdentity(String tag, int type, Parcel source)213     protected CellIdentity(String tag, int type, Parcel source) {
214         this(tag, type, source.readString(), source.readString(),
215                 source.readString(), source.readString());
216     }
217 
218     /** Implement the Parcelable interface */
219     public static final @android.annotation.NonNull Creator<CellIdentity> CREATOR =
220             new Creator<CellIdentity>() {
221                 @Override
222                 public CellIdentity createFromParcel(Parcel in) {
223                     int type = in.readInt();
224                     switch (type) {
225                         case CellInfo.TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
226                         case CellInfo.TYPE_WCDMA: return CellIdentityWcdma.createFromParcelBody(in);
227                         case CellInfo.TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
228                         case CellInfo.TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
229                         case CellInfo.TYPE_TDSCDMA:
230                             return CellIdentityTdscdma.createFromParcelBody(in);
231                         case CellInfo.TYPE_NR: return CellIdentityNr.createFromParcelBody(in);
232                         default: throw new IllegalArgumentException("Bad Cell identity Parcel");
233                     }
234                 }
235 
236                 @Override
237                 public CellIdentity[] newArray(int size) {
238                     return new CellIdentity[size];
239                 }
240             };
241 
242     /** @hide */
log(String s)243     protected void log(String s) {
244         Rlog.w(mTag, s);
245     }
246 
247     /** @hide */
inRangeOrUnavailable(int value, int rangeMin, int rangeMax)248     protected static final int inRangeOrUnavailable(int value, int rangeMin, int rangeMax) {
249         if (value < rangeMin || value > rangeMax) return CellInfo.UNAVAILABLE;
250         return value;
251     }
252 
253     /** @hide */
inRangeOrUnavailable(long value, long rangeMin, long rangeMax)254     protected static final long inRangeOrUnavailable(long value, long rangeMin, long rangeMax) {
255         if (value < rangeMin || value > rangeMax) return CellInfo.UNAVAILABLE_LONG;
256         return value;
257     }
258 
259     /** @hide */
inRangeOrUnavailable( int value, int rangeMin, int rangeMax, int special)260     protected static final int inRangeOrUnavailable(
261             int value, int rangeMin, int rangeMax, int special) {
262         if ((value < rangeMin || value > rangeMax) && value != special) return CellInfo.UNAVAILABLE;
263         return value;
264     }
265 }
266