|  | /* | 
|  | * 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.IntDef; | 
|  | import android.annotation.IntRange; | 
|  | import android.annotation.NonNull; | 
|  | import android.annotation.SystemApi; | 
|  | import android.os.Parcel; | 
|  | import android.os.Parcelable; | 
|  | import android.telephony.Annotation.NetworkType; | 
|  |  | 
|  | import java.lang.annotation.Retention; | 
|  | import java.lang.annotation.RetentionPolicy; | 
|  | import java.util.Arrays; | 
|  | import java.util.Objects; | 
|  |  | 
|  | /** | 
|  | * @hide | 
|  | */ | 
|  | @SystemApi | 
|  | public final class PhysicalChannelConfig implements Parcelable { | 
|  |  | 
|  | // TODO(b/72993578) consolidate these enums in a central location. | 
|  | /** @hide */ | 
|  | @Retention(RetentionPolicy.SOURCE) | 
|  | @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN}) | 
|  | public @interface ConnectionStatus {} | 
|  |  | 
|  | /** | 
|  | * UE has connection to cell for signalling and possibly data (3GPP 36.331, 25.331). | 
|  | */ | 
|  | public static final int CONNECTION_PRIMARY_SERVING = 1; | 
|  |  | 
|  | /** | 
|  | * UE has connection to cell for data (3GPP 36.331, 25.331). | 
|  | */ | 
|  | public static final int CONNECTION_SECONDARY_SERVING = 2; | 
|  |  | 
|  | /** Connection status is unknown. */ | 
|  | public static final int CONNECTION_UNKNOWN = -1; | 
|  |  | 
|  | /** Channel number is unknown. */ | 
|  | public static final int CHANNEL_NUMBER_UNKNOWN = -1; | 
|  |  | 
|  | /** Physical Cell Id is unknown. */ | 
|  | public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; | 
|  |  | 
|  | /** | 
|  | * Connection status of the cell. | 
|  | * | 
|  | * <p>One of {@link #CONNECTION_PRIMARY_SERVING}, {@link #CONNECTION_SECONDARY_SERVING}. | 
|  | */ | 
|  | @ConnectionStatus | 
|  | private int mCellConnectionStatus; | 
|  |  | 
|  | /** | 
|  | * Cell bandwidth, in kHz. | 
|  | */ | 
|  | private int mCellBandwidthDownlinkKhz; | 
|  |  | 
|  | /** | 
|  | * The radio technology for this physical channel. | 
|  | */ | 
|  | @NetworkType | 
|  | private int mRat; | 
|  |  | 
|  | /** | 
|  | * The rough frequency range for this physical channel. | 
|  | */ | 
|  | @ServiceState.FrequencyRange | 
|  | private int mFrequencyRange; | 
|  |  | 
|  | /** | 
|  | * The absolute radio frequency channel number, {@link CHANNEL_NUMBER_UNKNOWN} if unknown. | 
|  | */ | 
|  | private int mChannelNumber; | 
|  |  | 
|  | /** | 
|  | * A list of data calls mapped to this physical channel. An empty list means the physical | 
|  | * channel has no data call mapped to it. | 
|  | */ | 
|  | private int[] mContextIds; | 
|  |  | 
|  | /** | 
|  | * The physical cell identifier for this cell - PCI, PSC, {@link PHYSICAL_CELL_ID_UNKNOWN} | 
|  | * if unknown. | 
|  | */ | 
|  | private int mPhysicalCellId; | 
|  |  | 
|  | @Override | 
|  | public int describeContents() { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public void writeToParcel(@NonNull Parcel dest, int flags) { | 
|  | dest.writeInt(mCellConnectionStatus); | 
|  | dest.writeInt(mCellBandwidthDownlinkKhz); | 
|  | dest.writeInt(mRat); | 
|  | dest.writeInt(mChannelNumber); | 
|  | dest.writeInt(mFrequencyRange); | 
|  | dest.writeIntArray(mContextIds); | 
|  | dest.writeInt(mPhysicalCellId); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @return Cell bandwidth, in kHz | 
|  | */ | 
|  | public int getCellBandwidthDownlink() { | 
|  | return mCellBandwidthDownlinkKhz; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Get the list of data call ids mapped to this physical channel. This list is sorted into | 
|  | * ascending numerical order. Each id in this list must match the id in | 
|  | * {@link com.android.internal.telephony.dataconnection.DataConnection}. An empty list means the | 
|  | * physical channel has no data call mapped to it. | 
|  | * | 
|  | * @return an integer list indicates the data call ids. | 
|  | * @hide | 
|  | */ | 
|  | public int[] getContextIds() { | 
|  | return mContextIds; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @return the rough frequency range for this physical channel. | 
|  | * @see {@link ServiceState#FREQUENCY_RANGE_LOW} | 
|  | * @see {@link ServiceState#FREQUENCY_RANGE_MID} | 
|  | * @see {@link ServiceState#FREQUENCY_RANGE_HIGH} | 
|  | * @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE} | 
|  | * @hide | 
|  | */ | 
|  | @ServiceState.FrequencyRange | 
|  | public int getFrequencyRange() { | 
|  | return mFrequencyRange; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @return the absolute radio frequency channel number for this physical channel, | 
|  | * {@link CHANNEL_NUMBER_UNKNOWN} if unknown. | 
|  | */ | 
|  | public int getChannelNumber() { | 
|  | return mChannelNumber; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * In UTRAN, this value is primary scrambling code. The range is [0, 511]. | 
|  | * Reference: 3GPP TS 25.213 section 5.2.2. | 
|  | * | 
|  | * In EUTRAN, this value is physical layer cell identity. The range is [0, 503]. | 
|  | * Reference: 3GPP TS 36.211 section 6.11. | 
|  | * | 
|  | * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007]. | 
|  | * Reference: 3GPP TS 38.211 section 7.4.2.1. | 
|  | * | 
|  | * @return the physical cell identifier for this cell, {@link PHYSICAL_CELL_ID_UNKNOWN} | 
|  | * if {@link android.telephony.CellInfo#UNAVAILABLE}. | 
|  | */ | 
|  | @IntRange(from = 0, to = 1007) | 
|  | public int getPhysicalCellId() { | 
|  | return mPhysicalCellId; | 
|  | } | 
|  |  | 
|  | /**The radio technology for this physical channel. */ | 
|  | @NetworkType | 
|  | public int getNetworkType() { | 
|  | return mRat; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Gets the connection status of the cell. | 
|  | * | 
|  | * @see #CONNECTION_PRIMARY_SERVING | 
|  | * @see #CONNECTION_SECONDARY_SERVING | 
|  | * @see #CONNECTION_UNKNOWN | 
|  | * | 
|  | * @return Connection status of the cell | 
|  | */ | 
|  | @ConnectionStatus | 
|  | public int getConnectionStatus() { | 
|  | return mCellConnectionStatus; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @return String representation of the connection status | 
|  | * @hide | 
|  | */ | 
|  | private String getConnectionStatusString() { | 
|  | switch(mCellConnectionStatus) { | 
|  | case CONNECTION_PRIMARY_SERVING: | 
|  | return "PrimaryServing"; | 
|  | case CONNECTION_SECONDARY_SERVING: | 
|  | return "SecondaryServing"; | 
|  | case CONNECTION_UNKNOWN: | 
|  | return "Unknown"; | 
|  | default: | 
|  | return "Invalid(" + mCellConnectionStatus + ")"; | 
|  | } | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean equals(Object o) { | 
|  | if (this == o) { | 
|  | return true; | 
|  | } | 
|  |  | 
|  | if (!(o instanceof PhysicalChannelConfig)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | PhysicalChannelConfig config = (PhysicalChannelConfig) o; | 
|  | return mCellConnectionStatus == config.mCellConnectionStatus | 
|  | && mCellBandwidthDownlinkKhz == config.mCellBandwidthDownlinkKhz | 
|  | && mRat == config.mRat | 
|  | && mFrequencyRange == config.mFrequencyRange | 
|  | && mChannelNumber == config.mChannelNumber | 
|  | && mPhysicalCellId == config.mPhysicalCellId | 
|  | && Arrays.equals(mContextIds, config.mContextIds); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int hashCode() { | 
|  | return Objects.hash( | 
|  | mCellConnectionStatus, mCellBandwidthDownlinkKhz, mRat, mFrequencyRange, | 
|  | mChannelNumber, mPhysicalCellId, mContextIds); | 
|  | } | 
|  |  | 
|  | public static final @android.annotation.NonNull Parcelable.Creator<PhysicalChannelConfig> CREATOR = | 
|  | new Parcelable.Creator<PhysicalChannelConfig>() { | 
|  | public PhysicalChannelConfig createFromParcel(Parcel in) { | 
|  | return new PhysicalChannelConfig(in); | 
|  | } | 
|  |  | 
|  | public PhysicalChannelConfig[] newArray(int size) { | 
|  | return new PhysicalChannelConfig[size]; | 
|  | } | 
|  | }; | 
|  |  | 
|  | @Override | 
|  | public String toString() { | 
|  | return new StringBuilder() | 
|  | .append("{mConnectionStatus=") | 
|  | .append(getConnectionStatusString()) | 
|  | .append(",mCellBandwidthDownlinkKhz=") | 
|  | .append(mCellBandwidthDownlinkKhz) | 
|  | .append(",mRat=") | 
|  | .append(TelephonyManager.getNetworkTypeName(mRat)) | 
|  | .append(",mFrequencyRange=") | 
|  | .append(ServiceState.frequencyRangeToString(mFrequencyRange)) | 
|  | .append(",mChannelNumber=") | 
|  | .append(mChannelNumber) | 
|  | .append(",mContextIds=") | 
|  | .append(Arrays.toString(mContextIds)) | 
|  | .append(",mPhysicalCellId=") | 
|  | .append(mPhysicalCellId) | 
|  | .append("}") | 
|  | .toString(); | 
|  | } | 
|  |  | 
|  | /** @hide */ | 
|  | public PhysicalChannelConfig(int status, int bandwidth) { | 
|  | mCellConnectionStatus = status; | 
|  | mCellBandwidthDownlinkKhz = bandwidth; | 
|  | } | 
|  |  | 
|  | private PhysicalChannelConfig(Parcel in) { | 
|  | mCellConnectionStatus = in.readInt(); | 
|  | mCellBandwidthDownlinkKhz = in.readInt(); | 
|  | mRat = in.readInt(); | 
|  | mChannelNumber = in.readInt(); | 
|  | mFrequencyRange = in.readInt(); | 
|  | mContextIds = in.createIntArray(); | 
|  | mPhysicalCellId = in.readInt(); | 
|  | } | 
|  |  | 
|  | private PhysicalChannelConfig(Builder builder) { | 
|  | mCellConnectionStatus = builder.mCellConnectionStatus; | 
|  | mCellBandwidthDownlinkKhz = builder.mCellBandwidthDownlinkKhz; | 
|  | mRat = builder.mRat; | 
|  | mChannelNumber = builder.mChannelNumber; | 
|  | mFrequencyRange = builder.mFrequencyRange; | 
|  | mContextIds = builder.mContextIds; | 
|  | mPhysicalCellId = builder.mPhysicalCellId; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * The builder of {@code PhysicalChannelConfig}. | 
|  | * @hide | 
|  | */ | 
|  | public static final class Builder { | 
|  | private int mRat; | 
|  | private int mFrequencyRange; | 
|  | private int mChannelNumber; | 
|  | private int mCellBandwidthDownlinkKhz; | 
|  | private int mCellConnectionStatus; | 
|  | private int[] mContextIds; | 
|  | private int mPhysicalCellId; | 
|  |  | 
|  | public Builder() { | 
|  | mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; | 
|  | mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN; | 
|  | mChannelNumber = CHANNEL_NUMBER_UNKNOWN; | 
|  | mCellBandwidthDownlinkKhz = 0; | 
|  | mCellConnectionStatus = CONNECTION_UNKNOWN; | 
|  | mContextIds = new int[0]; | 
|  | mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN; | 
|  | } | 
|  |  | 
|  | public PhysicalChannelConfig build() { | 
|  | return new PhysicalChannelConfig(this); | 
|  | } | 
|  |  | 
|  | public Builder setRat(int rat) { | 
|  | this.mRat = rat; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public Builder setFrequencyRange(int frequencyRange) { | 
|  | this.mFrequencyRange = frequencyRange; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public Builder setChannelNumber(int channelNumber) { | 
|  | this.mChannelNumber = channelNumber; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) { | 
|  | this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public Builder setCellConnectionStatus(int connectionStatus) { | 
|  | this.mCellConnectionStatus = connectionStatus; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public Builder setContextIds(int[] contextIds) { | 
|  | if (contextIds != null) Arrays.sort(contextIds); | 
|  | this.mContextIds = contextIds; | 
|  | return this; | 
|  | } | 
|  |  | 
|  | public Builder setPhysicalCellId(int physicalCellId) { | 
|  | this.mPhysicalCellId = physicalCellId; | 
|  | return this; | 
|  | } | 
|  | } | 
|  | } |