Merge "Add S-NSSAI"
diff --git a/core/api/current.txt b/core/api/current.txt
index b0534a1..acd3389 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -40272,6 +40272,7 @@
     field public static final int SERVICE_OPTION_OUT_OF_ORDER = 34; // 0x22
     field public static final int SIGNAL_LOST = -3; // 0xfffffffd
     field public static final int SIM_CARD_CHANGED = 2043; // 0x7fb
+    field public static final int SLICE_REJECTED = 2252; // 0x8cc
     field public static final int SYNCHRONIZATION_FAILURE = 2184; // 0x888
     field public static final int TEST_LOOPBACK_REGULAR_DEACTIVATION = 2196; // 0x894
     field public static final int TETHERED_CALL_ACTIVE = -6; // 0xfffffffa
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ea23709..a1ab6aa 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10713,6 +10713,7 @@
     method public int getPduSessionId();
     method public int getProtocolType();
     method public long getRetryDurationMillis();
+    method @Nullable public android.telephony.data.SliceInfo getSliceInfo();
     method @Deprecated public int getSuggestedRetryTime();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR;
@@ -10747,6 +10748,7 @@
     method @NonNull public android.telephony.data.DataCallResponse.Builder setPduSessionId(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
     method @NonNull public android.telephony.data.DataCallResponse.Builder setRetryDurationMillis(long);
+    method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.SliceInfo);
     method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
   }
 
@@ -10819,7 +10821,7 @@
     method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
     method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
-    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @NonNull android.telephony.data.DataServiceCallback);
+    method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @NonNull android.telephony.data.DataServiceCallback);
     method public void startHandover(int, @NonNull android.telephony.data.DataServiceCallback);
   }
 
@@ -10867,6 +10869,32 @@
     method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>);
   }
 
+  public final class SliceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getMappedHplmnSliceDifferentiator();
+    method public int getMappedHplmnSliceServiceType();
+    method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getSliceDifferentiator();
+    method public int getSliceServiceType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.SliceInfo> CREATOR;
+    field public static final int MAX_SLICE_DIFFERENTIATOR = 16777214; // 0xfffffe
+    field public static final int MIN_SLICE_DIFFERENTIATOR = -1; // 0xffffffff
+    field public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; // 0xffffffff
+    field public static final int SLICE_SERVICE_TYPE_EMBB = 1; // 0x1
+    field public static final int SLICE_SERVICE_TYPE_MIOT = 3; // 0x3
+    field public static final int SLICE_SERVICE_TYPE_NONE = 0; // 0x0
+    field public static final int SLICE_SERVICE_TYPE_URLLC = 2; // 0x2
+  }
+
+  public static final class SliceInfo.Builder {
+    ctor public SliceInfo.Builder();
+    method @NonNull public android.telephony.data.SliceInfo build();
+    method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
+    method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceServiceType(int);
+    method @NonNull public android.telephony.data.SliceInfo.Builder setSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
+    method @NonNull public android.telephony.data.SliceInfo.Builder setSliceServiceType(int);
+  }
+
 }
 
 package android.telephony.euicc {
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index d502da9..99a77ae5 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -915,6 +915,8 @@
     public static final int IPV6_PREFIX_UNAVAILABLE = 0x8CA;
     /** System preference change back to SRAT during handoff */
     public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB;
+    /** Data call fail due to the slice not being allowed for the data call. */
+    public static final int SLICE_REJECTED = 0x8CC;
 
     //IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2).
 
@@ -985,7 +987,7 @@
      * the authentication failed.
      */
     public static final int IWLAN_IKEV2_AUTH_FAILURE = 0x4001;
-    /** IKE message timeout, tunnel setup failed due to no response from EPDG  */
+    /** IKE message timeout, tunnel setup failed due to no response from EPDG */
     public static final int IWLAN_IKEV2_MSG_TIMEOUT = 0x4002;
     /** IKE Certification validation failure  */
     public static final int IWLAN_IKEV2_CERT_INVALID = 0x4003;
@@ -1419,6 +1421,7 @@
         sFailCauseMap.put(VSNCP_RECONNECT_NOT_ALLOWED, "VSNCP_RECONNECT_NOT_ALLOWED");
         sFailCauseMap.put(IPV6_PREFIX_UNAVAILABLE, "IPV6_PREFIX_UNAVAILABLE");
         sFailCauseMap.put(HANDOFF_PREFERENCE_CHANGED, "HANDOFF_PREFERENCE_CHANGED");
+        sFailCauseMap.put(SLICE_REJECTED, "SLICE_REJECTED");
         sFailCauseMap.put(IWLAN_PDN_CONNECTION_REJECTION, "IWLAN_PDN_CONNECTION_REJECTION");
         sFailCauseMap.put(IWLAN_MAX_CONNECTION_REACHED, "IWLAN_MAX_CONNECTION_REACHED");
         sFailCauseMap.put(IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION,
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 8348502..46ec4a3 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -136,6 +136,7 @@
     private final int mPduSessionId;
     private final Qos mDefaultQos;
     private final List<QosSession> mQosSessions;
+    private final SliceInfo mSliceInfo;
 
     /**
      * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error.
@@ -186,6 +187,7 @@
         mPduSessionId = PDU_SESSION_ID_NOT_SET;
         mDefaultQos = null;
         mQosSessions = new ArrayList<>();
+        mSliceInfo = null;
     }
 
     private DataCallResponse(@DataFailureCause int cause, long suggestedRetryTime, int id,
@@ -194,7 +196,8 @@
             @Nullable List<InetAddress> dnsAddresses, @Nullable List<InetAddress> gatewayAddresses,
             @Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6,
             @HandoverFailureMode int handoverFailureMode, int pduSessionId,
-            @Nullable Qos defaultQos, @Nullable List<QosSession> qosSessions) {
+            @Nullable Qos defaultQos, @Nullable List<QosSession> qosSessions,
+            @Nullable SliceInfo sliceInfo) {
         mCause = cause;
         mSuggestedRetryTime = suggestedRetryTime;
         mId = id;
@@ -216,6 +219,7 @@
         mPduSessionId = pduSessionId;
         mDefaultQos = defaultQos;
         mQosSessions = qosSessions;
+        mSliceInfo = sliceInfo;
     }
 
     /** @hide */
@@ -243,6 +247,7 @@
         mDefaultQos = source.readParcelable(Qos.class.getClassLoader());
         mQosSessions = new ArrayList<>();
         source.readList(mQosSessions, QosSession.class.getClassLoader());
+        mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader());
     }
 
     /**
@@ -368,7 +373,7 @@
     }
 
     /**
-     * @return default QOS of the data call received from the network
+     * @return default QOS of the data connection received from the network
      *
      * @hide
      */
