blob: 8dd7bdd578417f45719d7b32e7df2771bd26b103 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.telephony.AccessNetworkConstants.NgranBands.NgranBand;
import android.telephony.gsm.GsmCellLocation;
import android.util.ArraySet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
/**
* Information to represent a unique NR(New Radio 5G) cell.
*/
public final class CellIdentityNr extends CellIdentity {
private static final String TAG = "CellIdentityNr";
private static final int MAX_PCI = 1007;
private static final int MAX_TAC = 65535;
private static final int MAX_NRARFCN = 3279165;
private static final long MAX_NCI = 68719476735L;
private final int mNrArfcn;
private final int mPci;
private final int mTac;
private final long mNci;
private final int[] mBands;
// a list of additional PLMN-IDs reported for this cell
private final ArraySet<String> mAdditionalPlmns;
/**
*
* @param pci Physical Cell Id in range [0, 1007].
* @param tac 16-bit Tracking Area Code.
* @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165].
* @param bands Bands used by the cell. Band number defined in 3GPP TS 38.101-1 and TS 38.101-2.
* @param mccStr 3-digit Mobile Country Code in string format.
* @param mncStr 2 or 3-digit Mobile Network Code in string format.
* @param nci The 36-bit NR Cell Identity in range [0, 68719476735].
* @param alphal long alpha Operator Name String or Enhanced Operator Name String.
* @param alphas short alpha Operator Name String or Enhanced Operator Name String.
* @param additionalPlmns a list of additional PLMN IDs broadcast by the cell
*
* @hide
*/
public CellIdentityNr(int pci, int tac, int nrArfcn, @NonNull @NgranBand int[] bands,
@Nullable String mccStr, @Nullable String mncStr, long nci,
@Nullable String alphal, @Nullable String alphas,
@NonNull Collection<String> additionalPlmns) {
super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas);
mPci = inRangeOrUnavailable(pci, 0, MAX_PCI);
mTac = inRangeOrUnavailable(tac, 0, MAX_TAC);
mNrArfcn = inRangeOrUnavailable(nrArfcn, 0, MAX_NRARFCN);
// TODO: input validation for bands
mBands = bands;
mNci = inRangeOrUnavailable(nci, 0, MAX_NCI);
mAdditionalPlmns = new ArraySet<>(additionalPlmns.size());
for (String plmn : additionalPlmns) {
if (isValidPlmn(plmn)) {
mAdditionalPlmns.add(plmn);
}
}
updateGlobalCellId();
}
/** @hide */
public CellIdentityNr(@NonNull android.hardware.radio.V1_4.CellIdentityNr cid) {
this(cid.pci, cid.tac, cid.nrarfcn, new int[] {}, cid.mcc, cid.mnc, cid.nci,
cid.operatorNames.alphaLong, cid.operatorNames.alphaShort,
new ArraySet<>());
}
/** @hide */
public CellIdentityNr(@NonNull android.hardware.radio.V1_5.CellIdentityNr cid) {
this(cid.base.pci, cid.base.tac, cid.base.nrarfcn,
cid.bands.stream().mapToInt(Integer::intValue).toArray(), cid.base.mcc,
cid.base.mnc, cid.base.nci, cid.base.operatorNames.alphaLong,
cid.base.operatorNames.alphaShort, cid.additionalPlmns);
}
/** @hide */
@Override
public @NonNull CellIdentityNr sanitizeLocationInfo() {
return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mNrArfcn,
mBands, mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort,
mAdditionalPlmns);
}
/** @hide */
protected void updateGlobalCellId() {
mGlobalCellId = null;
String plmn = getPlmn();
if (plmn == null) return;
if (mNci == CellInfo.UNAVAILABLE_LONG) return;
mGlobalCellId = plmn + String.format("%09x", mNci);
}
/**
* @return a CellLocation object for this CellIdentity.
* @hide
*/
@NonNull
@Override
public CellLocation asCellLocation() {
return new GsmCellLocation();
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), mPci, mTac,
mNrArfcn, Arrays.hashCode(mBands), mNci, mAdditionalPlmns.hashCode());
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof CellIdentityNr)) {
return false;
}
CellIdentityNr o = (CellIdentityNr) other;
return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn
&& Arrays.equals(mBands, o.mBands) && mNci == o.mNci
&& mAdditionalPlmns.equals(o.mAdditionalPlmns);
}
/**
* Get the NR(New Radio 5G) Cell Identity.
*
* @return The 36-bit NR Cell Identity in range [0, 68719476735] or
* {@link CellInfo#UNAVAILABLE_LONG} if unknown.
*/
public long getNci() {
return mNci;
}
/**
* Get the New Radio Absolute Radio Frequency Channel Number.
*
* Reference: 3GPP TS 38.101-1 section 5.4.2.1 NR-ARFCN and channel raster.
* Reference: 3GPP TS 38.101-2 section 5.4.2.1 NR-ARFCN and channel raster.
*
* @return Integer value in range [0, 3279165] or {@link CellInfo#UNAVAILABLE} if unknown.
*/
@IntRange(from = 0, to = 3279165)
public int getNrarfcn() {
return mNrArfcn;
}
/**
* Get bands of the cell
*
* Reference: TS 38.101-1 table 5.2-1
* Reference: TS 38.101-2 table 5.2-1
*
* @return Array of band number or empty array if not available.
*/
@NgranBand
@NonNull
public int[] getBands() {
return Arrays.copyOf(mBands, mBands.length);
}
/**
* Get the physical cell id.
* @return Integer value in range [0, 1007] or {@link CellInfo#UNAVAILABLE} if unknown.
*/
@IntRange(from = 0, to = 1007)
public int getPci() {
return mPci;
}
/**
* Get the tracking area code.
* @return a 16 bit integer or {@link CellInfo#UNAVAILABLE} if unknown.
*/
@IntRange(from = 0, to = 65535)
public int getTac() {
return mTac;
}
/**
* @return Mobile Country Code in string format, or {@code null} if unknown.
*/
@Nullable
public String getMccString() {
return mMccStr;
}
/**
* @return Mobile Network Code in string fomrat, or {@code null} if unknown.
*/
@Nullable
public String getMncString() {
return mMncStr;
}
/** @hide */
@Override
public int getChannelNumber() {
return mNrArfcn;
}
/**
* @return a list of additional PLMN IDs supported by this cell.
*/
@NonNull
public Set<String> getAdditionalPlmns() {
return Collections.unmodifiableSet(mAdditionalPlmns);
}
@Override
public String toString() {
return new StringBuilder(TAG + ":{")
.append(" mPci = ").append(mPci)
.append(" mTac = ").append(mTac)
.append(" mNrArfcn = ").append(mNrArfcn)
.append(" mBands = ").append(mBands)
.append(" mMcc = ").append(mMccStr)
.append(" mMnc = ").append(mMncStr)
.append(" mNci = ").append(mNci)
.append(" mAlphaLong = ").append(mAlphaLong)
.append(" mAlphaShort = ").append(mAlphaShort)
.append(" mAdditionalPlmns = ").append(mAdditionalPlmns)
.append(" }")
.toString();
}
@Override
public void writeToParcel(Parcel dest, int type) {
super.writeToParcel(dest, CellInfo.TYPE_NR);
dest.writeInt(mPci);
dest.writeInt(mTac);
dest.writeInt(mNrArfcn);
dest.writeIntArray(mBands);
dest.writeLong(mNci);
dest.writeArraySet(mAdditionalPlmns);
}
/** Construct from Parcel, type has already been processed */
private CellIdentityNr(Parcel in) {
super(TAG, CellInfo.TYPE_NR, in);
mPci = in.readInt();
mTac = in.readInt();
mNrArfcn = in.readInt();
mBands = in.createIntArray();
mNci = in.readLong();
mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null);
updateGlobalCellId();
}
/** Implement the Parcelable interface */
public static final @android.annotation.NonNull Creator<CellIdentityNr> CREATOR =
new Creator<CellIdentityNr>() {
@Override
public CellIdentityNr createFromParcel(Parcel in) {
// Skip the type info.
in.readInt();
return createFromParcelBody(in);
}
@Override
public CellIdentityNr[] newArray(int size) {
return new CellIdentityNr[size];
}
};
/** @hide */
protected static CellIdentityNr createFromParcelBody(Parcel in) {
return new CellIdentityNr(in);
}
}