Support getSlicingConfig() API for 5G Slicing Configuration

- add getSlicingConfig() API in TelephonyManager and ITelephony
- add Parcelable implmentations for RouteSelectionDescriptor,
  SlicingConfig, and UrspRule
- remove @hide and @SystemApi for TrafficDescriptor and
  NetworkSliceInfo to make them public

Bug: 178075247
Test: .
(1) run "atest TelephonyManagerTest#testGetSlicingConfig" for CTS result
[22/121] android.telephony.cts.TelephonyManagerTest#testGetSlicingConfig: PASSED (956ms)
(2) run "atest RILTest#testGetSlicingConfig" for RILTest result
[17/111] com.android.internal.telephony.RILTest#testGetSlicingConfig: PASSED (1ms)

Change-Id: I0addc2b22c11b13759e890d88f51490993fb72e1
Merged-In: I0addc2b22c11b13759e890d88f51490993fb72e1
diff --git a/core/api/current.txt b/core/api/current.txt
index 0b2c6f4..d100104 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -41036,6 +41036,7 @@
     method public String getNetworkOperator();
     method public String getNetworkOperatorName();
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getNetworkSelectionMode();
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getNetworkSlicingConfiguration(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.data.SlicingConfig,android.telephony.TelephonyManager.SlicingException>);
     method public String getNetworkSpecifier();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getNetworkType();
     method @Deprecated public int getPhoneCount();
@@ -41269,6 +41270,13 @@
     field public static final int ERROR_TIMEOUT = 1; // 0x1
   }
 
+  public static class TelephonyManager.SlicingException extends java.lang.Exception {
+    ctor public TelephonyManager.SlicingException(int);
+    method public int getErrorCode();
+    field public static final int ERROR_MODEM_ERROR = 2; // 0x2
+    field public static final int ERROR_TIMEOUT = 1; // 0x1
+  }
+
   public abstract static class TelephonyManager.UssdResponseCallback {
     ctor public TelephonyManager.UssdResponseCallback();
     method public void onReceiveUssdResponse(android.telephony.TelephonyManager, String, CharSequence);
@@ -41444,6 +41452,88 @@
     method @NonNull public android.telephony.data.ApnSetting.Builder setUser(@Nullable String);
   }
 
+  public final class NetworkSliceInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0xffffffff, to=0xfffffe) public int getMappedHplmnSliceDifferentiator();
+    method public int getMappedHplmnSliceServiceType();
+    method @IntRange(from=0xffffffff, to=0xfffffe) public int getSliceDifferentiator();
+    method public int getSliceServiceType();
+    method public int getStatus();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.NetworkSliceInfo> CREATOR;
+    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
+    field public static final int SLICE_STATUS_ALLOWED = 2; // 0x2
+    field public static final int SLICE_STATUS_CONFIGURED = 1; // 0x1
+    field public static final int SLICE_STATUS_DEFAULT_CONFIGURED = 5; // 0x5
+    field public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_PLMN = 3; // 0x3
+    field public static final int SLICE_STATUS_REJECTED_NOT_AVAILABLE_IN_REGISTERED_AREA = 4; // 0x4
+    field public static final int SLICE_STATUS_UNKNOWN = 0; // 0x0
+  }
+
+  public static final class NetworkSliceInfo.Builder {
+    ctor public NetworkSliceInfo.Builder();
+    method @NonNull public android.telephony.data.NetworkSliceInfo build();
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=0xffffffff, to=0xfffffe) int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceServiceType(int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceDifferentiator(@IntRange(from=0xffffffff, to=0xfffffe) int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceServiceType(int);
+    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setStatus(int);
+  }
+
+  public final class RouteSelectionDescriptor implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getDataNetworkName();
+    method @IntRange(from=0x0, to=0xff) public int getPrecedence();
+    method public int getSessionType();
+    method @NonNull public java.util.List<android.telephony.data.NetworkSliceInfo> getSliceInfo();
+    method public int getSscMode();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.RouteSelectionDescriptor> CREATOR;
+    field public static final int ROUTE_SSC_MODE_1 = 1; // 0x1
+    field public static final int ROUTE_SSC_MODE_2 = 2; // 0x2
+    field public static final int ROUTE_SSC_MODE_3 = 3; // 0x3
+    field public static final int SESSION_TYPE_IPV4 = 0; // 0x0
+    field public static final int SESSION_TYPE_IPV4V6 = 2; // 0x2
+    field public static final int SESSION_TYPE_IPV6 = 1; // 0x1
+  }
+
+  public final class SlicingConfig implements android.os.Parcelable {
+    ctor public SlicingConfig();
+    method public int describeContents();
+    method @NonNull public java.util.List<android.telephony.data.NetworkSliceInfo> getSliceInfo();
+    method @NonNull public java.util.List<android.telephony.data.UrspRule> getUrspRules();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.SlicingConfig> CREATOR;
+  }
+
+  public final class TrafficDescriptor implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public String getDataNetworkName();
+    method @Nullable public String getOsAppId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.TrafficDescriptor> CREATOR;
+  }
+
+  public static final class TrafficDescriptor.Builder {
+    ctor public TrafficDescriptor.Builder();
+    method @NonNull public android.telephony.data.TrafficDescriptor build();
+    method @NonNull public android.telephony.data.TrafficDescriptor.Builder setDataNetworkName(@NonNull String);
+    method @NonNull public android.telephony.data.TrafficDescriptor.Builder setOsAppId(@NonNull String);
+  }
+
+  public final class UrspRule implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0x0, to=0xff) public int getPrecedence();
+    method @NonNull public java.util.List<android.telephony.data.RouteSelectionDescriptor> getRouteSelectionDescriptor();
+    method @NonNull public java.util.List<android.telephony.data.TrafficDescriptor> getTrafficDescriptors();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.UrspRule> CREATOR;
+  }
+
 }
 
 package android.telephony.emergency {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 3e423e6..906a595 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10800,32 +10800,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.EpsBearerQosSessionAttributes> CREATOR;
   }
 