@@ -379,16 +384,24 @@
     }
 
     /**
-     * @return All the dedicated bearer QOS sessions of the data call received from the network
+     * @return All the dedicated bearer QOS sessions of the data connection received from the
+     * network.
      *
      * @hide
      */
-
     @NonNull
     public List<QosSession> getQosSessions() {
         return mQosSessions;
     }
 
+    /**
+     * @return The slice info related to this data connection.
+     */
+    @Nullable
+    public SliceInfo getSliceInfo() {
+        return mSliceInfo;
+    }
+
     @NonNull
     @Override
     public String toString() {
@@ -411,6 +424,7 @@
            .append(" pduSessionId=").append(getPduSessionId())
            .append(" defaultQos=").append(mDefaultQos)
            .append(" qosSessions=").append(mQosSessions)
+           .append(" sliceInfo=").append(mSliceInfo)
            .append("}");
         return sb.toString();
     }
@@ -454,7 +468,8 @@
                 && mHandoverFailureMode == other.mHandoverFailureMode
                 && mPduSessionId == other.mPduSessionId
                 && isQosSame
-                && isQosSessionsSame;
+                && isQosSessionsSame
+                && Objects.equals(mSliceInfo, other.mSliceInfo);
     }
 
     @Override
@@ -462,7 +477,7 @@
         return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType,
                 mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses,
                 mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, mDefaultQos,
-                mQosSessions);
+                mQosSessions, mSliceInfo);
     }
 
     @Override
@@ -493,6 +508,7 @@
             dest.writeParcelable((NrQos)mDefaultQos, flags);
         }
         dest.writeList(mQosSessions);
+        dest.writeParcelable(mSliceInfo, flags);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR =
@@ -576,6 +592,8 @@
 
         private List<QosSession> mQosSessions = new ArrayList<>();
 
+        private SliceInfo mSliceInfo;
+
         /**
          * Default constructor for Builder.
          */
