| /* |
| * Copyright (C) 2023 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.net.wifi; |
| |
| import android.annotation.IntDef; |
| import android.annotation.IntRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.SystemApi; |
| import android.net.DscpPolicy; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.util.Log; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.net.Inet4Address; |
| import java.net.Inet6Address; |
| import java.net.InetAddress; |
| import java.util.Arrays; |
| import java.util.Objects; |
| |
| /** |
| * Parameters for QoS policies requested by system applications. |
| * @hide |
| */ |
| @SystemApi |
| public final class QosPolicyParams implements Parcelable { |
| private static final String TAG = "QosPolicyParams"; |
| |
| /** |
| * Indicates that the policy does not specify a DSCP value. |
| */ |
| public static final int DSCP_ANY = -1; |
| |
| /** |
| * Indicates that the policy does not specify a protocol. |
| */ |
| public static final int PROTOCOL_ANY = DscpPolicy.PROTOCOL_ANY; |
| |
| /** |
| * Policy should match packets using the TCP protocol. |
| */ |
| public static final int PROTOCOL_TCP = 6; |
| |
| /** |
| * Policy should match packets using the UDP protocol. |
| */ |
| public static final int PROTOCOL_UDP = 17; |
| |
| /** |
| * Policy should match packets using the ESP protocol. |
| */ |
| public static final int PROTOCOL_ESP = 50; |
| |
| /** @hide */ |
| @IntDef(prefix = { "PROTOCOL_" }, value = { |
| PROTOCOL_ANY, |
| PROTOCOL_TCP, |
| PROTOCOL_UDP, |
| PROTOCOL_ESP |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface Protocol {} |
| |
| /** |
| * Policy should match packets in the uplink direction. |
| */ |
| public static final int DIRECTION_UPLINK = 0; |
| |
| /** |
| * Policy should match packets in the downlink direction. |
| */ |
| public static final int DIRECTION_DOWNLINK = 1; |
| |
| |
| /** @hide */ |
| @IntDef(prefix = { "DIRECTION_" }, value = { |
| DIRECTION_UPLINK, |
| DIRECTION_DOWNLINK, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface Direction {} |
| |
| /** |
| * Indicates that the policy does not specify a User Priority. |
| */ |
| public static final int USER_PRIORITY_ANY = -1; |
| |
| /** |
| * Policy should be assigned a low background priority. |
| */ |
| public static final int USER_PRIORITY_BACKGROUND_LOW = 1; |
| |
| /** |
| * Policy should be assigned a high background priority. |
| */ |
| public static final int USER_PRIORITY_BACKGROUND_HIGH = 2; |
| |
| /** |
| * Policy should be assigned a low best-effort priority. |
| */ |
| public static final int USER_PRIORITY_BEST_EFFORT_LOW = 0; |
| |
| /** |
| * Policy should be assigned a high best-effort priority. |
| */ |
| public static final int USER_PRIORITY_BEST_EFFORT_HIGH = 3; |
| |
| /** |
| * Policy should be assigned a low video priority. |
| */ |
| public static final int USER_PRIORITY_VIDEO_LOW = 4; |
| |
| /** |
| * Policy should be assigned a high video priority. |
| */ |
| public static final int USER_PRIORITY_VIDEO_HIGH = 5; |
| |
| /** |
| * Policy should be assigned a low voice priority. |
| */ |
| public static final int USER_PRIORITY_VOICE_LOW = 6; |
| |
| /** |
| * Policy should be assigned a high voice priority. |
| */ |
| public static final int USER_PRIORITY_VOICE_HIGH = 7; |
| |
| /** @hide */ |
| @IntDef(prefix = { "USER_PRIORITY_" }, value = { |
| USER_PRIORITY_ANY, |
| USER_PRIORITY_BACKGROUND_LOW, |
| USER_PRIORITY_BACKGROUND_HIGH, |
| USER_PRIORITY_BEST_EFFORT_LOW, |
| USER_PRIORITY_BEST_EFFORT_HIGH, |
| USER_PRIORITY_VIDEO_LOW, |
| USER_PRIORITY_VIDEO_HIGH, |
| USER_PRIORITY_VOICE_LOW, |
| USER_PRIORITY_VOICE_HIGH, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface UserPriority {} |
| |
| /** |
| * Indicates that the policy does not specify an IP version. |
| */ |
| public static final int IP_VERSION_ANY = -1; |
| |
| /** |
| * Policy should match packets using IPv4. |
| */ |
| public static final int IP_VERSION_4 = 4; |
| |
| /** |
| * Policy should match packets using IPv6. |
| */ |
| public static final int IP_VERSION_6 = 6; |
| |
| /** @hide */ |
| @IntDef(prefix = { "IP_VERSION_" }, value = { |
| IP_VERSION_ANY, |
| IP_VERSION_4, |
| IP_VERSION_6 |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface IpVersion {} |
| |
| /** |
| * Indicates that the policy does not specify a destination port. |
| */ |
| public static final int DESTINATION_PORT_ANY = -1; |
| |
| /** |
| * Unique policy ID. See {@link Builder#Builder(int, int)} for more information. |
| */ |
| private final int mPolicyId; |
| |
| /** |
| * Translated policy ID. Should only be set by the Wi-Fi service. |
| * @hide |
| */ |
| private int mTranslatedPolicyId; |
| |
| // QoS DSCP marking. See {@link Builder#setDscp(int)} for more information. |
| private final int mDscp; |
| |
| // User priority to apply to packets matching the policy. Only applicable to downlink requests. |
| private final int mUserPriority; |
| |
| // Source IP address. |
| private final @Nullable InetAddress mSrcIp; |
| |
| // Destination IP address. |
| private final @Nullable InetAddress mDstIp; |
| |
| // Source port. |
| private final int mSrcPort; |
| |
| // IP protocol that the policy requires. |
| private final @Protocol int mProtocol; |
| |
| // Single destination port. Only applicable to downlink requests. |
| private final int mDstPort; |
| |
| // Destination port range. Inclusive range. Only applicable to uplink requests. |
| private final @Nullable int[] mDstPortRange; |
| |
| // Direction of traffic stream. |
| private final @Direction int mDirection; |
| |
| // IP version. Only applicable to downlink requests. |
| private final @IpVersion int mIpVersion; |
| |
| // Flow label. Only applicable to downlink requests using IPv6. |
| private final @Nullable byte[] mFlowLabel; |
| |
| private QosPolicyParams(int policyId, int dscp, @UserPriority int userPriority, |
| @Nullable InetAddress srcIp, @Nullable InetAddress dstIp, int srcPort, |
| @Protocol int protocol, @Nullable int[] dstPortRange, @Direction int direction, |
| @IpVersion int ipVersion, int dstPort, @Nullable byte[] flowLabel) { |
| this.mPolicyId = policyId; |
| this.mDscp = dscp; |
| this.mUserPriority = userPriority; |
| this.mSrcIp = srcIp; |
| this.mDstIp = dstIp; |
| this.mSrcPort = srcPort; |
| this.mProtocol = protocol; |
| this.mDstPort = dstPort; |
| this.mDstPortRange = dstPortRange; |
| this.mDirection = direction; |
| this.mIpVersion = ipVersion; |
| this.mFlowLabel = flowLabel; |
| } |
| |
| /** |
| * Validate the parameters in this instance. |
| * |
| * @return true if all parameters are valid, false otherwise |
| * @hide |
| */ |
| public boolean validate() { |
| if (mPolicyId < 1 || mPolicyId > 255) { |
| Log.e(TAG, "Policy ID not in valid range: " + mPolicyId); |
| return false; |
| } |
| if (mDscp < DSCP_ANY || mDscp > 63) { |
| Log.e(TAG, "DSCP value not in valid range: " + mDscp); |
| return false; |
| } |
| if (mUserPriority < USER_PRIORITY_ANY || mUserPriority > USER_PRIORITY_VOICE_HIGH) { |
| Log.e(TAG, "User priority not in valid range: " + mUserPriority); |
| return false; |
| } |
| if (mSrcPort < DscpPolicy.SOURCE_PORT_ANY || mSrcPort > 65535) { |
| Log.e(TAG, "Source port not in valid range: " + mSrcPort); |
| return false; |
| } |
| if (mDstPort < DESTINATION_PORT_ANY || mDstPort > 65535) { |
| Log.e(TAG, "Destination port not in valid range: " + mDstPort); |
| return false; |
| } |
| if (mDstPortRange != null && (mDstPortRange[0] < 0 || mDstPortRange[0] > 65535 |
| || mDstPortRange[1] < 0 || mDstPortRange[1] > 65535)) { |
| Log.e(TAG, "Dst port range value not valid. start=" |
| + mDstPortRange[0] + ", end=" + mDstPortRange[1]); |
| return false; |
| } |
| if (!(mDirection == DIRECTION_UPLINK || mDirection == DIRECTION_DOWNLINK)) { |
| Log.e(TAG, "Invalid direction enum: " + mDirection); |
| return false; |
| } |
| if (!(mIpVersion == IP_VERSION_ANY || mIpVersion == IP_VERSION_4 |
| || mIpVersion == IP_VERSION_6)) { |
| Log.e(TAG, "Invalid ipVersion enum: " + mIpVersion); |
| return false; |
| } |
| if (mIpVersion == IP_VERSION_4) { |
| if (mSrcIp != null && !(mSrcIp instanceof Inet4Address)) { |
| Log.e(TAG, "Src address does not match IP version " + mIpVersion); |
| return false; |
| } |
| if (mDstIp != null && !(mDstIp instanceof Inet4Address)) { |
| Log.e(TAG, "Dst address does not match IP version " + mIpVersion); |
| return false; |
| } |
| } |
| if (mIpVersion == IP_VERSION_6) { |
| if (mSrcIp != null && !(mSrcIp instanceof Inet6Address)) { |
| Log.e(TAG, "Src address does not match IP version " + mIpVersion); |
| return false; |
| } |
| if (mDstIp != null && !(mDstIp instanceof Inet6Address)) { |
| Log.e(TAG, "Dst address does not match IP version " + mIpVersion); |
| return false; |
| } |
| } |
| |
| // Check required parameters based on direction. |
| if (mDirection == DIRECTION_UPLINK) { |
| if (mDscp == DSCP_ANY) { |
| Log.e(TAG, "DSCP must be provided for uplink requests"); |
| return false; |
| } |
| if (mIpVersion != IP_VERSION_ANY) { |
| Log.e(TAG, "IP Version should not be set for uplink requests"); |
| return false; |
| } |
| if (mDstPort != DESTINATION_PORT_ANY) { |
| Log.e(TAG, "Single destination port should not be set for uplink requests"); |
| return false; |
| } |
| if (mFlowLabel != null) { |
| Log.e(TAG, "Flow label should not be set for uplink requests"); |
| return false; |
| } |
| } else { |
| if (mUserPriority == USER_PRIORITY_ANY) { |
| Log.e(TAG, "User priority must be provided for downlink requests"); |
| return false; |
| } |
| if (mIpVersion == IP_VERSION_ANY) { |
| Log.e(TAG, "IP version must be provided for downlink requests"); |
| return false; |
| } |
| if (mDstPortRange != null) { |
| Log.e(TAG, "Destination port range should not be set for downlink requests"); |
| return false; |
| } |
| if (mFlowLabel != null) { |
| if (mIpVersion != IP_VERSION_6) { |
| Log.e(TAG, "Flow label can only be used with IP version 6"); |
| return false; |
| } |
| if (mFlowLabel.length != 3) { |
| Log.e(TAG, "Flow label must be of size 3, provided size is " |
| + mFlowLabel.length); |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * Set the translated policy ID for this policy. |
| * |
| * Note: Translated policy IDs should only be set by the Wi-Fi service. |
| * @hide |
| */ |
| public void setTranslatedPolicyId(int translatedPolicyId) { |
| mTranslatedPolicyId = translatedPolicyId; |
| } |
| |
| /** |
| * Get the ID for this policy. |
| * |
| * See {@link Builder#Builder(int, int)} for more information. |
| */ |
| @IntRange(from = 1, to = 255) |
| public int getPolicyId() { |
| return mPolicyId; |
| } |
| |
| /** |
| * Get the translated ID for this policy. |
| * |
| * See {@link #setTranslatedPolicyId} for more information. |
| * @hide |
| */ |
| public int getTranslatedPolicyId() { |
| return mTranslatedPolicyId; |
| } |
| |
| |
| /** |
| * Get the DSCP value for this policy. |
| * |
| * See {@link Builder#setDscp(int)} for more information. |
| * |
| * @return DSCP value, or {@link #DSCP_ANY} if not assigned. |
| */ |
| @IntRange(from = DSCP_ANY, to = 63) |
| public int getDscp() { |
| return mDscp; |
| } |
| |
| /** |
| * Get the User Priority (UP) for this policy. |
| * |
| * See {@link Builder#setUserPriority(int)} for more information. |
| * |
| * @return User Priority value, or {@link #USER_PRIORITY_ANY} if not assigned. |
| */ |
| public @UserPriority int getUserPriority() { |
| return mUserPriority; |
| } |
| |
| /** |
| * Get the source IP address for this policy. |
| * |
| * See {@link Builder#setSourceAddress(InetAddress)} for more information. |
| * |
| * @return source IP address, or null if not assigned. |
| */ |
| public @Nullable InetAddress getSourceAddress() { |
| return mSrcIp; |
| } |
| |
| /** |
| * Get the destination IP address for this policy. |
| * |
| * See {@link Builder#setDestinationAddress(InetAddress)} for more information. |
| * |
| * @return destination IP address, or null if not assigned. |
| */ |
| public @Nullable InetAddress getDestinationAddress() { |
| return mDstIp; |
| } |
| |
| /** |
| * Get the source port for this policy. |
| * |
| * See {@link Builder#setSourcePort(int)} for more information. |
| * |
| * @return source port, or {@link DscpPolicy#SOURCE_PORT_ANY} if not assigned. |
| */ |
| @IntRange(from = DscpPolicy.SOURCE_PORT_ANY, to = 65535) |
| public int getSourcePort() { |
| return mSrcPort; |
| } |
| |
| /** |
| * Get the protocol for this policy. |
| * |
| * See {@link Builder#setProtocol(int)} for more information. |
| * |
| * @return protocol, or {@link #PROTOCOL_ANY} if not assigned. |
| */ |
| public @Protocol int getProtocol() { |
| return mProtocol; |
| } |
| |
| /** |
| * Get the destination port for this policy. |
| * |
| * See {@link Builder#setDestinationPort(int)} for more information. |
| * |
| * @return destination port, or {@link #DESTINATION_PORT_ANY} if not assigned. |
| */ |
| @IntRange(from = DESTINATION_PORT_ANY, to = 65535) |
| public int getDestinationPort() { |
| return mDstPort; |
| } |
| |
| /** |
| * Get the destination port range for this policy. |
| * |
| * See {@link Builder#setDestinationPortRange(int, int)} for more information. |
| * |
| * @return destination port range, or null if not assigned. |
| */ |
| public @Nullable int[] getDestinationPortRange() { |
| return mDstPortRange; |
| } |
| |
| /** |
| * Get the direction for this policy. |
| * |
| * See {@link Builder#Builder(int, int)} for more information. |
| */ |
| public @Direction int getDirection() { |
| return mDirection; |
| } |
| |
| /** |
| * Get the IP version for this policy. |
| * |
| * See {@link Builder#setIpVersion(int)} for more information. |
| * |
| * @return IP version, or {@link #IP_VERSION_ANY} if not assigned. |
| */ |
| public @IpVersion int getIpVersion() { |
| return mIpVersion; |
| } |
| |
| /** |
| * Get the flow label for this policy. |
| * |
| * See {@link Builder#setFlowLabel(byte[])} for more information. |
| * |
| * @return flow label, or null if not assigned. |
| */ |
| public @Nullable byte[] getFlowLabel() { |
| return mFlowLabel; |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| QosPolicyParams that = (QosPolicyParams) o; |
| return mPolicyId == that.mPolicyId |
| && mDscp == that.mDscp |
| && mUserPriority == that.mUserPriority |
| && mSrcIp.equals(that.mSrcIp) |
| && mDstIp.equals(that.mDstIp) |
| && mSrcPort == that.mSrcPort |
| && mProtocol == that.mProtocol |
| && mDstPort == that.mDstPort |
| && Arrays.equals(mDstPortRange, that.mDstPortRange) |
| && mDirection == that.mDirection |
| && mIpVersion == that.mIpVersion |
| && mFlowLabel == that.mFlowLabel; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mPolicyId, mDscp, mUserPriority, mSrcIp, mDstIp, mSrcPort, |
| mProtocol, Arrays.hashCode(mDstPortRange), mDirection, mIpVersion, mDstPort, |
| Arrays.hashCode(mFlowLabel)); |
| } |
| |
| @Override |
| public String toString() { |
| return "{policyId=" + mPolicyId + ", " |
| + "dscp=" + mDscp + ", " |
| + "userPriority=" + mUserPriority + ", " |
| + "srcIp=" + mSrcIp + ", " |
| + "dstIp=" + mDstIp + ", " |
| + "srcPort=" + mSrcPort + ", " |
| + "protocol=" + mProtocol + ", " |
| + "dstPort=" + mDstPort + ", " |
| + "dstPortRange=" + Arrays.toString(mDstPortRange) + ", " |
| + "direction=" + mDirection + ", " |
| + "ipVersion=" + mIpVersion + ", " |
| + "flowLabel=" + Arrays.toString(mFlowLabel) + "}"; |
| } |
| |
| /** @hide */ |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| private InetAddress getInetAddrOrNull(byte[] byteAddr) { |
| if (byteAddr == null) return null; |
| try { |
| return InetAddress.getByAddress(byteAddr); |
| } catch (Exception e) { |
| return null; |
| } |
| } |
| |
| /** @hide */ |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeInt(mPolicyId); |
| dest.writeInt(mDscp); |
| dest.writeInt(mUserPriority); |
| dest.writeByteArray(mSrcIp != null ? mSrcIp.getAddress() : null); |
| dest.writeByteArray(mDstIp != null ? mDstIp.getAddress() : null); |
| dest.writeInt(mSrcPort); |
| dest.writeInt(mProtocol); |
| dest.writeInt(mDstPort); |
| dest.writeIntArray(mDstPortRange); |
| dest.writeInt(mDirection); |
| dest.writeInt(mIpVersion); |
| dest.writeByteArray(mFlowLabel); |
| } |
| |
| /** @hide */ |
| QosPolicyParams(@NonNull Parcel in) { |
| this.mPolicyId = in.readInt(); |
| this.mDscp = in.readInt(); |
| this.mUserPriority = in.readInt(); |
| this.mSrcIp = getInetAddrOrNull(in.createByteArray()); |
| this.mDstIp = getInetAddrOrNull(in.createByteArray()); |
| this.mSrcPort = in.readInt(); |
| this.mProtocol = in.readInt(); |
| this.mDstPort = in.readInt(); |
| this.mDstPortRange = in.createIntArray(); |
| this.mDirection = in.readInt(); |
| this.mIpVersion = in.readInt(); |
| this.mFlowLabel = in.createByteArray(); |
| } |
| |
| public static final @NonNull Parcelable.Creator<QosPolicyParams> CREATOR = |
| new Parcelable.Creator<QosPolicyParams>() { |
| @Override |
| public QosPolicyParams createFromParcel(Parcel in) { |
| return new QosPolicyParams(in); |
| } |
| |
| @Override |
| public QosPolicyParams[] newArray(int size) { |
| return new QosPolicyParams[size]; |
| } |
| }; |
| |
| /** |
| * Builder for {@link QosPolicyParams}. |
| */ |
| public static final class Builder { |
| private final int mPolicyId; |
| private final @Direction int mDirection; |
| private @Nullable InetAddress mSrcIp; |
| private @Nullable InetAddress mDstIp; |
| private int mDscp = DSCP_ANY; |
| private @UserPriority int mUserPriority = USER_PRIORITY_ANY; |
| private int mSrcPort = DscpPolicy.SOURCE_PORT_ANY; |
| private int mProtocol = PROTOCOL_ANY; |
| private int mDstPort = DESTINATION_PORT_ANY; |
| private @Nullable int[] mDstPortRange; |
| private @IpVersion int mIpVersion = IP_VERSION_ANY; |
| private byte[] mFlowLabel; |
| |
| /** |
| * Constructor for {@link Builder}. |
| * |
| * @param policyId Unique ID to identify this policy. Each requesting application is |
| * responsible for maintaining policy IDs unique for that app. IDs must be |
| * in the range 1 <= policyId <= 255. |
| * |
| * In the case where a policy with an existing ID is created, the new policy |
| * will be rejected. To update an existing policy, remove the existing one |
| * before sending the new one. |
| * @param direction Whether this policy applies to the uplink or downlink direction. |
| */ |
| public Builder(@IntRange(from = 1, to = 255) int policyId, @Direction int direction) { |
| mPolicyId = policyId; |
| mDirection = direction; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided source IP address. |
| */ |
| public @NonNull Builder setSourceAddress(@Nullable InetAddress value) { |
| mSrcIp = value; |
| return this; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided destination IP address. |
| */ |
| public @NonNull Builder setDestinationAddress(@Nullable InetAddress value) { |
| mDstIp = value; |
| return this; |
| } |
| |
| /** |
| * Specifies the DSCP value. For uplink requests, this value will be applied to packets |
| * that match the classifier. For downlink requests, this will be part of the classifier. |
| */ |
| public @NonNull Builder setDscp(@IntRange(from = DSCP_ANY, to = 63) int value) { |
| mDscp = value; |
| return this; |
| } |
| |
| /** |
| * Specifies that the provided User Priority should be applied to packets that |
| * match this classifier. Only applicable to downlink requests. |
| */ |
| public @NonNull Builder setUserPriority(@UserPriority int value) { |
| mUserPriority = value; |
| return this; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided source port. |
| */ |
| public @NonNull Builder setSourcePort( |
| @IntRange(from = DscpPolicy.SOURCE_PORT_ANY, to = 65535) int value) { |
| mSrcPort = value; |
| return this; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided protocol. |
| */ |
| public @NonNull Builder setProtocol(@Protocol int value) { |
| mProtocol = value; |
| return this; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided destination port. |
| * Only applicable to downlink requests. |
| */ |
| public @NonNull Builder setDestinationPort( |
| @IntRange(from = DESTINATION_PORT_ANY, to = 65535) int value) { |
| mDstPort = value; |
| return this; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided destination port range. |
| * Only applicable to uplink requests. |
| */ |
| public @NonNull Builder setDestinationPortRange( |
| @IntRange(from = 0, to = 65535) int start, |
| @IntRange(from = 0, to = 65535) int end) { |
| mDstPortRange = new int[]{start, end}; |
| return this; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided IP version. |
| * This argument is mandatory for downlink requests, and is ignored for uplink requests. |
| */ |
| public @NonNull Builder setIpVersion(@IpVersion int value) { |
| mIpVersion = value; |
| return this; |
| } |
| |
| /** |
| * Specifies that this policy matches packets with the provided flow label. |
| * Only applicable to downlink requests using IPv6. |
| */ |
| public @NonNull Builder setFlowLabel(@Nullable byte[] value) { |
| mFlowLabel = value; |
| return this; |
| } |
| |
| /** |
| * Construct a QosPolicyParams object with the specified parameters. |
| */ |
| public @NonNull QosPolicyParams build() { |
| QosPolicyParams params = new QosPolicyParams(mPolicyId, mDscp, mUserPriority, mSrcIp, |
| mDstIp, mSrcPort, mProtocol, mDstPortRange, mDirection, mIpVersion, mDstPort, |
| mFlowLabel); |
| if (!params.validate()) { |
| throw new IllegalArgumentException("Provided parameters are invalid"); |
| } |
| return params; |
| } |
| } |
| } |