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 android.annotation.IntDef;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.telephony.Annotation.NetworkType;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.Arrays;
29 import java.util.Objects;
30 
31 public final class PhysicalChannelConfig implements Parcelable {
32     // TODO(b/72993578) consolidate these enums in a central location.
33     /** @hide */
34     @Retention(RetentionPolicy.SOURCE)
35     @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN})
36     public @interface ConnectionStatus {}
37 
38     /**
39      * UE has connection to cell for signalling and possibly data (3GPP 36.331, 25.331).
40      *
41      * @deprecated Use {@link  CellInfo#CONNECTION_PRIMARY_SERVING} instead.
42      */
43     @Deprecated
44     public static final int CONNECTION_PRIMARY_SERVING = 1;
45 
46     /**
47      * UE has connection to cell for data (3GPP 36.331, 25.331).
48      *
49      * @deprecated Use {@link  CellInfo#CONNECTION_SECONDARY_SERVING} instead.
50      */
51     @Deprecated
52     public static final int CONNECTION_SECONDARY_SERVING = 2;
53 
54     /**
55      * Connection status is unknown.
56      *
57      * @deprecated Use {@link  CellInfo#CONNECTION_UNKNOWN} instead.
58      */
59     @Deprecated
60     public static final int CONNECTION_UNKNOWN = -1;
61 
62     /** Channel number is unknown. */
63     public static final int CHANNEL_NUMBER_UNKNOWN = Integer.MAX_VALUE;
64 
65     /** Physical Cell Id is unknown. */
66     public static final int PHYSICAL_CELL_ID_UNKNOWN = -1;
67 
68     /** Physical Cell Id's maximum value is 1007. */
69     public static final int PHYSICAL_CELL_ID_MAXIMUM_VALUE = 1007;
70 
71     /** Cell bandwidth is unknown. */
72     public static final int CELL_BANDWIDTH_UNKNOWN = 0;
73 
74     /** The frequency is unknown. */
75     public static final int FREQUENCY_UNKNOWN = -1;
76 
77     /** The band is unknown. */
78     public static final int BAND_UNKNOWN = 0;
79 
80     /**
81      * Connection status of the cell.
82      *
83      * <p>One of {@link #CONNECTION_PRIMARY_SERVING}, {@link #CONNECTION_SECONDARY_SERVING}.
84      */
85     @ConnectionStatus
86     private int mCellConnectionStatus;
87 
88     /**
89      * Downlink cell bandwidth, in kHz.
90      */
91     private int mCellBandwidthDownlinkKhz;
92 
93     /**
94      * Uplink cell bandwidth, in kHz.
95      */
96     private int mCellBandwidthUplinkKhz;
97 
98     /**
99      * The radio technology for this physical channel.
100      */
101     @NetworkType
102     private int mNetworkType;
103 
104     /**
105      * The rough frequency range for this physical channel.
106      */
107     @ServiceState.FrequencyRange
108     private int mFrequencyRange;
109 
110     /**
111      * The frequency of Downlink.
112      */
113     private int mDownlinkFrequency;
114 
115     /**
116      * The frequency of Uplink.
117      */
118     private int mUplinkFrequency;
119 
120     /**
121      * Downlink Absolute Radio Frequency Channel Number
122      */
123     private int mDownlinkChannelNumber;
124 
125     /**
126      * Uplink Absolute Radio Frequency Channel Number
127      */
128     private int mUplinkChannelNumber;
129 
130     /**
131      * A list of data calls mapped to this physical channel. An empty list means the physical
132      * channel has no data call mapped to it.
133      */
134     private int[] mContextIds;
135 
136     /**
137      * The physical cell identifier for this cell - PCI, PSC, {@link #PHYSICAL_CELL_ID_UNKNOWN}
138      * if unknown.
139      */
140     private int mPhysicalCellId;
141 
142     /**
143      * This is the band which is being used.
144      */
145     private int mBand;
146 
147     @Override
describeContents()148     public int describeContents() {
149         return 0;
150     }
151 
152     @Override
writeToParcel(@onNull Parcel dest, int flags)153     public void writeToParcel(@NonNull Parcel dest, int flags) {
154         dest.writeInt(mCellConnectionStatus);
155         dest.writeInt(mCellBandwidthDownlinkKhz);
156         dest.writeInt(mCellBandwidthUplinkKhz);
157         dest.writeInt(mNetworkType);
158         dest.writeInt(mDownlinkChannelNumber);
159         dest.writeInt(mUplinkChannelNumber);
160         dest.writeInt(mFrequencyRange);
161         dest.writeIntArray(mContextIds);
162         dest.writeInt(mPhysicalCellId);
163         dest.writeInt(mBand);
164     }
165 
166     /**
167      * @return Downlink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
168      */
169     @IntRange(from = 1)
getCellBandwidthDownlinkKhz()170     public int getCellBandwidthDownlinkKhz() {
171         return mCellBandwidthDownlinkKhz;
172     }
173 
174     /**
175      * @return Uplink cell bandwidth in kHz, {@link #CELL_BANDWIDTH_UNKNOWN} if unknown.
176      */
177     @IntRange(from = 1)
getCellBandwidthUplinkKhz()178     public int getCellBandwidthUplinkKhz() {
179         return mCellBandwidthUplinkKhz;
180     }
181 
182     /**
183      * Get the list of data call ids mapped to this physical channel. This list is sorted into
184      * ascending numerical order. Each id in this list must match the id in
185      * {@link com.android.internal.telephony.dataconnection.DataConnection}. An empty list means the
186      * physical channel has no data call mapped to it.
187      *
188      * @return an integer list indicates the data call ids,
189      * @hide
190      */
getContextIds()191     public int[] getContextIds() {
192         return mContextIds;
193     }
194 
195     /**
196      * @return the rough frequency range for this physical channel,
197      * {@link ServiceState#FREQUENCY_RANGE_UNKNOWN} if unknown.
198      * @see {@link ServiceState#FREQUENCY_RANGE_LOW}
199      * @see {@link ServiceState#FREQUENCY_RANGE_MID}
200      * @see {@link ServiceState#FREQUENCY_RANGE_HIGH}
201      * @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE}
202      * @hide
203      */
204     @ServiceState.FrequencyRange
getFrequencyRange()205     public int getFrequencyRange() {
206         return mFrequencyRange;
207     }
208 
209     /**
210      * @return Downlink Absolute Radio Frequency Channel Number,
211      * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
212      */
213     @IntRange(from = 0)
getDownlinkChannelNumber()214     public int getDownlinkChannelNumber() {
215         return mDownlinkChannelNumber;
216     }
217 
218     /**
219      * @return Uplink Absolute Radio Frequency Channel Number,
220      * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
221      */
222     @IntRange(from = 0)
getUplinkChannelNumber()223     public int getUplinkChannelNumber() {
224         return mUplinkChannelNumber;
225     }
226 
227     /**
228      * The valid bands are {@link AccessNetworkConstants.GeranBand},
229      * {@link AccessNetworkConstants.UtranBand}, {@link AccessNetworkConstants.EutranBand} and
230      * {@link AccessNetworkConstants.NgranBands}.
231      *
232      * @return the frequency band, {@link #BAND_UNKNOWN} if unknown. */
233     @IntRange(from = 1, to = 261)
getBand()234     public int getBand() {
235         return mBand;
236     }
237 
238     /**
239      * @return The downlink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
240      */
241     @IntRange(from = 0)
getDownlinkFrequencyKhz()242     public int getDownlinkFrequencyKhz() {
243         return mDownlinkFrequency;
244     }
245 
246     /**
247      * @return The uplink frequency in kHz, {@link #FREQUENCY_UNKNOWN} if unknown.
248      */
249     @IntRange(from = 0)
getUplinkFrequencyKhz()250     public int getUplinkFrequencyKhz() {
251         return mUplinkFrequency;
252     }
253 
254     /**
255      * The physical cell ID which differentiates cells using the same radio channel.
256      *
257      * In GERAN, this value is the BSIC. The range is [0-63].
258      * Reference: 3GPP TS 3.03 section 4.2.2.
259      *
260      * In UTRAN, this value is primary scrambling code. The range is [0, 511].
261      * Reference: 3GPP TS 25.213 section 5.2.2.
262      *
263      * In EUTRAN, this value is physical layer cell identity. The range is [0, 503].
264      * Reference: 3GPP TS 36.211 section 6.11.
265      *
266      * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007].
267      * Reference: 3GPP TS 38.211 section 7.4.2.1.
268      *
269      * @return the physical cell identifier for this cell, {@link #PHYSICAL_CELL_ID_UNKNOWN}
270      * if {@link android.telephony.CellInfo#UNAVAILABLE}.
271      */
272     @IntRange(from = 0, to = 1007)
getPhysicalCellId()273     public int getPhysicalCellId() {
274         return mPhysicalCellId;
275     }
276 
277     /**
278      * @return The network type for this physical channel,
279      * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if unknown.
280      */
281     @NetworkType
getNetworkType()282     public int getNetworkType() {
283         return mNetworkType;
284     }
285 
286     /**
287      * Gets the connection status of the cell.
288      *
289      * @see #CONNECTION_PRIMARY_SERVING
290      * @see #CONNECTION_SECONDARY_SERVING
291      * @see #CONNECTION_UNKNOWN
292      *
293      * @return Connection status of the cell, {@link #CONNECTION_UNKNOWN} if unknown.
294      */
295     @ConnectionStatus
getConnectionStatus()296     public int getConnectionStatus() {
297         return mCellConnectionStatus;
298     }
299 
300     /**
301      * Return a copy of this PhysicalChannelConfig object but redact all the location info.
302      * @hide
303      */
createLocationInfoSanitizedCopy()304     public PhysicalChannelConfig createLocationInfoSanitizedCopy() {
305         return new Builder(this).setPhysicalCellId(PHYSICAL_CELL_ID_UNKNOWN).build();
306     }
307 
308     /**
309      * @return String representation of the connection status
310      * @hide
311      */
getConnectionStatusString()312     private String getConnectionStatusString() {
313         switch(mCellConnectionStatus) {
314             case CONNECTION_PRIMARY_SERVING:
315                 return "PrimaryServing";
316             case CONNECTION_SECONDARY_SERVING:
317                 return "SecondaryServing";
318             case CONNECTION_UNKNOWN:
319                 return "Unknown";
320             default:
321                 return "Invalid(" + mCellConnectionStatus + ")";
322         }
323     }
324 
setDownlinkFrequency()325     private void setDownlinkFrequency() {
326         switch (mNetworkType) {
327             case TelephonyManager.NETWORK_TYPE_NR:
328                 mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromNrArfcn(
329                         mDownlinkChannelNumber);
330                 break;
331             case TelephonyManager.NETWORK_TYPE_LTE:
332                 mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
333                         mBand, mDownlinkChannelNumber, false);
334                 break;
335             case TelephonyManager.NETWORK_TYPE_HSPAP:
336             case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
337             case TelephonyManager.NETWORK_TYPE_UMTS:
338             case TelephonyManager.NETWORK_TYPE_HSDPA:
339             case TelephonyManager.NETWORK_TYPE_HSUPA:
340             case TelephonyManager.NETWORK_TYPE_HSPA:
341                 mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
342                         mBand, mDownlinkChannelNumber, false);
343                 break;
344             case TelephonyManager.NETWORK_TYPE_GPRS:
345             case TelephonyManager.NETWORK_TYPE_EDGE:
346             case TelephonyManager.NETWORK_TYPE_GSM:
347                 mDownlinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
348                         mBand, mDownlinkChannelNumber, false);
349                 break;
350         }
351     }
352 
setUplinkFrequency()353     private void setUplinkFrequency() {
354         switch (mNetworkType){
355             case TelephonyManager.NETWORK_TYPE_NR:
356                 mUplinkFrequency = AccessNetworkUtils.getFrequencyFromNrArfcn(
357                         mUplinkChannelNumber);
358                 break;
359             case TelephonyManager.NETWORK_TYPE_LTE:
360                 mUplinkFrequency = AccessNetworkUtils.getFrequencyFromEarfcn(
361                         mBand, mUplinkChannelNumber, true);
362                 break;
363             case TelephonyManager.NETWORK_TYPE_HSPAP:
364             case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
365             case TelephonyManager.NETWORK_TYPE_UMTS:
366             case TelephonyManager.NETWORK_TYPE_HSDPA:
367             case TelephonyManager.NETWORK_TYPE_HSUPA:
368             case TelephonyManager.NETWORK_TYPE_HSPA:
369                 mUplinkFrequency = AccessNetworkUtils.getFrequencyFromUarfcn(
370                         mBand, mUplinkChannelNumber, true);
371                 break;
372             case TelephonyManager.NETWORK_TYPE_GPRS:
373             case TelephonyManager.NETWORK_TYPE_EDGE:
374             case TelephonyManager.NETWORK_TYPE_GSM:
375                 mUplinkFrequency = AccessNetworkUtils.getFrequencyFromArfcn(
376                         mBand, mUplinkChannelNumber, true);
377                 break;
378         }
379     }
380 
setFrequencyRange()381     private void setFrequencyRange() {
382         if (mFrequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
383             return;
384         }
385 
386         switch (mNetworkType) {
387             case TelephonyManager.NETWORK_TYPE_NR:
388                 mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromNrBand(mBand);
389                 break;
390             case TelephonyManager.NETWORK_TYPE_LTE:
391                 mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromEutranBand(mBand);
392                 break;
393             case TelephonyManager.NETWORK_TYPE_HSPAP:
394             case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
395             case TelephonyManager.NETWORK_TYPE_UMTS:
396             case TelephonyManager.NETWORK_TYPE_HSDPA:
397             case TelephonyManager.NETWORK_TYPE_HSUPA:
398             case TelephonyManager.NETWORK_TYPE_HSPA:
399                 mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromUtranBand(mBand);
400                 break;
401             case TelephonyManager.NETWORK_TYPE_GPRS:
402             case TelephonyManager.NETWORK_TYPE_EDGE:
403             case TelephonyManager.NETWORK_TYPE_GSM:
404                 mFrequencyRange = AccessNetworkUtils.getFrequencyRangeGroupFromGeranBand(mBand);
405                 break;
406             default:
407                 mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
408                 break;
409         }
410 
411         if (mFrequencyRange == ServiceState.FREQUENCY_RANGE_UNKNOWN) {
412             mFrequencyRange = AccessNetworkUtils.getFrequencyRangeFromArfcn(
413                     mDownlinkFrequency);
414         }
415     }
416 
417     @Override
equals(Object o)418     public boolean equals(Object o) {
419         if (this == o) {
420             return true;
421         }
422 
423         if (!(o instanceof PhysicalChannelConfig)) {
424             return false;
425         }
426 
427         PhysicalChannelConfig config = (PhysicalChannelConfig) o;
428         return mCellConnectionStatus == config.mCellConnectionStatus
429                 && mCellBandwidthDownlinkKhz == config.mCellBandwidthDownlinkKhz
430                 && mCellBandwidthUplinkKhz == config.mCellBandwidthUplinkKhz
431                 && mNetworkType == config.mNetworkType
432                 && mFrequencyRange == config.mFrequencyRange
433                 && mDownlinkChannelNumber == config.mDownlinkChannelNumber
434                 && mUplinkChannelNumber == config.mUplinkChannelNumber
435                 && mPhysicalCellId == config.mPhysicalCellId
436                 && Arrays.equals(mContextIds, config.mContextIds)
437                 && mBand == config.mBand
438                 && mDownlinkFrequency == config.mDownlinkFrequency
439                 && mUplinkFrequency == config.mUplinkFrequency;
440     }
441 
442     @Override
hashCode()443     public int hashCode() {
444         return Objects.hash(
445                 mCellConnectionStatus, mCellBandwidthDownlinkKhz, mCellBandwidthUplinkKhz,
446                 mNetworkType, mFrequencyRange, mDownlinkChannelNumber, mUplinkChannelNumber,
447                 Arrays.hashCode(mContextIds), mPhysicalCellId, mBand, mDownlinkFrequency,
448                 mUplinkFrequency);
449     }
450 
451     public static final
452     @android.annotation.NonNull Parcelable.Creator<PhysicalChannelConfig> CREATOR =
453             new Parcelable.Creator<PhysicalChannelConfig>() {
454                 public PhysicalChannelConfig createFromParcel(Parcel in) {
455                     return new PhysicalChannelConfig(in);
456                 }
457 
458                 public PhysicalChannelConfig[] newArray(int size) {
459                     return new PhysicalChannelConfig[size];
460                 }
461             };
462 
463     @Override
toString()464     public String toString() {
465         return new StringBuilder()
466                 .append("{mConnectionStatus=")
467                 .append(getConnectionStatusString())
468                 .append(",mCellBandwidthDownlinkKhz=")
469                 .append(mCellBandwidthDownlinkKhz)
470                 .append(",mCellBandwidthUplinkKhz=")
471                 .append(mCellBandwidthUplinkKhz)
472                 .append(",mNetworkType=")
473                 .append(TelephonyManager.getNetworkTypeName(mNetworkType))
474                 .append(",mFrequencyRange=")
475                 .append(ServiceState.frequencyRangeToString(mFrequencyRange))
476                 .append(",mDownlinkChannelNumber=")
477                 .append(mDownlinkChannelNumber)
478                 .append(",mUplinkChannelNumber=")
479                 .append(mUplinkChannelNumber)
480                 .append(",mContextIds=")
481                 .append(Arrays.toString(mContextIds))
482                 .append(",mPhysicalCellId=")
483                 .append(mPhysicalCellId)
484                 .append(",mBand=")
485                 .append(mBand)
486                 .append(",mDownlinkFrequency=")
487                 .append(mDownlinkFrequency)
488                 .append(",mUplinkFrequency=")
489                 .append(mUplinkFrequency)
490                 .append("}")
491                 .toString();
492     }
493 
PhysicalChannelConfig(Parcel in)494     private PhysicalChannelConfig(Parcel in) {
495         mCellConnectionStatus = in.readInt();
496         mCellBandwidthDownlinkKhz = in.readInt();
497         mCellBandwidthUplinkKhz = in.readInt();
498         mNetworkType = in.readInt();
499         mDownlinkChannelNumber = in.readInt();
500         mUplinkChannelNumber = in.readInt();
501         mFrequencyRange = in.readInt();
502         mContextIds = in.createIntArray();
503         mPhysicalCellId = in.readInt();
504         mBand = in.readInt();
505         if (mBand > BAND_UNKNOWN) {
506             setDownlinkFrequency();
507             setUplinkFrequency();
508             setFrequencyRange();
509         }
510     }
511 
PhysicalChannelConfig(Builder builder)512     private PhysicalChannelConfig(Builder builder) {
513         mCellConnectionStatus = builder.mCellConnectionStatus;
514         mCellBandwidthDownlinkKhz = builder.mCellBandwidthDownlinkKhz;
515         mCellBandwidthUplinkKhz = builder.mCellBandwidthUplinkKhz;
516         mNetworkType = builder.mNetworkType;
517         mDownlinkChannelNumber = builder.mDownlinkChannelNumber;
518         mUplinkChannelNumber = builder.mUplinkChannelNumber;
519         mFrequencyRange = builder.mFrequencyRange;
520         mContextIds = builder.mContextIds;
521         mPhysicalCellId = builder.mPhysicalCellId;
522         mBand = builder.mBand;
523         if (mBand > BAND_UNKNOWN) {
524             setDownlinkFrequency();
525             setUplinkFrequency();
526             setFrequencyRange();
527         }
528     }
529 
530     /**
531      * The builder of {@code PhysicalChannelConfig}.
532      * @hide
533      */
534     public static final class Builder {
535         private int mNetworkType;
536         private int mFrequencyRange;
537         private int mDownlinkChannelNumber;
538         private int mUplinkChannelNumber;
539         private int mCellBandwidthDownlinkKhz;
540         private int mCellBandwidthUplinkKhz;
541         private int mCellConnectionStatus;
542         private int[] mContextIds;
543         private int mPhysicalCellId;
544         private int mBand;
545 
Builder()546         public Builder() {
547             mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
548             mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
549             mDownlinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
550             mUplinkChannelNumber = CHANNEL_NUMBER_UNKNOWN;
551             mCellBandwidthDownlinkKhz = CELL_BANDWIDTH_UNKNOWN;
552             mCellBandwidthUplinkKhz = CELL_BANDWIDTH_UNKNOWN;
553             mCellConnectionStatus = CONNECTION_UNKNOWN;
554             mContextIds = new int[0];
555             mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN;
556             mBand = BAND_UNKNOWN;
557         }
558 
559         /**
560          * Builder object constructed from existing PhysicalChannelConfig object.
561          * @hide
562          */
Builder(PhysicalChannelConfig config)563         public Builder(PhysicalChannelConfig config) {
564             mNetworkType = config.getNetworkType();
565             mFrequencyRange = config.getFrequencyRange();
566             mDownlinkChannelNumber = config.getDownlinkChannelNumber();
567             mUplinkChannelNumber = config.getUplinkChannelNumber();
568             mCellBandwidthDownlinkKhz = config.getCellBandwidthDownlinkKhz();
569             mCellBandwidthUplinkKhz = config.getCellBandwidthUplinkKhz();
570             mCellConnectionStatus = config.getConnectionStatus();
571             mContextIds = Arrays.copyOf(config.getContextIds(), config.getContextIds().length);
572             mPhysicalCellId = config.getPhysicalCellId();
573             mBand = config.getBand();
574         }
575 
build()576         public PhysicalChannelConfig build() {
577             return new PhysicalChannelConfig(this);
578         }
579 
setNetworkType(@etworkType int networkType)580         public @NonNull Builder setNetworkType(@NetworkType int networkType) {
581             if (!TelephonyManager.isNetworkTypeValid(networkType)) {
582                 throw new IllegalArgumentException("Network type " + networkType + " is invalid.");
583             }
584             mNetworkType = networkType;
585             return this;
586         }
587 
setFrequencyRange(int frequencyRange)588         public @NonNull Builder setFrequencyRange(int frequencyRange) {
589             if (!ServiceState.isFrequencyRangeValid(frequencyRange)
590                     && frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
591                 throw new IllegalArgumentException("Frequency range " + frequencyRange
592                         + " is invalid.");
593             }
594             mFrequencyRange = frequencyRange;
595             return this;
596         }
597 
setDownlinkChannelNumber(int downlinkChannelNumber)598         public @NonNull Builder setDownlinkChannelNumber(int downlinkChannelNumber) {
599             mDownlinkChannelNumber = downlinkChannelNumber;
600             return this;
601         }
602 
setUplinkChannelNumber(int uplinkChannelNumber)603         public @NonNull Builder setUplinkChannelNumber(int uplinkChannelNumber) {
604             mUplinkChannelNumber = uplinkChannelNumber;
605             return this;
606         }
607 
setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz)608         public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
609             if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) {
610                 throw new IllegalArgumentException("Cell downlink bandwidth(kHz) "
611                         + cellBandwidthDownlinkKhz + " is invalid.");
612             }
613             mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
614             return this;
615         }
616 
setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz)617         public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) {
618             if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) {
619                 throw new IllegalArgumentException("Cell uplink bandwidth(kHz) "
620                         + cellBandwidthUplinkKhz + " is invalid.");
621             }
622             mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
623             return this;
624         }
625 
setCellConnectionStatus(int connectionStatus)626         public @NonNull Builder setCellConnectionStatus(int connectionStatus) {
627             mCellConnectionStatus = connectionStatus;
628             return this;
629         }
630 
setContextIds(int[] contextIds)631         public @NonNull Builder setContextIds(int[] contextIds) {
632             if (contextIds != null) Arrays.sort(contextIds);
633             mContextIds = contextIds;
634             return this;
635         }
636 
setPhysicalCellId(int physicalCellId)637         public @NonNull Builder setPhysicalCellId(int physicalCellId) {
638             if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) {
639                 throw new IllegalArgumentException("Physical cell ID " + physicalCellId
640                         + " is over limit.");
641             }
642             mPhysicalCellId = physicalCellId;
643             return this;
644         }
645 
setBand(int band)646         public @NonNull Builder setBand(int band) {
647             if (band <= BAND_UNKNOWN) {
648                 throw new IllegalArgumentException("Band " + band + " is invalid.");
649             }
650             mBand = band;
651             return this;
652         }
653     }
654 }
655