-  public final class NetworkSliceInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method @IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getMappedHplmnSliceDifferentiator();
-    method public int getMappedHplmnSliceServiceType();
-    method @IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.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.NetworkSliceInfo> 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 NetworkSliceInfo.Builder {
-    ctor public NetworkSliceInfo.Builder();
-    method @NonNull public android.telephony.data.NetworkSliceInfo build();
-    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
-    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setMappedHplmnSliceServiceType(int);
-    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceDifferentiator(@IntRange(from=android.telephony.data.NetworkSliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.NetworkSliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
-    method @NonNull public android.telephony.data.NetworkSliceInfo.Builder setSliceServiceType(int);
-  }
-
   public final class NrQosSessionAttributes implements android.os.Parcelable android.net.QosSessionAttributes {
     method public int describeContents();
     method @NonNull public java.time.Duration getBitRateWindowDuration();
@@ -10882,15 +10856,6 @@
     method @NonNull public android.telephony.data.ThrottleStatus.Builder setTransportType(int);
   }
 
-  public final class TrafficDescriptor implements android.os.Parcelable {
-    ctor public TrafficDescriptor(@Nullable String, @Nullable String);
-    method public int describeContents();
-    method @Nullable public String getDnn();
-    method @Nullable public String getOsAppId();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.TrafficDescriptor> CREATOR;
-  }
-
 }
 
 package android.telephony.euicc {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b8a173e..f55dc8b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -86,6 +86,7 @@
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.ApnSetting.MvnoType;
+import android.telephony.data.SlicingConfig;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
 import android.telephony.gba.UaSecurityProtocolIdentifier;
@@ -15221,4 +15222,96 @@
             return PhoneCapability.DEFAULT_SSSS_CAPABILITY;
         }
     }
