1 /* 2 * Copyright (C) 2020 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.os.Parcel; 23 import android.os.Parcelable; 24 25 import java.lang.annotation.Retention; 26 import java.lang.annotation.RetentionPolicy; 27 import java.util.Objects; 28 29 /** 30 * Represents a S-NSSAI as defined in 3GPP TS 24.501, which represents a network slice. 31 * 32 * There are 2 main fields that define a slice, SliceServiceType and SliceDifferentiator. 33 * SliceServiceType defines the type of service provided by the slice, and SliceDifferentiator is 34 * used to differentiate between multiple slices of the same type. If the devices is not on HPLMN, 35 * the mappedHplmn versions of these 2 fields indicate the corresponding values in HPLMN. 36 */ 37 public final class NetworkSliceInfo implements Parcelable { 38 /** 39 * When set on a Slice Differentiator, this value indicates that there is no corresponding 40 * Slice. 41 */ 42 public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; 43 44 /** 45 * Indicates that the service type is not present. 46 */ 47 public static final int SLICE_SERVICE_TYPE_NONE = 0; 48 49 /** 50 * Slice suitable for the handling of 5G enhanced Mobile Broadband. 51 */ 52 public static final int SLICE_SERVICE_TYPE_EMBB = 1; 53 54 /** 55 * Slice suitable for the handling of ultra-reliable low latency communications. 56 */ 57 public static final int SLICE_SERVICE_TYPE_URLLC = 2; 58 59 /** 60 * Slice suitable for the handling of massive IoT. 61 */ 62 public static final int SLICE_SERVICE_TYPE_MIOT = 3; 63 64 /** 65 * The min acceptable value for a Slice Differentiator 66 * @hide 67 */ 68 public static final int MIN_SLICE_DIFFERENTIATOR = -1; 69 70 /** 71 * The max acceptable value for a Slice Differentiator 72 * @hide 73 */ 74 public static final int MAX_SLICE_DIFFERENTIATOR = 0xFFFFFE; 75 76 /** @hide */ 77 @IntDef(prefix = { "SLICE_SERVICE_TYPE_" }, value = { 78 SLICE_SERVICE_TYPE_NONE, 79 SLICE_SERVICE_TYPE_EMBB, 80 SLICE_SERVICE_TYPE_URLLC, 81 SLICE_SERVICE_TYPE_MIOT, 82 }) 83 @Retention(RetentionPolicy.SOURCE) 84 public @interface SliceServiceType {} 85 86 /** 87 * The slice status is unknown. This can happen during IWLAN->cellular handover when the 88 * NetworkSliceInfo is received over IWLAN. 89 */ 90 public static final int SLICE_STATUS_UNKNOWN = 0; 91 92 /** 93 * The slice is configured but not allowed or rejected yet. 94 */ 95 public static final int SLICE_STATUS_CONFIGURED = 1; 96 97 /** 98 * The slice is allowed to be used. 99 */ 100 public static final int SLICE_STATUS_ALLOWED = 2; 101 102 /** 103 * The slice is rejected because not available in PLMN. 104 */ 105 public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN = 3; 106 107 /** 108 * The slice is rejected because not available in registered area. 109 */ 110 public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA = 4; 111 112 /** 113 * The slice is configured by home operator(HPLMN) in default and is used if configured/allowed 114 * slices are not available for the serving PLMN. 115 */ 116 public static final int SLICE_STATUS_DEFAULT_CONFIGURED = 5; 117 118 /** 119 * The min acceptable value for a slice status. 120 * @hide 121 */ 122 public static final int MIN_SLICE_STATUS = SLICE_STATUS_UNKNOWN; 123 124 /** 125 * The max acceptable value for a slice status. 126 * @hide 127 */ 128 public static final int MAX_SLICE_STATUS = SLICE_STATUS_DEFAULT_CONFIGURED; 129 130 /** @hide */ 131 @IntDef(prefix = { "SLICE_STATUS_" }, value = { 132 SLICE_STATUS_UNKNOWN, 133 SLICE_STATUS_CONFIGURED, 134 SLICE_STATUS_ALLOWED, 135 SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN, 136 SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA, 137 SLICE_STATUS_DEFAULT_CONFIGURED, 138 }) 139 @Retention(RetentionPolicy.SOURCE) 140 public @interface SliceStatus {} 141 142 143 @SliceServiceType 144 private final int mSliceServiceType; 145 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) 146 private final int mSliceDifferentiator; 147 @SliceServiceType 148 private final int mMappedHplmnSliceServiceType; 149 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) 150 private final int mMappedHplmnSliceDifferentiator; 151 @SliceStatus 152 @IntRange(from = MIN_SLICE_STATUS, to = MAX_SLICE_STATUS) 153 private final int mStatus; 154 NetworkSliceInfo(@liceServiceType int sliceServiceType, int sliceDifferentiator, int mappedHplmnSliceServiceType, int mappedHplmnSliceDifferentiator, int status)155 private NetworkSliceInfo(@SliceServiceType int sliceServiceType, 156 int sliceDifferentiator, int mappedHplmnSliceServiceType, 157 int mappedHplmnSliceDifferentiator, int status) { 158 mSliceServiceType = sliceServiceType; 159 mSliceDifferentiator = sliceDifferentiator; 160 mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator; 161 mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType; 162 mStatus = status; 163 } 164 165 /** 166 * The type of service provided by the slice. 167 * <p/> 168 * see: 3GPP TS 24.501 Section 9.11.2.8. 169 */ 170 @SliceServiceType getSliceServiceType()171 public int getSliceServiceType() { 172 return mSliceServiceType; 173 } 174 175 /** 176 * Identifies the slice from others with the same Slice Service Type. 177 * <p/> 178 * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if {@link #getSliceServiceType} returns 179 * {@link #SLICE_SERVICE_TYPE_NONE}. 180 * <p/> 181 * see: 3GPP TS 24.501 Section 9.11.2.8. 182 */ 183 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) getSliceDifferentiator()184 public int getSliceDifferentiator() { 185 return mSliceDifferentiator; 186 } 187 188 /** 189 * Corresponds to a Slice Info (S-NSSAI) of the HPLMN. 190 * <p/> 191 * see: 3GPP TS 24.501 Section 9.11.2.8. 192 */ 193 @SliceServiceType getMappedHplmnSliceServiceType()194 public int getMappedHplmnSliceServiceType() { 195 return mMappedHplmnSliceServiceType; 196 } 197 198 /** 199 * This Slice Differentiator corresponds to a {@link NetworkSliceInfo} (S-NSSAI) of the HPLMN; 200 * {@link #getSliceDifferentiator()} is mapped to this value. 201 * <p/> 202 * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if either of the following are true: 203 * <ul> 204 * <li>{@link #getSliceDifferentiator()} returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE}</li> 205 * <li>{@link #getMappedHplmnSliceServiceType()} returns {@link #SLICE_SERVICE_TYPE_NONE}</li> 206 * </ul> 207 * <p/> 208 * see: 3GPP TS 24.501 Section 9.11.2.8. 209 */ 210 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) getMappedHplmnSliceDifferentiator()211 public int getMappedHplmnSliceDifferentiator() { 212 return mMappedHplmnSliceDifferentiator; 213 } 214 215 /** 216 * Field to indicate the current status of the slice. 217 * @return the current status for this slice info. 218 */ 219 @SliceStatus getStatus()220 public int getStatus() { 221 return mStatus; 222 } 223 NetworkSliceInfo(@onNull Parcel in)224 private NetworkSliceInfo(@NonNull Parcel in) { 225 mSliceServiceType = in.readInt(); 226 mSliceDifferentiator = in.readInt(); 227 mMappedHplmnSliceServiceType = in.readInt(); 228 mMappedHplmnSliceDifferentiator = in.readInt(); 229 mStatus = in.readInt(); 230 } 231 232 @Override describeContents()233 public int describeContents() { 234 return 0; 235 } 236 237 @Override writeToParcel(@onNull Parcel dest, int flags)238 public void writeToParcel(@NonNull Parcel dest, int flags) { 239 dest.writeInt(mSliceServiceType); 240 dest.writeInt(mSliceDifferentiator); 241 dest.writeInt(mMappedHplmnSliceServiceType); 242 dest.writeInt(mMappedHplmnSliceDifferentiator); 243 dest.writeInt(mStatus); 244 } 245 246 public static final @android.annotation.NonNull Parcelable.Creator<NetworkSliceInfo> CREATOR = 247 new Parcelable.Creator<NetworkSliceInfo>() { 248 @Override 249 @NonNull 250 public NetworkSliceInfo createFromParcel(@NonNull Parcel source) { 251 return new NetworkSliceInfo(source); 252 } 253 254 @Override 255 @NonNull 256 public NetworkSliceInfo[] newArray(int size) { 257 return new NetworkSliceInfo[size]; 258 } 259 }; 260 261 @Override toString()262 public String toString() { 263 return "SliceInfo{" 264 + "mSliceServiceType=" + sliceServiceTypeToString(mSliceServiceType) 265 + ", mSliceDifferentiator=" + mSliceDifferentiator 266 + ", mMappedHplmnSliceServiceType=" 267 + sliceServiceTypeToString(mMappedHplmnSliceServiceType) 268 + ", mMappedHplmnSliceDifferentiator=" + mMappedHplmnSliceDifferentiator 269 + ", mStatus=" + sliceStatusToString(mStatus) 270 + '}'; 271 } 272 sliceServiceTypeToString(@liceServiceType int sliceServiceType)273 private static String sliceServiceTypeToString(@SliceServiceType int sliceServiceType) { 274 switch(sliceServiceType) { 275 case SLICE_SERVICE_TYPE_NONE: 276 return "NONE"; 277 case SLICE_SERVICE_TYPE_EMBB: 278 return "EMBB"; 279 case SLICE_SERVICE_TYPE_URLLC: 280 return "URLLC"; 281 case SLICE_SERVICE_TYPE_MIOT: 282 return "MIOT"; 283 default: 284 return Integer.toString(sliceServiceType); 285 } 286 } 287 sliceStatusToString(@liceStatus int sliceStatus)288 private static String sliceStatusToString(@SliceStatus int sliceStatus) { 289 switch(sliceStatus) { 290 case SLICE_STATUS_UNKNOWN: 291 return "UNKNOWN"; 292 case SLICE_STATUS_CONFIGURED: 293 return "CONFIGURED"; 294 case SLICE_STATUS_ALLOWED: 295 return "ALLOWED"; 296 case SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN: 297 return "REJECTED_NOT_AVAILABLE_IN_PLMN"; 298 case SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA: 299 return "REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA"; 300 case SLICE_STATUS_DEFAULT_CONFIGURED: 301 return "DEFAULT_CONFIGURED"; 302 default: 303 return Integer.toString(sliceStatus); 304 } 305 } 306 307 @Override equals(Object o)308 public boolean equals(Object o) { 309 if (this == o) return true; 310 if (o == null || getClass() != o.getClass()) return false; 311 NetworkSliceInfo sliceInfo = (NetworkSliceInfo) o; 312 return mSliceServiceType == sliceInfo.mSliceServiceType 313 && mSliceDifferentiator == sliceInfo.mSliceDifferentiator 314 && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType 315 && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator 316 && mStatus == sliceInfo.mStatus; 317 } 318 319 @Override hashCode()320 public int hashCode() { 321 return Objects.hash(mSliceServiceType, mSliceDifferentiator, mMappedHplmnSliceServiceType, 322 mMappedHplmnSliceDifferentiator, mStatus); 323 } 324 325 /** 326 * Provides a convenient way to set the fields of a {@link NetworkSliceInfo} when creating a 327 * new instance. 328 * 329 * <p>The example below shows how you might create a new {@code SliceInfo}: 330 * 331 * <pre><code> 332 * 333 * SliceInfo response = new SliceInfo.Builder() 334 * .setSliceServiceType(SLICE_SERVICE_TYPE_URLLC) 335 * .build(); 336 * </code></pre> 337 */ 338 public static final class Builder { 339 @SliceServiceType 340 private int mSliceServiceType = SLICE_SERVICE_TYPE_NONE; 341 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) 342 private int mSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE; 343 @SliceServiceType 344 private int mMappedHplmnSliceServiceType = SLICE_SERVICE_TYPE_NONE; 345 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) 346 private int mMappedHplmnSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE; 347 @SliceStatus 348 @IntRange(from = MIN_SLICE_STATUS, to = MAX_SLICE_STATUS) 349 private int mStatus = SLICE_STATUS_UNKNOWN; 350 351 /** 352 * Default constructor for Builder. 353 */ Builder()354 public Builder() { 355 } 356 357 /** 358 * Set the Slice Service Type. 359 * 360 * @return The same instance of the builder. 361 */ 362 @NonNull setSliceServiceType(@liceServiceType int mSliceServiceType)363 public Builder setSliceServiceType(@SliceServiceType int mSliceServiceType) { 364 this.mSliceServiceType = mSliceServiceType; 365 return this; 366 } 367 368 /** 369 * Set the Slice Differentiator. 370 * <p/> 371 * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no 372 * corresponding Slice. 373 * 374 * @throws IllegalArgumentException if the parameter is not in the expected range. 375 * 376 * @return The same instance of the builder. 377 */ 378 @NonNull setSliceDifferentiator( @ntRangefrom = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) int sliceDifferentiator)379 public Builder setSliceDifferentiator( 380 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) 381 int sliceDifferentiator) { 382 if (sliceDifferentiator < MIN_SLICE_DIFFERENTIATOR 383 || sliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) { 384 throw new IllegalArgumentException("The slice diffentiator value is out of range"); 385 } 386 this.mSliceDifferentiator = sliceDifferentiator; 387 return this; 388 } 389 390 /** 391 * Set the HPLMN Slice Service Type. 392 * 393 * @return The same instance of the builder. 394 */ 395 @NonNull setMappedHplmnSliceServiceType( @liceServiceType int mappedHplmnSliceServiceType)396 public Builder setMappedHplmnSliceServiceType( 397 @SliceServiceType int mappedHplmnSliceServiceType) { 398 this.mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType; 399 return this; 400 } 401 402 /** 403 * Set the HPLMN Slice Differentiator. 404 * <p/> 405 * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no 406 * corresponding Slice of the HPLMN. 407 * 408 * @throws IllegalArgumentException if the parameter is not in the expected range. 409 * 410 * @return The same instance of the builder. 411 */ 412 @NonNull setMappedHplmnSliceDifferentiator( @ntRangefrom = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) int mappedHplmnSliceDifferentiator)413 public Builder setMappedHplmnSliceDifferentiator( 414 @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) 415 int mappedHplmnSliceDifferentiator) { 416 if (mappedHplmnSliceDifferentiator < MIN_SLICE_DIFFERENTIATOR 417 || mappedHplmnSliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) { 418 throw new IllegalArgumentException("The slice diffentiator value is out of range"); 419 } 420 this.mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator; 421 return this; 422 } 423 424 /** 425 * Set the slice status. 426 * 427 * @throws IllegalArgumentException if the status is invalid. 428 * 429 * @return The same instance of the builder. 430 */ 431 @NonNull setStatus(@liceStatus int status)432 public Builder setStatus(@SliceStatus int status) { 433 if (status < MIN_SLICE_STATUS || status > MAX_SLICE_STATUS) { 434 throw new IllegalArgumentException("The slice status is not valid"); 435 } 436 this.mStatus = status; 437 return this; 438 } 439 440 /** 441 * Build the {@link NetworkSliceInfo}. 442 * 443 * @return the {@link NetworkSliceInfo} object. 444 */ 445 @NonNull build()446 public NetworkSliceInfo build() { 447 return new NetworkSliceInfo(this.mSliceServiceType, this.mSliceDifferentiator, 448 this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator, 449 this.mStatus); 450 } 451 } 452 } 453