• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 static android.text.TextUtils.formatSimple;
20 
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.os.Parcel;
25 import android.telephony.AccessNetworkConstants.NgranBands.NgranBand;
26 import android.telephony.gsm.GsmCellLocation;
27 import android.util.ArraySet;
28 
29 import java.util.Arrays;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.Objects;
33 import java.util.Set;
34 
35 /**
36  * Information to represent a unique NR(New Radio 5G) cell.
37  */
38 public final class CellIdentityNr extends CellIdentity {
39     private static final String TAG = "CellIdentityNr";
40 
41     private static final int MAX_PCI = 1007;
42     private static final int MAX_TAC = 16777215; // 0xffffff
43     private static final int MAX_NRARFCN = 3279165;
44     private static final long MAX_NCI = 68719476735L;
45 
46     private final int mNrArfcn;
47     private final int mPci;
48     private final int mTac;
49     private final long mNci;
50     private final int[] mBands;
51 
52     // a list of additional PLMN-IDs reported for this cell
53     private final ArraySet<String> mAdditionalPlmns;
54 
55     /** @hide */
CellIdentityNr()56     public CellIdentityNr() {
57         super(TAG, CellInfo.TYPE_NR, null, null, null, null);
58         mNrArfcn = CellInfo.UNAVAILABLE;
59         mPci = CellInfo.UNAVAILABLE;
60         mTac = CellInfo.UNAVAILABLE;
61         mNci = CellInfo.UNAVAILABLE;
62         mBands = new int[] {};
63         mAdditionalPlmns = new ArraySet();
64         mGlobalCellId = null;
65     }
66 
67     /**
68      *
69      * @param pci Physical Cell Id in range [0, 1007].
70      * @param tac 24-bit Tracking Area Code.
71      * @param nrArfcn NR Absolute Radio Frequency Channel Number, in range [0, 3279165].
72      * @param bands Bands used by the cell. Band number defined in 3GPP TS 38.101-1 and TS 38.101-2.
73      * @param mccStr 3-digit Mobile Country Code in string format.
74      * @param mncStr 2 or 3-digit Mobile Network Code in string format.
75      * @param nci The 36-bit NR Cell Identity in range [0, 68719476735].
76      * @param alphal long alpha Operator Name String or Enhanced Operator Name String.
77      * @param alphas short alpha Operator Name String or Enhanced Operator Name String.
78      * @param additionalPlmns a list of additional PLMN IDs broadcast by the cell
79      *
80      * @hide
81      */
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)82     public CellIdentityNr(int pci, int tac, int nrArfcn, @NonNull @NgranBand int[] bands,
83                           @Nullable String mccStr, @Nullable String mncStr, long nci,
84                           @Nullable String alphal, @Nullable String alphas,
85                           @NonNull Collection<String> additionalPlmns) {
86         super(TAG, CellInfo.TYPE_NR, mccStr, mncStr, alphal, alphas);
87         mPci = inRangeOrUnavailable(pci, 0, MAX_PCI);
88         mTac = inRangeOrUnavailable(tac, 0, MAX_TAC);
89         mNrArfcn = inRangeOrUnavailable(nrArfcn, 0, MAX_NRARFCN);
90         // TODO: input validation for bands
91         mBands = bands;
92         mNci = inRangeOrUnavailable(nci, 0, MAX_NCI);
93         mAdditionalPlmns = new ArraySet<>(additionalPlmns.size());
94         for (String plmn : additionalPlmns) {
95             if (isValidPlmn(plmn)) {
96                 mAdditionalPlmns.add(plmn);
97             }
98         }
99         updateGlobalCellId();
100     }
101 
102     /** @hide */
CellIdentityNr(@onNull android.hardware.radio.V1_4.CellIdentityNr cid)103     public CellIdentityNr(@NonNull android.hardware.radio.V1_4.CellIdentityNr cid) {
104         this(cid.pci, cid.tac, cid.nrarfcn, new int[] {}, cid.mcc, cid.mnc, cid.nci,
105                 cid.operatorNames.alphaLong, cid.operatorNames.alphaShort,
106                 new ArraySet<>());
107     }
108 
109     /** @hide */
CellIdentityNr(@onNull android.hardware.radio.V1_5.CellIdentityNr cid)110     public CellIdentityNr(@NonNull android.hardware.radio.V1_5.CellIdentityNr cid) {
111         this(cid.base.pci, cid.base.tac, cid.base.nrarfcn,
112                 cid.bands.stream().mapToInt(Integer::intValue).toArray(), cid.base.mcc,
113                 cid.base.mnc, cid.base.nci, cid.base.operatorNames.alphaLong,
114                 cid.base.operatorNames.alphaShort, cid.additionalPlmns);
115     }
116 
117     /** @hide */
118     @Override
sanitizeLocationInfo()119     public @NonNull CellIdentityNr sanitizeLocationInfo() {
120         return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mNrArfcn,
121                 mBands, mMccStr, mMncStr, CellInfo.UNAVAILABLE_LONG, mAlphaLong, mAlphaShort,
122                 mAdditionalPlmns);
123     }
124 
125     /** @hide */
updateGlobalCellId()126     protected void updateGlobalCellId() {
127         mGlobalCellId = null;
128         String plmn = getPlmn();
129         if (plmn == null) return;
130 
131         if (mNci == CellInfo.UNAVAILABLE_LONG) return;
132 
133         mGlobalCellId = plmn + formatSimple("%09x", mNci);
134     }
135 
136     /**
137      * @return a CellLocation object for this CellIdentity.
138      * @hide
139      */
140     @NonNull
141     @Override
asCellLocation()142     public CellLocation asCellLocation() {
143         GsmCellLocation cl = new GsmCellLocation();
144         int tac = mTac != CellInfo.UNAVAILABLE ? mTac : -1;
145         cl.setLacAndCid(tac, -1);
146         cl.setPsc(0);
147         return cl;
148     }
149 
150     @Override
hashCode()151     public int hashCode() {
152         return Objects.hash(super.hashCode(), mPci, mTac,
153                 mNrArfcn, Arrays.hashCode(mBands), mNci, mAdditionalPlmns.hashCode());
154     }
155 
156     @Override
equals(Object other)157     public boolean equals(Object other) {
158         if (this == other) {
159             return true;
160         }
161 
162         if (!(other instanceof CellIdentityNr)) {
163             return false;
164         }
165 
166         CellIdentityNr o = (CellIdentityNr) other;
167         return super.equals(o) && mPci == o.mPci && mTac == o.mTac && mNrArfcn == o.mNrArfcn
168                 && Arrays.equals(mBands, o.mBands) && mNci == o.mNci
169                 && mAdditionalPlmns.equals(o.mAdditionalPlmns);
170     }
171 
172     /**
173      * Get the NR(New Radio 5G) Cell Identity.
174      *
175      * @return The 36-bit NR Cell Identity in range [0, 68719476735] or
176      *         {@link CellInfo#UNAVAILABLE_LONG} if unknown.
177      */
getNci()178     public long getNci() {
179         return mNci;
180     }
181 
182     /**
183      * Get the New Radio Absolute Radio Frequency Channel Number.
184      *
185      * Reference: 3GPP TS 38.101-1 section 5.4.2.1 NR-ARFCN and channel raster.
186      * Reference: 3GPP TS 38.101-2 section 5.4.2.1 NR-ARFCN and channel raster.
187      *
188      * @return Integer value in range [0, 3279165] or {@link CellInfo#UNAVAILABLE} if unknown.
189      */
190     @IntRange(from = 0, to = 3279165)
getNrarfcn()191     public int getNrarfcn() {
192         return mNrArfcn;
193     }
194 
195     /**
196      * Get bands of the cell
197      *
198      * Reference: TS 38.101-1 table 5.2-1
199      * Reference: TS 38.101-2 table 5.2-1
200      *
201      * @return Array of band number or empty array if not available.
202      */
203     @NgranBand
204     @NonNull
getBands()205     public int[] getBands() {
206         return Arrays.copyOf(mBands, mBands.length);
207     }
208 
209     /**
210      * Get the physical cell id.
211      * @return Integer value in range [0, 1007] or {@link CellInfo#UNAVAILABLE} if unknown.
212      */
213     @IntRange(from = 0, to = 1007)
getPci()214     public int getPci() {
215         return mPci;
216     }
217 
218     /**
219      * Get the tracking area code.
220      * @return a 24 bit integer or {@link CellInfo#UNAVAILABLE} if unknown.
221      */
222     @IntRange(from = 0, to = 16777215)
getTac()223     public int getTac() {
224         return mTac;
225     }
226 
227     /**
228      * @return Mobile Country Code in string format, or {@code null} if unknown.
229      */
230     @Nullable
getMccString()231     public String getMccString() {
232         return mMccStr;
233     }
234 
235     /**
236      * @return Mobile Network Code in string format, or {@code null} if unknown.
237      */
238     @Nullable
getMncString()239     public String getMncString() {
240         return mMncStr;
241     }
242 
243     /** @hide */
244     @Override
getChannelNumber()245     public int getChannelNumber() {
246         return mNrArfcn;
247     }
248 
249     /**
250      * @return a list of additional PLMN IDs supported by this cell.
251      */
252     @NonNull
getAdditionalPlmns()253     public Set<String> getAdditionalPlmns() {
254         return Collections.unmodifiableSet(mAdditionalPlmns);
255     }
256 
257     @Override
toString()258     public String toString() {
259         return new StringBuilder(TAG + ":{")
260                 .append(" mPci = ").append(mPci)
261                 .append(" mTac = ").append(mTac)
262                 .append(" mNrArfcn = ").append(mNrArfcn)
263                 .append(" mBands = ").append(Arrays.toString(mBands))
264                 .append(" mMcc = ").append(mMccStr)
265                 .append(" mMnc = ").append(mMncStr)
266                 .append(" mNci = ").append(mNci)
267                 .append(" mAlphaLong = ").append(mAlphaLong)
268                 .append(" mAlphaShort = ").append(mAlphaShort)
269                 .append(" mAdditionalPlmns = ").append(mAdditionalPlmns)
270                 .append(" }")
271                 .toString();
272     }
273 
274     @Override
writeToParcel(Parcel dest, int type)275     public void writeToParcel(Parcel dest, int type) {
276         super.writeToParcel(dest, CellInfo.TYPE_NR);
277         dest.writeInt(mPci);
278         dest.writeInt(mTac);
279         dest.writeInt(mNrArfcn);
280         dest.writeIntArray(mBands);
281         dest.writeLong(mNci);
282         dest.writeArraySet(mAdditionalPlmns);
283     }
284 
285     /** Construct from Parcel, type has already been processed */
CellIdentityNr(Parcel in)286     private CellIdentityNr(Parcel in) {
287         super(TAG, CellInfo.TYPE_NR, in);
288         mPci = in.readInt();
289         mTac = in.readInt();
290         mNrArfcn = in.readInt();
291         mBands = in.createIntArray();
292         mNci = in.readLong();
293         mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null);
294 
295         updateGlobalCellId();
296     }
297 
298     /** Implement the Parcelable interface */
299     public static final @android.annotation.NonNull Creator<CellIdentityNr> CREATOR =
300             new Creator<CellIdentityNr>() {
301                 @Override
302                 public CellIdentityNr createFromParcel(Parcel in) {
303                     // Skip the type info.
304                     in.readInt();
305                     return createFromParcelBody(in);
306                 }
307 
308                 @Override
309                 public CellIdentityNr[] newArray(int size) {
310                     return new CellIdentityNr[size];
311                 }
312             };
313 
314     /** @hide */
createFromParcelBody(Parcel in)315     protected static CellIdentityNr createFromParcelBody(Parcel in) {
316         return new CellIdentityNr(in);
317     }
318 }
319