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