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.os.Parcel;
21 import android.os.Parcelable;
22 import android.telephony.Annotation.NetworkType;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.util.Arrays;
27 import java.util.Objects;
28 
29 /**
30  * @hide
31  */
32 public final class PhysicalChannelConfig implements Parcelable {
33 
34     // TODO(b/72993578) consolidate these enums in a central location.
35     @Retention(RetentionPolicy.SOURCE)
36     @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN})
37     public @interface ConnectionStatus {}
38 
39     /**
40      * UE has connection to cell for signalling and possibly data (3GPP 36.331, 25.331).
41      */
42     public static final int CONNECTION_PRIMARY_SERVING = 1;
43 
44     /**
45      * UE has connection to cell for data (3GPP 36.331, 25.331).
46      */
47     public static final int CONNECTION_SECONDARY_SERVING = 2;
48 
49     /** Connection status is unknown. */
50     public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE;
51 
52     /**
53      * Connection status of the cell.
54      *
55      * <p>One of {@link #CONNECTION_PRIMARY_SERVING}, {@link #CONNECTION_SECONDARY_SERVING}.
56      */
57     @ConnectionStatus
58     private int mCellConnectionStatus;
59 
60     /**
61      * Cell bandwidth, in kHz.
62      */
63     private int mCellBandwidthDownlinkKhz;
64 
65     /**
66      * The radio technology for this physical channel.
67      */
68     @NetworkType
69     private int mRat;
70 
71     /**
72      * The rough frequency range for this physical channel.
73      */
74     @ServiceState.FrequencyRange
75     private int mFrequencyRange;
76 
77     /**
78      * The absolute radio frequency channel number, {@link Integer#MAX_VALUE} if unknown.
79      */
80     private int mChannelNumber;
81 
82     /**
83      * A list of data calls mapped to this physical channel. An empty list means the physical
84      * channel has no data call mapped to it.
85      */
86     private int[] mContextIds;
87 
88     /**
89      * The physical cell identifier for this cell - PCI, PSC, {@link Integer#MAX_VALUE} if known.
90      */
91     private int mPhysicalCellId;
92 
93     @Override
describeContents()94     public int describeContents() {
95         return 0;
96     }
97 
98     @Override
writeToParcel(Parcel dest, int flags)99     public void writeToParcel(Parcel dest, int flags) {
100         dest.writeInt(mCellConnectionStatus);
101         dest.writeInt(mCellBandwidthDownlinkKhz);
102         dest.writeInt(mRat);
103         dest.writeInt(mChannelNumber);
104         dest.writeInt(mFrequencyRange);
105         dest.writeIntArray(mContextIds);
106         dest.writeInt(mPhysicalCellId);
107     }
108 
109     /**
110      * @return Cell bandwidth, in kHz
111      */
getCellBandwidthDownlink()112     public int getCellBandwidthDownlink() {
113         return mCellBandwidthDownlinkKhz;
114     }
115 
116     /**
117      * Get the list of data call ids mapped to this physical channel. This list is sorted into
118      * ascending numerical order. Each id in this list must match the id in
119      * {@link com.android.internal.telephony.dataconnection.DataConnection}. An empty list means the
120      * physical channel has no data call mapped to it.
121      *
122      * @return an integer list indicates the data call ids.
123      */
getContextIds()124     public int[] getContextIds() {
125         return mContextIds;
126     }
127 
128     /**
129      * @return the rough frequency range for this physical channel.
130      * @see {@link ServiceState#FREQUENCY_RANGE_LOW}
131      * @see {@link ServiceState#FREQUENCY_RANGE_MID}
132      * @see {@link ServiceState#FREQUENCY_RANGE_HIGH}
133      * @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE}
134      */
135     @ServiceState.FrequencyRange
getFrequencyRange()136     public int getFrequencyRange() {
137         return mFrequencyRange;
138     }
139 
140     /**
141      * @return the absolute radio frequency channel number for this physical channel,
142      * {@link Integer#MAX_VALUE} if unknown.
143      */
getChannelNumber()144     public int getChannelNumber() {
145         return mChannelNumber;
146     }
147 
148     /**
149      * In UTRAN, this value is primary scrambling code. The range is [0, 511].
150      * Reference: 3GPP TS 25.213 section 5.2.2.
151      *
152      * In EUTRAN, this value is physical layer cell identity. The range is [0, 503].
153      * Reference: 3GPP TS 36.211 section 6.11.
154      *
155      * In 5G RAN, this value is physical layer cell identity. The range is [0, 1008].
156      * Reference: 3GPP TS 38.211 section 7.4.2.1.
157      *
158      * @return the physical cell identifier for this cell, {@link Integer#MAX_VALUE} if unknown.
159      */
getPhysicalCellId()160     public int getPhysicalCellId() {
161         return mPhysicalCellId;
162     }
163 
164     /**The radio technology for this physical channel. */
165     @NetworkType
getRat()166     public int getRat() {
167         return mRat;
168     }
169 
170     /**
171      * Gets the connection status of the cell.
172      *
173      * @see #CONNECTION_PRIMARY_SERVING
174      * @see #CONNECTION_SECONDARY_SERVING
175      * @see #CONNECTION_UNKNOWN
176      *
177      * @return Connection status of the cell
178      */
179     @ConnectionStatus
getConnectionStatus()180     public int getConnectionStatus() {
181         return mCellConnectionStatus;
182     }
183 
184     /** @return String representation of the connection status */
getConnectionStatusString()185     private String getConnectionStatusString() {
186         switch(mCellConnectionStatus) {
187             case CONNECTION_PRIMARY_SERVING:
188                 return "PrimaryServing";
189             case CONNECTION_SECONDARY_SERVING:
190                 return "SecondaryServing";
191             case CONNECTION_UNKNOWN:
192                 return "Unknown";
193             default:
194                 return "Invalid(" + mCellConnectionStatus + ")";
195         }
196     }
197 
198     @Override
equals(Object o)199     public boolean equals(Object o) {
200         if (this == o) {
201             return true;
202         }
203 
204         if (!(o instanceof PhysicalChannelConfig)) {
205             return false;
206         }
207 
208         PhysicalChannelConfig config = (PhysicalChannelConfig) o;
209         return mCellConnectionStatus == config.mCellConnectionStatus
210                 && mCellBandwidthDownlinkKhz == config.mCellBandwidthDownlinkKhz
211                 && mRat == config.mRat
212                 && mFrequencyRange == config.mFrequencyRange
213                 && mChannelNumber == config.mChannelNumber
214                 && mPhysicalCellId == config.mPhysicalCellId
215                 && Arrays.equals(mContextIds, config.mContextIds);
216     }
217 
218     @Override
hashCode()219     public int hashCode() {
220         return Objects.hash(
221                 mCellConnectionStatus, mCellBandwidthDownlinkKhz, mRat, mFrequencyRange,
222                 mChannelNumber, mPhysicalCellId, mContextIds);
223     }
224 
225     public static final @android.annotation.NonNull Parcelable.Creator<PhysicalChannelConfig> CREATOR =
226         new Parcelable.Creator<PhysicalChannelConfig>() {
227             public PhysicalChannelConfig createFromParcel(Parcel in) {
228                 return new PhysicalChannelConfig(in);
229             }
230 
231             public PhysicalChannelConfig[] newArray(int size) {
232                 return new PhysicalChannelConfig[size];
233             }
234         };
235 
236     @Override
toString()237     public String toString() {
238         return new StringBuilder()
239                 .append("{mConnectionStatus=")
240                 .append(getConnectionStatusString())
241                 .append(",mCellBandwidthDownlinkKhz=")
242                 .append(mCellBandwidthDownlinkKhz)
243                 .append(",mRat=")
244                 .append(TelephonyManager.getNetworkTypeName(mRat))
245                 .append(",mFrequencyRange=")
246                 .append(ServiceState.frequencyRangeToString(mFrequencyRange))
247                 .append(",mChannelNumber=")
248                 .append(mChannelNumber)
249                 .append(",mContextIds=")
250                 .append(Arrays.toString(mContextIds))
251                 .append(",mPhysicalCellId=")
252                 .append(mPhysicalCellId)
253                 .append("}")
254                 .toString();
255     }
256 
PhysicalChannelConfig(Parcel in)257     private PhysicalChannelConfig(Parcel in) {
258         mCellConnectionStatus = in.readInt();
259         mCellBandwidthDownlinkKhz = in.readInt();
260         mRat = in.readInt();
261         mChannelNumber = in.readInt();
262         mFrequencyRange = in.readInt();
263         mContextIds = in.createIntArray();
264         mPhysicalCellId = in.readInt();
265     }
266 
PhysicalChannelConfig(Builder builder)267     private PhysicalChannelConfig(Builder builder) {
268         mCellConnectionStatus = builder.mCellConnectionStatus;
269         mCellBandwidthDownlinkKhz = builder.mCellBandwidthDownlinkKhz;
270         mRat = builder.mRat;
271         mChannelNumber = builder.mChannelNumber;
272         mFrequencyRange = builder.mFrequencyRange;
273         mContextIds = builder.mContextIds;
274         mPhysicalCellId = builder.mPhysicalCellId;
275     }
276 
277     /** The builder of {@code PhysicalChannelConfig}. */
278     public static final class Builder {
279         private int mRat;
280         private int mFrequencyRange;
281         private int mChannelNumber;
282         private int mCellBandwidthDownlinkKhz;
283         private int mCellConnectionStatus;
284         private int[] mContextIds;
285         private int mPhysicalCellId;
286 
287         /** @hide */
Builder()288         public Builder() {
289             mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
290             mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
291             mChannelNumber = Integer.MAX_VALUE;
292             mCellBandwidthDownlinkKhz = 0;
293             mCellConnectionStatus = CONNECTION_UNKNOWN;
294             mContextIds = new int[0];
295             mPhysicalCellId = Integer.MAX_VALUE;
296         }
297 
298         /** @hide */
build()299         public PhysicalChannelConfig build() {
300             return new PhysicalChannelConfig(this);
301         }
302 
303         /** @hide */
setRat(int rat)304         public Builder setRat(int rat) {
305             this.mRat = rat;
306             return this;
307         }
308 
309         /** @hide */
setFrequencyRange(int frequencyRange)310         public Builder setFrequencyRange(int frequencyRange) {
311             this.mFrequencyRange = frequencyRange;
312             return this;
313         }
314 
315         /** @hide */
setChannelNumber(int channelNumber)316         public Builder setChannelNumber(int channelNumber) {
317             this.mChannelNumber = channelNumber;
318             return this;
319         }
320 
321         /** @hide */
setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz)322         public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
323             this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
324             return this;
325         }
326 
327         /** @hide */
setCellConnectionStatus(int connectionStatus)328         public Builder setCellConnectionStatus(int connectionStatus) {
329             this.mCellConnectionStatus = connectionStatus;
330             return this;
331         }
332 
333         /** @hide */
setContextIds(int[] contextIds)334         public Builder setContextIds(int[] contextIds) {
335             if (contextIds != null) Arrays.sort(contextIds);
336             this.mContextIds = contextIds;
337             return this;
338         }
339 
340         /** @hide */
setPhysicalCellId(int physicalCellId)341         public Builder setPhysicalCellId(int physicalCellId) {
342             this.mPhysicalCellId = physicalCellId;
343             return this;
344         }
345     }
346 }
347