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