@@ -799,6 +817,21 @@
         }
 
         /**
+         * The Slice used for this data connection.
+         * <p/>
+         * If a handover occurs from EPDG to 5G,
+         * this is the {@link SliceInfo} used in {@link DataService#setupDataCall}.
+         *
+         * @param sliceInfo the slice info for the data call
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setSliceInfo(@Nullable SliceInfo sliceInfo) {
+            mSliceInfo = sliceInfo;
+            return this;
+        }
+
+        /**
          * Build the DataCallResponse.
          *
          * @return the DataCallResponse object.
@@ -807,7 +840,7 @@
             return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
                     mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
                     mPcscfAddresses, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId,
-                    mDefaultQos, mQosSessions);
+                    mDefaultQos, mQosSessions, mSliceInfo);
         }
     }
 }
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 2ec9651..03c2ef9 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -194,13 +194,19 @@
          *                     The standard range of values are 1-15 while 0 means no pdu session id
          *                     was attached to this call.  Reference: 3GPP TS 24.007 section
          *                     11.2.3.1b.
+         * @param sliceInfo used within the data connection when a handover occurs from EPDG to 5G.
+         *        The value is null unless the access network is
+         *        {@link android.telephony.AccessNetworkConstants.AccessNetworkType#NGRAN} and a
+         *        handover is occurring from EPDG to 5G.  If the slice passed is rejected, then
+         *        {@link DataCallResponse#getCause()} is
+         *        {@link android.telephony.DataFailCause#SLICE_REJECTED}.
          * @param callback The result callback for this request.
          */
         public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
                 boolean isRoaming, boolean allowRoaming,
                 @SetupDataReason int reason,
                 @Nullable LinkProperties linkProperties,
-                @IntRange(from = 0, to = 15) int pduSessionId,
+                @IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo,
                 @NonNull DataServiceCallback callback) {
             /* Call the old version since the new version isn't supported */
             setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason,
@@ -392,10 +398,11 @@
         public final int reason;
         public final LinkProperties linkProperties;
         public final int pduSessionId;
+        public final SliceInfo sliceInfo;
         public final IDataServiceCallback callback;
         SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
                              boolean allowRoaming, int reason, LinkProperties linkProperties,
-                             int pduSessionId, IDataServiceCallback callback) {
+                             int pduSessionId, SliceInfo sliceInfo, IDataServiceCallback callback) {
             this.accessNetworkType = accessNetworkType;
             this.dataProfile = dataProfile;
             this.isRoaming = isRoaming;
@@ -403,6 +410,7 @@
             this.linkProperties = linkProperties;
             this.reason = reason;
             this.pduSessionId = pduSessionId;
+            this.sliceInfo = sliceInfo;
             this.callback = callback;
         }
     }
@@ -513,6 +521,7 @@
                             setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
                             setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
                             setupDataCallRequest.linkProperties, setupDataCallRequest.pduSessionId,
+                            setupDataCallRequest.sliceInfo,
                             (setupDataCallRequest.callback != null)
                                     ? new DataServiceCallback(setupDataCallRequest.callback)
                                     : null);
@@ -676,10 +685,12 @@
         @Override
         public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
                 boolean isRoaming, boolean allowRoaming, int reason,
-                LinkProperties linkProperties, int pduSessionId, IDataServiceCallback callback) {
+                LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo,
+                IDataServiceCallback callback) {
             mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
                     new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
-                            allowRoaming, reason, linkProperties, pduSessionId, callback))
+                            allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
+                            callback))
                     .sendToTarget();
         }
 
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 3f1f033..e0b9a1a 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -19,6 +19,7 @@
 import android.net.LinkProperties;
 import android.telephony.data.DataProfile;
 import android.telephony.data.IDataServiceCallback;
