/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.telephony.data; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** * Represents a S-NSSAI as defined in 3GPP TS 24.501, which represents a network slice. * * There are 2 main fields that define a slice, SliceServiceType and SliceDifferentiator. * SliceServiceType defines the type of service provided by the slice, and SliceDifferentiator is * used to differentiate between multiple slices of the same type. If the devices is not on HPLMN, * the mappedHplmn versions of these 2 fields indicate the corresponding values in HPLMN. */ public final class NetworkSliceInfo implements Parcelable { /** * When set on a Slice Differentiator, this value indicates that there is no corresponding * Slice. */ public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; /** * Indicates that the service type is not present. */ public static final int SLICE_SERVICE_TYPE_NONE = 0; /** * Slice suitable for the handling of 5G enhanced Mobile Broadband. */ public static final int SLICE_SERVICE_TYPE_EMBB = 1; /** * Slice suitable for the handling of ultra-reliable low latency communications. */ public static final int SLICE_SERVICE_TYPE_URLLC = 2; /** * Slice suitable for the handling of massive IoT. */ public static final int SLICE_SERVICE_TYPE_MIOT = 3; /** * The min acceptable value for a Slice Differentiator * @hide */ public static final int MIN_SLICE_DIFFERENTIATOR = -1; /** * The max acceptable value for a Slice Differentiator * @hide */ public static final int MAX_SLICE_DIFFERENTIATOR = 0xFFFFFE; /** @hide */ @IntDef(prefix = { "SLICE_SERVICE_TYPE_" }, value = { SLICE_SERVICE_TYPE_NONE, SLICE_SERVICE_TYPE_EMBB, SLICE_SERVICE_TYPE_URLLC, SLICE_SERVICE_TYPE_MIOT, }) @Retention(RetentionPolicy.SOURCE) public @interface SliceServiceType {} /** * The slice status is unknown. This can happen during IWLAN->cellular handover when the * NetworkSliceInfo is received over IWLAN. */ public static final int SLICE_STATUS_UNKNOWN = 0; /** * The slice is configured but not allowed or rejected yet. */ public static final int SLICE_STATUS_CONFIGURED = 1; /** * The slice is allowed to be used. */ public static final int SLICE_STATUS_ALLOWED = 2; /** * The slice is rejected because not available in PLMN. */ public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN = 3; /** * The slice is rejected because not available in registered area. */ public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA = 4; /** * The slice is configured by home operator(HPLMN) in default and is used if configured/allowed * slices are not available for the serving PLMN. */ public static final int SLICE_STATUS_DEFAULT_CONFIGURED = 5; /** * The min acceptable value for a slice status. * @hide */ public static final int MIN_SLICE_STATUS = SLICE_STATUS_UNKNOWN; /** * The max acceptable value for a slice status. * @hide */ public static final int MAX_SLICE_STATUS = SLICE_STATUS_DEFAULT_CONFIGURED; /** @hide */ @IntDef(prefix = { "SLICE_STATUS_" }, value = { SLICE_STATUS_UNKNOWN, SLICE_STATUS_CONFIGURED, SLICE_STATUS_ALLOWED, SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN, SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA, SLICE_STATUS_DEFAULT_CONFIGURED, }) @Retention(RetentionPolicy.SOURCE) public @interface SliceStatus {} @SliceServiceType private final int mSliceServiceType; @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) private final int mSliceDifferentiator; @SliceServiceType private final int mMappedHplmnSliceServiceType; @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) private final int mMappedHplmnSliceDifferentiator; @SliceStatus @IntRange(from = MIN_SLICE_STATUS, to = MAX_SLICE_STATUS) private final int mStatus; private NetworkSliceInfo(@SliceServiceType int sliceServiceType, int sliceDifferentiator, int mappedHplmnSliceServiceType, int mappedHplmnSliceDifferentiator, int status) { mSliceServiceType = sliceServiceType; mSliceDifferentiator = sliceDifferentiator; mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator; mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType; mStatus = status; } /** * The type of service provided by the slice. *

* see: 3GPP TS 24.501 Section 9.11.2.8. */ @SliceServiceType public int getSliceServiceType() { return mSliceServiceType; } /** * Identifies the slice from others with the same Slice Service Type. *

* Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if {@link #getSliceServiceType} returns * {@link #SLICE_SERVICE_TYPE_NONE}. *

* see: 3GPP TS 24.501 Section 9.11.2.8. */ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) public int getSliceDifferentiator() { return mSliceDifferentiator; } /** * Corresponds to a Slice Info (S-NSSAI) of the HPLMN. *

* see: 3GPP TS 24.501 Section 9.11.2.8. */ @SliceServiceType public int getMappedHplmnSliceServiceType() { return mMappedHplmnSliceServiceType; } /** * This Slice Differentiator corresponds to a {@link NetworkSliceInfo} (S-NSSAI) of the HPLMN; * {@link #getSliceDifferentiator()} is mapped to this value. *

* Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if either of the following are true: *

*

* see: 3GPP TS 24.501 Section 9.11.2.8. */ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) public int getMappedHplmnSliceDifferentiator() { return mMappedHplmnSliceDifferentiator; } /** * Field to indicate the current status of the slice. * @return the current status for this slice info. */ @SliceStatus public int getStatus() { return mStatus; } private NetworkSliceInfo(@NonNull Parcel in) { mSliceServiceType = in.readInt(); mSliceDifferentiator = in.readInt(); mMappedHplmnSliceServiceType = in.readInt(); mMappedHplmnSliceDifferentiator = in.readInt(); mStatus = in.readInt(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mSliceServiceType); dest.writeInt(mSliceDifferentiator); dest.writeInt(mMappedHplmnSliceServiceType); dest.writeInt(mMappedHplmnSliceDifferentiator); dest.writeInt(mStatus); } public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override @NonNull public NetworkSliceInfo createFromParcel(@NonNull Parcel source) { return new NetworkSliceInfo(source); } @Override @NonNull public NetworkSliceInfo[] newArray(int size) { return new NetworkSliceInfo[size]; } }; @Override public String toString() { return "SliceInfo{" + "mSliceServiceType=" + sliceServiceTypeToString(mSliceServiceType) + ", mSliceDifferentiator=" + mSliceDifferentiator + ", mMappedHplmnSliceServiceType=" + sliceServiceTypeToString(mMappedHplmnSliceServiceType) + ", mMappedHplmnSliceDifferentiator=" + mMappedHplmnSliceDifferentiator + ", mStatus=" + sliceStatusToString(mStatus) + '}'; } private static String sliceServiceTypeToString(@SliceServiceType int sliceServiceType) { switch(sliceServiceType) { case SLICE_SERVICE_TYPE_NONE: return "NONE"; case SLICE_SERVICE_TYPE_EMBB: return "EMBB"; case SLICE_SERVICE_TYPE_URLLC: return "URLLC"; case SLICE_SERVICE_TYPE_MIOT: return "MIOT"; default: return Integer.toString(sliceServiceType); } } private static String sliceStatusToString(@SliceStatus int sliceStatus) { switch(sliceStatus) { case SLICE_STATUS_UNKNOWN: return "UNKNOWN"; case SLICE_STATUS_CONFIGURED: return "CONFIGURED"; case SLICE_STATUS_ALLOWED: return "ALLOWED"; case SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN: return "REJECTED_NOT_AVAILABLE_IN_PLMN"; case SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA: return "REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA"; case SLICE_STATUS_DEFAULT_CONFIGURED: return "DEFAULT_CONFIGURED"; default: return Integer.toString(sliceStatus); } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NetworkSliceInfo sliceInfo = (NetworkSliceInfo) o; return mSliceServiceType == sliceInfo.mSliceServiceType && mSliceDifferentiator == sliceInfo.mSliceDifferentiator && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator && mStatus == sliceInfo.mStatus; } @Override public int hashCode() { return Objects.hash(mSliceServiceType, mSliceDifferentiator, mMappedHplmnSliceServiceType, mMappedHplmnSliceDifferentiator, mStatus); } /** * Provides a convenient way to set the fields of a {@link NetworkSliceInfo} when creating a * new instance. * *

The example below shows how you might create a new {@code SliceInfo}: * *


     *
     * SliceInfo response = new SliceInfo.Builder()
     *     .setSliceServiceType(SLICE_SERVICE_TYPE_URLLC)
     *     .build();
     * 
*/ public static final class Builder { @SliceServiceType private int mSliceServiceType = SLICE_SERVICE_TYPE_NONE; @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) private int mSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE; @SliceServiceType private int mMappedHplmnSliceServiceType = SLICE_SERVICE_TYPE_NONE; @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) private int mMappedHplmnSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE; @SliceStatus @IntRange(from = MIN_SLICE_STATUS, to = MAX_SLICE_STATUS) private int mStatus = SLICE_STATUS_UNKNOWN; /** * Default constructor for Builder. */ public Builder() { } /** * Set the Slice Service Type. * * @return The same instance of the builder. */ @NonNull public Builder setSliceServiceType(@SliceServiceType int mSliceServiceType) { this.mSliceServiceType = mSliceServiceType; return this; } /** * Set the Slice Differentiator. *

* A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no * corresponding Slice. * * @throws IllegalArgumentException if the parameter is not in the expected range. * * @return The same instance of the builder. */ @NonNull public Builder setSliceDifferentiator( @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) int sliceDifferentiator) { if (sliceDifferentiator < MIN_SLICE_DIFFERENTIATOR || sliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) { throw new IllegalArgumentException("The slice diffentiator value is out of range"); } this.mSliceDifferentiator = sliceDifferentiator; return this; } /** * Set the HPLMN Slice Service Type. * * @return The same instance of the builder. */ @NonNull public Builder setMappedHplmnSliceServiceType( @SliceServiceType int mappedHplmnSliceServiceType) { this.mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType; return this; } /** * Set the HPLMN Slice Differentiator. *

* A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no * corresponding Slice of the HPLMN. * * @throws IllegalArgumentException if the parameter is not in the expected range. * * @return The same instance of the builder. */ @NonNull public Builder setMappedHplmnSliceDifferentiator( @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR) int mappedHplmnSliceDifferentiator) { if (mappedHplmnSliceDifferentiator < MIN_SLICE_DIFFERENTIATOR || mappedHplmnSliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) { throw new IllegalArgumentException("The slice diffentiator value is out of range"); } this.mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator; return this; } /** * Set the slice status. * * @throws IllegalArgumentException if the status is invalid. * * @return The same instance of the builder. */ @NonNull public Builder setStatus(@SliceStatus int status) { if (status < MIN_SLICE_STATUS || status > MAX_SLICE_STATUS) { throw new IllegalArgumentException("The slice status is not valid"); } this.mStatus = status; return this; } /** * Build the {@link NetworkSliceInfo}. * * @return the {@link NetworkSliceInfo} object. */ @NonNull public NetworkSliceInfo build() { return new NetworkSliceInfo(this.mSliceServiceType, this.mSliceDifferentiator, this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator, this.mStatus); } } }