• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.wifi;
18 
19 import android.annotation.IntDef;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.net.DscpPolicy;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.util.Log;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.net.Inet4Address;
32 import java.net.Inet6Address;
33 import java.net.InetAddress;
34 import java.util.Arrays;
35 import java.util.Objects;
36 
37 /**
38  * Parameters for QoS policies requested by system applications.
39  * @hide
40  */
41 @SystemApi
42 public final class QosPolicyParams implements Parcelable {
43     private static final String TAG = "QosPolicyParams";
44 
45     /**
46      * Indicates that the policy does not specify a DSCP value.
47      */
48     public static final int DSCP_ANY = -1;
49 
50     /**
51      * Indicates that the policy does not specify a protocol.
52      */
53     public static final int PROTOCOL_ANY = DscpPolicy.PROTOCOL_ANY;
54 
55     /**
56      * Policy should match packets using the TCP protocol.
57      */
58     public static final int PROTOCOL_TCP = 6;
59 
60     /**
61      * Policy should match packets using the UDP protocol.
62      */
63     public static final int PROTOCOL_UDP = 17;
64 
65     /**
66      * Policy should match packets using the ESP protocol.
67      */
68     public static final int PROTOCOL_ESP = 50;
69 
70     /** @hide */
71     @IntDef(prefix = { "PROTOCOL_" }, value = {
72             PROTOCOL_ANY,
73             PROTOCOL_TCP,
74             PROTOCOL_UDP,
75             PROTOCOL_ESP
76     })
77     @Retention(RetentionPolicy.SOURCE)
78     public @interface Protocol {}
79 
80     /**
81      * Policy should match packets in the uplink direction.
82      */
83     public static final int DIRECTION_UPLINK = 0;
84 
85     /**
86      * Policy should match packets in the downlink direction.
87      */
88     public static final int DIRECTION_DOWNLINK = 1;
89 
90 
91     /** @hide */
92     @IntDef(prefix = { "DIRECTION_" }, value = {
93             DIRECTION_UPLINK,
94             DIRECTION_DOWNLINK,
95     })
96     @Retention(RetentionPolicy.SOURCE)
97     public @interface Direction {}
98 
99     /**
100      * Indicates that the policy does not specify a User Priority.
101      */
102     public static final int USER_PRIORITY_ANY = -1;
103 
104     /**
105      * Policy should be assigned a low background priority.
106      */
107     public static final int USER_PRIORITY_BACKGROUND_LOW = 1;
108 
109     /**
110      * Policy should be assigned a high background priority.
111      */
112     public static final int USER_PRIORITY_BACKGROUND_HIGH = 2;
113 
114     /**
115      * Policy should be assigned a low best-effort priority.
116      */
117     public static final int USER_PRIORITY_BEST_EFFORT_LOW = 0;
118 
119     /**
120      * Policy should be assigned a high best-effort priority.
121      */
122     public static final int USER_PRIORITY_BEST_EFFORT_HIGH = 3;
123 
124     /**
125      * Policy should be assigned a low video priority.
126      */
127     public static final int USER_PRIORITY_VIDEO_LOW = 4;
128 
129     /**
130      * Policy should be assigned a high video priority.
131      */
132     public static final int USER_PRIORITY_VIDEO_HIGH = 5;
133 
134     /**
135      * Policy should be assigned a low voice priority.
136      */
137     public static final int USER_PRIORITY_VOICE_LOW = 6;
138 
139     /**
140      * Policy should be assigned a high voice priority.
141      */
142     public static final int USER_PRIORITY_VOICE_HIGH = 7;
143 
144     /** @hide */
145     @IntDef(prefix = { "USER_PRIORITY_" }, value = {
146             USER_PRIORITY_ANY,
147             USER_PRIORITY_BACKGROUND_LOW,
148             USER_PRIORITY_BACKGROUND_HIGH,
149             USER_PRIORITY_BEST_EFFORT_LOW,
150             USER_PRIORITY_BEST_EFFORT_HIGH,
151             USER_PRIORITY_VIDEO_LOW,
152             USER_PRIORITY_VIDEO_HIGH,
153             USER_PRIORITY_VOICE_LOW,
154             USER_PRIORITY_VOICE_HIGH,
155     })
156     @Retention(RetentionPolicy.SOURCE)
157     public @interface UserPriority {}
158 
159     /**
160      * Indicates that the policy does not specify an IP version.
161      */
162     public static final int IP_VERSION_ANY = -1;
163 
164     /**
165      * Policy should match packets using IPv4.
166      */
167     public static final int IP_VERSION_4 = 4;
168 
169     /**
170      * Policy should match packets using IPv6.
171      */
172     public static final int IP_VERSION_6 = 6;
173 
174     /** @hide */
175     @IntDef(prefix = { "IP_VERSION_" }, value = {
176             IP_VERSION_ANY,
177             IP_VERSION_4,
178             IP_VERSION_6
179     })
180     @Retention(RetentionPolicy.SOURCE)
181     public @interface IpVersion {}
182 
183     /**
184      * Indicates that the policy does not specify a destination port.
185      */
186     public static final int DESTINATION_PORT_ANY = -1;
187 
188     /**
189      * Unique policy ID. See {@link Builder#Builder(int, int)} for more information.
190      */
191     private final int mPolicyId;
192 
193     /**
194      * Translated policy ID. Should only be set by the Wi-Fi service.
195      * @hide
196      */
197     private int mTranslatedPolicyId;
198 
199     // QoS DSCP marking. See {@link Builder#setDscp(int)} for more information.
200     private final int mDscp;
201 
202     // User priority to apply to packets matching the policy. Only applicable to downlink requests.
203     private final int mUserPriority;
204 
205     // Source IP address.
206     private final @Nullable InetAddress mSrcIp;
207 
208     // Destination IP address.
209     private final @Nullable InetAddress mDstIp;
210 
211     // Source port.
212     private final int mSrcPort;
213 
214     // IP protocol that the policy requires.
215     private final @Protocol int mProtocol;
216 
217     // Single destination port. Only applicable to downlink requests.
218     private final int mDstPort;
219 
220     // Destination port range. Inclusive range. Only applicable to uplink requests.
221     private final @Nullable int[] mDstPortRange;
222 
223     // Direction of traffic stream.
224     private final @Direction int mDirection;
225 
226     // IP version. Only applicable to downlink requests.
227     private final @IpVersion int mIpVersion;
228 
229     // Flow label. Only applicable to downlink requests using IPv6.
230     private final @Nullable byte[] mFlowLabel;
231 
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)232     private QosPolicyParams(int policyId, int dscp, @UserPriority int userPriority,
233             @Nullable InetAddress srcIp, @Nullable InetAddress dstIp, int srcPort,
234             @Protocol int protocol, @Nullable int[] dstPortRange, @Direction int direction,
235             @IpVersion int ipVersion, int dstPort, @Nullable byte[] flowLabel) {
236         this.mPolicyId = policyId;
237         this.mDscp = dscp;
238         this.mUserPriority = userPriority;
239         this.mSrcIp = srcIp;
240         this.mDstIp = dstIp;
241         this.mSrcPort = srcPort;
242         this.mProtocol = protocol;
243         this.mDstPort = dstPort;
244         this.mDstPortRange = dstPortRange;
245         this.mDirection = direction;
246         this.mIpVersion = ipVersion;
247         this.mFlowLabel = flowLabel;
248     }
249 
250     /**
251      * Validate the parameters in this instance.
252      *
253      * @return true if all parameters are valid, false otherwise
254      * @hide
255      */
validate()256     public boolean validate() {
257         if (mPolicyId < 1 || mPolicyId > 255) {
258             Log.e(TAG, "Policy ID not in valid range: " + mPolicyId);
259             return false;
260         }
261         if (mDscp < DSCP_ANY || mDscp > 63) {
262             Log.e(TAG, "DSCP value not in valid range: " + mDscp);
263             return false;
264         }
265         if (mUserPriority < USER_PRIORITY_ANY || mUserPriority > USER_PRIORITY_VOICE_HIGH) {
266             Log.e(TAG, "User priority not in valid range: " + mUserPriority);
267             return false;
268         }
269         if (mSrcPort < DscpPolicy.SOURCE_PORT_ANY || mSrcPort > 65535) {
270             Log.e(TAG, "Source port not in valid range: " + mSrcPort);
271             return false;
272         }
273         if (mDstPort < DESTINATION_PORT_ANY || mDstPort > 65535) {
274             Log.e(TAG, "Destination port not in valid range: " + mDstPort);
275             return false;
276         }
277         if (mDstPortRange != null && (mDstPortRange[0] < 0 || mDstPortRange[0] > 65535
278                 || mDstPortRange[1] < 0 || mDstPortRange[1] > 65535)) {
279             Log.e(TAG, "Dst port range value not valid. start="
280                     + mDstPortRange[0] + ", end=" + mDstPortRange[1]);
281             return false;
282         }
283         if (!(mDirection == DIRECTION_UPLINK || mDirection == DIRECTION_DOWNLINK)) {
284             Log.e(TAG, "Invalid direction enum: " + mDirection);
285             return false;
286         }
287         if (!(mIpVersion == IP_VERSION_ANY || mIpVersion == IP_VERSION_4
288                 || mIpVersion == IP_VERSION_6)) {
289             Log.e(TAG, "Invalid ipVersion enum: " + mIpVersion);
290             return false;
291         }
292         if (mIpVersion == IP_VERSION_4) {
293             if (mSrcIp != null && !(mSrcIp instanceof Inet4Address)) {
294                 Log.e(TAG, "Src address does not match IP version " + mIpVersion);
295                 return false;
296             }
297             if (mDstIp != null && !(mDstIp instanceof Inet4Address)) {
298                 Log.e(TAG, "Dst address does not match IP version " + mIpVersion);
299                 return false;
300             }
301         }
302         if (mIpVersion == IP_VERSION_6) {
303             if (mSrcIp != null && !(mSrcIp instanceof Inet6Address)) {
304                 Log.e(TAG, "Src address does not match IP version " + mIpVersion);
305                 return false;
306             }
307             if (mDstIp != null && !(mDstIp instanceof Inet6Address)) {
308                 Log.e(TAG, "Dst address does not match IP version " + mIpVersion);
309                 return false;
310             }
311         }
312 
313         // Check required parameters based on direction.
314         if (mDirection == DIRECTION_UPLINK) {
315             if (mDscp == DSCP_ANY) {
316                 Log.e(TAG, "DSCP must be provided for uplink requests");
317                 return false;
318             }
319             if (mIpVersion != IP_VERSION_ANY) {
320                 Log.e(TAG, "IP Version should not be set for uplink requests");
321                 return false;
322             }
323             if (mDstPort != DESTINATION_PORT_ANY) {
324                 Log.e(TAG, "Single destination port should not be set for uplink requests");
325                 return false;
326             }
327             if (mFlowLabel != null) {
328                 Log.e(TAG, "Flow label should not be set for uplink requests");
329                 return false;
330             }
331         } else {
332             if (mUserPriority == USER_PRIORITY_ANY) {
333                 Log.e(TAG, "User priority must be provided for downlink requests");
334                 return false;
335             }
336             if (mIpVersion == IP_VERSION_ANY) {
337                 Log.e(TAG, "IP version must be provided for downlink requests");
338                 return false;
339             }
340             if (mDstPortRange != null) {
341                 Log.e(TAG, "Destination port range should not be set for downlink requests");
342                 return false;
343             }
344             if (mFlowLabel != null) {
345                 if (mIpVersion != IP_VERSION_6) {
346                     Log.e(TAG, "Flow label can only be used with IP version 6");
347                     return false;
348                 }
349                 if (mFlowLabel.length != 3) {
350                     Log.e(TAG, "Flow label must be of size 3, provided size is "
351                             + mFlowLabel.length);
352                     return false;
353                 }
354             }
355         }
356         return true;
357     }
358 
359     /**
360      * Set the translated policy ID for this policy.
361      *
362      * Note: Translated policy IDs should only be set by the Wi-Fi service.
363      * @hide
364      */
setTranslatedPolicyId(int translatedPolicyId)365     public void setTranslatedPolicyId(int translatedPolicyId) {
366         mTranslatedPolicyId = translatedPolicyId;
367     }
368 
369     /**
370      * Get the ID for this policy.
371      *
372      * See {@link Builder#Builder(int, int)} for more information.
373      */
374     @IntRange(from = 1, to = 255)
getPolicyId()375     public int getPolicyId() {
376         return mPolicyId;
377     }
378 
379     /**
380      * Get the translated ID for this policy.
381      *
382      * See {@link #setTranslatedPolicyId} for more information.
383      * @hide
384      */
getTranslatedPolicyId()385     public int getTranslatedPolicyId() {
386         return mTranslatedPolicyId;
387     }
388 
389 
390     /**
391      * Get the DSCP value for this policy.
392      *
393      * See {@link Builder#setDscp(int)} for more information.
394      *
395      * @return DSCP value, or {@link #DSCP_ANY} if not assigned.
396      */
397     @IntRange(from = DSCP_ANY, to = 63)
getDscp()398     public int getDscp() {
399         return mDscp;
400     }
401 
402     /**
403      * Get the User Priority (UP) for this policy.
404      *
405      * See {@link Builder#setUserPriority(int)} for more information.
406      *
407      * @return User Priority value, or {@link #USER_PRIORITY_ANY} if not assigned.
408      */
getUserPriority()409     public @UserPriority int getUserPriority() {
410         return mUserPriority;
411     }
412 
413     /**
414      * Get the source IP address for this policy.
415      *
416      * See {@link Builder#setSourceAddress(InetAddress)} for more information.
417      *
418      * @return source IP address, or null if not assigned.
419      */
getSourceAddress()420     public @Nullable InetAddress getSourceAddress() {
421         return mSrcIp;
422     }
423 
424     /**
425      * Get the destination IP address for this policy.
426      *
427      * See {@link Builder#setDestinationAddress(InetAddress)} for more information.
428      *
429      * @return destination IP address, or null if not assigned.
430      */
getDestinationAddress()431     public @Nullable InetAddress getDestinationAddress() {
432         return mDstIp;
433     }
434 
435     /**
436      * Get the source port for this policy.
437      *
438      * See {@link Builder#setSourcePort(int)} for more information.
439      *
440      * @return source port, or {@link DscpPolicy#SOURCE_PORT_ANY} if not assigned.
441      */
442     @IntRange(from = DscpPolicy.SOURCE_PORT_ANY, to = 65535)
getSourcePort()443     public int getSourcePort() {
444         return mSrcPort;
445     }
446 
447     /**
448      * Get the protocol for this policy.
449      *
450      * See {@link Builder#setProtocol(int)} for more information.
451      *
452      * @return protocol, or {@link #PROTOCOL_ANY} if not assigned.
453      */
getProtocol()454     public @Protocol int getProtocol() {
455         return mProtocol;
456     }
457 
458     /**
459      * Get the destination port for this policy.
460      *
461      * See {@link Builder#setDestinationPort(int)} for more information.
462      *
463      * @return destination port, or {@link #DESTINATION_PORT_ANY} if not assigned.
464      */
465     @IntRange(from = DESTINATION_PORT_ANY, to = 65535)
getDestinationPort()466     public int getDestinationPort() {
467         return mDstPort;
468     }
469 
470     /**
471      * Get the destination port range for this policy.
472      *
473      * See {@link Builder#setDestinationPortRange(int, int)} for more information.
474      *
475      * @return destination port range, or null if not assigned.
476      */
getDestinationPortRange()477     public @Nullable int[] getDestinationPortRange() {
478         return mDstPortRange;
479     }
480 
481     /**
482      * Get the direction for this policy.
483      *
484      * See {@link Builder#Builder(int, int)} for more information.
485      */
getDirection()486     public @Direction int getDirection() {
487         return mDirection;
488     }
489 
490     /**
491      * Get the IP version for this policy.
492      *
493      * See {@link Builder#setIpVersion(int)} for more information.
494      *
495      * @return IP version, or {@link #IP_VERSION_ANY} if not assigned.
496      */
getIpVersion()497     public @IpVersion int getIpVersion() {
498         return mIpVersion;
499     }
500 
501     /**
502      * Get the flow label for this policy.
503      *
504      * See {@link Builder#setFlowLabel(byte[])} for more information.
505      *
506      * @return flow label, or null if not assigned.
507      */
getFlowLabel()508     public @Nullable byte[] getFlowLabel() {
509         return mFlowLabel;
510     }
511 
512     @Override
equals(@ullable Object o)513     public boolean equals(@Nullable Object o) {
514         if (this == o) return true;
515         if (o == null || getClass() != o.getClass()) return false;
516         QosPolicyParams that = (QosPolicyParams) o;
517         return mPolicyId == that.mPolicyId
518                 && mDscp == that.mDscp
519                 && mUserPriority == that.mUserPriority
520                 && mSrcIp.equals(that.mSrcIp)
521                 && mDstIp.equals(that.mDstIp)
522                 && mSrcPort == that.mSrcPort
523                 && mProtocol == that.mProtocol
524                 && mDstPort == that.mDstPort
525                 && Arrays.equals(mDstPortRange, that.mDstPortRange)
526                 && mDirection == that.mDirection
527                 && mIpVersion == that.mIpVersion
528                 && mFlowLabel == that.mFlowLabel;
529     }
530 
531     @Override
hashCode()532     public int hashCode() {
533         return Objects.hash(mPolicyId, mDscp, mUserPriority, mSrcIp, mDstIp, mSrcPort,
534                 mProtocol, Arrays.hashCode(mDstPortRange), mDirection, mIpVersion, mDstPort,
535                 Arrays.hashCode(mFlowLabel));
536     }
537 
538     @Override
toString()539     public String toString() {
540         return "{policyId=" + mPolicyId + ", "
541                 + "dscp=" + mDscp + ", "
542                 + "userPriority=" + mUserPriority + ", "
543                 + "srcIp=" + mSrcIp + ", "
544                 + "dstIp=" + mDstIp + ", "
545                 + "srcPort=" + mSrcPort + ", "
546                 + "protocol=" + mProtocol + ", "
547                 + "dstPort=" + mDstPort + ", "
548                 + "dstPortRange=" + Arrays.toString(mDstPortRange) + ", "
549                 + "direction=" + mDirection + ", "
550                 + "ipVersion=" + mIpVersion + ", "
551                 + "flowLabel=" + Arrays.toString(mFlowLabel) + "}";
552     }
553 
554     /** @hide */
555     @Override
describeContents()556     public int describeContents() {
557         return 0;
558     }
559 
getInetAddrOrNull(byte[] byteAddr)560     private InetAddress getInetAddrOrNull(byte[] byteAddr) {
561         if (byteAddr == null) return null;
562         try {
563             return InetAddress.getByAddress(byteAddr);
564         } catch (Exception e) {
565             return null;
566         }
567     }
568 
569     /** @hide */
570     @Override
writeToParcel(@onNull Parcel dest, int flags)571     public void writeToParcel(@NonNull Parcel dest, int flags) {
572         dest.writeInt(mPolicyId);
573         dest.writeInt(mDscp);
574         dest.writeInt(mUserPriority);
575         dest.writeByteArray(mSrcIp != null ? mSrcIp.getAddress() : null);
576         dest.writeByteArray(mDstIp != null ? mDstIp.getAddress() : null);
577         dest.writeInt(mSrcPort);
578         dest.writeInt(mProtocol);
579         dest.writeInt(mDstPort);
580         dest.writeIntArray(mDstPortRange);
581         dest.writeInt(mDirection);
582         dest.writeInt(mIpVersion);
583         dest.writeByteArray(mFlowLabel);
584     }
585 
586     /** @hide */
QosPolicyParams(@onNull Parcel in)587     QosPolicyParams(@NonNull Parcel in) {
588         this.mPolicyId = in.readInt();
589         this.mDscp = in.readInt();
590         this.mUserPriority = in.readInt();
591         this.mSrcIp = getInetAddrOrNull(in.createByteArray());
592         this.mDstIp = getInetAddrOrNull(in.createByteArray());
593         this.mSrcPort = in.readInt();
594         this.mProtocol = in.readInt();
595         this.mDstPort = in.readInt();
596         this.mDstPortRange = in.createIntArray();
597         this.mDirection = in.readInt();
598         this.mIpVersion = in.readInt();
599         this.mFlowLabel = in.createByteArray();
600     }
601 
602     public static final @NonNull Parcelable.Creator<QosPolicyParams> CREATOR =
603             new Parcelable.Creator<QosPolicyParams>() {
604                 @Override
605                 public QosPolicyParams createFromParcel(Parcel in) {
606                     return new QosPolicyParams(in);
607                 }
608 
609                 @Override
610                 public QosPolicyParams[] newArray(int size) {
611                     return new QosPolicyParams[size];
612                 }
613             };
614 
615     /**
616      * Builder for {@link QosPolicyParams}.
617      */
618     public static final class Builder {
619         private final int mPolicyId;
620         private final @Direction int mDirection;
621         private @Nullable InetAddress mSrcIp;
622         private @Nullable InetAddress mDstIp;
623         private int mDscp = DSCP_ANY;
624         private @UserPriority int mUserPriority = USER_PRIORITY_ANY;
625         private int mSrcPort = DscpPolicy.SOURCE_PORT_ANY;
626         private int mProtocol = PROTOCOL_ANY;
627         private int mDstPort = DESTINATION_PORT_ANY;
628         private @Nullable int[] mDstPortRange;
629         private @IpVersion int mIpVersion = IP_VERSION_ANY;
630         private byte[] mFlowLabel;
631 
632         /**
633          * Constructor for {@link Builder}.
634          *
635          * @param policyId Unique ID to identify this policy. Each requesting application is
636          *                 responsible for maintaining policy IDs unique for that app. IDs must be
637          *                 in the range 1 <= policyId <= 255.
638          *
639          *                 In the case where a policy with an existing ID is created, the new policy
640          *                 will be rejected. To update an existing policy, remove the existing one
641          *                 before sending the new one.
642          * @param direction Whether this policy applies to the uplink or downlink direction.
643          */
Builder(@ntRangefrom = 1, to = 255) int policyId, @Direction int direction)644         public Builder(@IntRange(from = 1, to = 255) int policyId, @Direction int direction) {
645             mPolicyId = policyId;
646             mDirection = direction;
647         }
648 
649         /**
650          * Specifies that this policy matches packets with the provided source IP address.
651          */
setSourceAddress(@ullable InetAddress value)652         public @NonNull Builder setSourceAddress(@Nullable InetAddress value) {
653             mSrcIp = value;
654             return this;
655         }
656 
657         /**
658          * Specifies that this policy matches packets with the provided destination IP address.
659          */
setDestinationAddress(@ullable InetAddress value)660         public @NonNull Builder setDestinationAddress(@Nullable InetAddress value) {
661             mDstIp = value;
662             return this;
663         }
664 
665         /**
666          * Specifies the DSCP value. For uplink requests, this value will be applied to packets
667          * that match the classifier. For downlink requests, this will be part of the classifier.
668          */
setDscp(@ntRangefrom = DSCP_ANY, to = 63) int value)669         public @NonNull Builder setDscp(@IntRange(from = DSCP_ANY, to = 63) int value) {
670             mDscp = value;
671             return this;
672         }
673 
674         /**
675          * Specifies that the provided User Priority should be applied to packets that
676          * match this classifier. Only applicable to downlink requests.
677          */
setUserPriority(@serPriority int value)678         public @NonNull Builder setUserPriority(@UserPriority int value) {
679             mUserPriority = value;
680             return this;
681         }
682 
683         /**
684          * Specifies that this policy matches packets with the provided source port.
685          */
setSourcePort( @ntRangefrom = DscpPolicy.SOURCE_PORT_ANY, to = 65535) int value)686         public @NonNull Builder setSourcePort(
687                 @IntRange(from = DscpPolicy.SOURCE_PORT_ANY, to = 65535) int value) {
688             mSrcPort = value;
689             return this;
690         }
691 
692         /**
693          * Specifies that this policy matches packets with the provided protocol.
694          */
setProtocol(@rotocol int value)695         public @NonNull Builder setProtocol(@Protocol int value) {
696             mProtocol = value;
697             return this;
698         }
699 
700         /**
701          * Specifies that this policy matches packets with the provided destination port.
702          * Only applicable to downlink requests.
703          */
setDestinationPort( @ntRangefrom = DESTINATION_PORT_ANY, to = 65535) int value)704         public @NonNull Builder setDestinationPort(
705                 @IntRange(from = DESTINATION_PORT_ANY, to = 65535) int value) {
706             mDstPort = value;
707             return this;
708         }
709 
710         /**
711          * Specifies that this policy matches packets with the provided destination port range.
712          * Only applicable to uplink requests.
713          */
setDestinationPortRange( @ntRangefrom = 0, to = 65535) int start, @IntRange(from = 0, to = 65535) int end)714         public @NonNull Builder setDestinationPortRange(
715                 @IntRange(from = 0, to = 65535) int start,
716                 @IntRange(from = 0, to = 65535) int end) {
717             mDstPortRange = new int[]{start, end};
718             return this;
719         }
720 
721         /**
722          * Specifies that this policy matches packets with the provided IP version.
723          * This argument is mandatory for downlink requests, and is ignored for uplink requests.
724          */
setIpVersion(@pVersion int value)725         public @NonNull Builder setIpVersion(@IpVersion int value) {
726             mIpVersion = value;
727             return this;
728         }
729 
730         /**
731          * Specifies that this policy matches packets with the provided flow label.
732          * Only applicable to downlink requests using IPv6.
733          */
setFlowLabel(@ullable byte[] value)734         public @NonNull Builder setFlowLabel(@Nullable byte[] value) {
735             mFlowLabel = value;
736             return this;
737         }
738 
739         /**
740          * Construct a QosPolicyParams object with the specified parameters.
741          */
build()742         public @NonNull QosPolicyParams build() {
743             QosPolicyParams params = new QosPolicyParams(mPolicyId, mDscp, mUserPriority, mSrcIp,
744                     mDstIp, mSrcPort, mProtocol, mDstPortRange, mDirection, mIpVersion, mDstPort,
745                     mFlowLabel);
746             if (!params.validate()) {
747                 throw new IllegalArgumentException("Provided parameters are invalid");
748             }
749             return params;
750         }
751     }
752 }
753