+import android.telephony.data.SliceInfo;
 
 /**
  * {@hide}
@@ -29,7 +30,7 @@
     void removeDataServiceProvider(int slotId);
     void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
                        boolean allowRoaming, int reason, in LinkProperties linkProperties,
-                       int pduSessionId, IDataServiceCallback callback);
+                       int pduSessionId, in SliceInfo sliceInfo, IDataServiceCallback callback);
     void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
     void setInitialAttachApn(int slotId, in DataProfile dataProfile, boolean isRoaming,
                              IDataServiceCallback callback);
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/telephony/java/android/telephony/data/SliceInfo.aidl
new file mode 100644
index 0000000..286ea5e
--- /dev/null
+++ b/telephony/java/android/telephony/data/SliceInfo.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright 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.
+ */
+
+/** @hide */
+package android.telephony.data;
+
+parcelable SliceInfo;
diff --git a/telephony/java/android/telephony/data/SliceInfo.java b/telephony/java/android/telephony/data/SliceInfo.java
new file mode 100644
index 0000000..51857a7
--- /dev/null
+++ b/telephony/java/android/telephony/data/SliceInfo.java
@@ -0,0 +1,342 @@
+/*
+ * 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.annotation.SuppressLint;
+import android.annotation.SystemApi;
+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.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SliceInfo 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
+     */
+    @SuppressLint("MinMaxConstant")
+    public static final int MIN_SLICE_DIFFERENTIATOR = -1;
+
+    /**
+     * The max acceptable value for a Slice Differentiator
+     */
+    @SuppressLint("MinMaxConstant")
+    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 {}
+
+
+    @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;
+
+    private SliceInfo(@SliceServiceType int sliceServiceType,
+            int sliceDifferentiator, int mappedHplmnSliceServiceType,
+            int mappedHplmnSliceDifferentiator) {
+        mSliceServiceType = sliceServiceType;
+        mSliceDifferentiator = sliceDifferentiator;
+        mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator;
+        mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType;
+    }
+
+    /**
+     * The type of service provided by the slice.
+     * <p/>
+     * 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.
+     * <p/>
+     * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if {@link #getSliceServiceType} returns
+     * {@link #SLICE_SERVICE_TYPE_NONE}.
+     * <p/>
+     * 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.
+     * <p/>
+     * see: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    @SliceServiceType
+    public int getMappedHplmnSliceServiceType() {
+        return mMappedHplmnSliceServiceType;
+    }
+
+    /**
+     * This Slice Differentiator corresponds to a {@link SliceInfo} (S-NSSAI) of the HPLMN;
+     * {@link #getSliceDifferentiator()} is mapped to this value.
+     * <p/>
+     * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if either of the following are true:
+     * <ul>
+     * <li>{@link #getSliceDifferentiator()} returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE}</li>
+     * <li>{@link #getMappedHplmnSliceServiceType()} returns {@link #SLICE_SERVICE_TYPE_NONE}</li>
+     * </ul>
+     * <p/>
+     * see: 3GPP TS 24.501 Section 9.11.2.8.
+     */
+    @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+    public int getMappedHplmnSliceDifferentiator() {
+        return mMappedHplmnSliceDifferentiator;
+    }
+
+    private SliceInfo(@NonNull Parcel in) {
+        mSliceServiceType = in.readInt();
+        mSliceDifferentiator = in.readInt();
+        mMappedHplmnSliceServiceType = in.readInt();
+        mMappedHplmnSliceDifferentiator = 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);
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<SliceInfo> CREATOR =
+            new Parcelable.Creator<SliceInfo>() {
+                @Override
+                @NonNull
+                public SliceInfo createFromParcel(@NonNull Parcel source) {
+                    return new SliceInfo(source);
+                }
+
+                @Override
+                @NonNull
+                public SliceInfo[] newArray(int size) {
+                    return new SliceInfo[size];
+                }
+            };
+
+    @Override
+    public String toString() {
+        return "SliceInfo{"
+                + "mSliceServiceType=" + sliceServiceTypeToString(mSliceServiceType)
+                + ", mSliceDifferentiator=" + mSliceDifferentiator
+                + ", mMappedHplmnSliceServiceType="
+                + sliceServiceTypeToString(mMappedHplmnSliceServiceType)
+                + ", mMappedHplmnSliceDifferentiator=" + mMappedHplmnSliceDifferentiator
+                + '}';
+    }
+
+    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);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SliceInfo sliceInfo = (SliceInfo) o;
+        return mSliceServiceType == sliceInfo.mSliceServiceType
+                && mSliceDifferentiator == sliceInfo.mSliceDifferentiator
+                && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType
+                && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mSliceServiceType, mSliceDifferentiator, mMappedHplmnSliceServiceType,
+                mMappedHplmnSliceDifferentiator);
+    }
+
+    /**
+     * Provides a convenient way to set the fields of a {@link SliceInfo} when creating a
+     * new instance.
+     *
+     * <p>The example below shows how you might create a new {@code SliceInfo}:
+     *
+     * <pre><code>
+     *
+     * SliceInfo response = new SliceInfo.Builder()
+     *     .setSliceServiceType(SLICE_SERVICE_TYPE_URLLC)
+     *     .build();
+     * </code></pre>
+     */
+    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;
+
+        /**
+         * 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.
+         * <p/>
+         * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no
+         * corresponding Slice.
+         *
+         * @throws IllegalArgumentException if the parameter is not between
+         * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+         *
+         * @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.
+         * <p/>
+         * 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 between
+         * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+         *
+         * @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;
+        }
+
+        /**
+         * Build the {@link SliceInfo}.
+         *
+         * @return the {@link SliceInfo} object.
+         */
+        @NonNull
+        public SliceInfo build() {
+            return new SliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
+                    this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator);
+        }
+    }
+}