1 /*
2  * Copyright (C) 2021 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.telephony.data;
18 
19 import android.annotation.IntRange;
20 import android.annotation.NonNull;
21 import android.annotation.SystemApi;
22 import android.net.QosSessionAttributes;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.util.Log;
26 
27 import java.net.InetAddress;
28 import java.net.InetSocketAddress;
29 import java.net.UnknownHostException;
30 import java.time.Duration;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.List;
34 import java.util.Objects;
35 
36 /**
37  * Provides Qos attributes of an NR bearer.
38  *
39  * {@hide}
40  */
41 @SystemApi
42 public final class NrQosSessionAttributes implements Parcelable, QosSessionAttributes {
43     private static final String TAG = NrQosSessionAttributes.class.getSimpleName();
44     private final int m5Qi;
45     private final @IntRange(from=1, to=63) int mQfi;
46     private final long mMaxUplinkBitRate;
47     private final long mMaxDownlinkBitRate;
48     private final long mGuaranteedUplinkBitRate;
49     private final long mGuaranteedDownlinkBitRate;
50     private final long mAveragingWindow;
51     @NonNull private final List<InetSocketAddress> mRemoteAddresses;
52 
53     /**
54      * 5G QOS Identifier (5QI), see 3GPP TS 24.501 and 23.501.
55      * The allowed values are standard values(1-9, 65-68, 69-70, 75, 79-80, 82-85)
56      * defined in the spec and operator specific values in the range 128-254.
57      *
58      * @return the 5QI of the QOS flow
59      */
getQosIdentifier()60     public int getQosIdentifier() {
61         return m5Qi;
62     }
63 
64     /**
65      * QOS flow identifier of the QOS flow description in the
66      * range of 1 to 63. see 3GPP TS 24.501 and 23.501.
67      *
68      * @return the QOS flow identifier of the session
69      */
getQosFlowIdentifier()70     public @IntRange(from=1, to=63) int getQosFlowIdentifier() {
71         return mQfi;
72     }
73 
74     /**
75      * Minimum bit rate in kbps that is guaranteed to be provided by the network on the uplink.
76      *
77      * see 3GPP TS 24.501 section 6.2.5
78      *
79      * Note: The Qos Session may be shared with OTHER applications besides yours.
80      *
81      * @return the guaranteed bit rate in kbps
82      */
getGuaranteedUplinkBitRateKbps()83     public long getGuaranteedUplinkBitRateKbps() {
84         return mGuaranteedUplinkBitRate;
85     }
86 
87     /**
88      * Minimum bit rate in kbps that is guaranteed to be provided by the network on the downlink.
89      *
90      * see 3GPP TS 24.501 section 6.2.5
91      *
92      * Note: The Qos Session may be shared with OTHER applications besides yours.
93      *
94      * @return the guaranteed bit rate in kbps
95      */
getGuaranteedDownlinkBitRateKbps()96     public long getGuaranteedDownlinkBitRateKbps() {
97         return mGuaranteedDownlinkBitRate;
98     }
99 
100     /**
101      * The maximum uplink kbps that the network will accept.
102      *
103      * see 3GPP TS 24.501 section 6.2.5
104      *
105      * Note: The Qos Session may be shared with OTHER applications besides yours.
106      *
107      * @return the max uplink bit rate in kbps
108      */
getMaxUplinkBitRateKbps()109     public long getMaxUplinkBitRateKbps() {
110         return mMaxUplinkBitRate;
111     }
112 
113     /**
114      * The maximum downlink kbps that the network can provide.
115      *
116      * see 3GPP TS 24.501 section 6.2.5
117      *
118      * Note: The Qos Session may be shared with OTHER applications besides yours.
119      *
120      * @return the max downlink bit rate in kbps
121      */
getMaxDownlinkBitRateKbps()122     public long getMaxDownlinkBitRateKbps() {
123         return mMaxDownlinkBitRate;
124     }
125 
126     /**
127      * The duration in milliseconds over which the maximum bit rates and guaranteed bit rates
128      * are calculated
129      *
130      * see 3GPP TS 24.501 section 6.2.5
131      *
132      * @return the averaging window duration in milliseconds
133      */
134     @NonNull
getBitRateWindowDuration()135     public Duration getBitRateWindowDuration() {
136         return Duration.ofMillis(mAveragingWindow);
137     }
138 
139     /**
140      * List of remote addresses associated with the Qos Session.  The given uplink bit rates apply
141      * to this given list of remote addresses.
142      *
143      * Note: In the event that the list is empty, it is assumed that the uplink bit rates apply to
144      * all remote addresses that are not contained in a different set of attributes.
145      *
146      * @return list of remote socket addresses that the attributes apply to
147      */
148     @NonNull
getRemoteAddresses()149     public List<InetSocketAddress> getRemoteAddresses() {
150         return mRemoteAddresses;
151     }
152 
153     /**
154      * ..ctor for attributes
155      *
156      * @param fiveQi 5G quality class indicator
157      * @param qfi QOS flow identifier
158      * @param maxDownlinkBitRate the max downlink bit rate in kbps
159      * @param maxUplinkBitRate the max uplink bit rate in kbps
160      * @param guaranteedDownlinkBitRate the guaranteed downlink bit rate in kbps
161      * @param guaranteedUplinkBitRate the guaranteed uplink bit rate in kbps
162      * @param averagingWindow the averaging window duration in milliseconds
163      * @param remoteAddresses the remote addresses that the uplink bit rates apply to
164      *
165      * @hide
166      */
NrQosSessionAttributes(final int fiveQi, final int qfi, final long maxDownlinkBitRate, final long maxUplinkBitRate, final long guaranteedDownlinkBitRate, final long guaranteedUplinkBitRate, final long averagingWindow, @NonNull final List<InetSocketAddress> remoteAddresses)167     public NrQosSessionAttributes(final int fiveQi, final int qfi,
168             final long maxDownlinkBitRate, final long maxUplinkBitRate,
169             final long guaranteedDownlinkBitRate, final long guaranteedUplinkBitRate,
170             final long averagingWindow, @NonNull final List<InetSocketAddress> remoteAddresses) {
171         Objects.requireNonNull(remoteAddresses, "remoteAddress must be non-null");
172         m5Qi = fiveQi;
173         mQfi = qfi;
174         mMaxDownlinkBitRate = maxDownlinkBitRate;
175         mMaxUplinkBitRate = maxUplinkBitRate;
176         mGuaranteedDownlinkBitRate = guaranteedDownlinkBitRate;
177         mGuaranteedUplinkBitRate = guaranteedUplinkBitRate;
178         mAveragingWindow = averagingWindow;
179 
180         final List<InetSocketAddress> remoteAddressesTemp = copySocketAddresses(remoteAddresses);
181         mRemoteAddresses = Collections.unmodifiableList(remoteAddressesTemp);
182     }
183 
copySocketAddresses( @onNull final List<InetSocketAddress> remoteAddresses)184     private static List<InetSocketAddress> copySocketAddresses(
185             @NonNull final List<InetSocketAddress> remoteAddresses) {
186         final List<InetSocketAddress> remoteAddressesTemp = new ArrayList<>();
187         for (final InetSocketAddress socketAddress : remoteAddresses) {
188             if (socketAddress != null && socketAddress.getAddress() != null) {
189                 remoteAddressesTemp.add(socketAddress);
190             }
191         }
192         return remoteAddressesTemp;
193     }
194 
NrQosSessionAttributes(@onNull final Parcel in)195     private NrQosSessionAttributes(@NonNull final Parcel in) {
196         m5Qi = in.readInt();
197         mQfi = in.readInt();
198         mMaxDownlinkBitRate = in.readLong();
199         mMaxUplinkBitRate = in.readLong();
200         mGuaranteedDownlinkBitRate = in.readLong();
201         mGuaranteedUplinkBitRate = in.readLong();
202         mAveragingWindow = in.readLong();
203 
204         final int size = in.readInt();
205         final List<InetSocketAddress> remoteAddresses = new ArrayList<>(size);
206         for (int i = 0; i < size; i++) {
207             final byte[] addressBytes = in.createByteArray();
208             final int port = in.readInt();
209             try {
210                 remoteAddresses.add(
211                         new InetSocketAddress(InetAddress.getByAddress(addressBytes), port));
212             } catch (final UnknownHostException e) {
213                 // Impossible case since its filtered out the null values in the ..ctor
214                 Log.e(TAG, "unable to unparcel remote address at index: " + i, e);
215             }
216         }
217         mRemoteAddresses = Collections.unmodifiableList(remoteAddresses);
218     }
219 
220     @Override
describeContents()221     public int describeContents() {
222         return 0;
223     }
224 
225     @Override
writeToParcel(@onNull final Parcel dest, final int flags)226     public void writeToParcel(@NonNull final Parcel dest, final int flags) {
227         dest.writeInt(m5Qi);
228         dest.writeInt(mQfi);
229         dest.writeLong(mMaxDownlinkBitRate);
230         dest.writeLong(mMaxUplinkBitRate);
231         dest.writeLong(mGuaranteedDownlinkBitRate);
232         dest.writeLong(mGuaranteedUplinkBitRate);
233         dest.writeLong(mAveragingWindow);
234 
235         final int size = mRemoteAddresses.size();
236         dest.writeInt(size);
237         for (int i = 0; i < size; i++) {
238             final InetSocketAddress address = mRemoteAddresses.get(i);
239             dest.writeByteArray(address.getAddress().getAddress());
240             dest.writeInt(address.getPort());
241         }
242     }
243 
244     @Override
equals(Object o)245     public boolean equals(Object o) {
246         if (this == o) return true;
247         if (o == null || getClass() != o.getClass()) return false;
248         NrQosSessionAttributes nrQosAttr = (NrQosSessionAttributes) o;
249         return m5Qi == nrQosAttr.m5Qi
250                 && mQfi == nrQosAttr.mQfi
251                 && mMaxUplinkBitRate == nrQosAttr.mMaxUplinkBitRate
252                 && mMaxDownlinkBitRate == nrQosAttr.mMaxDownlinkBitRate
253                 && mGuaranteedUplinkBitRate == nrQosAttr.mGuaranteedUplinkBitRate
254                 && mGuaranteedDownlinkBitRate == nrQosAttr.mGuaranteedDownlinkBitRate
255                 && mAveragingWindow == nrQosAttr.mAveragingWindow
256                 && mRemoteAddresses.size() == nrQosAttr.mRemoteAddresses.size()
257                 && mRemoteAddresses.containsAll(nrQosAttr.mRemoteAddresses);
258     }
259 
260     @Override
hashCode()261     public int hashCode() {
262         return Objects.hash(m5Qi, mQfi, mMaxUplinkBitRate,
263                 mMaxDownlinkBitRate, mGuaranteedUplinkBitRate,
264                 mGuaranteedDownlinkBitRate, mAveragingWindow, mRemoteAddresses);
265     }
266 
267 
268     @NonNull
269     public static final Creator<NrQosSessionAttributes> CREATOR =
270             new Creator<NrQosSessionAttributes>() {
271         @NonNull
272         @Override
273         public NrQosSessionAttributes createFromParcel(@NonNull final Parcel in) {
274             return new NrQosSessionAttributes(in);
275         }
276 
277         @NonNull
278         @Override
279         public NrQosSessionAttributes[] newArray(final int size) {
280             return new NrQosSessionAttributes[size];
281         }
282     };
283 }
284