+
+    /**
+     * Exception that may be supplied to the callback in {@link #getNetworkSlicingConfiguration} if
+     * something goes awry.
+     */
+    public static class SlicingException extends Exception {
+        /**
+         * Getting the current slicing configuration successfully. Used internally only.
+         * @hide
+         */
+        public static final int SUCCESS = 0;
+
+        /**
+         * The system timed out waiting for a response from the Radio.
+         */
+        public static final int ERROR_TIMEOUT = 1;
+
+        /**
+         * The modem returned a failure.
+         */
+        public static final int ERROR_MODEM_ERROR = 2;
+
+        /** @hide */
+        @IntDef(prefix = {"ERROR_"}, value = {
+                ERROR_TIMEOUT,
+                ERROR_MODEM_ERROR,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface SlicingError {}
+
+        private final int mErrorCode;
+
+        public SlicingException(@SlicingError int errorCode) {
+            mErrorCode = errorCode;
+        }
+
+        /**
+         * Fetches the error code associated with this exception.
+         * @return An error code.
+         */
+        public @SlicingError int getErrorCode() {
+            return mErrorCode;
+        }
+    }
+
+    /** @hide */
+    public static final String KEY_SLICING_CONFIG_HANDLE = "slicing_config_handle";
+
+    /**
+     * Request to get the current slicing configuration including URSP rules and
+     * NSSAIs (configured, allowed and rejected).
+     *
+     * This method can be invoked if one of the following requirements is met:
+     * <ul>
+     *     <li>If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this
+     *     is a privileged permission that can only be granted to apps preloaded on the device.
+     *     <li>If the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * </ul>
+     *
+     * @param executor the executor on which callback will be invoked.
+     * @param callback a callback to receive the current slicing configuration.
+     */
+    @SuppressAutoDoc // No support for carrier privileges (b/72967236).
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void getNetworkSlicingConfiguration(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull OutcomeReceiver<SlicingConfig, SlicingException> callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) {
+                throw new IllegalStateException("telephony service is null.");
+            }
+            telephony.getSlicingConfig(new ResultReceiver(null) {
+                    @Override
+                    protected void onReceiveResult(int resultCode, Bundle result) {
+                        if (resultCode != SlicingException.SUCCESS) {
+                            executor.execute(() -> callback.onError(
+                                    new SlicingException(resultCode)));
+                            return;
+                        }
+                        SlicingConfig slicingConfig =
+                                result.getParcelable(KEY_SLICING_CONFIG_HANDLE);
+                        executor.execute(() -> callback.onResult(slicingConfig));
+                    }
+            });
+        } catch (RemoteException ex) {
+            ex.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/data/NetworkSliceInfo.java b/telephony/java/android/telephony/data/NetworkSliceInfo.java
index 1d90095..232a930 100644
--- a/telephony/java/android/telephony/data/NetworkSliceInfo.java
+++ b/telephony/java/android/telephony/data/NetworkSliceInfo.java
@@ -19,8 +19,6 @@
 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;
 
@@ -35,10 +33,7 @@
  * 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.
- *
- * @hide
  */
-@SystemApi
 public final class NetworkSliceInfo implements Parcelable {
     /**
      * When set on a Slice Differentiator, this value indicates that there is no corresponding
@@ -68,14 +63,14 @@
 
     /**
      * The min acceptable value for a Slice Differentiator
+     * @hide
      */
-    @SuppressLint("MinMaxConstant")
     public static final int MIN_SLICE_DIFFERENTIATOR = -1;
 
     /**
      * The max acceptable value for a Slice Differentiator
+     * @hide
      */
-    @SuppressLint("MinMaxConstant")
     public static final int MAX_SLICE_DIFFERENTIATOR = 0xFFFFFE;
 
     /** @hide */
@@ -88,6 +83,62 @@
     @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;
@@ -97,14 +148,18 @@
     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 mappedHplmnSliceDifferentiator, int status) {
         mSliceServiceType = sliceServiceType;
         mSliceDifferentiator = sliceDifferentiator;
         mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator;
         mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType;
+        mStatus = status;
     }
 
     /**
@@ -157,11 +212,21 @@
         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
@@ -175,6 +240,7 @@
         dest.writeInt(mSliceDifferentiator);
         dest.writeInt(mMappedHplmnSliceServiceType);
         dest.writeInt(mMappedHplmnSliceDifferentiator);
+        dest.writeInt(mStatus);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<NetworkSliceInfo> CREATOR =
@@ -200,6 +266,7 @@
                 + ", mMappedHplmnSliceServiceType="
                 + sliceServiceTypeToString(mMappedHplmnSliceServiceType)
                 + ", mMappedHplmnSliceDifferentiator=" + mMappedHplmnSliceDifferentiator
+                + ", mStatus=" + sliceStatusToString(mStatus)
                 + '}';
     }
 
@@ -218,6 +285,25 @@
         }
     }
 
+    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;
@@ -226,13 +312,14 @@
         return mSliceServiceType == sliceInfo.mSliceServiceType
                 && mSliceDifferentiator == sliceInfo.mSliceDifferentiator
                 && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType
-                && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator;
+                && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator
+                && mStatus == sliceInfo.mStatus;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mSliceServiceType, mSliceDifferentiator, mMappedHplmnSliceServiceType,
-                mMappedHplmnSliceDifferentiator);
+                mMappedHplmnSliceDifferentiator, mStatus);
     }
 
     /**
@@ -257,6 +344,9 @@
         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.
@@ -281,8 +371,7 @@
          * 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}.
+         * @throws IllegalArgumentException if the parameter is not in the expected range.
          *
          * @return The same instance of the builder.
          */
@@ -316,8 +405,7 @@
          * 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}.
+         * @throws IllegalArgumentException if the parameter is not in the expected range.
          *
          * @return The same instance of the builder.
          */
@@ -334,6 +422,22 @@
         }
 
         /**
+         * 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.
@@ -341,7 +445,8 @@
         @NonNull
         public NetworkSliceInfo build() {
             return new NetworkSliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
-                    this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator);
+                    this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator,
+                    this.mStatus);
         }
     }
 }
diff --git a/telephony/java/android/telephony/data/RouteSelectionDescriptor.aidl b/telephony/java/android/telephony/data/RouteSelectionDescriptor.aidl
new file mode 100644
index 0000000..563a00e
--- /dev/null
+++ b/telephony/java/android/telephony/data/RouteSelectionDescriptor.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2021 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;
+
+parcelable RouteSelectionDescriptor;
diff --git a/telephony/java/android/telephony/data/RouteSelectionDescriptor.java b/telephony/java/android/telephony/data/RouteSelectionDescriptor.java
new file mode 100644
index 0000000..c2457f2
--- /dev/null
+++ b/telephony/java/android/telephony/data/RouteSelectionDescriptor.java
@@ -0,0 +1,263 @@
+/**
+ * Copyright 2021 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.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a single route selection descriptor as defined in
+ * 3GPP TS 24.526.
+ */
+public final class RouteSelectionDescriptor implements Parcelable {
+    /**
+     * The min acceptable value for the precedence of a route selection descriptor.
+     * @hide
+     */
+    public static final int MIN_ROUTE_PRECEDENCE = 0;
+
+    /**
+     * The max acceptable value for the precedence of a route selection descriptor.
+     * @hide
+     */
+    public static final int MAX_ROUTE_PRECEDENCE = 255;
+
+    /**
+     * The route selection descriptor is for the session with IPV4 type.
+     */
+    public static final int SESSION_TYPE_IPV4 = 0;
+
+    /**
+     * The route selection descriptor is for the session with IPV6 type.
+     */
+    public static final int SESSION_TYPE_IPV6 = 1;
+
+    /**
+     * The route selection descriptor is for the session with both IP and IPV6 types.
+     */
+    public static final int SESSION_TYPE_IPV4V6 = 2;
+
+    /** @hide */
+    @IntDef(prefix = { "SESSION_TYPE_" }, value = {
+            SESSION_TYPE_IPV4,
+            SESSION_TYPE_IPV6,
+            SESSION_TYPE_IPV4V6,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RouteSessionType {}
+
+    /**
+     * The route selection descriptor is using SSC mode 1. The session will provide continual
+     * support when UE's location is updated.
+     */
+    public static final int ROUTE_SSC_MODE_1 = 1;
+
+    /**
+     * The route selection descriptor is using SSC mode 2. The new session for the same network
+     * will be established after releasing the old session when UE's location is updated.
+     */
+    public static final int ROUTE_SSC_MODE_2 = 2;
+
+    /**
+     * The route selection descriptor is using SSC mode 3. The new session for the same network is
+     * allowed to be established before releasing the old session when UE's location is updated.
+     */
+    public static final int ROUTE_SSC_MODE_3 = 3;
+
+    /**
+     * The min acceptable value for the SSC mode of a route selection descriptor.
+     * @hide
+     */
+    public static final int MIN_ROUTE_SSC_MODE = ROUTE_SSC_MODE_1;
+
+    /**
+     * The max acceptable value for the SSC mode of a route selection descriptor.
+     * @hide
+     */
+    public static final int MAX_ROUTE_SSC_MODE = ROUTE_SSC_MODE_3;
+
+    /** @hide */
+    @IntDef(prefix = { "ROUTE_SSC_MODE_" }, value = {
+            ROUTE_SSC_MODE_1,
+            ROUTE_SSC_MODE_2,
+            ROUTE_SSC_MODE_3,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RouteSscMode {}
+
+    @IntRange(from = MIN_ROUTE_PRECEDENCE, to = MAX_ROUTE_PRECEDENCE)
+    private final int mPrecedence;
+    @RouteSessionType
+    private final int mSessionType;
+    @RouteSscMode
+    @IntRange(from = MIN_ROUTE_SSC_MODE, to = MAX_ROUTE_SSC_MODE)
+    private final int mSscMode;
+    private final List<NetworkSliceInfo> mSliceInfo;
+    private final List<String> mDnn;
+
+    /** @hide */
+    RouteSelectionDescriptor(android.hardware.radio.V1_6.RouteSelectionDescriptor rsd) {
+        this(rsd.precedence, rsd.sessionType.value(), rsd.sscMode.value(), rsd.sliceInfo,
+                rsd.dnn);
+    }
+
+    /** @hide */
+    public RouteSelectionDescriptor(int precedence, int sessionType, int sscMode,
+            List<android.hardware.radio.V1_6.SliceInfo> sliceInfo, List<String> dnn) {
+        mPrecedence = precedence;
+        mSessionType = sessionType;
+        mSscMode = sscMode;
+        mSliceInfo = new ArrayList<NetworkSliceInfo>();
+        for (android.hardware.radio.V1_6.SliceInfo si : sliceInfo) {
+            mSliceInfo.add(sliceInfoBuilder(si));
+        }
+        mDnn = new ArrayList<String>();
+        mDnn.addAll(dnn);
+    }
+
+    private NetworkSliceInfo sliceInfoBuilder(android.hardware.radio.V1_6.SliceInfo si) {
+        NetworkSliceInfo.Builder builder = new NetworkSliceInfo.Builder()
+                .setSliceServiceType(si.sst)
+                .setMappedHplmnSliceServiceType(si.mappedHplmnSst);
+        if (si.sliceDifferentiator != NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE) {
+            builder
+                .setSliceDifferentiator(si.sliceDifferentiator)
+                .setMappedHplmnSliceDifferentiator(si.mappedHplmnSD);
+        }
+        return builder.build();
+    }
+
+    private RouteSelectionDescriptor(Parcel p) {
+        mPrecedence = p.readInt();
+        mSessionType = p.readInt();
+        mSscMode = p.readInt();
+        mSliceInfo = p.createTypedArrayList(NetworkSliceInfo.CREATOR);
+        mDnn = new ArrayList<String>();
+        p.readStringList(mDnn);
+    }
+
+    /**
+     * Precedence value in the range of 0 to 255. Higher value has lower precedence.
+     * @return the precedence value for this route selection descriptor.
+     */
+    @IntRange(from = MIN_ROUTE_PRECEDENCE, to = MAX_ROUTE_PRECEDENCE)
+    public int getPrecedence() {
+        return mPrecedence;
+    }
+
+    /**
+     * This is used for checking which session type defined in 3GPP TS 23.501 is allowed for the
+     * route in a route selection descriptor.
+     * @return the session type for this route selection descriptor.
+     */
+    @RouteSessionType
+    public int getSessionType() {
+        return mSessionType;
+    }
+
+    /**
+     * SSC mode stands for Session and Service Continuity mode (which specifies the IP continuity
+     * mode) as defined in 3GPP TS 23.501.
+     * @return the SSC mode for this route selection descriptor.
+     */
+    @RouteSscMode
+    public int getSscMode() {
+        return mSscMode;
+    }
+
+    /**
+     * This is the list of all the slices available in the route selection descriptor as indicated
+     * by the network. These are the slices that can be used by the device if this route selection
+     * descriptor is used based the traffic (see 3GPP TS 23.501 for details).
+     * @return the list of all the slices available in the route selection descriptor.
+     */
+    public @NonNull List<NetworkSliceInfo> getSliceInfo() {
+        return mSliceInfo;
+    }
+
+    /**
+     * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003. There
+     * can be 0 or more DNNs specified in a route selection descriptor.
+     * @return the list of DNN for this route selection descriptor.
+     */
+    public @NonNull List<String> getDataNetworkName() {
+        return mDnn;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mPrecedence);
+        dest.writeInt(mSessionType);
+        dest.writeInt(mSscMode);
+        dest.writeTypedList(mSliceInfo, flags);
+        dest.writeStringList(mDnn);
+    }
+
+    public static final @NonNull Parcelable.Creator<RouteSelectionDescriptor> CREATOR =
+            new Parcelable.Creator<RouteSelectionDescriptor>() {
+                @Override
+                public RouteSelectionDescriptor createFromParcel(Parcel source) {
+                    return new RouteSelectionDescriptor(source);
+                }
+
+                @Override
+                public RouteSelectionDescriptor[] newArray(int size) {
+                    return new RouteSelectionDescriptor[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        RouteSelectionDescriptor that = (RouteSelectionDescriptor) o;
+        return mPrecedence == that.mPrecedence
+                && mSessionType == that.mSessionType
+                && mSscMode == that.mSscMode
+                && mSliceInfo.size() == that.mSliceInfo.size()
+                && mSliceInfo.containsAll(that.mSliceInfo)
+                && mDnn.size() == that.mDnn.size()
+                && mDnn.containsAll(that.mDnn);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPrecedence, mSessionType, mSscMode, mSliceInfo, mDnn);
+    }
+
+    @Override
+    public String toString() {
+        return "{.precedence = " + mPrecedence + ", .sessionType = " + mSessionType
+                + ", .sscMode = " + mSscMode + ", .sliceInfo = " + mSliceInfo
+                + ", .dnn = " + mDnn + "}";
+    }
+}
diff --git a/telephony/java/android/telephony/data/SlicingConfig.aidl b/telephony/java/android/telephony/data/SlicingConfig.aidl
new file mode 100644
index 0000000..ad93d8c
--- /dev/null
+++ b/telephony/java/android/telephony/data/SlicingConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2021 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;
+
+parcelable SlicingConfig;
diff --git a/telephony/java/android/telephony/data/SlicingConfig.java b/telephony/java/android/telephony/data/SlicingConfig.java
new file mode 100644
index 0000000..990e4d2
--- /dev/null
+++ b/telephony/java/android/telephony/data/SlicingConfig.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2021 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.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a slicing configuration
+ */
+public final class SlicingConfig implements Parcelable {
+    private final List<UrspRule> mUrspRules;
+    private final List<NetworkSliceInfo> mSliceInfo;
+
+    public SlicingConfig() {
+        mUrspRules = new ArrayList<UrspRule>();
+        mSliceInfo = new ArrayList<NetworkSliceInfo>();
+    }
+
+    /** @hide */
+    public SlicingConfig(android.hardware.radio.V1_6.SlicingConfig sc) {
+        this(sc.urspRules, sc.sliceInfo);
+    }
+
+    /** @hide */
+    public SlicingConfig(List<android.hardware.radio.V1_6.UrspRule> urspRules,
+            List<android.hardware.radio.V1_6.SliceInfo> sliceInfo) {
+        mUrspRules = new ArrayList<UrspRule>();
+        for (android.hardware.radio.V1_6.UrspRule ur : urspRules) {
+            mUrspRules.add(new UrspRule(ur.precedence, ur.trafficDescriptors,
+                    ur.routeSelectionDescriptor));
+        }
+        mSliceInfo = new ArrayList<NetworkSliceInfo>();
+        for (android.hardware.radio.V1_6.SliceInfo si : sliceInfo) {
+            mSliceInfo.add(sliceInfoBuilder(si));
+        }
+    }
+
+    private NetworkSliceInfo sliceInfoBuilder(android.hardware.radio.V1_6.SliceInfo si) {
+        NetworkSliceInfo.Builder builder = new NetworkSliceInfo.Builder()
+                .setSliceServiceType(si.sst)
+                .setMappedHplmnSliceServiceType(si.mappedHplmnSst);
+        if (si.sliceDifferentiator != NetworkSliceInfo.SLICE_DIFFERENTIATOR_NO_SLICE) {
+            builder
+                .setSliceDifferentiator(si.sliceDifferentiator)
+                .setMappedHplmnSliceDifferentiator(si.mappedHplmnSD);
+        }
+        return builder.build();
+    }
+
+    /** @hide */
+    public SlicingConfig(Parcel p) {
+        mUrspRules = p.createTypedArrayList(UrspRule.CREATOR);
+        mSliceInfo = p.createTypedArrayList(NetworkSliceInfo.CREATOR);
+    }
+
+    /**
+     * This list contains the current URSP rules. Empty list represents that no rules are
+     * configured.
+     * @return the current URSP rules for this slicing configuration.
+     */
+    public @NonNull List<UrspRule> getUrspRules() {
+        return mUrspRules;
+    }
+
+    /**
+     * @return the list of all slices for this slicing configuration.
+     */
+    public @NonNull List<NetworkSliceInfo> getSliceInfo() {
+        return mSliceInfo;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeTypedList(mUrspRules, flags);
+        dest.writeTypedList(mSliceInfo, flags);
+    }
+
+    public static final @NonNull Parcelable.Creator<SlicingConfig> CREATOR =
+            new Parcelable.Creator<SlicingConfig>() {
+                @Override
+                public SlicingConfig createFromParcel(Parcel source) {
+                    return new SlicingConfig(source);
+                }
+
+                @Override
+                public SlicingConfig[] newArray(int size) {
+                    return new SlicingConfig[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SlicingConfig that = (SlicingConfig) o;
+        return mUrspRules.size() == that.mUrspRules.size()
+                && mUrspRules.containsAll(that.mUrspRules)
+                && mSliceInfo.size() == that.mSliceInfo.size()
+                && mSliceInfo.containsAll(that.mSliceInfo);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mUrspRules, mSliceInfo);
+    }
+
+    @Override
+    public String toString() {
+        return "{.urspRules = " + mUrspRules + ", .sliceInfo = " + mSliceInfo + "}";
+    }
+}
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java
index 480379d..d813bc5 100644
--- a/telephony/java/android/telephony/data/TrafficDescriptor.java
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.java
@@ -18,20 +18,17 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import java.util.Objects;
 
 /**
- * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for URSP traffic
- * matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an optional DNN, which,
- * if present, must be used for traffic matching; it does not specify the end point to be used for
- * the data call.
- * @hide
+ * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for UE Route Selection
+ * Policy(URSP) traffic matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an
+ * optional Data Network Name(DNN), which, if present, must be used for traffic matching; it does
+ * not specify the end point to be used for the data call.
  */
-@SystemApi
 public final class TrafficDescriptor implements Parcelable {
     private final String mDnn;
     private final String mOsAppId;
@@ -45,8 +42,10 @@
      * Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
      * @param dnn optional DNN, which must be used for traffic matching, if present
      * @param osAppId OsId + osAppId of the traffic descriptor
+     *
+     * @hide
      */
-    public TrafficDescriptor(@Nullable String dnn, @Nullable String osAppId) {
+    public TrafficDescriptor(String dnn, String osAppId) {
         mDnn = dnn;
         mOsAppId = osAppId;
     }
@@ -55,12 +54,13 @@
      * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003.
      * @return the DNN of this traffic descriptor.
      */
-    public @Nullable String getDnn() {
+    public @Nullable String getDataNetworkName() {
         return mDnn;
     }
 
     /**
-     * OsAppId represents the OsId + OsAppId as defined in 3GPP TS 24.526 Section 5.2.
+     * OsAppId is the app id as defined in 3GPP TS 24.526 Section 5.2, and it identifies a traffic
+     * category.
      * @return the OS App ID of this traffic descriptor.
      */
     public @Nullable String getOsAppId() {
@@ -108,4 +108,65 @@
     public int hashCode() {
         return Objects.hash(mDnn, mOsAppId);
     }
+
+    /**
+     * Provides a convenient way to set the fields of a {@link TrafficDescriptor} when creating a
+     * new instance.
+     *
+     * <p>The example below shows how you might create a new {@code TrafficDescriptor}:
+     *
+     * <pre><code>
+     *
+     * TrafficDescriptor response = new TrafficDescriptor.Builder()
+     *     .setDnn("")
+     *     .build();
+     * </code></pre>
+     */
+    public static final class Builder {
+        private String mDnn = null;
+        private String mOsAppId = null;
+
+        /**
+         * Default constructor for Builder.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Set the Data Network Name(DNN).
+         *
+         * @return The same instance of the builder.
+         */
+        @NonNull
+        public Builder setDataNetworkName(@NonNull String dnn) {
+            this.mDnn = dnn;
+            return this;
+        }
+
+        /**
+         * Set the OS App ID.
+         *
+         * @return The same instance of the builder.
+         */
+        @NonNull
+        public Builder setOsAppId(@NonNull String osAppId) {
+            this.mOsAppId = osAppId;
+            return this;
+        }
+
+        /**
+         * Build the {@link TrafficDescriptor}.
+         *
+         * @throws IllegalArgumentException if DNN and OS App ID are null.
+         *
+         * @return the {@link TrafficDescriptor} object.
+         */
+        @NonNull
+        public TrafficDescriptor build() {
+            if (this.mDnn == null && this.mOsAppId == null) {
+                throw new IllegalArgumentException("DNN and OS App ID are null");
+            }
+            return new TrafficDescriptor(this.mDnn, this.mOsAppId);
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/data/UrspRule.aidl b/telephony/java/android/telephony/data/UrspRule.aidl
new file mode 100644
index 0000000..2bed583
--- /dev/null
+++ b/telephony/java/android/telephony/data/UrspRule.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2021 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;
+
+parcelable UrspRule;
diff --git a/telephony/java/android/telephony/data/UrspRule.java b/telephony/java/android/telephony/data/UrspRule.java
new file mode 100644
index 0000000..e2c47fd
--- /dev/null
+++ b/telephony/java/android/telephony/data/UrspRule.java
@@ -0,0 +1,178 @@
+/**
+ * Copyright 2021 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.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.radio.V1_6.OptionalDnn;
+import android.hardware.radio.V1_6.OptionalOsAppId;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a single URSP rule as defined in 3GPP TS 24.526. URSP stands for UE Route Selection
+ * Policy. In 5G, network can provide URSP information to devices which provides information on
+ * what connection parameters should be used for what traffic.
+ */
+public final class UrspRule implements Parcelable {
+    /**
+     * The min acceptable value for the precedence of a URSP rule.
+     * @hide
+     */
+    public static final int MIN_URSP_PRECEDENCE = 0;
+
+    /**
+     * The max acceptable value for the precedence of a URSP rule.
+     * @hide
+     */
+    public static final int MAX_URSP_PRECEDENCE = 255;
+
+    @IntRange(from = MIN_URSP_PRECEDENCE, to = MAX_URSP_PRECEDENCE)
+    private final int mPrecedence;
+    private final List<TrafficDescriptor> mTrafficDescriptors;
+    private final List<RouteSelectionDescriptor> mRouteSelectionDescriptor;
+
+    UrspRule(android.hardware.radio.V1_6.UrspRule ur) {
+        this(ur.precedence, ur.trafficDescriptors, ur.routeSelectionDescriptor);
+    }
+
+    /** @hide */
+    public UrspRule(int precedence,
+            List<android.hardware.radio.V1_6.TrafficDescriptor> trafficDescriptors,
+            List<android.hardware.radio.V1_6.RouteSelectionDescriptor> routeSelectionDescriptor) {
+        mPrecedence = precedence;
+        mTrafficDescriptors = new ArrayList<TrafficDescriptor>();
+        for (android.hardware.radio.V1_6.TrafficDescriptor td : trafficDescriptors) {
+            mTrafficDescriptors.add(convertToTrafficDescriptor(td));
+        }
+        mRouteSelectionDescriptor = new ArrayList<RouteSelectionDescriptor>();
+        for (android.hardware.radio.V1_6.RouteSelectionDescriptor rsd : routeSelectionDescriptor) {
+            mRouteSelectionDescriptor.add(new RouteSelectionDescriptor(rsd));
+        }
+    }
+
+    /** Convert an ArrayList of Bytes to an exactly-sized primitive array */
+    private byte[] arrayListToPrimitiveArray(ArrayList<Byte> bytes) {
+        byte[] ret = new byte[bytes.size()];
+        for (int i = 0; i < ret.length; i++) {
+            ret[i] = bytes.get(i);
+        }
+        return ret;
+    }
+
+    private TrafficDescriptor convertToTrafficDescriptor(
+            android.hardware.radio.V1_6.TrafficDescriptor td) {
+        String dnn = td.dnn.getDiscriminator() == OptionalDnn.hidl_discriminator.noinit
+                ? null : td.dnn.value();
+        String osAppId = td.osAppId.getDiscriminator() == OptionalOsAppId.hidl_discriminator.noinit
+                ? null : new String(arrayListToPrimitiveArray(td.osAppId.value().osAppId));
+        TrafficDescriptor.Builder builder = new TrafficDescriptor.Builder();
+        if (dnn != null) {
+            builder.setDataNetworkName(dnn);
+        }
+        if (osAppId != null) {
+            builder.setOsAppId(osAppId);
+        }
+        return builder.build();
+    }
+
+    private UrspRule(Parcel p) {
+        mPrecedence = p.readInt();
+        mTrafficDescriptors = p.createTypedArrayList(TrafficDescriptor.CREATOR);
+        mRouteSelectionDescriptor = p.createTypedArrayList(RouteSelectionDescriptor.CREATOR);
+    }
+
+    /**
+     * Precedence value in the range of 0 to 255. Higher value has lower precedence.
+     * @return the precedence value for this URSP rule.
+     */
+    @IntRange(from = MIN_URSP_PRECEDENCE, to = MAX_URSP_PRECEDENCE)
+    public int getPrecedence() {
+        return mPrecedence;
+    }
+
+    /**
+     * These traffic descriptors are used as a matcher for network requests.
+     * @return the traffic descriptors which are associated to this URSP rule.
+     */
+    public @NonNull List<TrafficDescriptor> getTrafficDescriptors() {
+        return mTrafficDescriptors;
+    }
+
+    /**
+     * List of routes (connection parameters) that must be used by the device for requests matching
+     * a traffic descriptor.
+     * @return the route selection descriptors which are associated to this URSP rule.
+     */
+    public @NonNull List<RouteSelectionDescriptor> getRouteSelectionDescriptor() {
+        return mRouteSelectionDescriptor;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mPrecedence);
+        dest.writeTypedList(mTrafficDescriptors, flags);
+        dest.writeTypedList(mRouteSelectionDescriptor, flags);
+    }
+
+    public static final @NonNull Parcelable.Creator<UrspRule> CREATOR =
+            new Parcelable.Creator<UrspRule>() {
+                @Override
+                public UrspRule createFromParcel(Parcel source) {
+                    return new UrspRule(source);
+                }
+
+                @Override
+                public UrspRule[] newArray(int size) {
+                    return new UrspRule[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        UrspRule that = (UrspRule) o;
+        return mPrecedence == that.mPrecedence
+                && mTrafficDescriptors.size() == that.mTrafficDescriptors.size()
+                && mTrafficDescriptors.containsAll(that.mTrafficDescriptors)
+                && mRouteSelectionDescriptor.size() == that.mRouteSelectionDescriptor.size()
+                && mRouteSelectionDescriptor.containsAll(that.mRouteSelectionDescriptor);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPrecedence, mTrafficDescriptors, mRouteSelectionDescriptor);
+    }
+
+    @Override
+    public String toString() {
+        return "{.precedence = " + mPrecedence + ", .trafficDescriptors = " + mTrafficDescriptors
+                + ", .routeSelectionDescriptor = " + mRouteSelectionDescriptor + "}";
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index ae5f997..d812b46 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2447,4 +2447,10 @@
      * Gets the current phone capability.
      */
     PhoneCapability getPhoneCapability();
+
+    /**
+     * Request to get the current slicing configuration including URSP rules and
+     * NSSAIs (configured, allowed and rejected).
+     */
+    void getSlicingConfig(in ResultReceiver callback);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 822fc44..fe8e671 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -527,6 +527,7 @@
     int RIL_REQUEST_SET_DATA_THROTTLING = 221;
     int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP = 222;
     int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPES_BITMAP = 223;
+    int RIL_REQUEST_GET_SLICING_CONFIG = 224;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;