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