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.ElapsedRealtimeLong; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.hardware.radio.V1_4.CellInfo.Info; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 29 import java.lang.annotation.Retention; 30 import java.lang.annotation.RetentionPolicy; 31 import java.util.Objects; 32 33 /** 34 * Immutable cell information from a point in time. 35 */ 36 public abstract class CellInfo implements Parcelable { 37 38 /** 39 * This value indicates that the integer field is unreported. 40 */ 41 public static final int UNAVAILABLE = Integer.MAX_VALUE; 42 43 /** 44 * This value indicates that the long field is unreported. 45 */ 46 public static final long UNAVAILABLE_LONG = Long.MAX_VALUE; 47 48 /** 49 * Cell identity type 50 * @hide 51 */ 52 @Retention(RetentionPolicy.SOURCE) 53 @IntDef(prefix = "TYPE_", 54 value = {TYPE_GSM, TYPE_CDMA, TYPE_LTE, TYPE_WCDMA, TYPE_TDSCDMA, TYPE_NR}) 55 public @interface Type {} 56 57 /** 58 * Unknown cell identity type 59 * @hide 60 */ 61 public static final int TYPE_UNKNOWN = 0; 62 63 /** 64 * GSM cell identity type 65 * @hide 66 */ 67 public static final int TYPE_GSM = 1; 68 69 /** 70 * CDMA cell identity type 71 * @hide 72 */ 73 public static final int TYPE_CDMA = 2; 74 75 /** 76 * LTE cell identity type 77 * @hide 78 */ 79 public static final int TYPE_LTE = 3; 80 81 /** 82 * WCDMA cell identity type 83 * @hide 84 */ 85 public static final int TYPE_WCDMA = 4; 86 87 /** 88 * TD-SCDMA cell identity type 89 * @hide 90 */ 91 public static final int TYPE_TDSCDMA = 5; 92 93 /** 94 * 5G cell identity type 95 * @hide 96 */ 97 public static final int TYPE_NR = 6; 98 99 // Type to distinguish where time stamp gets recorded. 100 101 /** @hide */ 102 @UnsupportedAppUsage 103 public static final int TIMESTAMP_TYPE_UNKNOWN = 0; 104 /** @hide */ 105 @UnsupportedAppUsage 106 public static final int TIMESTAMP_TYPE_ANTENNA = 1; 107 /** @hide */ 108 @UnsupportedAppUsage 109 public static final int TIMESTAMP_TYPE_MODEM = 2; 110 /** @hide */ 111 @UnsupportedAppUsage 112 public static final int TIMESTAMP_TYPE_OEM_RIL = 3; 113 /** @hide */ 114 @UnsupportedAppUsage 115 public static final int TIMESTAMP_TYPE_JAVA_RIL = 4; 116 117 /** @hide */ 118 @Retention(RetentionPolicy.SOURCE) 119 @IntDef({ 120 CONNECTION_NONE, 121 CONNECTION_PRIMARY_SERVING, 122 CONNECTION_SECONDARY_SERVING, 123 CONNECTION_UNKNOWN 124 }) 125 public @interface CellConnectionStatus {} 126 127 /** 128 * Cell is not a serving cell. 129 * 130 * <p>The cell has been measured but is neither a camped nor serving cell (3GPP 36.304). 131 */ 132 public static final int CONNECTION_NONE = 0; 133 134 /** UE is connected to cell for signalling and possibly data (3GPP 36.331, 25.331). */ 135 public static final int CONNECTION_PRIMARY_SERVING = 1; 136 137 /** UE is connected to cell for data (3GPP 36.331, 25.331). */ 138 public static final int CONNECTION_SECONDARY_SERVING = 2; 139 140 /** Connection status is unknown. */ 141 public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE; 142 143 /** A cell connection status */ 144 private int mCellConnectionStatus; 145 146 // True if device is mRegistered to the mobile network 147 private boolean mRegistered; 148 149 // Observation time stamped as type in nanoseconds since boot 150 private long mTimeStamp; 151 152 /** @hide */ CellInfo()153 protected CellInfo() { 154 this.mRegistered = false; 155 this.mTimeStamp = Long.MAX_VALUE; 156 this.mCellConnectionStatus = CONNECTION_NONE; 157 } 158 159 /** @hide */ CellInfo(CellInfo ci)160 protected CellInfo(CellInfo ci) { 161 this.mRegistered = ci.mRegistered; 162 this.mTimeStamp = ci.mTimeStamp; 163 this.mCellConnectionStatus = ci.mCellConnectionStatus; 164 } 165 166 /** 167 * True if the phone is registered to a mobile network that provides service on this cell 168 * and this cell is being used or would be used for network signaling. 169 */ isRegistered()170 public boolean isRegistered() { 171 return mRegistered; 172 } 173 174 /** @hide */ setRegistered(boolean registered)175 public void setRegistered(boolean registered) { 176 mRegistered = registered; 177 } 178 179 /** 180 * Approximate time this cell information was received from the modem. 181 * 182 * @return a time stamp in millis since boot. 183 */ 184 @ElapsedRealtimeLong getTimestampMillis()185 public long getTimestampMillis() { 186 return mTimeStamp / 1000000; 187 } 188 189 /** 190 * Approximate time this cell information was received from the modem. 191 * 192 * @return a time stamp in nanos since boot. 193 * @deprecated Use {@link #getTimestampMillis} instead. 194 */ 195 @Deprecated getTimeStamp()196 public long getTimeStamp() { 197 return mTimeStamp; 198 } 199 200 /** @hide */ 201 @VisibleForTesting setTimeStamp(long ts)202 public void setTimeStamp(long ts) { 203 mTimeStamp = ts; 204 } 205 206 /** 207 * @return a {@link CellIdentity} instance. 208 */ 209 @NonNull getCellIdentity()210 public abstract CellIdentity getCellIdentity(); 211 212 /** 213 * @return a {@link CellSignalStrength} instance. 214 */ 215 @NonNull getCellSignalStrength()216 public abstract CellSignalStrength getCellSignalStrength(); 217 218 /** @hide */ sanitizeLocationInfo()219 public CellInfo sanitizeLocationInfo() { 220 return null; 221 } 222 223 /** 224 * Gets the connection status of this cell. 225 * 226 * @see #CONNECTION_NONE 227 * @see #CONNECTION_PRIMARY_SERVING 228 * @see #CONNECTION_SECONDARY_SERVING 229 * @see #CONNECTION_UNKNOWN 230 * 231 * @return The connection status of the cell. 232 */ 233 @CellConnectionStatus getCellConnectionStatus()234 public int getCellConnectionStatus() { 235 return mCellConnectionStatus; 236 } 237 /** @hide */ setCellConnectionStatus(@ellConnectionStatus int cellConnectionStatus)238 public void setCellConnectionStatus(@CellConnectionStatus int cellConnectionStatus) { 239 mCellConnectionStatus = cellConnectionStatus; 240 } 241 242 @Override hashCode()243 public int hashCode() { 244 return Objects.hash(mCellConnectionStatus, mRegistered, mTimeStamp); 245 } 246 247 @Override equals(Object o)248 public boolean equals(Object o) { 249 if (this == o) return true; 250 if (!(o instanceof CellInfo)) return false; 251 CellInfo cellInfo = (CellInfo) o; 252 return mCellConnectionStatus == cellInfo.mCellConnectionStatus 253 && mRegistered == cellInfo.mRegistered 254 && mTimeStamp == cellInfo.mTimeStamp; 255 } 256 257 @Override toString()258 public String toString() { 259 StringBuffer sb = new StringBuffer(); 260 261 sb.append("mRegistered=").append(mRegistered ? "YES" : "NO"); 262 sb.append(" mTimeStamp=").append(mTimeStamp).append("ns"); 263 sb.append(" mCellConnectionStatus=").append(mCellConnectionStatus); 264 265 return sb.toString(); 266 } 267 268 /** 269 * Implement the Parcelable interface 270 */ 271 @Override describeContents()272 public int describeContents() { 273 return 0; 274 } 275 276 /** Implement the Parcelable interface */ 277 @Override writeToParcel(Parcel dest, int flags)278 public abstract void writeToParcel(Parcel dest, int flags); 279 280 /** 281 * Used by child classes for parceling. 282 * 283 * @hide 284 */ writeToParcel(Parcel dest, int flags, int type)285 protected void writeToParcel(Parcel dest, int flags, int type) { 286 dest.writeInt(type); 287 dest.writeInt(mRegistered ? 1 : 0); 288 dest.writeLong(mTimeStamp); 289 dest.writeInt(mCellConnectionStatus); 290 } 291 292 /** 293 * Used by child classes for parceling 294 * 295 * @hide 296 */ CellInfo(Parcel in)297 protected CellInfo(Parcel in) { 298 mRegistered = (in.readInt() == 1) ? true : false; 299 mTimeStamp = in.readLong(); 300 mCellConnectionStatus = in.readInt(); 301 } 302 303 /** Implement the Parcelable interface */ 304 public static final @android.annotation.NonNull Creator<CellInfo> CREATOR = new Creator<CellInfo>() { 305 @Override 306 public CellInfo createFromParcel(Parcel in) { 307 int type = in.readInt(); 308 switch (type) { 309 case TYPE_GSM: return CellInfoGsm.createFromParcelBody(in); 310 case TYPE_CDMA: return CellInfoCdma.createFromParcelBody(in); 311 case TYPE_LTE: return CellInfoLte.createFromParcelBody(in); 312 case TYPE_WCDMA: return CellInfoWcdma.createFromParcelBody(in); 313 case TYPE_TDSCDMA: return CellInfoTdscdma.createFromParcelBody(in); 314 case TYPE_NR: return CellInfoNr.createFromParcelBody(in); 315 default: throw new RuntimeException("Bad CellInfo Parcel"); 316 } 317 } 318 319 @Override 320 public CellInfo[] newArray(int size) { 321 return new CellInfo[size]; 322 } 323 }; 324 325 /** @hide */ CellInfo(android.hardware.radio.V1_0.CellInfo ci)326 protected CellInfo(android.hardware.radio.V1_0.CellInfo ci) { 327 this.mRegistered = ci.registered; 328 this.mTimeStamp = ci.timeStamp; 329 this.mCellConnectionStatus = CONNECTION_UNKNOWN; 330 } 331 332 /** @hide */ CellInfo(android.hardware.radio.V1_2.CellInfo ci)333 protected CellInfo(android.hardware.radio.V1_2.CellInfo ci) { 334 this.mRegistered = ci.registered; 335 this.mTimeStamp = ci.timeStamp; 336 this.mCellConnectionStatus = ci.connectionStatus; 337 } 338 339 /** @hide */ CellInfo(android.hardware.radio.V1_4.CellInfo ci, long timeStamp)340 protected CellInfo(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) { 341 this.mRegistered = ci.isRegistered; 342 this.mTimeStamp = timeStamp; 343 this.mCellConnectionStatus = ci.connectionStatus; 344 } 345 346 /** @hide */ CellInfo(android.hardware.radio.V1_5.CellInfo ci, long timeStamp)347 protected CellInfo(android.hardware.radio.V1_5.CellInfo ci, long timeStamp) { 348 this.mRegistered = ci.registered; 349 this.mTimeStamp = timeStamp; 350 this.mCellConnectionStatus = ci.connectionStatus; 351 } 352 353 /** @hide */ CellInfo(android.hardware.radio.V1_6.CellInfo ci, long timeStamp)354 protected CellInfo(android.hardware.radio.V1_6.CellInfo ci, long timeStamp) { 355 this.mRegistered = ci.registered; 356 this.mTimeStamp = timeStamp; 357 this.mCellConnectionStatus = ci.connectionStatus; 358 } 359 360 /** @hide */ create(android.hardware.radio.V1_0.CellInfo ci)361 public static CellInfo create(android.hardware.radio.V1_0.CellInfo ci) { 362 if (ci == null) return null; 363 switch(ci.cellInfoType) { 364 case android.hardware.radio.V1_0.CellInfoType.GSM: return new CellInfoGsm(ci); 365 case android.hardware.radio.V1_0.CellInfoType.CDMA: return new CellInfoCdma(ci); 366 case android.hardware.radio.V1_0.CellInfoType.LTE: return new CellInfoLte(ci); 367 case android.hardware.radio.V1_0.CellInfoType.WCDMA: return new CellInfoWcdma(ci); 368 case android.hardware.radio.V1_0.CellInfoType.TD_SCDMA: return new CellInfoTdscdma(ci); 369 default: return null; 370 } 371 } 372 373 /** @hide */ create(android.hardware.radio.V1_2.CellInfo ci)374 public static CellInfo create(android.hardware.radio.V1_2.CellInfo ci) { 375 if (ci == null) return null; 376 switch(ci.cellInfoType) { 377 case android.hardware.radio.V1_0.CellInfoType.GSM: return new CellInfoGsm(ci); 378 case android.hardware.radio.V1_0.CellInfoType.CDMA: return new CellInfoCdma(ci); 379 case android.hardware.radio.V1_0.CellInfoType.LTE: return new CellInfoLte(ci); 380 case android.hardware.radio.V1_0.CellInfoType.WCDMA: return new CellInfoWcdma(ci); 381 case android.hardware.radio.V1_0.CellInfoType.TD_SCDMA: return new CellInfoTdscdma(ci); 382 default: return null; 383 } 384 } 385 386 /** @hide */ create(android.hardware.radio.V1_4.CellInfo ci, long timeStamp)387 public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) { 388 if (ci == null) return null; 389 switch (ci.info.getDiscriminator()) { 390 case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci, timeStamp); 391 case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci, timeStamp); 392 case Info.hidl_discriminator.lte: return new CellInfoLte(ci, timeStamp); 393 case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci, timeStamp); 394 case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci, timeStamp); 395 case Info.hidl_discriminator.nr: return new CellInfoNr(ci, timeStamp); 396 default: return null; 397 } 398 } 399 400 /** @hide */ create(android.hardware.radio.V1_5.CellInfo ci, long timeStamp)401 public static CellInfo create(android.hardware.radio.V1_5.CellInfo ci, long timeStamp) { 402 if (ci == null) return null; 403 switch (ci.ratSpecificInfo.getDiscriminator()) { 404 case android.hardware.radio.V1_5.CellInfo 405 .CellInfoRatSpecificInfo.hidl_discriminator.gsm: 406 return new CellInfoGsm(ci, timeStamp); 407 case android.hardware.radio.V1_5.CellInfo 408 .CellInfoRatSpecificInfo.hidl_discriminator.cdma: 409 return new CellInfoCdma(ci, timeStamp); 410 case android.hardware.radio.V1_5.CellInfo 411 .CellInfoRatSpecificInfo.hidl_discriminator.lte: 412 return new CellInfoLte(ci, timeStamp); 413 case android.hardware.radio.V1_5.CellInfo 414 .CellInfoRatSpecificInfo.hidl_discriminator.wcdma: 415 return new CellInfoWcdma(ci, timeStamp); 416 case android.hardware.radio.V1_5.CellInfo 417 .CellInfoRatSpecificInfo.hidl_discriminator.tdscdma: 418 return new CellInfoTdscdma(ci, timeStamp); 419 case android.hardware.radio.V1_5.CellInfo 420 .CellInfoRatSpecificInfo.hidl_discriminator.nr: 421 return new CellInfoNr(ci, timeStamp); 422 default: return null; 423 } 424 } 425 426 /** @hide */ create(android.hardware.radio.V1_6.CellInfo ci, long timeStamp)427 public static CellInfo create(android.hardware.radio.V1_6.CellInfo ci, long timeStamp) { 428 if (ci == null) return null; 429 switch (ci.ratSpecificInfo.getDiscriminator()) { 430 case android.hardware.radio.V1_6.CellInfo 431 .CellInfoRatSpecificInfo.hidl_discriminator.gsm: 432 return new CellInfoGsm(ci, timeStamp); 433 case android.hardware.radio.V1_6.CellInfo 434 .CellInfoRatSpecificInfo.hidl_discriminator.cdma: 435 return new CellInfoCdma(ci, timeStamp); 436 case android.hardware.radio.V1_6.CellInfo 437 .CellInfoRatSpecificInfo.hidl_discriminator.lte: 438 return new CellInfoLte(ci, timeStamp); 439 case android.hardware.radio.V1_6.CellInfo 440 .CellInfoRatSpecificInfo.hidl_discriminator.wcdma: 441 return new CellInfoWcdma(ci, timeStamp); 442 case android.hardware.radio.V1_6.CellInfo 443 .CellInfoRatSpecificInfo.hidl_discriminator.tdscdma: 444 return new CellInfoTdscdma(ci, timeStamp); 445 case android.hardware.radio.V1_6.CellInfo 446 .CellInfoRatSpecificInfo.hidl_discriminator.nr: 447 return new CellInfoNr(ci, timeStamp); 448 default: return null; 449 } 450 } 451 } 452