diff options
-rw-r--r-- | StubLibraries.bp | 1 | ||||
-rw-r--r-- | telephony/java/android/telephony/data/DataCallResponse.java | 107 | ||||
-rw-r--r-- | telephony/java/android/telephony/data/EpsQos.java | 105 | ||||
-rw-r--r-- | telephony/java/android/telephony/data/NrQos.java | 112 | ||||
-rw-r--r-- | telephony/java/android/telephony/data/Qos.java | 175 | ||||
-rw-r--r-- | telephony/java/android/telephony/data/QosFilter.java | 373 | ||||
-rw-r--r-- | telephony/java/android/telephony/data/QosSession.java | 125 |
7 files changed, 988 insertions, 10 deletions
diff --git a/StubLibraries.bp b/StubLibraries.bp index 90bac37b944e..2f3945f88f35 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -68,6 +68,7 @@ stubs_defaults { "android.hardware.cas-V1.2-java", "android.hardware.health-V1.0-java-constants", "android.hardware.radio-V1.5-java", + "android.hardware.radio-V1.6-java", "android.hardware.thermal-V1.0-java-constants", "android.hardware.thermal-V2.0-java", "android.hardware.tv.input-V1.0-java-constants", diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index ca9bf3cfaa0d..f0088b913d4e 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -134,6 +134,8 @@ public final class DataCallResponse implements Parcelable { private final int mMtuV6; private final @HandoverFailureMode int mHandoverFailureMode; private final int mPduSessionId; + private final Qos mDefaultQos; + private final List<QosSession> mQosSessions; /** * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error. @@ -182,6 +184,8 @@ public final class DataCallResponse implements Parcelable { mMtu = mMtuV4 = mMtuV6 = mtu; mHandoverFailureMode = HANDOVER_FAILURE_MODE_LEGACY; mPduSessionId = PDU_SESSION_ID_NOT_SET; + mDefaultQos = null; + mQosSessions = new ArrayList<>(); } private DataCallResponse(@DataFailureCause int cause, long suggestedRetryTime, int id, @@ -189,7 +193,8 @@ public final class DataCallResponse implements Parcelable { @Nullable String interfaceName, @Nullable List<LinkAddress> addresses, @Nullable List<InetAddress> dnsAddresses, @Nullable List<InetAddress> gatewayAddresses, @Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6, - @HandoverFailureMode int handoverFailureMode, int pduSessionId) { + @HandoverFailureMode int handoverFailureMode, int pduSessionId, + @Nullable Qos defaultQos, @Nullable List<QosSession> qosSessions) { mCause = cause; mSuggestedRetryTime = suggestedRetryTime; mId = id; @@ -209,6 +214,8 @@ public final class DataCallResponse implements Parcelable { mMtuV6 = mtuV6; mHandoverFailureMode = handoverFailureMode; mPduSessionId = pduSessionId; + mDefaultQos = defaultQos; + mQosSessions = qosSessions; } /** @hide */ @@ -233,6 +240,9 @@ public final class DataCallResponse implements Parcelable { mMtuV6 = source.readInt(); mHandoverFailureMode = source.readInt(); mPduSessionId = source.readInt(); + mDefaultQos = source.readParcelable(Qos.class.getClassLoader()); + mQosSessions = new ArrayList<>(); + source.readList(mQosSessions, QosSession.class.getClassLoader()); } /** @@ -350,6 +360,28 @@ public final class DataCallResponse implements Parcelable { return mPduSessionId; } + /** + * @return default QOS of the data call received from the network + * + * @hide + */ + + @Nullable + public Qos getDefaultQos() { + return mDefaultQos; + } + + /** + * @return All the dedicated bearer QOS sessions of the data call received from the network + * + * @hide + */ + + @NonNull + public List<QosSession> getQosSessions() { + return mQosSessions; + } + @NonNull @Override public String toString() { @@ -370,6 +402,8 @@ public final class DataCallResponse implements Parcelable { .append(" mtuV6=").append(getMtuV6()) .append(" handoverFailureMode=").append(getHandoverFailureMode()) .append(" pduSessionId=").append(getPduSessionId()) + .append(" defaultQos=").append(mDefaultQos) + .append(" qosSessions=").append(mQosSessions) .append("}"); return sb.toString(); } @@ -383,12 +417,22 @@ public final class DataCallResponse implements Parcelable { } DataCallResponse other = (DataCallResponse) o; - return this.mCause == other.mCause - && this.mSuggestedRetryTime == other.mSuggestedRetryTime - && this.mId == other.mId - && this.mLinkStatus == other.mLinkStatus - && this.mProtocolType == other.mProtocolType - && this.mInterfaceName.equals(other.mInterfaceName) + + final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null) ? + mDefaultQos == other.mDefaultQos : + mDefaultQos.equals(other.mDefaultQos); + + final boolean isQosSessionsSame = (mQosSessions == null || mQosSessions == null) ? + mQosSessions == other.mQosSessions : + mQosSessions.size() == other.mQosSessions.size() + && mQosSessions.containsAll(other.mQosSessions); + + return mCause == other.mCause + && mSuggestedRetryTime == other.mSuggestedRetryTime + && mId == other.mId + && mLinkStatus == other.mLinkStatus + && mProtocolType == other.mProtocolType + && mInterfaceName.equals(other.mInterfaceName) && mAddresses.size() == other.mAddresses.size() && mAddresses.containsAll(other.mAddresses) && mDnsAddresses.size() == other.mDnsAddresses.size() @@ -401,14 +445,17 @@ public final class DataCallResponse implements Parcelable { && mMtuV4 == other.mMtuV4 && mMtuV6 == other.mMtuV6 && mHandoverFailureMode == other.mHandoverFailureMode - && mPduSessionId == other.mPduSessionId; + && mPduSessionId == other.mPduSessionId + && isQosSame + && isQosSessionsSame; } @Override public int hashCode() { return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses, - mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId); + mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, mDefaultQos, + mQosSessions); } @Override @@ -433,6 +480,12 @@ public final class DataCallResponse implements Parcelable { dest.writeInt(mMtuV6); dest.writeInt(mHandoverFailureMode); dest.writeInt(mPduSessionId); + if (mDefaultQos.getType() == Qos.QOS_TYPE_EPS) { + dest.writeParcelable((EpsQos)mDefaultQos, flags); + } else { + dest.writeParcelable((NrQos)mDefaultQos, flags); + } + dest.writeList(mQosSessions); } public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR = @@ -512,6 +565,10 @@ public final class DataCallResponse implements Parcelable { private int mPduSessionId = PDU_SESSION_ID_NOT_SET; + private Qos mDefaultQos; + + private List<QosSession> mQosSessions = new ArrayList<>(); + /** * Default constructor for Builder. */ @@ -706,6 +763,35 @@ public final class DataCallResponse implements Parcelable { } /** + * Set the default QOS for this data connection. + * + * @param defaultQos QOS (Quality Of Service) received from network. + * + * @return The same instance of the builder. + * + * @hide + */ + public @NonNull Builder setDefaultQos(@Nullable Qos defaultQos) { + mDefaultQos = defaultQos; + return this; + } + + /** + * Set the dedicated bearer QOS sessions for this data connection. + * + * @param qosSessions Dedicated bearer QOS (Quality Of Service) sessions received + * from network. + * + * @return The same instance of the builder. + * + * @hide + */ + public @NonNull Builder setQosSessions(@NonNull List<QosSession> qosSessions) { + mQosSessions = qosSessions; + return this; + } + + /** * Build the DataCallResponse. * * @return the DataCallResponse object. @@ -713,7 +799,8 @@ public final class DataCallResponse implements Parcelable { public @NonNull DataCallResponse build() { return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, - mPcscfAddresses, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId); + mPcscfAddresses, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, + mDefaultQos, mQosSessions); } } } diff --git a/telephony/java/android/telephony/data/EpsQos.java b/telephony/java/android/telephony/data/EpsQos.java new file mode 100644 index 000000000000..ad43068b2f11 --- /dev/null +++ b/telephony/java/android/telephony/data/EpsQos.java @@ -0,0 +1,105 @@ +/** + * Copyright 2020 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.data; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + + +/** + * Class that stores information specific to NR QOS. + * + * @hide + */ +public final class EpsQos extends Qos implements Parcelable { + + int qosClassId; + + public EpsQos() { + super(Qos.QOS_TYPE_EPS, + new android.hardware.radio.V1_6.QosBandwidth(), + new android.hardware.radio.V1_6.QosBandwidth()); + } + + public EpsQos(@NonNull android.hardware.radio.V1_6.EpsQos qos) { + super(Qos.QOS_TYPE_EPS, qos.downlink, qos.uplink); + qosClassId = qos.qci; + } + + private EpsQos(Parcel source) { + super(source); + qosClassId = source.readInt(); + } + + public static @NonNull EpsQos createFromParcelBody(@NonNull Parcel in) { + return new EpsQos(in); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(Qos.QOS_TYPE_EPS, dest, flags); + dest.writeInt(qosClassId); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), qosClassId); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || !(o instanceof EpsQos)) { + return false; + } + + EpsQos other = (EpsQos) o; + + return this.qosClassId == other.qosClassId + && super.equals(other); + } + + @Override + public String toString() { + return "EpsQos {" + + " qosClassId=" + qosClassId + + " downlink=" + downlink + + " uplink=" + uplink + "}"; + } + + public static final @NonNull Parcelable.Creator<EpsQos> CREATOR = + new Parcelable.Creator<EpsQos>() { + @Override + public EpsQos createFromParcel(Parcel source) { + return new EpsQos(source); + } + + @Override + public EpsQos[] newArray(int size) { + return new EpsQos[size]; + } + }; +} diff --git a/telephony/java/android/telephony/data/NrQos.java b/telephony/java/android/telephony/data/NrQos.java new file mode 100644 index 000000000000..2011eed26977 --- /dev/null +++ b/telephony/java/android/telephony/data/NrQos.java @@ -0,0 +1,112 @@ +/** + * Copyright 2020 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.data; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Class that stores information specific to NR QOS. + * + * @hide + */ +public final class NrQos extends Qos implements Parcelable { + int qosFlowId; + int fiveQi; + int averagingWindowMs; + + public NrQos(@NonNull android.hardware.radio.V1_6.NrQos qos) { + super(Qos.QOS_TYPE_NR, qos.downlink, qos.uplink); + fiveQi = qos.fiveQi; + qosFlowId = qos.qfi; + averagingWindowMs = qos.averagingWindowMs; + } + + private NrQos(Parcel source) { + super(source); + this.qosFlowId = source.readInt(); + this.fiveQi = source.readInt(); + this.averagingWindowMs = source.readInt(); + } + + public static @NonNull NrQos createFromParcelBody(@NonNull Parcel in) { + return new NrQos(in); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(Qos.QOS_TYPE_NR, dest, flags); + dest.writeInt(qosFlowId); + dest.writeInt(fiveQi); + dest.writeInt(averagingWindowMs); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), qosFlowId, fiveQi, averagingWindowMs); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || !(o instanceof NrQos)) { + return false; + } + + NrQos other = (NrQos) o; + + if (!super.equals(other)) { + return false; + } + + return this.qosFlowId == other.qosFlowId + && this.fiveQi == other.fiveQi + && this.averagingWindowMs == other.averagingWindowMs; + } + + @Override + public String toString() { + return "NrQos {" + + " fiveQi=" + fiveQi + + " downlink=" + downlink + + " uplink=" + uplink + + " qosFlowId=" + qosFlowId + + " averagingWindowMs=" + averagingWindowMs + "}"; + } + + public static final @NonNull Parcelable.Creator<NrQos> CREATOR = + new Parcelable.Creator<NrQos>() { + @Override + public NrQos createFromParcel(Parcel source) { + return new NrQos(source); + } + + @Override + public NrQos[] newArray(int size) { + return new NrQos[size]; + } + }; +} diff --git a/telephony/java/android/telephony/data/Qos.java b/telephony/java/android/telephony/data/Qos.java new file mode 100644 index 000000000000..c8bb91e28bf2 --- /dev/null +++ b/telephony/java/android/telephony/data/Qos.java @@ -0,0 +1,175 @@ +/** + * Copyright 2020 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.data; + +import android.annotation.CallSuper; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Class that stores information specific to QOS. + * + * @hide + */ +public abstract class Qos { + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "QOS_TYPE_", + value = {QOS_TYPE_EPS, QOS_TYPE_NR}) + public @interface QosType {} + + @QosType + final int type; + + static final int QOS_TYPE_EPS = 1; + static final int QOS_TYPE_NR = 2; + + final QosBandwidth downlink; + final QosBandwidth uplink; + + Qos(int type, + @NonNull android.hardware.radio.V1_6.QosBandwidth downlink, + @NonNull android.hardware.radio.V1_6.QosBandwidth uplink) { + this.type = type; + this.downlink = new QosBandwidth(downlink.maxBitrateKbps, downlink.guaranteedBitrateKbps); + this.uplink = new QosBandwidth(uplink.maxBitrateKbps, uplink.guaranteedBitrateKbps); + } + + static class QosBandwidth implements Parcelable { + int maxBitrateKbps; + int guaranteedBitrateKbps; + + QosBandwidth() { + } + + QosBandwidth(int maxBitrateKbps, int guaranteedBitrateKbps) { + this.maxBitrateKbps = maxBitrateKbps; + this.guaranteedBitrateKbps = guaranteedBitrateKbps; + } + + private QosBandwidth(Parcel source) { + maxBitrateKbps = source.readInt(); + guaranteedBitrateKbps = source.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(maxBitrateKbps); + dest.writeInt(guaranteedBitrateKbps); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public int hashCode() { + return Objects.hash(maxBitrateKbps, guaranteedBitrateKbps); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || !(o instanceof QosBandwidth)) { + return false; + } + + QosBandwidth other = (QosBandwidth) o; + return maxBitrateKbps == other.maxBitrateKbps + && guaranteedBitrateKbps == other.guaranteedBitrateKbps; + } + + @Override + public String toString() { + return "Bandwidth {" + + " maxBitrateKbps=" + maxBitrateKbps + + " guaranteedBitrateKbps=" + guaranteedBitrateKbps + "}"; + } + + public static final @NonNull Parcelable.Creator<QosBandwidth> CREATOR = + new Parcelable.Creator<QosBandwidth>() { + @Override + public QosBandwidth createFromParcel(Parcel source) { + return new QosBandwidth(source); + } + + @Override + public QosBandwidth[] newArray(int size) { + return new QosBandwidth[size]; + } + }; + }; + + protected Qos(@NonNull Parcel source) { + type = source.readInt(); + downlink = source.readParcelable(QosBandwidth.class.getClassLoader()); + uplink = source.readParcelable(QosBandwidth.class.getClassLoader()); + } + + /** + * Used by child classes for parceling. + * + * @hide + */ + @CallSuper + public void writeToParcel(@QosType int type, Parcel dest, int flags) { + dest.writeInt(type); + dest.writeParcelable(downlink, flags); + dest.writeParcelable(uplink, flags); + } + + /** @hide */ + public static @NonNull Qos create(@NonNull android.hardware.radio.V1_6.Qos qos) { + switch (qos.getDiscriminator()) { + case android.hardware.radio.V1_6.Qos.hidl_discriminator.eps: + return new EpsQos(qos.eps()); + case android.hardware.radio.V1_6.Qos.hidl_discriminator.nr: + return new NrQos(qos.nr()); + default: + return null; + } + } + + /** @hide */ + public @QosType int getType() { + return type; + } + + @Override + public int hashCode() { + return Objects.hash(downlink, uplink); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + Qos other = (Qos) o; + return type == other.type + && downlink.equals(other.downlink) + && uplink.equals(other.uplink); + } +} diff --git a/telephony/java/android/telephony/data/QosFilter.java b/telephony/java/android/telephony/data/QosFilter.java new file mode 100644 index 000000000000..69277445634d --- /dev/null +++ b/telephony/java/android/telephony/data/QosFilter.java @@ -0,0 +1,373 @@ +/** + * Copyright 2020 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.data; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.net.InetAddresses; +import android.net.LinkAddress; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.InetAddress; +import java.net.Inet4Address; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + + +/** + * Class that stores QOS filter parameters as defined in + * 3gpp 24.008 10.5.6.12 and 3gpp 24.501 9.11.4.13. + * + * @hide + */ +public final class QosFilter implements Parcelable { + + private List<LinkAddress> localAddresses; + private List<LinkAddress> remoteAddresses; + private PortRange localPort; + private PortRange remotePort; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "QOS_PROTOCOL_", + value = {QOS_PROTOCOL_UNSPECIFIED, QOS_PROTOCOL_TCP, QOS_PROTOCOL_UDP, + QOS_PROTOCOL_ESP, QOS_PROTOCOL_AH}) + public @interface QosProtocol {} + + public static final int QOS_PROTOCOL_UNSPECIFIED = + android.hardware.radio.V1_6.QosProtocol.UNSPECIFIED; + public static final int QOS_PROTOCOL_TCP = android.hardware.radio.V1_6.QosProtocol.TCP; + public static final int QOS_PROTOCOL_UDP = android.hardware.radio.V1_6.QosProtocol.UDP; + public static final int QOS_PROTOCOL_ESP = android.hardware.radio.V1_6.QosProtocol.ESP; + public static final int QOS_PROTOCOL_AH = android.hardware.radio.V1_6.QosProtocol.AH; + + @QosProtocol + private int protocol; + + private int typeOfServiceMask; + + private long flowLabel; + + /** IPSec security parameter index */ + private long securityParameterIndex; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "QOS_FILTER_DIRECTION_", + value = {QOS_FILTER_DIRECTION_DOWNLINK, QOS_FILTER_DIRECTION_UPLINK, + QOS_FILTER_DIRECTION_BIDIRECTIONAL}) + public @interface QosFilterDirection {} + + public static final int QOS_FILTER_DIRECTION_DOWNLINK = + android.hardware.radio.V1_6.QosFilterDirection.DOWNLINK; + public static final int QOS_FILTER_DIRECTION_UPLINK = + android.hardware.radio.V1_6.QosFilterDirection.UPLINK; + public static final int QOS_FILTER_DIRECTION_BIDIRECTIONAL = + android.hardware.radio.V1_6.QosFilterDirection.BIDIRECTIONAL; + + @QosFilterDirection + private int filterDirection; + + /** + * Specified the order in which the filter needs to be matched. + * A Lower numerical value has a higher precedence. + */ + private int precedence; + + QosFilter() { + localAddresses = new ArrayList<>(); + remoteAddresses = new ArrayList<>(); + localPort = new PortRange(); + remotePort = new PortRange(); + protocol = QOS_PROTOCOL_UNSPECIFIED; + filterDirection = QOS_FILTER_DIRECTION_BIDIRECTIONAL; + } + + public QosFilter(List<LinkAddress> localAddresses, List<LinkAddress> remoteAddresses, + PortRange localPort, PortRange remotePort, int protocol, int tos, + long flowLabel, long spi, int direction, int precedence) { + this.localAddresses = localAddresses; + this.remoteAddresses = remoteAddresses; + this.localPort = localPort; + this.remotePort = remotePort; + this.protocol = protocol; + this.typeOfServiceMask = tos; + this.flowLabel = flowLabel; + this.securityParameterIndex = spi; + this.filterDirection = direction; + this.precedence = precedence; + } + + /** @hide */ + public static @NonNull QosFilter create( + @NonNull android.hardware.radio.V1_6.QosFilter qosFilter) { + QosFilter ret = new QosFilter(); + + String[] localAddresses = qosFilter.localAddresses.stream().toArray(String[]::new); + if (localAddresses != null) { + for (String address : localAddresses) { + ret.localAddresses.add(createLinkAddressFromString(address)); + } + } + + String[] remoteAddresses = qosFilter.remoteAddresses.stream().toArray(String[]::new); + if (remoteAddresses != null) { + for (String address : remoteAddresses) { + ret.remoteAddresses.add(createLinkAddressFromString(address)); + } + } + + if (qosFilter.localPort != null) { + if (qosFilter.localPort.getDiscriminator() + == android.hardware.radio.V1_6.MaybePort.hidl_discriminator.range) { + final android.hardware.radio.V1_6.PortRange portRange = qosFilter.localPort.range(); + ret.localPort.start = portRange.start; + ret.localPort.end = portRange.end; + } + } + + if (qosFilter.remotePort != null) { + if (qosFilter.remotePort.getDiscriminator() + == android.hardware.radio.V1_6.MaybePort.hidl_discriminator.range) { + final android.hardware.radio.V1_6.PortRange portRange + = qosFilter.remotePort.range(); + ret.remotePort.start = portRange.start; + ret.remotePort.end = portRange.end; + } + } + + ret.protocol = qosFilter.protocol; + + if (qosFilter.tos != null) { + if (qosFilter.tos.getDiscriminator() + == android.hardware.radio.V1_6.QosFilter.TypeOfService.hidl_discriminator.value) { + ret.typeOfServiceMask = qosFilter.tos.value(); + } + } + + if (qosFilter.flowLabel != null) { + if (qosFilter.flowLabel.getDiscriminator() + == android.hardware.radio.V1_6.QosFilter.Ipv6FlowLabel.hidl_discriminator.value) { + ret.flowLabel = qosFilter.flowLabel.value(); + } + } + + if (qosFilter.spi != null) { + if (qosFilter.spi.getDiscriminator() + == android.hardware.radio.V1_6.QosFilter.IpsecSpi.hidl_discriminator.value) { + ret.securityParameterIndex = qosFilter.spi.value(); + } + } + + ret.filterDirection = qosFilter.direction; + ret.precedence = qosFilter.precedence; + + return ret; + } + + public static class PortRange implements Parcelable { + int start; + int end; + + PortRange() { + start = -1; + end = -1; + } + + private PortRange(Parcel source) { + start = source.readInt(); + end = source.readInt(); + } + + public PortRange(int start, int end) { + this.start = start; + this.end = end; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(start); + dest.writeInt(end); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Parcelable.Creator<PortRange> CREATOR = + new Parcelable.Creator<PortRange>() { + @Override + public PortRange createFromParcel(Parcel source) { + return new PortRange(source); + } + + @Override + public PortRange[] newArray(int size) { + return new PortRange[size]; + } + }; + + @Override + public String toString() { + return "PortRange {" + + " start=" + start + + " end=" + end + "}"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || !(o instanceof PortRange)) { + return false; + } + + PortRange other = (PortRange) o; + return start == other.start + && end == other.end; + } + + @Override + public int hashCode() { + return Objects.hash(start, end); + } + }; + + @Override + public String toString() { + return "QosFilter {" + + " localAddresses=" + localAddresses + + " remoteAddresses=" + remoteAddresses + + " localPort=" + localPort + + " remotePort=" + remotePort + + " protocol=" + protocol + + " typeOfServiceMask=" + typeOfServiceMask + + " flowLabel=" + flowLabel + + " securityParameterIndex=" + securityParameterIndex + + " filterDirection=" + filterDirection + + " precedence=" + precedence + "}"; + } + + @Override + public int hashCode() { + return Objects.hash(localAddresses, remoteAddresses, localPort, + remotePort, protocol, typeOfServiceMask, flowLabel, + securityParameterIndex, filterDirection, precedence); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || !(o instanceof QosFilter)) { + return false; + } + + QosFilter other = (QosFilter) o; + + return localAddresses.size() == other.localAddresses.size() + && localAddresses.containsAll(other.localAddresses) + && remoteAddresses.size() == other.remoteAddresses.size() + && remoteAddresses.containsAll(other.remoteAddresses) + && localPort.equals(other.localPort) + && remotePort.equals(other.remotePort) + && protocol == other.protocol + && typeOfServiceMask == other.typeOfServiceMask + && flowLabel == other.flowLabel + && securityParameterIndex == other.securityParameterIndex + && filterDirection == other.filterDirection + && precedence == other.precedence; + } + + private static LinkAddress createLinkAddressFromString(String addressString) { + addressString = addressString.trim(); + InetAddress address = null; + int prefixLength = -1; + try { + String[] pieces = addressString.split("/", 2); + address = InetAddresses.parseNumericAddress(pieces[0]); + if (pieces.length == 1) { + prefixLength = (address instanceof Inet4Address) ? 32 : 128; + } else if (pieces.length == 2) { + prefixLength = Integer.parseInt(pieces[1]); + } + } catch (NullPointerException e) { // Null string. + } catch (ArrayIndexOutOfBoundsException e) { // No prefix length. + } catch (NumberFormatException e) { // Non-numeric prefix. + } catch (IllegalArgumentException e) { // Invalid IP address. + } + + if (address == null || prefixLength == -1) { + throw new IllegalArgumentException("Invalid link address " + addressString); + } + + return new LinkAddress(address, prefixLength, 0, 0, + LinkAddress.LIFETIME_UNKNOWN, LinkAddress.LIFETIME_UNKNOWN); + } + + private QosFilter(Parcel source) { + localAddresses = new ArrayList<>(); + source.readList(localAddresses, LinkAddress.class.getClassLoader()); + remoteAddresses = new ArrayList<>(); + source.readList(remoteAddresses, LinkAddress.class.getClassLoader()); + localPort = source.readParcelable(PortRange.class.getClassLoader()); + remotePort = source.readParcelable(PortRange.class.getClassLoader()); + protocol = source.readInt(); + typeOfServiceMask = source.readInt(); + flowLabel = source.readLong(); + securityParameterIndex = source.readLong(); + filterDirection = source.readInt(); + precedence = source.readInt(); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeList(localAddresses); + dest.writeList(remoteAddresses); + dest.writeParcelable(localPort, flags); + dest.writeParcelable(remotePort, flags); + dest.writeInt(protocol); + dest.writeInt(typeOfServiceMask); + dest.writeLong(flowLabel); + dest.writeLong(securityParameterIndex); + dest.writeInt(filterDirection); + dest.writeInt(precedence); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Parcelable.Creator<QosFilter> CREATOR = + new Parcelable.Creator<QosFilter>() { + @Override + public QosFilter createFromParcel(Parcel source) { + return new QosFilter(source); + } + + @Override + public QosFilter[] newArray(int size) { + return new QosFilter[size]; + } + }; +} diff --git a/telephony/java/android/telephony/data/QosSession.java b/telephony/java/android/telephony/data/QosSession.java new file mode 100644 index 000000000000..f07b6a9f6725 --- /dev/null +++ b/telephony/java/android/telephony/data/QosSession.java @@ -0,0 +1,125 @@ +/** + * Copyright 2020 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.data; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + + +/** + * Class that stores information specific to QOS session. + * + * @hide + */ +public final class QosSession implements Parcelable{ + + final int qosSessionId; + final Qos qos; + final List<QosFilter> qosFilterList; + + public QosSession(int qosSessionId, @NonNull Qos qos, @NonNull List<QosFilter> qosFilterList) { + this.qosSessionId = qosSessionId; + this.qos = qos; + this.qosFilterList = qosFilterList; + } + + private QosSession(Parcel source) { + qosSessionId = source.readInt(); + qos = source.readParcelable(Qos.class.getClassLoader()); + qosFilterList = new ArrayList<>(); + source.readList(qosFilterList, QosFilter.class.getClassLoader()); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(qosSessionId); + if (qos.getType() == Qos.QOS_TYPE_EPS) { + dest.writeParcelable((EpsQos)qos, flags); + } else { + dest.writeParcelable((NrQos)qos, flags); + } + dest.writeList(qosFilterList); + } + + public static @NonNull QosSession create( + @NonNull android.hardware.radio.V1_6.QosSession qosSession) { + List<QosFilter> qosFilters = new ArrayList<>(); + + if (qosSession.qosFilters != null) { + for (android.hardware.radio.V1_6.QosFilter filter : qosSession.qosFilters) { + qosFilters.add(QosFilter.create(filter)); + } + } + + return new QosSession( + qosSession.qosSessionId, + Qos.create(qosSession.qos), + qosFilters); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + return "QosSession {" + + " qosSessionId=" + qosSessionId + + " qos=" + qos + + " qosFilterList=" + qosFilterList + "}"; + } + + @Override + public int hashCode() { + return Objects.hash(qosSessionId, qos, qosFilterList); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || !(o instanceof QosSession)) { + return false; + } + + QosSession other = (QosSession) o; + return this.qosSessionId == other.qosSessionId + && this.qos.equals(other.qos) + && this.qosFilterList.size() == other.qosFilterList.size() + && this.qosFilterList.containsAll(other.qosFilterList); + } + + + public static final @NonNull Parcelable.Creator<QosSession> CREATOR = + new Parcelable.Creator<QosSession>() { + @Override + public QosSession createFromParcel(Parcel source) { + return new QosSession(source); + } + + @Override + public QosSession[] newArray(int size) { + return new QosSession[size]; + } + }; +} |