• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.os.Parcel;
26 import android.os.Parcelable;
27 import android.util.Log;
28 
29 import com.android.wifi.flags.Flags;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.util.Objects;
34 
35 /**
36  * Additional QoS parameters as defined in Section 9.4.2.316
37  * of the IEEE P802.11be/D4.0 Standard.
38  * @hide
39  */
40 @SystemApi
41 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
42 public final class QosCharacteristics implements Parcelable {
43     private static final String TAG = "QosCharacteristics";
44 
45     /**
46      * Maximum size of an MSDU.
47      * @hide
48      */
49     public static final int MAX_MSDU_SIZE = 1 << 0;
50 
51     /**
52      * Anticipated time and link ID indicating when traffic starts for the associated TID.
53      * @hide
54      */
55     public static final int SERVICE_START_TIME = 1 << 1;
56 
57 
58     /**
59      * Data rate specified for transport of MSDUs or A-MSDUs belonging to the traffic flow.
60      * @hide
61      */
62     public static final int MEAN_DATA_RATE = 1 << 2;
63 
64     /**
65      * Maximum burst of the MSDUs or A-MSDUs belonging to the traffic flow.
66      * @hide
67      */
68     public static final int BURST_SIZE = 1 << 3;
69 
70     /**
71      * Maximum amount of time beyond which the MSDU is not useful.
72      * @hide
73      */
74     public static final int MSDU_LIFETIME = 1 << 4;
75 
76     /**
77      * MSDU delivery information.
78      * @hide
79      */
80     public static final int MSDU_DELIVERY_INFO = 1 << 5;
81 
82     /** @hide */
83     @Retention(RetentionPolicy.SOURCE)
84     @IntDef(flag = true, value = {
85             MAX_MSDU_SIZE,
86             SERVICE_START_TIME,
87             MEAN_DATA_RATE,
88             BURST_SIZE,
89             MSDU_LIFETIME,
90             MSDU_DELIVERY_INFO,
91     })
92     public @interface QosCharacteristicsOptionalField {}
93 
94     /**
95      * Indicates that 95% of MSDUs are expected to be delivered.
96      */
97     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
98     public static final int DELIVERY_RATIO_95 = 0;
99 
100     /**
101      * Indicates that 96% of MSDUs are expected to be delivered.
102      */
103     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
104     public static final int DELIVERY_RATIO_96 = 1;
105 
106     /**
107      * Indicates that 97% of MSDUs are expected to be delivered.
108      */
109     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
110     public static final int DELIVERY_RATIO_97 = 2;
111 
112     /**
113      * Indicates that 98% of MSDUs are expected to be delivered.
114      */
115     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
116     public static final int DELIVERY_RATIO_98 = 3;
117 
118     /**
119      * Indicates that 99% of MSDUs are expected to be delivered.
120      */
121     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
122     public static final int DELIVERY_RATIO_99 = 5;
123 
124     /**
125      * Indicates that 99.9% of MSDUs are expected to be delivered.
126      */
127     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
128     public static final int DELIVERY_RATIO_99_9 = 6;
129 
130     /**
131      * Indicates that 99.99% of MSDUs are expected to be delivered.
132      */
133     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
134     public static final int DELIVERY_RATIO_99_99 = 7;
135 
136     /**
137      * Indicates that 99.999% of MSDUs are expected to be delivered.
138      */
139     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
140     public static final int DELIVERY_RATIO_99_999 = 8;
141 
142     /**
143      * Indicates that 99.9999% of MSDUs are expected to be delivered.
144      */
145     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
146     public static final int DELIVERY_RATIO_99_9999 = 9;
147 
148     /** @hide */
149     @Retention(RetentionPolicy.SOURCE)
150     @IntDef(value = {
151             DELIVERY_RATIO_95,
152             DELIVERY_RATIO_96,
153             DELIVERY_RATIO_97,
154             DELIVERY_RATIO_98,
155             DELIVERY_RATIO_99,
156             DELIVERY_RATIO_99_9,
157             DELIVERY_RATIO_99_99,
158             DELIVERY_RATIO_99_999,
159             DELIVERY_RATIO_99_9999,
160     })
161     public @interface DeliveryRatio {}
162 
163     private final int mMinServiceIntervalMicros;
164     private final int mMaxServiceIntervalMicros;
165     private final int mMinDataRateKbps;
166     private final int mDelayBoundMicros;
167     private final int mOptionalFieldBitmap;
168     private final int mMaxMsduSizeOctets;
169     private final int mServiceStartTimeMicros;
170     private final int mServiceStartTimeLinkId;
171     private final int mMeanDataRateKbps;
172     private final int mBurstSizeOctets;
173     private final int mMsduLifetimeMillis;
174     private final @DeliveryRatio int mDeliveryRatio;
175     private final int mCountExponent;
176 
QosCharacteristics(int minServiceIntervalMicros, int maxServiceIntervalMicros, int minDataRateKbps, int delayBoundMicros, int optionalFieldBitmap, int maxMsduSizeOctets, int serviceStartTimeMicros, int serviceStartTimeLinkId, int meanDataRateKbps, int burstSizeOctets, int msduLifetimeMillis, @DeliveryRatio int deliveryRatio, int countExponent)177     private QosCharacteristics(int minServiceIntervalMicros, int maxServiceIntervalMicros,
178             int minDataRateKbps, int delayBoundMicros, int optionalFieldBitmap,
179             int maxMsduSizeOctets, int serviceStartTimeMicros, int serviceStartTimeLinkId,
180             int meanDataRateKbps, int burstSizeOctets, int msduLifetimeMillis,
181             @DeliveryRatio int deliveryRatio, int countExponent) {
182         mMinServiceIntervalMicros = minServiceIntervalMicros;
183         mMaxServiceIntervalMicros = maxServiceIntervalMicros;
184         mMinDataRateKbps = minDataRateKbps;
185         mDelayBoundMicros = delayBoundMicros;
186         mOptionalFieldBitmap = optionalFieldBitmap;
187         mMaxMsduSizeOctets = maxMsduSizeOctets;
188         mServiceStartTimeMicros = serviceStartTimeMicros;
189         mServiceStartTimeLinkId = serviceStartTimeLinkId;
190         mMeanDataRateKbps = meanDataRateKbps;
191         mBurstSizeOctets = burstSizeOctets;
192         mMsduLifetimeMillis = msduLifetimeMillis;
193         mDeliveryRatio = deliveryRatio;
194         mCountExponent = countExponent;
195     }
196 
197     /**
198      * Check whether this instance contains the indicated optional field.
199      * @hide
200      */
containsOptionalField(@osCharacteristicsOptionalField int field)201     public boolean containsOptionalField(@QosCharacteristicsOptionalField int field) {
202         return (mOptionalFieldBitmap & field) != 0;
203     }
204 
205     /**
206      * Check that the value can be cast to an unsigned integer of size |expectedSizeInBits|.
207      */
checkSizeInBits(int value, int expectedSizeInBits)208     private static boolean checkSizeInBits(int value, int expectedSizeInBits) {
209         int bitmask = (0x1 << expectedSizeInBits) - 1;
210         return (bitmask & value) == value;
211     }
212 
213     /**
214      * Check that the value falls within the provided inclusive range.
215      */
checkIntRange(int value, int min, int max)216     private static boolean checkIntRange(int value, int min, int max) {
217         return (value >= min) && (value <= max);
218     }
219 
220     /**
221      * Validate the parameters in this instance.
222      * @hide
223      */
validate()224     public boolean validate() {
225         if (mMinServiceIntervalMicros <= 0 || mMaxServiceIntervalMicros <= 0
226                 || mMinDataRateKbps <= 0 || mDelayBoundMicros <= 0) {
227             Log.e(TAG, "All mandatory fields must be positive integers");
228             return false;
229         }
230         if (mMinServiceIntervalMicros > mMaxServiceIntervalMicros) {
231             Log.e(TAG, "Minimum service interval must be less than or equal to"
232                     + " the maximum service interval");
233             return false;
234         }
235         if (containsOptionalField(MAX_MSDU_SIZE)
236                 && !checkIntRange(mMaxMsduSizeOctets, 1, Short.MAX_VALUE)) {
237             Log.e(TAG, "Invalid value provided for maxMsduSize");
238             return false;
239         }
240         if (containsOptionalField(SERVICE_START_TIME)
241                 && (mServiceStartTimeMicros < 0
242                 || !checkSizeInBits(mServiceStartTimeLinkId, 4))) {
243             Log.e(TAG, "serviceStartTime information is invalid");
244             return false;
245         }
246         if (containsOptionalField(MEAN_DATA_RATE) && mMeanDataRateKbps <= 0) {
247             Log.e(TAG, "meanDataRateKbps must be a positive integer");
248             return false;
249         }
250         if (containsOptionalField(BURST_SIZE) && mBurstSizeOctets == 0) {
251             Log.e(TAG, "burstSizeOctets must be non-zero");
252             return false;
253         }
254         if (containsOptionalField(MSDU_LIFETIME)
255                 && !checkIntRange(mMsduLifetimeMillis, 1, Short.MAX_VALUE)) {
256             Log.e(TAG, "Invalid value provided for msduLifetimeMillis");
257             return false;
258         }
259         if (containsOptionalField(MSDU_LIFETIME)
260                 && (mMsduLifetimeMillis * 1000) < mDelayBoundMicros) {
261             Log.e(TAG, "MSDU lifetime must be greater than or equal to the delay bound");
262             return false;
263         }
264         if (containsOptionalField(MSDU_DELIVERY_INFO)
265                 && !checkIntRange(mDeliveryRatio, DELIVERY_RATIO_95, DELIVERY_RATIO_99_9999)) {
266             Log.e(TAG, "MSDU delivery ratio must be a valid enum value");
267             return false;
268         }
269         if (containsOptionalField(MSDU_DELIVERY_INFO)
270                 && !checkIntRange(mCountExponent, 0, 15)) {
271             Log.e(TAG, "MSDU count exponent must be between 0 and 15 (inclusive)");
272             return false;
273         }
274         return true;
275     }
276 
277     /**
278      * Get the minimum service interval in microseconds.
279      *
280      * See {@link Builder#Builder(int, int, int, int)} for more information.
281      */
282     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
283     @IntRange(from = 1, to = Integer.MAX_VALUE)
getMinServiceIntervalMicros()284     public int getMinServiceIntervalMicros() {
285         return mMinServiceIntervalMicros;
286     }
287 
288     /**
289      * Get the maximum service interval in microseconds.
290      *
291      * See {@link Builder#Builder(int, int, int, int)} for more information.
292      */
293     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
294     @IntRange(from = 1, to = Integer.MAX_VALUE)
getMaxServiceIntervalMicros()295     public int getMaxServiceIntervalMicros() {
296         return mMaxServiceIntervalMicros;
297     }
298 
299     /**
300      * Get the minimum data rate in kilobits per second.
301      *
302      * See {@link Builder#Builder(int, int, int, int)} for more information.
303      */
304     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
305     @IntRange(from = 1, to = Integer.MAX_VALUE)
getMinDataRateKbps()306     public int getMinDataRateKbps() {
307         return mMinDataRateKbps;
308     }
309 
310     /**
311      * Get the delay bound in microseconds.
312      *
313      * See {@link Builder#Builder(int, int, int, int)} for more information.
314      */
315     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
316     @IntRange(from = 1, to = Integer.MAX_VALUE)
getDelayBoundMicros()317     public int getDelayBoundMicros() {
318         return mDelayBoundMicros;
319     }
320 
321     /**
322      * Get the maximum MSDU size in octets. See {@link Builder#setMaxMsduSizeOctets(int)}
323      * for more information.
324      *
325      * @throws IllegalStateException if this field was not set in the Builder.
326      */
327     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
328     @IntRange(from = 1, to = Short.MAX_VALUE)
getMaxMsduSizeOctets()329     public int getMaxMsduSizeOctets() {
330         if (!containsOptionalField(MAX_MSDU_SIZE)) {
331             throw new IllegalStateException("maxMsduSize was not provided in the builder");
332         }
333         return mMaxMsduSizeOctets;
334     }
335 
336     /**
337      * Get the service start time in microseconds.
338      * See {@link Builder#setServiceStartTimeInfo(int, int)} for more information.
339      *
340      * @throws IllegalStateException if this field was not set in the Builder.
341      */
342     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
343     @IntRange(from = 0, to = Integer.MAX_VALUE)
getServiceStartTimeMicros()344     public int getServiceStartTimeMicros() {
345         if (!containsOptionalField(SERVICE_START_TIME)) {
346             throw new IllegalStateException("serviceStartTime was not provided in the builder");
347         }
348         return mServiceStartTimeMicros;
349     }
350 
351     /**
352      * Get the service start time link ID. See {@link Builder#setServiceStartTimeInfo(int, int)}
353      * for more information.
354      *
355      * @throws IllegalStateException if this field was not set in the Builder.
356      */
357     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getServiceStartTimeLinkId()358     public int getServiceStartTimeLinkId() {
359         if (!containsOptionalField(SERVICE_START_TIME)) {
360             throw new IllegalStateException("serviceStartTime was not provided in the builder");
361         }
362         return mServiceStartTimeLinkId;
363     }
364 
365     /**
366      * Get the mean data rate in kilobits per second. See {@link Builder#setMeanDataRateKbps(int)}
367      * for more information.
368      *
369      * @throws IllegalStateException if this field was not set in the Builder.
370      */
371     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
372     @IntRange(from = 1, to = Integer.MAX_VALUE)
getMeanDataRateKbps()373     public int getMeanDataRateKbps() {
374         if (!containsOptionalField(MEAN_DATA_RATE)) {
375             throw new IllegalStateException("meanDataRate was not provided in the builder");
376         }
377         return mMeanDataRateKbps;
378     }
379 
380     /**
381      * Get the burst size in octets. See {@link Builder#setBurstSizeOctets(int)} for
382      * more information.
383      *
384      * @throws IllegalStateException if this field was not set in the Builder.
385      */
386     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
387     @IntRange(from = 1, to = Integer.MAX_VALUE)
getBurstSizeOctets()388     public int getBurstSizeOctets() {
389         if (!containsOptionalField(BURST_SIZE)) {
390             throw new IllegalStateException("burstSize was not provided in the builder");
391         }
392         return mBurstSizeOctets;
393     }
394 
395     /**
396      * Get the MSDU lifetime in milliseconds. See {@link Builder#setMsduLifetimeMillis(int)}
397      * for more information.
398      *
399      * @throws IllegalStateException if this field was not set in the Builder.
400      */
401     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
402     @IntRange(from = 1, to = Short.MAX_VALUE)
getMsduLifetimeMillis()403     public int getMsduLifetimeMillis() {
404         if (!containsOptionalField(MSDU_LIFETIME)) {
405             throw new IllegalStateException("msduLifetime was not provided in the builder");
406         }
407         return mMsduLifetimeMillis;
408     }
409 
410     /**
411      * Get the delivery ratio enum. See {@link Builder#setMsduDeliveryInfo(int, int)} for
412      * more information.
413      *
414      * @throws IllegalStateException if this field was not set in the Builder.
415      */
416     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getDeliveryRatio()417     public @DeliveryRatio int getDeliveryRatio() {
418         if (!containsOptionalField(MSDU_DELIVERY_INFO)) {
419             throw new IllegalStateException("msduDeliveryInfo was not provided in the builder");
420         }
421         return mDeliveryRatio;
422     }
423 
424     /**
425      * Get the count exponent. See {@link Builder#setMsduDeliveryInfo(int, int)} for
426      * more information.
427      *
428      * @throws IllegalStateException if this field was not set in the Builder.
429      */
430     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
431     @IntRange(from = 0, to = 15)
getCountExponent()432     public int getCountExponent() {
433         if (!containsOptionalField(MSDU_DELIVERY_INFO)) {
434             throw new IllegalStateException("msduDeliveryInfo was not provided in the builder");
435         }
436         return mCountExponent;
437     }
438 
439     @Override
440     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
equals(@ullable Object o)441     public boolean equals(@Nullable Object o) {
442         if (this == o) return true;
443         if (o == null || getClass() != o.getClass()) return false;
444         QosCharacteristics that = (QosCharacteristics) o;
445         return mMinServiceIntervalMicros == that.mMinServiceIntervalMicros
446                 && mMaxServiceIntervalMicros == that.mMaxServiceIntervalMicros
447                 && mMinDataRateKbps == that.mMinDataRateKbps
448                 && mDelayBoundMicros == that.mDelayBoundMicros
449                 && mOptionalFieldBitmap == that.mOptionalFieldBitmap
450                 && mMaxMsduSizeOctets == that.mMaxMsduSizeOctets
451                 && mServiceStartTimeMicros == that.mServiceStartTimeMicros
452                 && mServiceStartTimeLinkId == that.mServiceStartTimeLinkId
453                 && mMeanDataRateKbps == that.mMeanDataRateKbps
454                 && mBurstSizeOctets == that.mBurstSizeOctets
455                 && mMsduLifetimeMillis == that.mMsduLifetimeMillis
456                 && mDeliveryRatio == that.mDeliveryRatio
457                 && mCountExponent == that.mCountExponent;
458     }
459 
460     @Override
461     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
hashCode()462     public int hashCode() {
463         return Objects.hash(mMinServiceIntervalMicros, mMaxServiceIntervalMicros, mMinDataRateKbps,
464                 mDelayBoundMicros, mOptionalFieldBitmap, mMaxMsduSizeOctets,
465                 mServiceStartTimeMicros, mServiceStartTimeLinkId, mMeanDataRateKbps,
466                 mBurstSizeOctets, mMsduLifetimeMillis, mDeliveryRatio, mCountExponent);
467     }
468 
469     @Override
470     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
toString()471     public String toString() {
472         StringBuilder sb = new StringBuilder("{");
473         sb.append("mMinServiceIntervalMicros=").append(mMinServiceIntervalMicros);
474         sb.append(", mMaxServiceIntervalMicros=").append(mMaxServiceIntervalMicros);
475         sb.append(", mMinDataRateKbps=").append(mMinDataRateKbps);
476         sb.append(", mDelayBoundMicros=").append(mDelayBoundMicros);
477         sb.append(", mOptionalFieldBitmap=").append(String.format("%02x", mOptionalFieldBitmap));
478         if (containsOptionalField(MAX_MSDU_SIZE)) {
479             sb.append(", mMaxMsduSizeOctets=").append(mMaxMsduSizeOctets);
480         }
481         if (containsOptionalField(SERVICE_START_TIME)) {
482             sb.append(", mServiceStartTimeMicros=").append(mServiceStartTimeMicros);
483             sb.append(", mServiceStartTimeLinkId=");
484             sb.append(String.format("%01x", mServiceStartTimeLinkId));
485         }
486         if (containsOptionalField(MEAN_DATA_RATE)) {
487             sb.append(", mMeanDataRateKbps=").append(mMeanDataRateKbps);
488         }
489         if (containsOptionalField(BURST_SIZE)) {
490             sb.append(", mBurstSizeOctets=").append(mBurstSizeOctets);
491         }
492         if (containsOptionalField(MSDU_LIFETIME)) {
493             sb.append(", mMsduLifetimeMillis=").append(mMsduLifetimeMillis);
494         }
495         if (containsOptionalField(MSDU_DELIVERY_INFO)) {
496             sb.append(", mDeliveryRatio=").append(mDeliveryRatio);
497             sb.append(", mCountExponent=").append(mCountExponent);
498         }
499         return sb.append("}").toString();
500     }
501 
502     @Override
503     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
describeContents()504     public int describeContents() {
505         return 0;
506     }
507 
508     /** @hide */
509     @Override
510     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
writeToParcel(@onNull Parcel dest, int flags)511     public void writeToParcel(@NonNull Parcel dest, int flags) {
512         dest.writeInt(mMinServiceIntervalMicros);
513         dest.writeInt(mMaxServiceIntervalMicros);
514         dest.writeInt(mMinDataRateKbps);
515         dest.writeInt(mDelayBoundMicros);
516         dest.writeInt(mOptionalFieldBitmap);
517         dest.writeInt(mMaxMsduSizeOctets);
518         dest.writeInt(mServiceStartTimeMicros);
519         dest.writeInt(mServiceStartTimeLinkId);
520         dest.writeInt(mMeanDataRateKbps);
521         dest.writeInt(mBurstSizeOctets);
522         dest.writeInt(mMsduLifetimeMillis);
523         dest.writeInt(mDeliveryRatio);
524         dest.writeInt(mCountExponent);
525     }
526 
527     /** @hide */
QosCharacteristics(@onNull Parcel in)528     QosCharacteristics(@NonNull Parcel in) {
529         this.mMinServiceIntervalMicros = in.readInt();
530         this.mMaxServiceIntervalMicros = in.readInt();
531         this.mMinDataRateKbps = in.readInt();
532         this.mDelayBoundMicros = in.readInt();
533         this.mOptionalFieldBitmap = in.readInt();
534         this.mMaxMsduSizeOctets = in.readInt();
535         this.mServiceStartTimeMicros = in.readInt();
536         this.mServiceStartTimeLinkId = in.readInt();
537         this.mMeanDataRateKbps = in.readInt();
538         this.mBurstSizeOctets = in.readInt();
539         this.mMsduLifetimeMillis = in.readInt();
540         this.mDeliveryRatio = in.readInt();
541         this.mCountExponent = in.readInt();
542     }
543 
544     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
545     public static final @NonNull Parcelable.Creator<QosCharacteristics> CREATOR =
546             new Parcelable.Creator<QosCharacteristics>() {
547                 @Override
548                 public QosCharacteristics createFromParcel(Parcel in) {
549                     return new QosCharacteristics(in);
550                 }
551 
552                 @Override
553                 public QosCharacteristics[] newArray(int size) {
554                     return new QosCharacteristics[size];
555                 }
556             };
557 
558     /**
559      * Builder for {@link QosCharacteristics}.
560      */
561     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
562     public static final class Builder {
563         // Mandatory fields
564         private final int mMinServiceIntervalMicros;
565         private final int mMaxServiceIntervalMicros;
566         private final int mMinDataRateKbps;
567         private final int mDelayBoundMicros;
568 
569         // Optional fields
570         private int mOptionalFieldBitmap;
571         private int mMaxMsduSizeOctets;
572         private int mServiceStartTimeMicros;
573         private int mServiceStartTimeLinkId;
574         private int mMeanDataRateKbps;
575         private int mBurstSizeOctets;
576         private int mMsduLifetimeMillis;
577         private @DeliveryRatio int mDeliveryRatio;
578         private int mCountExponent;
579 
580         /**
581          * Constructor for {@link Builder}.
582          *
583          * @param minServiceIntervalMicros Positive integer specifying the minimum interval (in
584          *                             microseconds) between the start of two consecutive service
585          *                             periods (SPs) that are allocated for frame exchanges.
586          * @param maxServiceIntervalMicros Positive integer specifying the maximum interval (in
587          *                             microseconds) between the start of two consecutive SPs that
588          *                             are allocated for frame exchanges.
589          * @param minDataRateKbps Positive integer specifying the lowest data rate (in kilobits/sec)
590          *                        for the transport of MSDUs or A-MSDUs belonging to the traffic
591          *                        flow.
592          * @param delayBoundMicros Positive integer specifying the maximum amount of time (in
593          *                     microseconds) targeted to transport an MSDU or A-MSDU belonging to
594          *                     the traffic flow.
595          */
596         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
Builder(@ntRangefrom = 1, to = Integer.MAX_VALUE) int minServiceIntervalMicros, @IntRange(from = 1, to = Integer.MAX_VALUE) int maxServiceIntervalMicros, @IntRange(from = 1, to = Integer.MAX_VALUE) int minDataRateKbps, @IntRange(from = 1, to = Integer.MAX_VALUE) int delayBoundMicros)597         public Builder(@IntRange(from = 1, to = Integer.MAX_VALUE) int minServiceIntervalMicros,
598                 @IntRange(from = 1, to = Integer.MAX_VALUE) int maxServiceIntervalMicros,
599                 @IntRange(from = 1, to = Integer.MAX_VALUE) int minDataRateKbps,
600                 @IntRange(from = 1, to = Integer.MAX_VALUE) int delayBoundMicros) {
601             mMinServiceIntervalMicros = minServiceIntervalMicros;
602             mMaxServiceIntervalMicros = maxServiceIntervalMicros;
603             mMinDataRateKbps = minDataRateKbps;
604             mDelayBoundMicros = delayBoundMicros;
605         }
606 
607         /**
608          * Set the maximum MSDU size in octets.
609          *
610          * @param maxMsduSizeOctets Positive integer specifying the maximum size (in octets)
611          *                          of an MSDU belonging to the traffic flow.
612          */
613         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
setMaxMsduSizeOctets( @ntRangefrom = 1, to = Short.MAX_VALUE) int maxMsduSizeOctets)614         public @NonNull Builder setMaxMsduSizeOctets(
615                 @IntRange(from = 1, to = Short.MAX_VALUE) int maxMsduSizeOctets) {
616             mOptionalFieldBitmap |= MAX_MSDU_SIZE;
617             mMaxMsduSizeOctets = maxMsduSizeOctets;
618             return this;
619         }
620 
621         /**
622          * Set the service start time information.
623          *
624          * @param serviceStartTimeMicros Integer specifying the anticipated time (in microseconds)
625          *                               when the traffic starts for the associated TID.
626          * @param serviceStartTimeLinkId Bitmap in which the four LSBs indicate the link identifier
627          *                               that corresponds to the link for which the TSF timer is
628          *                               used to indicate the Service Start Time. No other bits
629          *                               should be used.
630          */
631         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
setServiceStartTimeInfo( @ntRangefrom = 0, to = Integer.MAX_VALUE) int serviceStartTimeMicros, int serviceStartTimeLinkId)632         public @NonNull Builder setServiceStartTimeInfo(
633                 @IntRange(from = 0, to = Integer.MAX_VALUE) int serviceStartTimeMicros,
634                 int serviceStartTimeLinkId) {
635             mOptionalFieldBitmap |= SERVICE_START_TIME;
636             mServiceStartTimeMicros = serviceStartTimeMicros;
637             mServiceStartTimeLinkId = serviceStartTimeLinkId;
638             return this;
639         }
640 
641         /**
642          * Set the mean data rate in kilobits per second.
643          *
644          * @param meanDataRateKbps Positive integer indicating the data rate specified (in
645          *                         kilobits/sec) for transport of MSDUs or A-MSDUs belonging to the
646          *                         traffic flow.
647          */
648         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
setMeanDataRateKbps( @ntRangefrom = 1, to = Integer.MAX_VALUE) int meanDataRateKbps)649         public @NonNull Builder setMeanDataRateKbps(
650                 @IntRange(from = 1, to = Integer.MAX_VALUE) int meanDataRateKbps) {
651             mOptionalFieldBitmap |= MEAN_DATA_RATE;
652             mMeanDataRateKbps = meanDataRateKbps;
653             return this;
654         }
655 
656         /**
657          * Set the burst size in octets.
658          *
659          * @param burstSizeOctets Positive integer specifying the maximum burst (in octets) of
660          *                        the MSDUs or A-MSDUs belonging to the traffic flow that arrive at
661          *                        the MAC SAP within any time duration equal to the value specified
662          *                        in the |delayBound| field.
663          */
664         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
setBurstSizeOctets( @ntRangefrom = 1, to = Integer.MAX_VALUE) int burstSizeOctets)665         public @NonNull Builder setBurstSizeOctets(
666                 @IntRange(from = 1, to = Integer.MAX_VALUE) int burstSizeOctets) {
667             mOptionalFieldBitmap |= BURST_SIZE;
668             mBurstSizeOctets = burstSizeOctets;
669             return this;
670         }
671 
672         /**
673          * Set the MSDU lifetime in milliseconds.
674          *
675          * @param msduLifetimeMillis Positive integer specifying the maximum amount of time (in
676          *                       milliseconds) since the arrival of the MSDU at the MAC data service
677          *                       interface beyond which the MSDU is not useful even if received by
678          *                       the receiver. The amount of time specified in this field is larger
679          *                       than or equal to the amount of time specified in the |delayBound|
680          *                       field, if present.
681          */
682         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
setMsduLifetimeMillis( @ntRangefrom = 1, to = Short.MAX_VALUE) int msduLifetimeMillis)683         public @NonNull Builder setMsduLifetimeMillis(
684                 @IntRange(from = 1, to = Short.MAX_VALUE) int msduLifetimeMillis) {
685             mOptionalFieldBitmap |= MSDU_LIFETIME;
686             mMsduLifetimeMillis = msduLifetimeMillis;
687             return this;
688         }
689 
690         /**
691          * Set the MSDU delivery information.
692          *
693          * @param deliveryRatio Enum indicating the percentage of the MSDUs that are expected to be
694          *                      delivered successfully.
695          * @param countExponent Exponent from which the number of incoming MSDUs is computed. The
696          *                      number of incoming MSDUs is 10^|countExponent|, and is used to
697          *                      determine the MSDU delivery ratio. Must be a number between
698          *                      0 and 15 (inclusive).
699          */
700         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
setMsduDeliveryInfo( @eliveryRatio int deliveryRatio, @IntRange(from = 0, to = 15) int countExponent)701         public @NonNull Builder setMsduDeliveryInfo(
702                 @DeliveryRatio int deliveryRatio, @IntRange(from = 0, to = 15) int countExponent) {
703             mOptionalFieldBitmap |= MSDU_DELIVERY_INFO;
704             mDeliveryRatio = deliveryRatio;
705             mCountExponent = countExponent;
706             return this;
707         }
708 
709         /**
710          * Construct a QosCharacteristics object with the specified parameters.
711          */
712         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
build()713         public @NonNull QosCharacteristics build() {
714             QosCharacteristics qosCharacteristics = new QosCharacteristics(
715                     mMinServiceIntervalMicros, mMaxServiceIntervalMicros,
716                     mMinDataRateKbps, mDelayBoundMicros, mOptionalFieldBitmap,
717                     mMaxMsduSizeOctets, mServiceStartTimeMicros, mServiceStartTimeLinkId,
718                     mMeanDataRateKbps, mBurstSizeOctets, mMsduLifetimeMillis,
719                     mDeliveryRatio, mCountExponent);
720             if (!qosCharacteristics.validate()) {
721                 throw new IllegalArgumentException("Provided parameters are invalid");
722             }
723             return qosCharacteristics;
724         }
725     }
726 }
727