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.annotation.Nullable; 20 import android.annotation.UnsupportedAppUsage; 21 import android.os.Build; 22 import android.os.Parcel; 23 import android.telephony.gsm.GsmCellLocation; 24 import android.text.TextUtils; 25 26 import java.util.Objects; 27 28 /** 29 * CellIdentity is to represent a unique LTE cell 30 */ 31 public final class CellIdentityLte extends CellIdentity { 32 private static final String TAG = CellIdentityLte.class.getSimpleName(); 33 private static final boolean DBG = false; 34 35 private static final int MAX_CI = 268435455; 36 private static final int MAX_PCI = 503; 37 private static final int MAX_TAC = 65535; 38 private static final int MAX_EARFCN = 262143; 39 private static final int MAX_BANDWIDTH = 20000; 40 41 // 28-bit cell identity 42 private final int mCi; 43 // physical cell id 0..503 44 private final int mPci; 45 // 16-bit tracking area code 46 private final int mTac; 47 // 18-bit Absolute RF Channel Number 48 private final int mEarfcn; 49 // cell bandwidth, in kHz 50 private final int mBandwidth; 51 52 /** 53 * @hide 54 */ 55 @UnsupportedAppUsage CellIdentityLte()56 public CellIdentityLte() { 57 super(TAG, CellInfo.TYPE_LTE, null, null, null, null); 58 mCi = CellInfo.UNAVAILABLE; 59 mPci = CellInfo.UNAVAILABLE; 60 mTac = CellInfo.UNAVAILABLE; 61 mEarfcn = CellInfo.UNAVAILABLE; 62 mBandwidth = CellInfo.UNAVAILABLE; 63 } 64 65 /** 66 * 67 * @param mcc 3-digit Mobile Country Code, 0..999 68 * @param mnc 2 or 3-digit Mobile Network Code, 0..999 69 * @param ci 28-bit Cell Identity 70 * @param pci Physical Cell Id 0..503 71 * @param tac 16-bit Tracking Area Code 72 * 73 * @hide 74 */ 75 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac)76 public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) { 77 this(ci, pci, tac, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, String.valueOf(mcc), 78 String.valueOf(mnc), null, null); 79 } 80 81 /** 82 * 83 * @param ci 28-bit Cell Identity 84 * @param pci Physical Cell Id 0..503 85 * @param tac 16-bit Tracking Area Code 86 * @param earfcn 18-bit LTE Absolute RF Channel Number 87 * @param bandwidth cell bandwidth in kHz 88 * @param mccStr 3-digit Mobile Country Code in string format 89 * @param mncStr 2 or 3-digit Mobile Network Code in string format 90 * @param alphal long alpha Operator Name String or Enhanced Operator Name String 91 * @param alphas short alpha Operator Name String or Enhanced Operator Name String 92 * 93 * @hide 94 */ CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, String mccStr, String mncStr, String alphal, String alphas)95 public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth, String mccStr, 96 String mncStr, String alphal, String alphas) { 97 super(TAG, CellInfo.TYPE_LTE, mccStr, mncStr, alphal, alphas); 98 mCi = inRangeOrUnavailable(ci, 0, MAX_CI); 99 mPci = inRangeOrUnavailable(pci, 0, MAX_PCI); 100 mTac = inRangeOrUnavailable(tac, 0, MAX_TAC); 101 mEarfcn = inRangeOrUnavailable(earfcn, 0, MAX_EARFCN); 102 mBandwidth = inRangeOrUnavailable(bandwidth, 0, MAX_BANDWIDTH); 103 } 104 105 /** @hide */ CellIdentityLte(android.hardware.radio.V1_0.CellIdentityLte cid)106 public CellIdentityLte(android.hardware.radio.V1_0.CellIdentityLte cid) { 107 this(cid.ci, cid.pci, cid.tac, cid.earfcn, CellInfo.UNAVAILABLE, cid.mcc, cid.mnc, "", ""); 108 } 109 110 /** @hide */ CellIdentityLte(android.hardware.radio.V1_2.CellIdentityLte cid)111 public CellIdentityLte(android.hardware.radio.V1_2.CellIdentityLte cid) { 112 this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, cid.bandwidth, 113 cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong, 114 cid.operatorNames.alphaShort); 115 } 116 CellIdentityLte(CellIdentityLte cid)117 private CellIdentityLte(CellIdentityLte cid) { 118 this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mBandwidth, cid.mMccStr, 119 cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort); 120 } 121 122 /** @hide */ sanitizeLocationInfo()123 public CellIdentityLte sanitizeLocationInfo() { 124 return new CellIdentityLte(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, 125 CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, 126 mMccStr, mMncStr, mAlphaLong, mAlphaShort); 127 } 128 copy()129 CellIdentityLte copy() { 130 return new CellIdentityLte(this); 131 } 132 133 /** 134 * @return 3-digit Mobile Country Code, 0..999, 135 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 136 * @deprecated Use {@link #getMccString} instead. 137 */ 138 @Deprecated getMcc()139 public int getMcc() { 140 return (mMccStr != null) ? Integer.valueOf(mMccStr) : CellInfo.UNAVAILABLE; 141 } 142 143 /** 144 * @return 2 or 3-digit Mobile Network Code, 0..999, 145 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 146 * @deprecated Use {@link #getMncString} instead. 147 */ 148 @Deprecated getMnc()149 public int getMnc() { 150 return (mMncStr != null) ? Integer.valueOf(mMncStr) : CellInfo.UNAVAILABLE; 151 } 152 153 /** 154 * @return 28-bit Cell Identity, 155 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 156 */ getCi()157 public int getCi() { 158 return mCi; 159 } 160 161 /** 162 * @return Physical Cell Id 0..503, 163 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 164 */ getPci()165 public int getPci() { 166 return mPci; 167 } 168 169 /** 170 * @return 16-bit Tracking Area Code, 171 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 172 */ getTac()173 public int getTac() { 174 return mTac; 175 } 176 177 /** 178 * @return 18-bit Absolute RF Channel Number, 179 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 180 */ getEarfcn()181 public int getEarfcn() { 182 return mEarfcn; 183 } 184 185 /** 186 * @return Cell bandwidth in kHz, 187 * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable. 188 */ getBandwidth()189 public int getBandwidth() { 190 return mBandwidth; 191 } 192 193 /** 194 * @return Mobile Country Code in string format, null if unavailable. 195 */ 196 @Nullable getMccString()197 public String getMccString() { 198 return mMccStr; 199 } 200 201 /** 202 * @return Mobile Network Code in string format, null if unavailable. 203 */ 204 @Nullable getMncString()205 public String getMncString() { 206 return mMncStr; 207 } 208 209 /** 210 * @return a 5 or 6 character string (MCC+MNC), null if any field is unknown. 211 */ 212 @Nullable getMobileNetworkOperator()213 public String getMobileNetworkOperator() { 214 return (mMccStr == null || mMncStr == null) ? null : mMccStr + mMncStr; 215 } 216 217 /** @hide */ 218 @Override getChannelNumber()219 public int getChannelNumber() { 220 return mEarfcn; 221 } 222 223 /** 224 * A hack to allow tunneling of LTE information via GsmCellLocation 225 * so that older Network Location Providers can return some information 226 * on LTE only networks, see bug 9228974. 227 * 228 * The tunnel'd LTE information is returned as follows: 229 * LAC = TAC field 230 * CID = CI field 231 * PSC = 0. 232 * 233 * @hide 234 */ 235 @Override asCellLocation()236 public GsmCellLocation asCellLocation() { 237 GsmCellLocation cl = new GsmCellLocation(); 238 int tac = mTac != CellInfo.UNAVAILABLE ? mTac : -1; 239 int cid = mCi != CellInfo.UNAVAILABLE ? mCi : -1; 240 cl.setLacAndCid(tac, cid); 241 cl.setPsc(0); 242 return cl; 243 } 244 245 @Override hashCode()246 public int hashCode() { 247 return Objects.hash(mCi, mPci, mTac, super.hashCode()); 248 } 249 250 @Override equals(Object other)251 public boolean equals(Object other) { 252 if (this == other) { 253 return true; 254 } 255 256 if (!(other instanceof CellIdentityLte)) { 257 return false; 258 } 259 260 CellIdentityLte o = (CellIdentityLte) other; 261 return mCi == o.mCi 262 && mPci == o.mPci 263 && mTac == o.mTac 264 && mEarfcn == o.mEarfcn 265 && mBandwidth == o.mBandwidth 266 && TextUtils.equals(mMccStr, o.mMccStr) 267 && TextUtils.equals(mMncStr, o.mMncStr) 268 && super.equals(other); 269 } 270 271 @Override toString()272 public String toString() { 273 return new StringBuilder(TAG) 274 .append(":{ mCi=").append(mCi) 275 .append(" mPci=").append(mPci) 276 .append(" mTac=").append(mTac) 277 .append(" mEarfcn=").append(mEarfcn) 278 .append(" mBandwidth=").append(mBandwidth) 279 .append(" mMcc=").append(mMccStr) 280 .append(" mMnc=").append(mMncStr) 281 .append(" mAlphaLong=").append(mAlphaLong) 282 .append(" mAlphaShort=").append(mAlphaShort) 283 .append("}").toString(); 284 } 285 286 /** Implement the Parcelable interface */ 287 @Override writeToParcel(Parcel dest, int flags)288 public void writeToParcel(Parcel dest, int flags) { 289 if (DBG) log("writeToParcel(Parcel, int): " + toString()); 290 super.writeToParcel(dest, CellInfo.TYPE_LTE); 291 dest.writeInt(mCi); 292 dest.writeInt(mPci); 293 dest.writeInt(mTac); 294 dest.writeInt(mEarfcn); 295 dest.writeInt(mBandwidth); 296 } 297 298 /** Construct from Parcel, type has already been processed */ CellIdentityLte(Parcel in)299 private CellIdentityLte(Parcel in) { 300 super(TAG, CellInfo.TYPE_LTE, in); 301 mCi = in.readInt(); 302 mPci = in.readInt(); 303 mTac = in.readInt(); 304 mEarfcn = in.readInt(); 305 mBandwidth = in.readInt(); 306 307 if (DBG) log(toString()); 308 } 309 310 /** Implement the Parcelable interface */ 311 @SuppressWarnings("hiding") 312 public static final @android.annotation.NonNull Creator<CellIdentityLte> CREATOR = 313 new Creator<CellIdentityLte>() { 314 @Override 315 public CellIdentityLte createFromParcel(Parcel in) { 316 in.readInt(); // skip; 317 return createFromParcelBody(in); 318 } 319 320 @Override 321 public CellIdentityLte[] newArray(int size) { 322 return new CellIdentityLte[size]; 323 } 324 }; 325 326 /** @hide */ createFromParcelBody(Parcel in)327 protected static CellIdentityLte createFromParcelBody(Parcel in) { 328 return new CellIdentityLte(in); 329 } 330 } 331