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