1 /**
2  * Copyright 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.IntDef;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Objects;
31 
32 /**
33  * Represents a single route selection descriptor as defined in
34  * 3GPP TS 24.526.
35  */
36 public final class RouteSelectionDescriptor implements Parcelable {
37     /**
38      * The min acceptable value for the precedence of a route selection descriptor.
39      * @hide
40      */
41     public static final int MIN_ROUTE_PRECEDENCE = 0;
42 
43     /**
44      * The max acceptable value for the precedence of a route selection descriptor.
45      * @hide
46      */
47     public static final int MAX_ROUTE_PRECEDENCE = 255;
48 
49     /**
50      * The route selection descriptor is for the session with IPV4 type.
51      */
52     public static final int SESSION_TYPE_IPV4 = 0;
53 
54     /**
55      * The route selection descriptor is for the session with IPV6 type.
56      */
57     public static final int SESSION_TYPE_IPV6 = 1;
58 
59     /**
60      * The route selection descriptor is for the session with both IP and IPV6 types.
61      */
62     public static final int SESSION_TYPE_IPV4V6 = 2;
63 
64     /** @hide */
65     @IntDef(prefix = { "SESSION_TYPE_" }, value = {
66             SESSION_TYPE_IPV4,
67             SESSION_TYPE_IPV6,
68             SESSION_TYPE_IPV4V6,
69     })
70     @Retention(RetentionPolicy.SOURCE)
71     public @interface RouteSessionType {}
72 
73     /**
74      * The route selection descriptor is using SSC mode 1. The session will provide continual
75      * support when UE's location is updated.
76      */
77     public static final int ROUTE_SSC_MODE_1 = 1;
78 
79     /**
80      * The route selection descriptor is using SSC mode 2. The new session for the same network
81      * will be established after releasing the old session when UE's location is updated.
82      */
83     public static final int ROUTE_SSC_MODE_2 = 2;
84 
85     /**
86      * The route selection descriptor is using SSC mode 3. The new session for the same network is
87      * allowed to be established before releasing the old session when UE's location is updated.
88      */
89     public static final int ROUTE_SSC_MODE_3 = 3;
90 
91     /**
92      * The min acceptable value for the SSC mode of a route selection descriptor.
93      * @hide
94      */
95     public static final int MIN_ROUTE_SSC_MODE = ROUTE_SSC_MODE_1;
96 
97     /**
98      * The max acceptable value for the SSC mode of a route selection descriptor.
99      * @hide
100      */
101     public static final int MAX_ROUTE_SSC_MODE = ROUTE_SSC_MODE_3;
102 
103     /** @hide */
104     @IntDef(prefix = { "ROUTE_SSC_MODE_" }, value = {
105             ROUTE_SSC_MODE_1,
106             ROUTE_SSC_MODE_2,
107             ROUTE_SSC_MODE_3,
108     })
109     @Retention(RetentionPolicy.SOURCE)
110     public @interface RouteSscMode {}
111 
112     @IntRange(from = MIN_ROUTE_PRECEDENCE, to = MAX_ROUTE_PRECEDENCE)
113     private final int mPrecedence;
114     @RouteSessionType
115     private final int mSessionType;
116     @RouteSscMode
117     @IntRange(from = MIN_ROUTE_SSC_MODE, to = MAX_ROUTE_SSC_MODE)
118     private final int mSscMode;
119     private final List<NetworkSliceInfo> mSliceInfo;
120     private final List<String> mDnn;
121 
122     /** @hide */
RouteSelectionDescriptor(android.hardware.radio.V1_6.RouteSelectionDescriptor rsd)123     RouteSelectionDescriptor(android.hardware.radio.V1_6.RouteSelectionDescriptor rsd) {
124         this(rsd.precedence, rsd.sessionType.value(), rsd.sscMode.value(), rsd.sliceInfo,
125                 rsd.dnn);
126     }
127 
128     /** @hide */
RouteSelectionDescriptor(int precedence, int sessionType, int sscMode, List<android.hardware.radio.V1_6.SliceInfo> sliceInfo, List<String> dnn)129     public RouteSelectionDescriptor(int precedence, int sessionType, int sscMode,
130             List<android.hardware.radio.V1_6.SliceInfo> sliceInfo, List<String> dnn) {
131         mPrecedence = precedence;
132         mSessionType = sessionType;
133         mSscMode = sscMode;
134         mSliceInfo = new ArrayList<NetworkSliceInfo>();
135         for (android.hardware.radio.V1_6.SliceInfo si : sliceInfo) {
136             mSliceInfo.add(sliceInfoBuilder(si));
137         }
138         mDnn = new ArrayList<String>();
139         mDnn.addAll(dnn);
140     }
141 
sliceInfoBuilder(android.hardware.radio.V1_6.SliceInfo si)142     private NetworkSliceInfo sliceInfoBuilder(android.hardware.radio.V1_6.SliceInfo si) {
143         NetworkSliceInfo.Builder builder = new NetworkSliceInfo.Builder()
144                 .setSliceServiceType(si.sst)
145                 .setMappedHplmnSliceServiceType(si.mappedHplmnSst);
146         if (si.sliceDifferentiator != NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE) {
147             builder
148                 .setSliceDifferentiator(si.sliceDifferentiator)
149                 .setMappedHplmnSliceDifferentiator(si.mappedHplmnSD);
150         }
151         return builder.build();
152     }
153 
RouteSelectionDescriptor(Parcel p)154     private RouteSelectionDescriptor(Parcel p) {
155         mPrecedence = p.readInt();
156         mSessionType = p.readInt();
157         mSscMode = p.readInt();
158         mSliceInfo = p.createTypedArrayList(NetworkSliceInfo.CREATOR);
159         mDnn = new ArrayList<String>();
160         p.readStringList(mDnn);
161     }
162 
163     /**
164      * Precedence value in the range of 0 to 255. Higher value has lower precedence.
165      * @return the precedence value for this route selection descriptor.
166      */
167     @IntRange(from = MIN_ROUTE_PRECEDENCE, to = MAX_ROUTE_PRECEDENCE)
getPrecedence()168     public int getPrecedence() {
169         return mPrecedence;
170     }
171 
172     /**
173      * This is used for checking which session type defined in 3GPP TS 23.501 is allowed for the
174      * route in a route selection descriptor.
175      * @return the session type for this route selection descriptor.
176      */
177     @RouteSessionType
getSessionType()178     public int getSessionType() {
179         return mSessionType;
180     }
181 
182     /**
183      * SSC mode stands for Session and Service Continuity mode (which specifies the IP continuity
184      * mode) as defined in 3GPP TS 23.501.
185      * @return the SSC mode for this route selection descriptor.
186      */
187     @RouteSscMode
getSscMode()188     public int getSscMode() {
189         return mSscMode;
190     }
191 
192     /**
193      * This is the list of all the slices available in the route selection descriptor as indicated
194      * by the network. These are the slices that can be used by the device if this route selection
195      * descriptor is used based the traffic (see 3GPP TS 23.501 for details).
196      * @return the list of all the slices available in the route selection descriptor.
197      */
getSliceInfo()198     public @NonNull List<NetworkSliceInfo> getSliceInfo() {
199         return mSliceInfo;
200     }
201 
202     /**
203      * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003. There
204      * can be 0 or more DNNs specified in a route selection descriptor.
205      * @return the list of DNN for this route selection descriptor.
206      */
getDataNetworkName()207     public @NonNull List<String> getDataNetworkName() {
208         return mDnn;
209     }
210 
211     @Override
writeToParcel(@onNull Parcel dest, int flags)212     public void writeToParcel(@NonNull Parcel dest, int flags) {
213         dest.writeInt(mPrecedence);
214         dest.writeInt(mSessionType);
215         dest.writeInt(mSscMode);
216         dest.writeTypedList(mSliceInfo, flags);
217         dest.writeStringList(mDnn);
218     }
219 
220     public static final @NonNull Parcelable.Creator<RouteSelectionDescriptor> CREATOR =
221             new Parcelable.Creator<RouteSelectionDescriptor>() {
222                 @Override
223                 public RouteSelectionDescriptor createFromParcel(Parcel source) {
224                     return new RouteSelectionDescriptor(source);
225                 }
226 
227                 @Override
228                 public RouteSelectionDescriptor[] newArray(int size) {
229                     return new RouteSelectionDescriptor[size];
230                 }
231             };
232 
233     @Override
describeContents()234     public int describeContents() {
235         return 0;
236     }
237 
238     @Override
equals(@ullable Object o)239     public boolean equals(@Nullable Object o) {
240         if (this == o) return true;
241         if (o == null || getClass() != o.getClass()) return false;
242         RouteSelectionDescriptor that = (RouteSelectionDescriptor) o;
243         return mPrecedence == that.mPrecedence
244                 && mSessionType == that.mSessionType
245                 && mSscMode == that.mSscMode
246                 && mSliceInfo.size() == that.mSliceInfo.size()
247                 && mSliceInfo.containsAll(that.mSliceInfo)
248                 && mDnn.size() == that.mDnn.size()
249                 && mDnn.containsAll(that.mDnn);
250     }
251 
252     @Override
hashCode()253     public int hashCode() {
254         return Objects.hash(mPrecedence, mSessionType, mSscMode, mSliceInfo, mDnn);
255     }
256 
257     @Override
toString()258     public String toString() {
259         return "{.precedence = " + mPrecedence + ", .sessionType = " + mSessionType
260                 + ", .sscMode = " + mSscMode + ", .sliceInfo = " + mSliceInfo
261                 + ", .dnn = " + mDnn + "}";
262     }
263 }
264