Define APIs for fetching QoS parameters
- Define AIDL APIs for fetching QoS parameters
- Define classes to map HAL structures for QoS params
Change-Id: Ie6adc4e98189ded58abdb9d2a232093a8cb33602
CRs-Fixed: 3293236
diff --git a/extphone/Android.bp b/extphone/Android.bp
index b451b90..0e2dd51 100644
--- a/extphone/Android.bp
+++ b/extphone/Android.bp
@@ -11,6 +11,11 @@
"src/com/**/*.java",
"src/com/**/I*.aidl",
],
+
+ static_libs: [
+ "android.hardware.radio-V1.6-java",
+ ],
+
system_ext_specific: true,
}
@@ -26,6 +31,11 @@
"src/com/**/*.java",
"src/com/**/I*.aidl",
],
+
+ static_libs: [
+ "android.hardware.radio-V1.6-java",
+ ],
+
product_specific: true,
}
diff --git a/extphone/src/com/qti/extphone/EpsQos.java b/extphone/src/com/qti/extphone/EpsQos.java
new file mode 100644
index 0000000..7c10624
--- /dev/null
+++ b/extphone/src/com/qti/extphone/EpsQos.java
@@ -0,0 +1,115 @@
+/**
+ * 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.
+ */
+
+/**
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+
+/**
+ * Class that stores information specific to NR QOS.
+ */
+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 int getQci() {
+ return qosClassId;
+ }
+
+ // @NonNull
+ public static 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 + "}";
+ }
+
+ // @NonNull
+ public static final 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/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java b/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java
index 0c84ab6..3a77c0a 100644
--- a/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java
+++ b/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java
@@ -120,6 +120,11 @@
" token = " + token + " status" + status + " raf = " + raf);
}
+ @Override
+ public void getQosParametersResponse(int slotId, Token token, Status status,
+ QosParametersResult result) throws RemoteException {
+ }
+
public void onNrDcParam(int slotId, Token token, Status status, DcParam dcParam) throws
RemoteException {
Log.d(TAG, "UNIMPLEMENTED: onNrDcParam: slotId = " + slotId +
@@ -251,4 +256,9 @@
@Override
public void setMsimPreferenceResponse(Token token, Status status) throws RemoteException {
}
+
+ @Override
+ public void onQosParametersChanged(int slotId, int cid, QosParametersResult result)
+ throws RemoteException {
+ }
}
diff --git a/extphone/src/com/qti/extphone/ExtTelephonyManager.java b/extphone/src/com/qti/extphone/ExtTelephonyManager.java
index 115eb87..8390999 100644
--- a/extphone/src/com/qti/extphone/ExtTelephonyManager.java
+++ b/extphone/src/com/qti/extphone/ExtTelephonyManager.java
@@ -976,6 +976,21 @@
return support;
}
+ public Token getQosParameters(int slotId, int cid, Client client) throws RemoteException {
+ Log.d(LOG_TAG, "[" + slotId + "] getQosParameters, cid: " + cid);
+ Token token = null;
+ if (!isServiceConnected()) {
+ Log.e(LOG_TAG, "service not connected!");
+ return token;
+ }
+ try {
+ token = mExtTelephonyService.getQosParameters(slotId, cid, client);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "getQosParameters ended in remote exception", e);
+ }
+ return token;
+ }
+
public Token getSecureModeStatus(Client client) throws RemoteException {
Token token = null;
if (!isServiceConnected()) {
diff --git a/extphone/src/com/qti/extphone/IExtPhone.aidl b/extphone/src/com/qti/extphone/IExtPhone.aidl
index 470d072..5bc5345 100644
--- a/extphone/src/com/qti/extphone/IExtPhone.aidl
+++ b/extphone/src/com/qti/extphone/IExtPhone.aidl
@@ -519,6 +519,15 @@
boolean isEpdgOverCellularDataSupported(int slotId);
/**
+ * Request for QoS parameters for a particular data call.
+ *
+ * @param - slotId slot ID
+ * @param - cid connection id of the data call for which the QoS parameters are requested
+ * @return - Integer Token to be used to map the response.
+ */
+ Token getQosParameters(int slot, int cid, in Client client);
+
+ /**
* Query the status of Secure Mode
*
* @param client - Client registered with package name to receive callbacks
diff --git a/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl b/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl
index 7389073..90d6f6b 100644
--- a/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl
+++ b/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl
@@ -43,8 +43,9 @@
import com.qti.extphone.NrConfig;
import com.qti.extphone.NrConfigType;
import com.qti.extphone.NrIconType;
-import com.qti.extphone.QtiCallForwardInfo;
import com.qti.extphone.QRadioResponseInfo;
+import com.qti.extphone.QosParametersResult;
+import com.qti.extphone.QtiCallForwardInfo;
import com.qti.extphone.QtiImeiInfo;
import com.qti.extphone.SignalStrength;
import com.qti.extphone.SmsResult;
@@ -247,6 +248,26 @@
void onEpdgOverCellularDataSupported(int slotId, boolean support);
/**
+ * Response to IExtPhone.getQosParameters() request
+ *
+ * @param slotId
+ * @param token is the same token which is received in getQosParameters request
+ * @param status SUCCESS/FAILURE based on the modem result code
+ * @param result QosParametersResult containing the requested QoS parameters
+ */
+ void getQosParametersResponse(int slotId, in Token token, in Status status,
+ in QosParametersResult result);
+
+ /**
+ * Indication received when QoS parameters have changed for a given connection id
+ *
+ * @param slotId
+ * @param cid Connection id for which the QoS parameters have changed
+ * @param result QosParametersResult containing the updated QoS parameters
+ */
+ void onQosParametersChanged(int slotId, int cid, in QosParametersResult result);
+
+ /**
* Response to getSecureModeStatus
* @param - token is the same token which is received in setSmartDdsSwitchToggle
* @param - status SUCCESS/FAILURE based on RIL data module response
diff --git a/extphone/src/com/qti/extphone/NrQos.java b/extphone/src/com/qti/extphone/NrQos.java
new file mode 100644
index 0000000..e45d7de
--- /dev/null
+++ b/extphone/src/com/qti/extphone/NrQos.java
@@ -0,0 +1,130 @@
+/**
+ * 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.
+ */
+
+/**
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Class that stores information specific to NR QOS.
+ */
+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();
+ }
+
+ // @NonNull
+ public static NrQos createFromParcelBody(/* @NonNull */ Parcel in) {
+ return new NrQos(in);
+ }
+
+ public int get5Qi() {
+ return fiveQi;
+ }
+
+ public int getQfi() {
+ return qosFlowId;
+ }
+
+ public int getAveragingWindow() {
+ return averagingWindowMs;
+ }
+
+ @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 + "}";
+ }
+
+ // @NonNull
+ public static final 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/extphone/src/com/qti/extphone/Qos.java b/extphone/src/com/qti/extphone/Qos.java
new file mode 100644
index 0000000..af17698
--- /dev/null
+++ b/extphone/src/com/qti/extphone/Qos.java
@@ -0,0 +1,199 @@
+/**
+ * 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.
+ */
+
+/**
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+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.
+ */
+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;
+
+ public static final int QOS_TYPE_EPS = 1;
+ public 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);
+ }
+
+ public QosBandwidth getDownlinkBandwidth() {
+ return downlink;
+ }
+
+ public QosBandwidth getUplinkBandwidth() {
+ return uplink;
+ }
+
+ public 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();
+ }
+
+ public int getMaxBitrateKbps() {
+ return maxBitrateKbps;
+ }
+
+ public int getGuaranteedBitrateKbps() {
+ return guaranteedBitrateKbps;
+ }
+
+ @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 + "}";
+ }
+
+ // @NonNull
+ public static final 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
+ * @NonNull
+ */
+ public static 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);
+ }
+}
\ No newline at end of file
diff --git a/extphone/src/com/qti/extphone/QosBearerFilter.java b/extphone/src/com/qti/extphone/QosBearerFilter.java
new file mode 100644
index 0000000..a682e63
--- /dev/null
+++ b/extphone/src/com/qti/extphone/QosBearerFilter.java
@@ -0,0 +1,455 @@
+/**
+ * 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.
+ */
+
+/**
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+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.
+ */
+public final class QosBearerFilter implements Parcelable {
+ private /* @NonNull */ List<LinkAddress> localAddresses;
+ private /* @NonNull */ List<LinkAddress> remoteAddresses;
+ private /* @Nullable */ PortRange localPort;
+ private /* @Nullable */ 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;
+ public static final int QOS_MIN_PORT =
+ android.hardware.radio.V1_6.QosPortRange.MIN;
+ /**
+ * Hardcoded in place of android.hardware.radio.V1_6.QosPortRange.MAX as it
+ * returns -1 due to uint16_t to int conversion in java. (TODO: Fix the HAL)
+ */
+ public static final int QOS_MAX_PORT = 65535;
+
+ private @QosProtocol 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 QosBearerFilterDirection {}
+
+ 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;
+
+ private @QosBearerFilterDirection int filterDirection;
+
+ /**
+ * Specified the order in which the filter needs to be matched.
+ * A Lower numerical value has a higher precedence.
+ */
+ private int precedence;
+
+ QosBearerFilter() {
+ localAddresses = new ArrayList<>();
+ remoteAddresses = new ArrayList<>();
+ localPort = new PortRange();
+ remotePort = new PortRange();
+ protocol = QOS_PROTOCOL_UNSPECIFIED;
+ filterDirection = QOS_FILTER_DIRECTION_BIDIRECTIONAL;
+ }
+
+ public QosBearerFilter(/* @NonNull */ List<LinkAddress> localAddresses,
+ /* @NonNull */ List<LinkAddress> remoteAddresses, /* @Nullable */ PortRange localPort,
+ /* @Nullable */ PortRange remotePort, @QosProtocol int protocol, int tos,
+ long flowLabel, long spi, @QosBearerFilterDirection 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;
+ }
+
+ // @NonNull
+ public List<LinkAddress> getLocalAddresses() {
+ return localAddresses;
+ }
+
+ // @NonNull
+ public List<LinkAddress> getRemoteAddresses() {
+ return remoteAddresses;
+ }
+
+ // @Nullable
+ public PortRange getLocalPortRange() {
+ return localPort;
+ }
+
+ // @Nullable
+ public PortRange getRemotePortRange() {
+ return remotePort;
+ }
+
+ public int getProtocol() {
+ return protocol;
+ }
+
+ public int getTypeOfServiceMask() {
+ return typeOfServiceMask;
+ }
+
+ public long getFlowLabel() {
+ return flowLabel;
+ }
+
+ public long getSpi() {
+ return securityParameterIndex;
+ }
+
+ public int getDirection() {
+ return filterDirection;
+ }
+
+ public int getPrecedence() {
+ return precedence;
+ }
+
+ /*
+ * @hide
+ * @NonNull
+ */
+ public static QosBearerFilter create(
+ /* @NonNull */ android.hardware.radio.V1_6.QosFilter qosFilter) {
+ QosBearerFilter ret = new QosBearerFilter();
+
+ 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;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ public boolean isValid() {
+ return start >= QOS_MIN_PORT && start <= QOS_MAX_PORT
+ && end >= QOS_MIN_PORT && end <= QOS_MAX_PORT
+ && start <= end;
+ }
+
+ @Override
+ public void writeToParcel(/* @NonNull */ Parcel dest, int flags) {
+ dest.writeInt(start);
+ dest.writeInt(end);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ // @NonNull
+ public static final 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 "QosBearerFilter {"
+ + " 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 QosBearerFilter)) {
+ return false;
+ }
+
+ QosBearerFilter other = (QosBearerFilter) o;
+
+ return localAddresses.size() == other.localAddresses.size()
+ && localAddresses.containsAll(other.localAddresses)
+ && remoteAddresses.size() == other.remoteAddresses.size()
+ && remoteAddresses.containsAll(other.remoteAddresses)
+ && Objects.equals(localPort, other.localPort)
+ && Objects.equals(remotePort, 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 QosBearerFilter(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;
+ }
+
+ // @NonNull
+ public static final Parcelable.Creator<QosBearerFilter> CREATOR =
+ new Parcelable.Creator<QosBearerFilter>() {
+ @Override
+ public QosBearerFilter createFromParcel(Parcel source) {
+ return new QosBearerFilter(source);
+ }
+
+ @Override
+ public QosBearerFilter[] newArray(int size) {
+ return new QosBearerFilter[size];
+ }
+ };
+}
diff --git a/extphone/src/com/qti/extphone/QosBearerSession.java b/extphone/src/com/qti/extphone/QosBearerSession.java
new file mode 100644
index 0000000..da3261a
--- /dev/null
+++ b/extphone/src/com/qti/extphone/QosBearerSession.java
@@ -0,0 +1,145 @@
+/**
+ * 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.
+ */
+
+/**
+ * Changes from Qualcomm Innovation Center are provided under the following license:
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+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.
+ */
+public final class QosBearerSession implements Parcelable{
+
+ final int qosBearerSessionId;
+ final Qos qos;
+ final List<QosBearerFilter> qosBearerFilterList;
+
+ public QosBearerSession(int qosBearerSessionId,
+ /* @NonNull */ Qos qos,
+ /* @NonNull */ List<QosBearerFilter> qosBearerFilterList) {
+ this.qosBearerSessionId = qosBearerSessionId;
+ this.qos = qos;
+ this.qosBearerFilterList = qosBearerFilterList;
+ }
+
+ private QosBearerSession(Parcel source) {
+ qosBearerSessionId = source.readInt();
+ qos = source.readParcelable(Qos.class.getClassLoader());
+ qosBearerFilterList = new ArrayList<>();
+ source.readList(qosBearerFilterList, QosBearerFilter.class.getClassLoader());
+ }
+
+ public int getQosBearerSessionId() {
+ return qosBearerSessionId;
+ }
+
+ public Qos getQos() {
+ return qos;
+ }
+
+ public List<QosBearerFilter> getQosBearerFilterList() {
+ return qosBearerFilterList;
+ }
+
+ @Override
+ public void writeToParcel(/* @NonNull */ Parcel dest, int flags) {
+ dest.writeInt(qosBearerSessionId);
+ if (qos.getType() == Qos.QOS_TYPE_EPS) {
+ dest.writeParcelable((EpsQos)qos, flags);
+ } else {
+ dest.writeParcelable((NrQos)qos, flags);
+ }
+ dest.writeList(qosBearerFilterList);
+ }
+
+ // @NonNull
+ public static QosBearerSession create(
+ /* @NonNull */ android.hardware.radio.V1_6.QosSession qosSession) {
+ List<QosBearerFilter> qosBearerFilters = new ArrayList<>();
+
+ if (qosSession.qosFilters != null) {
+ for (android.hardware.radio.V1_6.QosFilter filter : qosSession.qosFilters) {
+ qosBearerFilters.add(QosBearerFilter.create(filter));
+ }
+ }
+
+ return new QosBearerSession(
+ qosSession.qosSessionId,
+ Qos.create(qosSession.qos),
+ qosBearerFilters);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "QosBearerSession {"
+ + " qosBearerSessionId=" + qosBearerSessionId
+ + " qos=" + qos
+ + " qosBearerFilterList=" + qosBearerFilterList + "}";
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(qosBearerSessionId, qos, qosBearerFilterList);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (o == null || !(o instanceof QosBearerSession)) {
+ return false;
+ }
+
+ QosBearerSession other = (QosBearerSession) o;
+ return this.qosBearerSessionId == other.qosBearerSessionId
+ && this.qos.equals(other.qos)
+ && this.qosBearerFilterList.size() == other.qosBearerFilterList.size()
+ && this.qosBearerFilterList.containsAll(other.qosBearerFilterList);
+ }
+
+
+ // @NonNull
+ public static final Parcelable.Creator<QosBearerSession> CREATOR =
+ new Parcelable.Creator<QosBearerSession>() {
+ @Override
+ public QosBearerSession createFromParcel(Parcel source) {
+ return new QosBearerSession(source);
+ }
+
+ @Override
+ public QosBearerSession[] newArray(int size) {
+ return new QosBearerSession[size];
+ }
+ };
+}
diff --git a/extphone/src/com/qti/extphone/QosParametersResult.aidl b/extphone/src/com/qti/extphone/QosParametersResult.aidl
new file mode 100644
index 0000000..7867243
--- /dev/null
+++ b/extphone/src/com/qti/extphone/QosParametersResult.aidl
@@ -0,0 +1,8 @@
+/**
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+parcelable QosParametersResult;
\ No newline at end of file
diff --git a/extphone/src/com/qti/extphone/QosParametersResult.java b/extphone/src/com/qti/extphone/QosParametersResult.java
new file mode 100644
index 0000000..ac8fca3
--- /dev/null
+++ b/extphone/src/com/qti/extphone/QosParametersResult.java
@@ -0,0 +1,202 @@
+/**
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class QosParametersResult implements Parcelable {
+
+ private static final String TAG = "QosParametersResult";
+
+ public static final int QOS_TYPE_EPS = Qos.QOS_TYPE_EPS;
+ public static final int QOS_TYPE_NR = Qos.QOS_TYPE_NR;
+
+ private final Qos mDefaultQos;
+ private final List<QosBearerSession> mQosBearerSessions;
+
+ public QosParametersResult() {
+ mDefaultQos = null;
+ mQosBearerSessions = new ArrayList<>();
+ }
+
+
+ public QosParametersResult(/* @Nullable */ Qos defaultQos,
+ /* @Nullable */ List<QosBearerSession> qosBearerSessions) {
+ mDefaultQos = defaultQos;
+ mQosBearerSessions = (qosBearerSessions == null)
+ ? new ArrayList<>() : new ArrayList<>(qosBearerSessions);
+ }
+
+ public QosParametersResult(Parcel source) {
+ mDefaultQos = source.readParcelable(Qos.class.getClassLoader());
+ mQosBearerSessions = new ArrayList<>();
+ source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader());
+ }
+
+ /**
+ * @return default QOS of the data connection received from the network
+ *
+ * @hide
+ * @Nullable
+ */
+ public Qos getDefaultQos() {
+ return mDefaultQos;
+ }
+
+ /**
+ * @return All the dedicated bearer QOS sessions of the data connection received from the
+ * network.
+ *
+ * @hide
+ * @NonNull
+ */
+ public List<QosBearerSession> getQosBearerSessions() {
+ return mQosBearerSessions;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("QosParametersResult: {")
+ .append(" defaultQos=").append(mDefaultQos)
+ .append(" qosBearerSessions=").append(mQosBearerSessions)
+ .append("}");
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(/* @Nullable */ Object o) {
+ if (this == o) return true;
+
+ if (!(o instanceof QosParametersResult)) {
+ return false;
+ }
+
+ QosParametersResult other = (QosParametersResult) o;
+
+ final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null)
+ ? mDefaultQos == other.mDefaultQos
+ : mDefaultQos.equals(other.mDefaultQos);
+
+ final boolean isQosBearerSessionsSame =
+ (mQosBearerSessions == null || other.mQosBearerSessions == null)
+ ? mQosBearerSessions == other.mQosBearerSessions
+ : mQosBearerSessions.size() == other.mQosBearerSessions.size()
+ && mQosBearerSessions.containsAll(other.mQosBearerSessions);
+
+ return isQosSame && isQosBearerSessionsSame;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDefaultQos, mQosBearerSessions);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (mDefaultQos != null) {
+ if (mDefaultQos.getType() == Qos.QOS_TYPE_EPS) {
+ dest.writeParcelable((EpsQos) mDefaultQos, flags);
+ } else {
+ dest.writeParcelable((NrQos) mDefaultQos, flags);
+ }
+ } else {
+ dest.writeParcelable(null, flags);
+ }
+ dest.writeList(mQosBearerSessions);
+ }
+
+ // @NonNull
+ public static final Parcelable.Creator<QosParametersResult> CREATOR =
+ new Parcelable.Creator<QosParametersResult>() {
+ @Override
+ public QosParametersResult createFromParcel(Parcel source) {
+ return new QosParametersResult(source);
+ }
+
+ @Override
+ public QosParametersResult[] newArray(int size) {
+ return new QosParametersResult[size];
+ }
+ };
+
+ /**
+ * Provides a convenient way to set the fields of a {@link QosParametersResult} when
+ * creating a new instance.
+ *
+ * <p>The example below shows how you might create a new {@code QosParametersResult}:
+ *
+ * <pre><code>
+ *
+ * QosParametersResult response = new QosParametersResult.Builder()
+ * .setAddresses(Arrays.asList("192.168.1.2"))
+ * .setProtocolType(ApnSetting.PROTOCOL_IPV4V6)
+ * .build();
+ * </code></pre>
+ */
+ public static final class Builder {
+ private Qos mDefaultQos;
+ private List<QosBearerSession> mQosBearerSessions = new ArrayList<>();
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {
+ }
+
+ /**
+ * 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
+ * @NonNull
+ */
+ public Builder setDefaultQos(/* Nullable */ Qos defaultQos) {
+ mDefaultQos = defaultQos;
+ return this;
+ }
+
+ /**
+ * Set the dedicated bearer QOS sessions for this data connection.
+ *
+ * @param qosBearerSessions Dedicated bearer QOS (Quality Of Service) sessions received
+ * from network.
+ *
+ * @return The same instance of the builder.
+ *
+ * @hide
+ * @NonNull
+ */
+ public Builder setQosBearerSessions(
+ /* @NonNull */ List<QosBearerSession> qosBearerSessions) {
+ mQosBearerSessions = qosBearerSessions;
+ return this;
+ }
+
+ /**
+ * Build the QosParametersResult.
+ *
+ * @return the QosParametersResult object.
+ * @NonNull
+ */
+ public QosParametersResult build() {
+ return new QosParametersResult(mDefaultQos, mQosBearerSessions);
+ }
+ }
+}
\ No newline at end of file