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.os.Parcel;
26 import android.os.Parcelable;
27 
28 import com.android.wifi.flags.Flags;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 import java.util.Objects;
33 
34 /**
35  * Mirrored Stream Classification Service (MSCS) parameters.
36  * Refer to section 3.1 of the Wi-Fi QoS Management Specification v3.0.
37  * @hide
38  */
39 @SystemApi
40 @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
41 public final class MscsParams implements Parcelable {
42     /** IP version used by the traffic stream */
43     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
44     public static final int FRAME_CLASSIFIER_IP_VERSION = 1 << 0;
45 
46     /** Source IP address used by the traffic stream */
47     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
48     public static final int FRAME_CLASSIFIER_SRC_IP_ADDR = 1 << 1;
49 
50     /** Destination IP address used by the traffic stream */
51     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
52     public static final int FRAME_CLASSIFIER_DST_IP_ADDR = 1 << 2;
53 
54     /** Source port used by the traffic stream */
55     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
56     public static final int FRAME_CLASSIFIER_SRC_PORT = 1 << 3;
57 
58     /** Destination port used by the traffic stream */
59     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
60     public static final int FRAME_CLASSIFIER_DST_PORT = 1 << 4;
61 
62     /** DSCP value used by the traffic stream */
63     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
64     public static final int FRAME_CLASSIFIER_DSCP = 1 << 5;
65 
66     /** Indicates Protocol if using IPv4, or Next Header if using IPv6 */
67     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
68     public static final int FRAME_CLASSIFIER_PROTOCOL_NEXT_HDR = 1 << 6;
69 
70     /** Flow label. Only applicable if using IPv6 */
71     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
72     public static final int FRAME_CLASSIFIER_FLOW_LABEL = 1 << 7;
73 
74     /** @hide */
75     @Retention(RetentionPolicy.SOURCE)
76     @IntDef(flag = true, prefix = { "FRAME_CLASSIFIER_" }, value = {
77             FRAME_CLASSIFIER_IP_VERSION,
78             FRAME_CLASSIFIER_SRC_IP_ADDR,
79             FRAME_CLASSIFIER_DST_IP_ADDR,
80             FRAME_CLASSIFIER_SRC_PORT,
81             FRAME_CLASSIFIER_DST_PORT,
82             FRAME_CLASSIFIER_DSCP,
83             FRAME_CLASSIFIER_PROTOCOL_NEXT_HDR,
84             FRAME_CLASSIFIER_FLOW_LABEL,
85     })
86     public @interface FrameClassifierField {}
87 
88     /** @hide */
89     public static final int DEFAULT_FRAME_CLASSIFIER_FIELDS =
90             FRAME_CLASSIFIER_IP_VERSION
91                 | FRAME_CLASSIFIER_SRC_IP_ADDR
92                 | FRAME_CLASSIFIER_DST_IP_ADDR
93                 | FRAME_CLASSIFIER_SRC_PORT
94                 | FRAME_CLASSIFIER_DST_PORT
95                 | FRAME_CLASSIFIER_PROTOCOL_NEXT_HDR;
96     /** @hide */
97     public static final int DEFAULT_USER_PRIORITY_BITMAP = (1 << 6) | (1 << 7);
98     /** @hide */
99     public static final int DEFAULT_USER_PRIORITY_LIMIT = 7;   // keep the original priority
100     /** @hide */
101     public static final int MAX_STREAM_TIMEOUT_US = 60_000_000;    // 60 seconds
102 
103     private final int mFrameClassifierFields;
104     private final int mUserPriorityBitmap;
105     private final int mUserPriorityLimit;
106     private final int mStreamTimeoutUs;
107 
MscsParams(int frameClassifierFields, int userPriorityBitmap, int userPriorityLimit, int streamTimeoutUs)108     private MscsParams(int frameClassifierFields, int userPriorityBitmap,
109             int userPriorityLimit, int streamTimeoutUs) {
110         mFrameClassifierFields = frameClassifierFields;
111         mUserPriorityBitmap = userPriorityBitmap;
112         mUserPriorityLimit = userPriorityLimit;
113         mStreamTimeoutUs = streamTimeoutUs;
114     }
115 
116     /**
117      * Get the frame classifier fields bitmap.
118      * See {@link Builder#setFrameClassifierFields(int)}
119      *
120      * @return Bitmap of {@link FrameClassifierField} represented as an int.
121      */
122     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getFrameClassifierFields()123     public @FrameClassifierField int getFrameClassifierFields() {
124         return mFrameClassifierFields;
125     }
126 
127     /**
128      * Get the user priority bitmap. See {@link Builder#setUserPriorityBitmap(int)}
129      *
130      * @return Bitmap of user priorities represented as an int.
131      */
132     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getUserPriorityBitmap()133     public int getUserPriorityBitmap() {
134         return mUserPriorityBitmap;
135     }
136 
137     /**
138      * Get the user priority limit. See {@link Builder#setUserPriorityLimit(int)}
139      *
140      * @return User priority limit.
141      */
142     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
143     @IntRange(from = 0, to = 7)
getUserPriorityLimit()144     public int getUserPriorityLimit() {
145         return mUserPriorityLimit;
146     }
147 
148     /**
149      * Get the stream timeout in microseconds. See {@link Builder#setStreamTimeoutUs(int)}
150      *
151      * @return Stream timeout in microseconds.
152      */
153     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
154     @IntRange(from = 0, to = MAX_STREAM_TIMEOUT_US)
getStreamTimeoutUs()155     public int getStreamTimeoutUs() {
156         return mStreamTimeoutUs;
157     }
158 
159     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
160     @Override
equals(@ullable Object o)161     public boolean equals(@Nullable Object o) {
162         if (this == o) return true;
163         if (o == null || getClass() != o.getClass()) return false;
164         MscsParams that = (MscsParams) o;
165         return mFrameClassifierFields == that.mFrameClassifierFields
166                 && mUserPriorityBitmap == that.mUserPriorityBitmap
167                 && mUserPriorityLimit == that.mUserPriorityLimit
168                 && mStreamTimeoutUs == that.mStreamTimeoutUs;
169     }
170 
171     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
172     @Override
hashCode()173     public int hashCode() {
174         return Objects.hash(mFrameClassifierFields, mUserPriorityBitmap,
175                 mUserPriorityLimit, mStreamTimeoutUs);
176     }
177 
178     @Override
179     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
describeContents()180     public int describeContents() {
181         return 0;
182     }
183 
184     /** @hide */
185     @Override
186     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
writeToParcel(@onNull Parcel dest, int flags)187     public void writeToParcel(@NonNull Parcel dest, int flags) {
188         dest.writeInt(mFrameClassifierFields);
189         dest.writeInt(mUserPriorityBitmap);
190         dest.writeInt(mUserPriorityLimit);
191         dest.writeInt(mStreamTimeoutUs);
192     }
193 
194     /** @hide */
MscsParams(@onNull Parcel in)195     MscsParams(@NonNull Parcel in) {
196         this.mFrameClassifierFields = in.readInt();
197         this.mUserPriorityBitmap = in.readInt();
198         this.mUserPriorityLimit = in.readInt();
199         this.mStreamTimeoutUs = in.readInt();
200     }
201 
202     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
203     public static final @NonNull Parcelable.Creator<MscsParams> CREATOR =
204             new Parcelable.Creator<MscsParams>() {
205                 @Override
206                 public MscsParams createFromParcel(Parcel in) {
207                     return new MscsParams(in);
208                 }
209 
210                 @Override
211                 public MscsParams[] newArray(int size) {
212                     return new MscsParams[size];
213                 }
214             };
215 
216     /** Builder for {@link MscsParams}. */
217     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
218     public static final class Builder {
219         private int mFrameClassifierFields = DEFAULT_FRAME_CLASSIFIER_FIELDS;
220         private int mUserPriorityBitmap = DEFAULT_USER_PRIORITY_BITMAP;
221         private int mUserPriorityLimit = DEFAULT_USER_PRIORITY_LIMIT;
222         private int mStreamTimeoutUs = MAX_STREAM_TIMEOUT_US;
223 
224         /**
225          * Constructor for {@link Builder}.
226          */
227         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
Builder()228         public Builder() {}
229 
230         /**
231          * Sets a bitmap of {@link FrameClassifierField} indicating which TCLAS Type 4 frame
232          * classifier fields should be used to build a classifier.
233          *
234          * @param frameClassifierFields Bitmap indicating the requested fields.
235          * @throws IllegalArgumentException if any bits other than bits 0-7 are set.
236          */
237         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
238         @NonNull
setFrameClassifierFields(@rameClassifierField int frameClassifierFields)239         public Builder setFrameClassifierFields(@FrameClassifierField int frameClassifierFields) {
240             if ((frameClassifierFields & 0xFFFFFF00) != 0) {
241                 throw new IllegalArgumentException("frameClassifierFields can only use bits 0-7");
242             }
243             mFrameClassifierFields = frameClassifierFields;
244             return this;
245         }
246 
247         /**
248          * Sets a bitmap indicating which User Priorities (UPs) should be classified using MSCS.
249          * The least significant bit corresponds to UP 0, and the most significant
250          * bit to UP 7. Setting a bit to 1 indicates that UP should be classified.
251          *
252          * @param userPriorityBitmap Bitmap indicating which UPs should be classified.
253          * @throws IllegalArgumentException if any bits other than bits 0-7 are set.
254          */
255         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
256         @NonNull
setUserPriorityBitmap(int userPriorityBitmap)257         public Builder setUserPriorityBitmap(int userPriorityBitmap) {
258             if ((userPriorityBitmap & 0xFFFFFF00) != 0) {
259                 throw new IllegalArgumentException("userPriorityBitmap can only use bits 0-7");
260             }
261             mUserPriorityBitmap = userPriorityBitmap;
262             return this;
263         }
264 
265         /**
266          * Sets the maximum user priority that can be assigned using the MSCS service.
267          * Value must be between 0 and 7 (inclusive).
268          *
269          * @param userPriorityLimit Maximum user priority that can be assigned by MSCS.
270          * @throws IllegalArgumentException if the provided value is outside the expected range of
271          *                                  0-7 (inclusive).
272          */
273         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
274         @NonNull
setUserPriorityLimit(@ntRangefrom = 0, to = 7) int userPriorityLimit)275         public Builder setUserPriorityLimit(@IntRange(from = 0, to = 7) int userPriorityLimit) {
276             if (userPriorityLimit < 0 || userPriorityLimit > 7) {
277                 throw new IllegalArgumentException(
278                         "userPriorityLimit must be between 0-7 (inclusive)");
279             }
280             mUserPriorityLimit = userPriorityLimit;
281             return this;
282         }
283 
284         /**
285          * Set the minimum timeout (in microseconds) to keep this request in the MSCS list.
286          *
287          * @param streamTimeoutUs Minimum timeout in microseconds.
288          * @throws IllegalArgumentException if the provided value is outside the expected range of
289          *                                  0-60 seconds (inclusive).
290          */
291         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
292         @NonNull
setStreamTimeoutUs( @ntRangefrom = 0, to = MAX_STREAM_TIMEOUT_US) int streamTimeoutUs)293         public Builder setStreamTimeoutUs(
294                 @IntRange(from = 0, to = MAX_STREAM_TIMEOUT_US) int streamTimeoutUs) {
295             if (streamTimeoutUs < 0 || streamTimeoutUs > MAX_STREAM_TIMEOUT_US) {
296                 throw new IllegalArgumentException("streamTimeoutUs must be 60 seconds or less");
297             }
298             mStreamTimeoutUs = streamTimeoutUs;
299             return this;
300         }
301 
302         /**
303          * Construct an MscsParams object using the specified parameters.
304          */
305         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
306         @NonNull
build()307         public MscsParams build() {
308             return new MscsParams(mFrameClassifierFields, mUserPriorityBitmap,
309                     mUserPriorityLimit, mStreamTimeoutUs);
310         }
311     }
312 }
313