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